@@ -2,3 +2,4 @@
pub(crate) mod types;
pub(crate) use types::{manifest_capnp, metadata_capnp};
pub(crate) mod inode;
+pub(crate) mod oci;
@@ -3,20 +3,32 @@
use crate::puzzle::error::Result;
use crate::puzzle::error::WireFormatError;
+use crate::puzzle::oci::Image;
use crate::puzzle::types as format;
-use crate::puzzle::types::{Inode, InodeMode, MetadataBlob};
+use crate::puzzle::types::{Digest, Inode, InodeMode};
use alloc::vec::Vec;
+use kernel::mount::Vfsmount;
use kernel::prelude::ENOENT;
+use kernel::str::CStr;
+use kernel::sync::Arc;
pub(crate) struct PuzzleFS {
+ pub(crate) oci: Image,
layers: Vec<format::MetadataBlob>,
}
impl PuzzleFS {
- pub(crate) fn new(md: MetadataBlob) -> Result<Self> {
- let mut v = Vec::new();
- v.try_push(md)?;
- Ok(PuzzleFS { layers: v })
+ pub(crate) fn open(vfsmount: Arc<Vfsmount>, rootfs_path: &CStr) -> Result<PuzzleFS> {
+ let oci = Image::open(vfsmount)?;
+ let rootfs = oci.open_rootfs_blob(rootfs_path)?;
+
+ let mut layers = Vec::new();
+ for md in rootfs.metadatas.iter() {
+ let digest = Digest::try_from(md)?;
+ layers.try_push(oci.open_metadata_blob(&digest)?)?;
+ }
+
+ Ok(PuzzleFS { oci, layers })
}
pub(crate) fn find_inode(&self, ino: u64) -> Result<Inode> {
new file mode 100644
@@ -0,0 +1,51 @@
+use crate::puzzle::error::Result;
+use crate::puzzle::types::{Digest, MetadataBlob, Rootfs};
+use kernel::c_str;
+use kernel::file;
+use kernel::file::RegularFile;
+use kernel::mount::Vfsmount;
+use kernel::pr_info;
+use kernel::str::{CStr, CString};
+use kernel::sync::Arc;
+
+pub(crate) struct Image {
+ vfs_mount: Arc<Vfsmount>,
+}
+
+impl Image {
+ pub(crate) fn open(vfsmount: Arc<Vfsmount>) -> Result<Self> {
+ Ok(Image {
+ vfs_mount: vfsmount,
+ })
+ }
+
+ pub(crate) fn blob_path_relative(&self) -> &CStr {
+ c_str!("blobs/sha256")
+ }
+
+ fn open_raw_blob(&self, digest: &Digest) -> Result<RegularFile> {
+ let filename =
+ CString::try_from_fmt(format_args!("{}/{digest}", self.blob_path_relative()))?;
+ pr_info!("trying to open {:?}\n", &filename);
+
+ let file = RegularFile::from_path_in_root_mnt(
+ &self.vfs_mount,
+ &filename,
+ file::flags::O_RDONLY.try_into().unwrap(),
+ 0,
+ )?;
+
+ Ok(file)
+ }
+
+ pub(crate) fn open_metadata_blob(&self, digest: &Digest) -> Result<MetadataBlob> {
+ let f = self.open_raw_blob(digest)?;
+ MetadataBlob::new(f)
+ }
+
+ pub(crate) fn open_rootfs_blob(&self, path: &CStr) -> Result<Rootfs> {
+ let digest = Digest::try_from(path)?;
+ let rootfs = Rootfs::open(self.open_raw_blob(&digest)?)?;
+ Ok(rootfs)
+ }
+}
@@ -14,7 +14,7 @@
mod puzzle;
// Required by the autogenerated '_capnp.rs' files
use puzzle::inode::PuzzleFS;
-use puzzle::types::{Inode, InodeMode, MetadataBlob};
+use puzzle::types::{Inode, InodeMode};
use puzzle::{manifest_capnp, metadata_capnp};
use kernel::fs::{DEntry, INodeParams, NeedsRoot, NewSuperBlock, RootDEntry};
@@ -69,7 +69,7 @@ fn puzzlefs_populate_dir(
return Err(E2BIG);
}
- let inode = Arc::try_new(pfs.find_inode(ino).map_err(|_| EINVAL)?)?;
+ let inode = Arc::try_new(pfs.find_inode(ino)?)?;
match &inode.mode {
InodeMode::File { chunks: _ } => {
let params = INodeParams {
@@ -154,18 +154,17 @@ fn fill_super(_data: (), sb: fs::NewSuperBlock<'_, Self>) -> Result<&fs::SuperBl
},
)?;
- let file = file::RegularFile::from_path_in_root_mnt(
- &arc_vfs_mount,
- c_str!("997eed138af30d187e87d682dd2ae9f240fae78f668907a0519460b397c82467"),
- file::flags::O_RDONLY.try_into().unwrap(),
- 0,
- )?;
+ let puzzlefs = PuzzleFS::open(
+ arc_vfs_mount,
+ c_str!("2d6602d678140540dc7e96de652a76a8b16e8aca190bae141297bcffdcae901b"),
+ );
- // TODO: figure out how to go from WireFormatError to kernel::error::Error
- let metadata = MetadataBlob::new(file).map_err(|_| EINVAL)?;
+ if let Err(ref e) = puzzlefs {
+ pr_info!("error opening puzzlefs {e}\n");
+ }
- let mut puzzlefs = PuzzleFS::new(metadata).map_err(|_| EINVAL)?;
- let root_inode = Arc::try_new(puzzlefs.find_inode(1).map_err(|_| EINVAL)?)?;
+ let mut puzzlefs = puzzlefs?;
+ let root_inode = Arc::try_new(puzzlefs.find_inode(1)?)?;
let root = try_new_populated_root_puzzlefs_dentry(&sb, &mut puzzlefs, root_inode)?;
let sb = sb.init_root(root)?;
The puzzlefs image manifest is the file referenced by index.json and it contains the array of metadata layers that describe the puzzlefs image. This file represents the root of the puzzlefs filesystem since we can't parse json files. When this filesystem is mounted, usermode will need to read the tag from index.json, find the corresponding puzzlefs image manifest and pass it to the kernel module. Due to the lack of BTreeMap in the kernel, only image manifests without fs verity information are supported for now. Signed-off-by: Ariel Miculas <amiculas@cisco.com> --- samples/rust/puzzle.rs | 1 + samples/rust/puzzle/inode.rs | 22 ++++++++++++---- samples/rust/puzzle/oci.rs | 51 ++++++++++++++++++++++++++++++++++++ samples/rust/puzzlefs.rs | 23 ++++++++-------- 4 files changed, 80 insertions(+), 17 deletions(-) create mode 100644 samples/rust/puzzle/oci.rs