|
44 | 44 | use std::convert::From;
|
45 | 45 | use std::fs::File;
|
46 | 46 | use std::io;
|
| 47 | +use std::mem::size_of; |
47 | 48 | use std::ops::{BitAnd, BitOr, Deref};
|
48 | 49 | use std::rc::Rc;
|
49 | 50 | use std::sync::atomic::Ordering;
|
@@ -591,17 +592,62 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
|
591 | 592 | }
|
592 | 593 |
|
593 | 594 | fn store<O: AtomicAccess>(&self, val: O, addr: GuestAddress, order: Ordering) -> Result<()> {
|
594 |
| - // `find_region` should really do what `to_region_addr` is doing right now, except |
595 |
| - // it should keep returning a `Result`. |
596 |
| - self.to_region_addr(addr) |
597 |
| - .ok_or(Error::InvalidGuestAddress(addr)) |
598 |
| - .and_then(|(region, region_addr)| region.store(val, region_addr, order)) |
| 595 | + let expected = size_of::<O>(); |
| 596 | + |
| 597 | + let completed = self.try_access( |
| 598 | + expected, |
| 599 | + addr, |
| 600 | + |offset, len, region_addr, region| -> Result<usize> { |
| 601 | + assert_eq!(offset, 0); |
| 602 | + if len < expected { |
| 603 | + return Err(Error::PartialBuffer { |
| 604 | + expected, |
| 605 | + completed: len, |
| 606 | + }); |
| 607 | + } |
| 608 | + region.store(val, region_addr, order).map(|()| expected) |
| 609 | + }, |
| 610 | + )?; |
| 611 | + |
| 612 | + if completed < expected { |
| 613 | + Err(Error::PartialBuffer { |
| 614 | + expected, |
| 615 | + completed, |
| 616 | + }) |
| 617 | + } else { |
| 618 | + Ok(()) |
| 619 | + } |
599 | 620 | }
|
600 | 621 |
|
601 | 622 | fn load<O: AtomicAccess>(&self, addr: GuestAddress, order: Ordering) -> Result<O> {
|
602 |
| - self.to_region_addr(addr) |
603 |
| - .ok_or(Error::InvalidGuestAddress(addr)) |
604 |
| - .and_then(|(region, region_addr)| region.load(region_addr, order)) |
| 623 | + let expected = size_of::<O>(); |
| 624 | + let mut result = None::<O>; |
| 625 | + |
| 626 | + let completed = self.try_access( |
| 627 | + expected, |
| 628 | + addr, |
| 629 | + |offset, len, region_addr, region| -> Result<usize> { |
| 630 | + assert_eq!(offset, 0); |
| 631 | + if len < expected { |
| 632 | + return Err(Error::PartialBuffer { |
| 633 | + expected, |
| 634 | + completed: len, |
| 635 | + }); |
| 636 | + } |
| 637 | + result = Some(region.load(region_addr, order)?); |
| 638 | + Ok(expected) |
| 639 | + }, |
| 640 | + )?; |
| 641 | + |
| 642 | + if completed < expected { |
| 643 | + Err(Error::PartialBuffer { |
| 644 | + expected, |
| 645 | + completed, |
| 646 | + }) |
| 647 | + } else { |
| 648 | + // Must be set because `completed == expected` |
| 649 | + Ok(result.unwrap()) |
| 650 | + } |
605 | 651 | }
|
606 | 652 | }
|
607 | 653 |
|
|
0 commit comments