diff options
author | Chirantan Ekbote <chirantan@chromium.org> | 2020-03-17 18:20:10 +0900 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-03-19 08:13:31 +0000 |
commit | 6dfa1e4ce5c260eabbda21c12d7bd9769f1cc995 (patch) | |
tree | 580c39835d82fa4d7ed6da367ede4f47ee0e50d2 /devices | |
parent | 93a987705782a882c9f1d05b8b472276c20ae50f (diff) | |
download | crosvm-6dfa1e4ce5c260eabbda21c12d7bd9769f1cc995.tar crosvm-6dfa1e4ce5c260eabbda21c12d7bd9769f1cc995.tar.gz crosvm-6dfa1e4ce5c260eabbda21c12d7bd9769f1cc995.tar.bz2 crosvm-6dfa1e4ce5c260eabbda21c12d7bd9769f1cc995.tar.lz crosvm-6dfa1e4ce5c260eabbda21c12d7bd9769f1cc995.tar.xz crosvm-6dfa1e4ce5c260eabbda21c12d7bd9769f1cc995.tar.zst crosvm-6dfa1e4ce5c260eabbda21c12d7bd9769f1cc995.zip |
devices: fs: Implement copy_file_range
BUG=none TEST=vm.Virtiofs Change-Id: I2ed7137a901e6e506e6b1562b77fdb042bdc58ab Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2105822 Tested-by: Chirantan Ekbote <chirantan@chromium.org> Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Daniel Verkamp <dverkamp@chromium.org> Commit-Queue: Chirantan Ekbote <chirantan@chromium.org>
Diffstat (limited to 'devices')
-rw-r--r-- | devices/src/virtio/fs/passthrough.rs | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/devices/src/virtio/fs/passthrough.rs b/devices/src/virtio/fs/passthrough.rs index aab1403..419d466 100644 --- a/devices/src/virtio/fs/passthrough.rs +++ b/devices/src/virtio/fs/passthrough.rs @@ -1696,4 +1696,58 @@ impl FileSystem for PassthroughFs { Err(io::Error::from_raw_os_error(libc::ENOTTY)) } } + + fn copy_file_range( + &self, + ctx: Context, + inode_src: Inode, + handle_src: Handle, + offset_src: u64, + inode_dst: Inode, + handle_dst: Handle, + offset_dst: u64, + length: u64, + flags: u64, + ) -> io::Result<usize> { + // We need to change credentials during a write so that the kernel will remove setuid or + // setgid bits from the file if it was written to by someone other than the owner. + let (_uid, _gid) = set_creds(ctx.uid, ctx.gid)?; + let src_data = self + .handles + .read() + .unwrap() + .get(&handle_src) + .filter(|hd| hd.inode == inode_src) + .map(Arc::clone) + .ok_or_else(ebadf)?; + let dst_data = self + .handles + .read() + .unwrap() + .get(&handle_dst) + .filter(|hd| hd.inode == inode_dst) + .map(Arc::clone) + .ok_or_else(ebadf)?; + + let src = src_data.file.lock().as_raw_fd(); + let dst = dst_data.file.lock().as_raw_fd(); + + let res = unsafe { + libc::syscall( + libc::SYS_copy_file_range, + src, + &offset_src, + dst, + offset_dst, + length, + flags, + ) + }; + + if res >= 0 { + Ok(res as usize) + } else { + Err(io::Error::last_os_error()) + } + } } |