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,
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);
}

@ -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 {

@ -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]),

Loading…
Cancel
Save