|
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