|
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; |
@@ -678,17 +679,62 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T { |
678 | 679 | } |
679 | 680 |
|
680 | 681 | fn store<O: AtomicAccess>(&self, val: O, addr: GuestAddress, order: Ordering) -> Result<()> { |
681 | | - // `find_region` should really do what `to_region_addr` is doing right now, except |
682 | | - // it should keep returning a `Result`. |
683 | | - self.to_region_addr(addr) |
684 | | - .ok_or(Error::InvalidGuestAddress(addr)) |
685 | | - .and_then(|(region, region_addr)| region.store(val, region_addr, order)) |
| 682 | + let expected = size_of::<O>(); |
| 683 | + |
| 684 | + let completed = self.try_access( |
| 685 | + expected, |
| 686 | + addr, |
| 687 | + |offset, len, region_addr, region| -> Result<usize> { |
| 688 | + assert_eq!(offset, 0); |
| 689 | + if len < expected { |
| 690 | + return Err(Error::PartialBuffer { |
| 691 | + expected, |
| 692 | + completed: 0, |
| 693 | + }); |
| 694 | + } |
| 695 | + region.store(val, region_addr, order).map(|()| expected) |
| 696 | + }, |
| 697 | + )?; |
| 698 | + |
| 699 | + if completed < expected { |
| 700 | + Err(Error::PartialBuffer { |
| 701 | + expected, |
| 702 | + completed, |
| 703 | + }) |
| 704 | + } else { |
| 705 | + Ok(()) |
| 706 | + } |
686 | 707 | } |
687 | 708 |
|
688 | 709 | fn load<O: AtomicAccess>(&self, addr: GuestAddress, order: Ordering) -> Result<O> { |
689 | | - self.to_region_addr(addr) |
690 | | - .ok_or(Error::InvalidGuestAddress(addr)) |
691 | | - .and_then(|(region, region_addr)| region.load(region_addr, order)) |
| 710 | + let expected = size_of::<O>(); |
| 711 | + let mut result = None::<O>; |
| 712 | + |
| 713 | + let completed = self.try_access( |
| 714 | + expected, |
| 715 | + addr, |
| 716 | + |offset, len, region_addr, region| -> Result<usize> { |
| 717 | + assert_eq!(offset, 0); |
| 718 | + if len < expected { |
| 719 | + return Err(Error::PartialBuffer { |
| 720 | + expected, |
| 721 | + completed: 0, |
| 722 | + }); |
| 723 | + } |
| 724 | + result = Some(region.load(region_addr, order)?); |
| 725 | + Ok(expected) |
| 726 | + }, |
| 727 | + )?; |
| 728 | + |
| 729 | + if completed < expected { |
| 730 | + Err(Error::PartialBuffer { |
| 731 | + expected, |
| 732 | + completed, |
| 733 | + }) |
| 734 | + } else { |
| 735 | + // Must be set because `completed == expected` |
| 736 | + Ok(result.unwrap()) |
| 737 | + } |
692 | 738 | } |
693 | 739 | } |
694 | 740 |
|
|
0 commit comments