|
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;
|
@@ -718,17 +719,62 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
|
718 | 719 | }
|
719 | 720 |
|
720 | 721 | fn store<O: AtomicAccess>(&self, val: O, addr: GuestAddress, order: Ordering) -> Result<()> {
|
721 |
| - // `find_region` should really do what `to_region_addr` is doing right now, except |
722 |
| - // it should keep returning a `Result`. |
723 |
| - self.to_region_addr(addr) |
724 |
| - .ok_or(Error::InvalidGuestAddress(addr)) |
725 |
| - .and_then(|(region, region_addr)| region.store(val, region_addr, order)) |
| 722 | + let expected = size_of::<O>(); |
| 723 | + |
| 724 | + let completed = self.try_access( |
| 725 | + expected, |
| 726 | + addr, |
| 727 | + |offset, len, region_addr, region| -> Result<usize> { |
| 728 | + assert_eq!(offset, 0); |
| 729 | + if len < expected { |
| 730 | + return Err(Error::PartialBuffer { |
| 731 | + expected, |
| 732 | + completed: len, |
| 733 | + }); |
| 734 | + } |
| 735 | + region.store(val, region_addr, order).map(|()| expected) |
| 736 | + }, |
| 737 | + )?; |
| 738 | + |
| 739 | + if completed < expected { |
| 740 | + Err(Error::PartialBuffer { |
| 741 | + expected, |
| 742 | + completed, |
| 743 | + }) |
| 744 | + } else { |
| 745 | + Ok(()) |
| 746 | + } |
726 | 747 | }
|
727 | 748 |
|
728 | 749 | fn load<O: AtomicAccess>(&self, addr: GuestAddress, order: Ordering) -> Result<O> {
|
729 |
| - self.to_region_addr(addr) |
730 |
| - .ok_or(Error::InvalidGuestAddress(addr)) |
731 |
| - .and_then(|(region, region_addr)| region.load(region_addr, order)) |
| 750 | + let expected = size_of::<O>(); |
| 751 | + let mut result = None::<O>; |
| 752 | + |
| 753 | + let completed = self.try_access( |
| 754 | + expected, |
| 755 | + addr, |
| 756 | + |offset, len, region_addr, region| -> Result<usize> { |
| 757 | + assert_eq!(offset, 0); |
| 758 | + if len < expected { |
| 759 | + return Err(Error::PartialBuffer { |
| 760 | + expected, |
| 761 | + completed: len, |
| 762 | + }); |
| 763 | + } |
| 764 | + result = Some(region.load(region_addr, order)?); |
| 765 | + Ok(expected) |
| 766 | + }, |
| 767 | + )?; |
| 768 | + |
| 769 | + if completed < expected { |
| 770 | + Err(Error::PartialBuffer { |
| 771 | + expected, |
| 772 | + completed, |
| 773 | + }) |
| 774 | + } else { |
| 775 | + // Must be set because `completed == expected` |
| 776 | + Ok(result.unwrap()) |
| 777 | + } |
732 | 778 | }
|
733 | 779 | }
|
734 | 780 |
|
|
0 commit comments