mirror of
https://github.com/rcore-os/rCore.git
synced 2024-11-23 00:16:17 +04:00
Implement sys_sendfile
This commit is contained in:
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…
Reference in New Issue
Block a user