mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-24 01:43:22 +00:00
Optimize the CpioEntry to send data to the Write trait
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
4b3cf8daeb
commit
13c4c614b5
@ -232,6 +232,9 @@ impl From<cpio_decoder::error::Error> for Error {
|
||||
cpio_decoder::error::Error::BufferShortError => {
|
||||
Error::with_message(Errno::EINVAL, "CPIO buffer is too short")
|
||||
}
|
||||
cpio_decoder::error::Error::IoError => {
|
||||
Error::with_message(Errno::EIO, "CPIO buffer I/O error")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ use super::utils::{InodeMode, InodeType};
|
||||
use crate::prelude::*;
|
||||
|
||||
use cpio_decoder::{CpioDecoder, FileType};
|
||||
use lending_iterator::LendingIterator;
|
||||
use libflate::gzip::Decoder as GZipDecoder;
|
||||
|
||||
/// Unpack and prepare the fs from the ramdisk CPIO buffer.
|
||||
@ -13,8 +14,13 @@ pub fn init(gzip_ramdisk_buf: &[u8]) -> Result<()> {
|
||||
GZipDecoder::new(gzip_ramdisk_buf)
|
||||
.map_err(|_| Error::with_message(Errno::EINVAL, "invalid gzip buffer"))?,
|
||||
);
|
||||
for entry_result in decoder.decode_entries() {
|
||||
let entry = entry_result?;
|
||||
|
||||
loop {
|
||||
let Some(entry_result) = decoder.next() else {
|
||||
break;
|
||||
};
|
||||
|
||||
let mut entry = entry_result?;
|
||||
|
||||
// Make sure the name is a relative path, and is not end with "/".
|
||||
let entry_name = entry.name().trim_start_matches('/').trim_end_matches('/');
|
||||
@ -40,18 +46,22 @@ pub fn init(gzip_ramdisk_buf: &[u8]) -> Result<()> {
|
||||
match metadata.file_type() {
|
||||
FileType::File => {
|
||||
let dentry = parent.create(name, InodeType::File, mode)?;
|
||||
dentry.vnode().write_at(0, entry.data())?;
|
||||
entry.read_all(dentry.vnode().writer(0))?;
|
||||
}
|
||||
FileType::Dir => {
|
||||
let _ = parent.create(name, InodeType::Dir, mode)?;
|
||||
}
|
||||
FileType::Link => {
|
||||
let dentry = parent.create(name, InodeType::SymLink, mode)?;
|
||||
let link_content = core::str::from_utf8(entry.data())?;
|
||||
dentry.vnode().write_link(link_content)?;
|
||||
let link_content = {
|
||||
let mut link_data: Vec<u8> = Vec::new();
|
||||
entry.read_all(&mut link_data)?;
|
||||
core::str::from_utf8(&link_data)?.to_string()
|
||||
};
|
||||
dentry.vnode().write_link(&link_content)?;
|
||||
}
|
||||
type_ => {
|
||||
warn!("unsupported file type = {:?} in initramfs", type_);
|
||||
panic!("unsupported file type = {:?} in initramfs", type_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ pub use ioctl::IoctlCmd;
|
||||
pub use page_cache::PageCache;
|
||||
pub use poll::{Pollee, Poller};
|
||||
pub use status_flags::StatusFlags;
|
||||
pub use vnode::Vnode;
|
||||
pub use vnode::{Vnode, VnodeWriter};
|
||||
|
||||
mod access_mode;
|
||||
mod channel;
|
||||
|
@ -8,6 +8,7 @@ use crate::vm::vmo::Vmo;
|
||||
|
||||
use alloc::string::String;
|
||||
use core::time::Duration;
|
||||
use core2::io::{Error as IoError, ErrorKind as IoErrorKind, Result as IoResult, Write};
|
||||
use jinux_frame::vm::VmIo;
|
||||
use jinux_rights::Full;
|
||||
|
||||
@ -245,4 +246,33 @@ impl Vnode {
|
||||
pub fn is_dentry_cacheable(&self) -> bool {
|
||||
self.inner.read().inode.is_dentry_cacheable()
|
||||
}
|
||||
|
||||
pub fn writer(&self, from_offset: usize) -> VnodeWriter {
|
||||
VnodeWriter {
|
||||
inner: &self,
|
||||
offset: from_offset,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VnodeWriter<'a> {
|
||||
inner: &'a Vnode,
|
||||
offset: usize,
|
||||
}
|
||||
|
||||
impl<'a> Write for VnodeWriter<'a> {
|
||||
#[inline]
|
||||
fn write(&mut self, buf: &[u8]) -> IoResult<usize> {
|
||||
let write_len = self
|
||||
.inner
|
||||
.write_at(self.offset, buf)
|
||||
.map_err(|_| IoError::new(IoErrorKind::WriteZero, "failed to write buffer"))?;
|
||||
self.offset += write_len;
|
||||
Ok(write_len)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn flush(&mut self) -> IoResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -216,7 +216,7 @@ impl VmoInner {
|
||||
if self.should_share_frame_with_parent(write_page) {
|
||||
return Ok(inherited_frame);
|
||||
}
|
||||
|
||||
|
||||
let frame = {
|
||||
let options = VmAllocOptions::new(1);
|
||||
VmFrameVec::allocate(&options)?.pop().unwrap()
|
||||
|
Reference in New Issue
Block a user