Optimize the CpioEntry to send data to the Write trait

This commit is contained in:
LI Qing
2023-07-21 16:04:12 +08:00
committed by Tate, Hongliang Tian
parent 4b3cf8daeb
commit 13c4c614b5
11 changed files with 275 additions and 117 deletions

View File

@ -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")
}
}
}
}

View File

@ -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_);
}
}
}

View File

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

View File

@ -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(())
}
}

View File

@ -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()