Implement sys_copy_file_range and use it for sendfile

master
Jiajie Chen 6 years ago
parent ccc7eea114
commit e3595dd0f5

@ -736,10 +736,22 @@ impl Syscall<'_> {
in_fd: usize, in_fd: usize,
offset_ptr: *mut usize, offset_ptr: *mut usize,
count: 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 { ) -> SysResult {
info!( info!(
"sendfile:BEG out: {}, in: {}, offset_ptr: {:?}, count: {}", "copy_file_range:BEG in: {}, out: {}, in_offset: {:?}, out_offset: {:?}, count: {} flags {}",
out_fd, in_fd, offset_ptr, count in_fd, out_fd, in_offset, out_offset, count, flags
); );
let proc = self.process(); let proc = self.process();
// We know it's save, pacify the borrow checker // 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 out_file = unsafe { (*proc_cell.get()).get_file(out_fd)? };
let mut buffer = [0u8; 1024]; let mut buffer = [0u8; 1024];
let mut read_offset = if !offset_ptr.is_null() { // for in_offset and out_offset
unsafe { *self.vm().check_read_ptr(offset_ptr)? } // 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 { } else {
in_file.seek(SeekFrom::Current(0))? as usize 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 // read from specified offset and write new offset back
let mut bytes_read = 0; let mut bytes_read = 0;
let mut total_written = 0; let mut total_written = 0;
@ -772,8 +797,8 @@ impl Syscall<'_> {
let write_len = out_file.write(&buffer[bytes_written..(bytes_written + rlen)])?; let write_len = out_file.write(&buffer[bytes_written..(bytes_written + rlen)])?;
if write_len == 0 { if write_len == 0 {
info!( info!(
"sendfile:END_ERR out: {}, in: {}, 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 {}",
out_fd, in_fd, offset_ptr, 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); return Err(SysError::EBADF);
} }
@ -783,16 +808,23 @@ impl Syscall<'_> {
total_written += bytes_written; total_written += bytes_written;
} }
if !offset_ptr.is_null() { if !in_offset.is_null() {
unsafe { unsafe {
offset_ptr.write(read_offset); in_offset.write(read_offset);
} }
} else { } else {
in_file.seek(SeekFrom::Current(bytes_read as i64))?; 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!( info!(
"sendfile:END out: {}, in: {}, offset_ptr: {:?}, count: {} = bytes_read {}, total_written {}", "copy_file_range:END in: {}, out: {}, in_offset: {:?}, out_offset: {:?}, count: {} flags {}",
out_fd, in_fd, offset_ptr, count, bytes_read, total_written in_fd, out_fd, in_offset, out_offset, count, flags
); );
return Ok(total_written); return Ok(total_written);
} }

@ -59,16 +59,15 @@ impl Syscall<'_> {
uaddr: usize, uaddr: usize,
op: u32, op: u32,
val: i32, val: i32,
// timeout: *const TimeSpec, timeout: *const TimeSpec,
) -> SysResult { ) -> SysResult {
info!( info!(
//"futex: [{}] uaddr: {:#x}, op: {:#x}, val: {}, timeout_ptr: {:?}", "futex: [{}] uaddr: {:#x}, op: {:#x}, val: {}, timeout_ptr: {:?}",
"futex: [{}] uaddr: {:#x}, op: {:#x}, val: {}. timeout ALWAYS 0",
thread::current().id(), thread::current().id(),
uaddr, uaddr,
op, op,
val val,
// timeout timeout
); );
// if op & OP_PRIVATE == 0 { // if op & OP_PRIVATE == 0 {
// unimplemented!("futex only support process-private"); // unimplemented!("futex only support process-private");
@ -78,13 +77,6 @@ impl Syscall<'_> {
return Err(SysError::EINVAL); return Err(SysError::EINVAL);
} }
let atomic = unsafe { self.vm().check_write_ptr(uaddr as *mut AtomicI32)? }; 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_WAIT: u32 = 0;
const OP_WAKE: u32 = 1; const OP_WAKE: u32 = 1;
@ -95,6 +87,12 @@ impl Syscall<'_> {
match op & 0xf { match op & 0xf {
OP_WAIT => { OP_WAIT => {
let _timeout = if timeout.is_null() {
None
} else {
Some(unsafe { *self.vm().check_read_ptr(timeout)? })
};
if atomic.load(Ordering::Acquire) != val { if atomic.load(Ordering::Acquire) != val {
return Err(SysError::EAGAIN); 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 // we will skip verifying magic
if cmd == LINUX_REBOOT_CMD_HALT { if cmd == LINUX_REBOOT_CMD_HALT {
unsafe { unsafe {

@ -229,7 +229,7 @@ impl Syscall<'_> {
args[0], args[0],
args[1] as u32, args[1] as u32,
args[2] as i32, args[2] as i32,
// args[3] as *const TimeSpec, args[3] as *const TimeSpec,
), ),
// time // time
@ -276,6 +276,14 @@ impl Syscall<'_> {
args[2] as u32, args[2] as u32,
args[3] as *const u8, 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 // custom
SYS_MAP_PCI_DEVICE => self.sys_map_pci_device(args[0], args[1]), SYS_MAP_PCI_DEVICE => self.sys_map_pci_device(args[0], args[1]),

Loading…
Cancel
Save