Skip to content

Conversation

@alexandruag
Copy link
Collaborator

This PR is based on code from Sebastien's original proposal (#20) and the subsequent comments and conversations.

As per Paolo's suggestion, the offset is now represented as an u64. I didn't name the new struct FileRange, because it should've also kept a length field, and that information is already available via the len() method of the GuestMemoryRegion. Instead I've called it FileOffset (will rename on demand), and it only keeps the Arc<File> and offset.

The Linux code is clearly ahead of the Windows one right now, and some harmonization is in order. I've just created a Windows VM on my machine, but didn't get the chance to install Rust and test things yet. It would be good to know if ppl are ok with the proposed way of implementing this functionality on Linux, and then we can bring the Windows implementation up to date as well (and add some more tests to this PR).

pub fn new(mapping: MmapRegion, guest_base: GuestAddress) -> result::Result<Self, Error> {
if guest_base.0.checked_add(mapping.len() as u64).is_none() {
return Err(Error::InvalidGuestRegion);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also check that the offset and len are page aligned? Or just let the mmap syscall to check them?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it's better to check it ourselves since we cannot assume that both Linux and Windows mmap syscall will check for that, right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should do the checks at this point; this method expects to be passed a valid MmapRegion. For Linux mmap already checks that offset is aligned (like Sebastien pointed out a while ago), and the length of the mapping doesn't need to be page aligned. I don't know what Windows does, but if the equivalent of mmap doesn't check alignment when necessary, our code should do it when creating the Windows MmapRegion.

let file = tempfile::tempfile().unwrap();
let start = 1234;
let file_offset = FileOffset::new(file, start);
assert_eq!(file_offset.start(), start);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about adding a test case for non-page-aligned offset?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to keep FileOffset as lightweight as possible. If a FileOffset object is invalid for some reason, this will be caught when actually trying to map the memory. I'll add an offset alignment test for MmapRegion if there isn't one already.

@alexandruag alexandruag requested a review from bonzini as a code owner June 11, 2019 09:51
@rbradford
Copy link
Contributor

@sboeuf What's your thoughts on this?

@sboeuf
Copy link

sboeuf commented Jun 13, 2019

@rbradford

@sboeuf What's your thoughts on this?

I'm planning to review this today :)

sboeuf
sboeuf previously approved these changes Jun 13, 2019
Copy link

@sboeuf sboeuf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alexandruag From a design perspective, the PR looks perfect to me! You can definitely move forward and complete it, unless @jiangliu or @bonzini have some objections.
Thanks!

Copy link
Collaborator Author

@alexandruag alexandruag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi everyone,

Just finished answering comments and rebasing the PR with the following changes:

  • Added the arc(&self) method to FileOffset so now file(&self) returns an actual &File.
  • Renamed fd_overlaps to fds_overlap.
  • Added tests for mmap::build and mmap::fds_overlap.
  • Added the test changes from Sebastien's original to the last commit.

There's still the question of what to do on the Windows side. Unfortunately, I didn't have the time to pursue that as well. Will try to reach out to @tkreuzer and see how we can proceed.

let file = tempfile::tempfile().unwrap();
let start = 1234;
let file_offset = FileOffset::new(file, start);
assert_eq!(file_offset.start(), start);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to keep FileOffset as lightweight as possible. If a FileOffset object is invalid for some reason, this will be caught when actually trying to map the memory. I'll add an offset alignment test for MmapRegion if there isn't one already.

pub fn new(mapping: MmapRegion, guest_base: GuestAddress) -> result::Result<Self, Error> {
if guest_base.0.checked_add(mapping.len() as u64).is_none() {
return Err(Error::InvalidGuestRegion);
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should do the checks at this point; this method expects to be passed a valid MmapRegion. For Linux mmap already checks that offset is aligned (like Sebastien pointed out a while ago), and the length of the mapping doesn't need to be page aligned. I don't know what Windows does, but if the equivalent of mmap doesn't check alignment when necessary, our code should do it when creating the Windows MmapRegion.

sboeuf
sboeuf previously approved these changes Jun 17, 2019
Copy link

@sboeuf sboeuf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, the only thing missing is to adapt the Windows code too. It looks like it should be pretty easy since it's mostly about renaming functions, or am I missing something?

}

/// Creates a new mapping based on the provided arguments.
pub fn build(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that half of this function should be generic to unix and windows, therefore should be defined in mmap.rs. The file offset processing is the part that should be common.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sense, I refactored this by adding the check_file_offset function to mmap.rs in the same commit.

fd.as_raw_fd(),
offset,
)
pub fn from_file(file_offset: FileOffset, size: usize) -> Result<Self> {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to modify the same way the function from_fd in mmap_windows.rs. This should be pretty straightforward.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pulled in the commit where you did this, thanks!

Added a struct which keeps track of the file and offset associated with
a guest memory region backed by a memory mapped file.

Signed-off-by: Alexandru Agache <aagch@amazon.com>
Copy link
Collaborator Author

@alexandruag alexandruag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did a bit of refactoring (as mentioned in one of the responses), and cherry-picked a commit from Sebastien which makes the Windows tests succeed. We still need more Windows testing, but the CI should be happy at least.

fd.as_raw_fd(),
offset,
)
pub fn from_file(file_offset: FileOffset, size: usize) -> Result<Self> {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pulled in the commit where you did this, thanks!

}

/// Creates a new mapping based on the provided arguments.
pub fn build(
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sense, I refactored this by adding the check_file_offset function to mmap.rs in the same commit.

alexandruag and others added 5 commits June 25, 2019 00:12
Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
Signed-off-by: Alexandru Agache <aagch@amazon.com>
Also, refactored some names and the way we resolve paths to use
different `Error` and `Result` definitions.

Signed-off-by: Alexandru Agache <aagch@amazon.com>
The GuestRegionMmap constructor now checks that adding the guest base
address to the length of the mapped region does not overflow.

Signed-off-by: Alexandru Agache <aagch@amazon.com>
The new method simplifies the creation of a GuestMemoryMmap object
that contains file backed regions (potentially alongside anonymous
memory regions). Also, updated the GuestMemoryRegion trait with
the `file_offset` method, and implemented it for GuestRegionMmap.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
Signed-off-by: Alexandru Agache <aagch@amazon.com>
Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
@alexandruag alexandruag force-pushed the file_backed_regions branch from c5e6d2a to e6e235e Compare June 24, 2019 21:12
@alexandruag
Copy link
Collaborator Author

@bonzini @jiangliu can you please take a look?

if metadata.len() < end {
return Err(MmapRegionError::MappingPastEof);
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to handle the case when file.metadata() fails?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could create a special Error case for it.
Once @alexandruag updates it, we need to re-approve the PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could merge the big PR first and submit another bugfix PR for this issue.
Review a small bugfix PR is much easier:)

@sboeuf
Copy link

sboeuf commented Jun 25, 2019

The green button is very tempting :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants