From e3595dd0f55fed2184858235e21541bec6579390 Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Wed, 8 May 2019 19:23:07 +0800 Subject: [PATCH] Implement sys_copy_file_range and use it for sendfile --- kernel/src/syscall/fs.rs | 52 ++++++++++++++++++++++++++++++-------- kernel/src/syscall/misc.rs | 30 ++++++++++++---------- kernel/src/syscall/mod.rs | 10 +++++++- 3 files changed, 68 insertions(+), 24 deletions(-) diff --git a/kernel/src/syscall/fs.rs b/kernel/src/syscall/fs.rs index 0031baa..401a950 100644 --- a/kernel/src/syscall/fs.rs +++ b/kernel/src/syscall/fs.rs @@ -736,10 +736,22 @@ impl Syscall<'_> { in_fd: usize, offset_ptr: *mut usize, count: usize, + ) -> SysResult { + self.sys_copy_file_range(in_fd, offset_ptr, out_fd, 0 as *mut usize, count, 0) + } + + pub fn sys_copy_file_range( + &mut self, + in_fd: usize, + in_offset: *mut usize, + out_fd: usize, + out_offset: *mut usize, + count: usize, + flags: usize, ) -> SysResult { info!( - "sendfile:BEG out: {}, in: {}, offset_ptr: {:?}, count: {}", - out_fd, in_fd, offset_ptr, count + "copy_file_range:BEG in: {}, out: {}, in_offset: {:?}, out_offset: {:?}, count: {} flags {}", + in_fd, out_fd, in_offset, out_offset, count, flags ); let proc = self.process(); // We know it's save, pacify the borrow checker @@ -748,12 +760,25 @@ impl Syscall<'_> { let out_file = unsafe { (*proc_cell.get()).get_file(out_fd)? }; let mut buffer = [0u8; 1024]; - let mut read_offset = if !offset_ptr.is_null() { - unsafe { *self.vm().check_read_ptr(offset_ptr)? } + // for in_offset and out_offset + // null means update file offset + // non-null means update {in,out}_offset instead + + let mut read_offset = if !in_offset.is_null() { + unsafe { *self.vm().check_read_ptr(in_offset)? } } else { in_file.seek(SeekFrom::Current(0))? as usize }; + let orig_out_file_offset = out_file.seek(SeekFrom::Current(0))?; + let write_offset = if !out_offset.is_null() { + out_file.seek(SeekFrom::Start( + unsafe { *self.vm().check_read_ptr(out_offset)? } as u64, + ))? as usize + } else { + 0 + }; + // read from specified offset and write new offset back let mut bytes_read = 0; let mut total_written = 0; @@ -772,8 +797,8 @@ impl Syscall<'_> { let write_len = out_file.write(&buffer[bytes_written..(bytes_written + rlen)])?; if write_len == 0 { info!( - "sendfile:END_ERR out: {}, in: {}, offset_ptr: {:?}, count: {} = bytes_read {}, bytes_written {}, write_len {}", - out_fd, in_fd, offset_ptr, count, bytes_read, bytes_written, write_len + "copy_file_range:END_ERR in: {}, out: {}, in_offset: {:?}, out_offset: {:?}, count: {} = bytes_read {}, bytes_written {}, write_len {}", + in_fd, out_fd, in_offset, out_offset, count, bytes_read, bytes_written, write_len ); return Err(SysError::EBADF); } @@ -783,16 +808,23 @@ impl Syscall<'_> { total_written += bytes_written; } - if !offset_ptr.is_null() { + if !in_offset.is_null() { unsafe { - offset_ptr.write(read_offset); + in_offset.write(read_offset); } } else { in_file.seek(SeekFrom::Current(bytes_read as i64))?; } + + if !out_offset.is_null() { + unsafe { + out_offset.write(write_offset + total_written); + } + out_file.seek(SeekFrom::Start(orig_out_file_offset))?; + } info!( - "sendfile:END out: {}, in: {}, offset_ptr: {:?}, count: {} = bytes_read {}, total_written {}", - out_fd, in_fd, offset_ptr, count, bytes_read, total_written + "copy_file_range:END in: {}, out: {}, in_offset: {:?}, out_offset: {:?}, count: {} flags {}", + in_fd, out_fd, in_offset, out_offset, count, flags ); return Ok(total_written); } diff --git a/kernel/src/syscall/misc.rs b/kernel/src/syscall/misc.rs index f792ced..119cf8b 100644 --- a/kernel/src/syscall/misc.rs +++ b/kernel/src/syscall/misc.rs @@ -59,16 +59,15 @@ impl Syscall<'_> { uaddr: usize, op: u32, val: i32, -// timeout: *const TimeSpec, + timeout: *const TimeSpec, ) -> SysResult { info!( - //"futex: [{}] uaddr: {:#x}, op: {:#x}, val: {}, timeout_ptr: {:?}", - "futex: [{}] uaddr: {:#x}, op: {:#x}, val: {}. timeout ALWAYS 0", + "futex: [{}] uaddr: {:#x}, op: {:#x}, val: {}, timeout_ptr: {:?}", thread::current().id(), uaddr, op, - val -// timeout + val, + timeout ); // if op & OP_PRIVATE == 0 { // unimplemented!("futex only support process-private"); @@ -78,13 +77,6 @@ impl Syscall<'_> { return Err(SysError::EINVAL); } let atomic = unsafe { self.vm().check_write_ptr(uaddr as *mut AtomicI32)? }; - // musl libc 1.1.22 _wake FUN didn't provide timeout, ___futexwait FUN set timeout=0 - // now rcore just ignored the timeout parameter. TODO -// let _timeout = if timeout.is_null() { -// None -// } else { -// Some(unsafe { *self.vm().check_read_ptr(timeout)? }) -// }; const OP_WAIT: u32 = 0; const OP_WAKE: u32 = 1; @@ -95,6 +87,12 @@ impl Syscall<'_> { match op & 0xf { OP_WAIT => { + let _timeout = if timeout.is_null() { + None + } else { + Some(unsafe { *self.vm().check_read_ptr(timeout)? }) + }; + if atomic.load(Ordering::Acquire) != val { return Err(SysError::EAGAIN); } @@ -113,7 +111,13 @@ impl Syscall<'_> { } } - pub fn sys_reboot(&mut self, _magic: u32, _magic2: u32, cmd: u32, _arg: *const u8) -> SysResult { + pub fn sys_reboot( + &mut self, + _magic: u32, + _magic2: u32, + cmd: u32, + _arg: *const u8, + ) -> SysResult { // we will skip verifying magic if cmd == LINUX_REBOOT_CMD_HALT { unsafe { diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 9af2b88..101dfc4 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -229,7 +229,7 @@ impl Syscall<'_> { args[0], args[1] as u32, args[2] as i32, - // args[3] as *const TimeSpec, + args[3] as *const TimeSpec, ), // time @@ -276,6 +276,14 @@ impl Syscall<'_> { args[2] as u32, args[3] as *const u8, ), + SYS_COPY_FILE_RANGE => self.sys_copy_file_range( + args[0], + args[1] as *mut usize, + args[2], + args[3] as *mut usize, + args[4], + args[5], + ), // custom SYS_MAP_PCI_DEVICE => self.sys_map_pci_device(args[0], args[1]),