summary refs log tree commit diff
path: root/devices
diff options
context:
space:
mode:
authorChirantan Ekbote <chirantan@chromium.org>2020-03-17 18:20:10 +0900
committerCommit Bot <commit-bot@chromium.org>2020-03-19 08:13:31 +0000
commit6dfa1e4ce5c260eabbda21c12d7bd9769f1cc995 (patch)
tree580c39835d82fa4d7ed6da367ede4f47ee0e50d2 /devices
parent93a987705782a882c9f1d05b8b472276c20ae50f (diff)
downloadcrosvm-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.rs54
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())
+        }
+    }
 }