Implement sys_sendfile

master
Jiajie Chen 6 years ago
parent 638a2215b2
commit 4e0c18914f

@ -105,7 +105,7 @@ bitflags! {
impl Driver for VirtIOBlkDriver {
fn try_handle_interrupt(&self, _irq: Option<u32>) -> bool {
let mut driver = self.0.lock();
let driver = self.0.lock();
// ensure header page is mapped
active_table().map_if_not_exists(driver.header as usize, driver.header as usize);
@ -214,7 +214,7 @@ pub fn virtio_blk_init(node: &Node) {
// configure two virtqueues: ingress and egress
header.guest_page_size.write(PAGE_SIZE as u32); // one page
let mut driver = VirtIOBlkDriver(Mutex::new(VirtIOBlk {
let driver = VirtIOBlkDriver(Mutex::new(VirtIOBlk {
interrupt: node.prop_u32("interrupts").unwrap(),
interrupt_parent: node.prop_u32("interrupt-parent").unwrap(),
header: from as usize,

@ -206,7 +206,7 @@ impl<'a> phy::Device<'a> for E1000Driver {
let send_desc = &mut send_queue[index];
let recv_queue_size = PAGE_SIZE / size_of::<E1000RecvDesc>();
let mut recv_queue = unsafe {
let recv_queue = unsafe {
slice::from_raw_parts_mut(driver.recv_page as *mut E1000RecvDesc, recv_queue_size)
};
let mut rdt = e1000[E1000_RDT].read();
@ -296,7 +296,7 @@ impl phy::TxToken for E1000TxToken {
slice::from_raw_parts_mut(driver.header as *mut Volatile<u32>, driver.size / 4)
};
let send_queue_size = PAGE_SIZE / size_of::<E1000SendDesc>();
let mut send_queue = unsafe {
let send_queue = unsafe {
slice::from_raw_parts_mut(driver.send_page as *mut E1000SendDesc, send_queue_size)
};
let mut tdt = e1000[E1000_TDT].read();

@ -2,6 +2,7 @@
use core::mem::size_of;
use core::cmp::min;
use core::cell::UnsafeCell;
use rcore_fs::vfs::Timespec;
use crate::fs::*;
@ -587,6 +588,70 @@ pub fn sys_sync() -> SysResult {
Ok(0)
}
pub fn sys_sendfile(out_fd: usize, in_fd: usize, offset: *mut usize, count: usize) -> SysResult {
info!("sendfile: out: {}, in: {}, offset: {:?}, count: {}", out_fd, in_fd, offset, count);
let proc = process();
// We know it's save, pacify the borrow checker
let proc_cell = UnsafeCell::new(proc);
let proc_in = unsafe {&mut *proc_cell.get()};
let proc_out = unsafe {&mut *proc_cell.get()};
//let in_file: &mut FileHandle = unsafe { &mut *UnsafeCell::new(proc.get_file(in_fd)?).get() };
//let out_file: &mut FileHandle = unsafe { &mut *UnsafeCell::new(proc.get_file(out_fd)?).get() };
let in_file = proc_in.get_file(in_fd)?;
let out_file = proc_out.get_file(out_fd)?;
let mut buffer = [0u8; 1024];
if offset.is_null() {
// read from current file offset
let mut bytes_read = 0;
while bytes_read < count {
let len = min(buffer.len(), count - bytes_read);
let read_len = in_file.read(&mut buffer)?;
if read_len == 0 {
break;
}
bytes_read += read_len;
let mut bytes_written = 0;
while bytes_written < read_len {
let write_len = out_file.write(&buffer[bytes_written..])?;
if write_len == 0 {
return Err(SysError::EBADF);
}
bytes_written += write_len;
}
}
return Ok(bytes_read);
} else {
let mut proc_mem = unsafe {&mut *proc_cell.get()};
proc_mem.vm.check_mut_ptr(offset)?;
let mut read_offset = unsafe {
*offset
};
// read from specified offset and write back
let mut bytes_read = 0;
while bytes_read < count {
let len = min(buffer.len(), count - bytes_read);
let read_len = in_file.read_at(read_offset, &mut buffer)?;
if read_len == 0 {
break;
}
bytes_read += read_len;
read_offset += read_len;
let mut bytes_written = 0;
while bytes_written < read_len {
let write_len = out_file.write(&buffer[bytes_written..])?;
if write_len == 0 {
return Err(SysError::EBADF);
}
bytes_written += write_len;
}
}
unsafe {
*offset = read_offset;
}
return Ok(bytes_read);
}
}
impl Process {
pub fn get_file(&mut self, fd: usize) -> Result<&mut FileHandle, SysError> {
self.files.get_mut(&fd).ok_or(SysError::EBADF).and_then(|f| {

@ -117,9 +117,7 @@ const LINUX_REBOOT_CMD_HALT: u32 = 0xcdef0123;
pub fn sys_reboot(magic: u32, magic2: u32, cmd: u32, arg: *const u8) -> SysResult {
// we will skip verifying magic
if cmd == LINUX_REBOOT_CMD_HALT {
unsafe {
cpu::exit_in_qemu(1);
}
cpu::exit_in_qemu(1);
}
Ok(0)
}

@ -66,6 +66,7 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
SYS_SCHED_YIELD => sys_yield(),
SYS_NANOSLEEP => sys_nanosleep(args[0] as *const TimeSpec),
SYS_GETPID => sys_getpid(),
SYS_SENDFILE => sys_sendfile(args[0], args[1], args[3] as *mut usize, args[4]),
SYS_SOCKET => sys_socket(args[0], args[1], args[2]),
SYS_CONNECT => sys_connect(args[0], args[1] as *const SockAddr, args[2]),
SYS_ACCEPT => sys_accept(args[0], args[1] as *mut SockAddr, args[2] as *mut u32),

Loading…
Cancel
Save