Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nydusify & nydus-image: v6 image conversion support #473

Merged
merged 21 commits into from
Jun 10, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
d6e0a95
nydus-image: bug fix for `dirents_offset` overflow for non-dir/non-sy…
yawqi Jun 2, 2022
282cd91
nydus-image: feature, begin adding support for v6 image multi layer b…
yawqi Jun 2, 2022
c0f6d41
nydus-image: feature, implement interfaces for v6 OndiskInodeWrapper
yawqi Jun 2, 2022
9228759
nydus-image: feature, v6 multi layer build suppot
yawqi Jun 2, 2022
1244ac6
nydus-image: bug fix, correct implementation of chunk info for v6
zyfjeff Jun 6, 2022
4a0a6d2
nydus-image: bug fix, fix . and .. 's incorrent dirent order
zyfjeff Jun 6, 2022
449303a
nydus-image: bug fix, fix invalid xatttr size
zyfjeff Jun 7, 2022
448cf2b
nydusify: support nydus v6 image build
zyfjeff Jun 6, 2022
e87929f
nydus-image: enable image validate for v6
zyfjeff Jun 7, 2022
8779711
nydus-image: enable rafsv6 smoke test
zyfjeff Jun 7, 2022
90fc1ab
test: disable digest validate for v6
zyfjeff Jun 7, 2022
e57f42d
nydusify: support v6 image build test
zyfjeff Jun 7, 2022
dc1fdcc
nydusify: disable digest validate and use direct mode for v6
zyfjeff Jun 7, 2022
c58ef29
nydusify: rename `image_version` to `fs-version` to be consistent wit…
yawqi Jun 8, 2022
e0c085b
test: fix wrong spelling
zyfjeff Jun 8, 2022
9d991f8
test: safe to stop registry container
zyfjeff Jun 8, 2022
712bd1d
nydus-image: partial implementation inspect subcommand for v6
zyfjeff Jun 8, 2022
2fca2db
Fix code review comments
zyfjeff Jun 8, 2022
8da4bd3
nydusify: change fs-image args usage describe
zyfjeff Jun 8, 2022
e033493
Use native rust way replace if-self
zyfjeff Jun 9, 2022
5bb773d
Handle borrow_mut panic
zyfjeff Jun 9, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions rafs/src/metadata/layout/v6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ pub const EROFS_I_VERSION_BITS: u16 = 1;
pub const EROFS_I_DATALAYOUT_BITS: u16 = 3;

// Offset of EROFS super block.
const EROFS_SUPER_OFFSET: u16 = 1024;
pub const EROFS_SUPER_OFFSET: u16 = 1024;
// Size of EROFS super block.
const EROFS_SUPER_BLOCK_SIZE: u16 = 128;
pub const EROFS_SUPER_BLOCK_SIZE: u16 = 128;
// Size of extended super block, used for rafs v6 specific fields
const EROFS_EXT_SUPER_BLOCK_SIZE: u16 = 256;
// Magic number for EROFS super block.
Expand Down
103 changes: 90 additions & 13 deletions src/bin/nydus-image/inspect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ use rafs::metadata::layout::v5::{
RafsV5BlobTable, RafsV5ChunkInfo, RafsV5ExtBlobTable, RafsV5Inode, RafsV5InodeTable,
RafsV5PrefetchTable, RafsV5SuperBlock, RafsV5XAttrsTable,
};
use rafs::metadata::layout::v6::{
RafsV6BlobTable, RafsV6SuperBlockExt, EROFS_SUPER_BLOCK_SIZE, EROFS_SUPER_OFFSET,
};
use rafs::metadata::RafsSuperFlags;
use rafs::{RafsIoRead, RafsIoReader};
use storage::RAFS_DEFAULT_CHUNK_SIZE;
Expand All @@ -42,6 +45,14 @@ impl RafsLayout {
chunk_info_size: 80,
}
}
fn rafsv6_layout() -> Self {
RafsLayout {
super_block_offset: (EROFS_SUPER_OFFSET + EROFS_SUPER_BLOCK_SIZE) as u32,
super_block_size: 256,
inode_size: 128,
chunk_info_size: 80,
}
}
}

struct RafsMeta {
Expand Down Expand Up @@ -80,6 +91,26 @@ impl From<&RafsV5SuperBlock> for RafsMeta {
}
}

impl From<&RafsV6SuperBlockExt> for RafsMeta {
fn from(sb: &RafsV6SuperBlockExt) -> Self {
Self {
inodes_count: 0,
inode_table_offset: 0,
inode_table_entries: 0,
prefetch_table_offset: sb.prefetch_table_offset(),
blob_table_offset: sb.blob_table_offset(),
blob_table_size: sb.blob_table_size(),
prefetch_table_entries: sb.prefetch_table_size() / std::mem::size_of::<u32>() as u32,
extended_blob_table_offset: 0,
extended_blob_table_entries: 0,
chunk_size: sb.chunk_size(),
flags: RafsSuperFlags::default(),
fs_version: 0,
version: RafsVersion::V6,
}
}
}

pub enum Action {
Break,
Continue,
Expand All @@ -91,8 +122,13 @@ struct RafsV5State {
extended_blobs_table: Option<RafsV5ExtBlobTable>,
}

struct RafsV6State {
blobs_table: RafsV6BlobTable,
}

enum RafsState {
V5(RafsV5State),
V6(RafsV6State),
}

impl RafsState {
Expand All @@ -102,6 +138,10 @@ impl RafsState {
let blob = b.blobs_table.get(blob_index)?;
Ok(blob.blob_id().to_owned())
}
RafsState::V6(b) => {
let blob = b.blobs_table.get(blob_index)?;
Ok(blob.blob_id().to_owned())
}
}
}
}
Expand All @@ -124,7 +164,7 @@ impl RafsInspector {
let (rafs_meta, layout_profile) = Self::load_meta(&mut f)?;
let state = match rafs_meta.version {
RafsVersion::V5 => Self::load_state_v5(&mut f, &rafs_meta)?,
RafsVersion::V6 => todo!(),
RafsVersion::V6 => Self::load_state_v6(&mut f, &rafs_meta)?,
};

Ok(RafsInspector {
Expand All @@ -141,20 +181,19 @@ impl RafsInspector {

fn load_meta(f: &mut RafsIoReader) -> Result<(RafsMeta, RafsLayout)> {
let layout_profile = RafsLayout::rafsv5_layout();
match Self::super_block_v5(f, &layout_profile) {
Ok(sb) => {
let mut res = Self::super_block_v5(f, &layout_profile).map(|sb| {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

super_block_v5 does RafsV5SuperBlock::load() which doesn't check fs magic or fs version, so it won't return errors if it's a v6 superblock.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I modified the super_block_v5 and added a checker for rafs versions.

      if !sb.detect() {
            return Err(anyhow!("invalid rafs v5 version"));
        }

let rafs_meta: RafsMeta = (&sb).into();
(rafs_meta, layout_profile)
});

if res.is_err() {
let layout_v6_profile = RafsLayout::rafsv6_layout();
res = Self::super_block_v6(f).map(|sb| {
let rafs_meta: RafsMeta = (&sb).into();
Ok((rafs_meta, layout_profile))
}
Err(e) => Err(e),
}

/*
match Self::super_block_v6(f, &layout_profile) {
Ok(sb) => {}
Err(e) => Err(e),
(rafs_meta, layout_v6_profile)
});
}
*/
res
}

/// Index is u32, by which the inode can be found.
Expand Down Expand Up @@ -257,6 +296,9 @@ Blocks: {blocks}"#,
trace!("inode: {:?}; name: {:?}", child_inode, name);
let inode_offset = match &self.state {
RafsState::V5(s) => s.inodes_table.data[idx as usize] << 3,
_ => {
unimplemented!()
}
};

match op(name.as_os_str(), &child_inode, idx, inode_offset) {
Expand Down Expand Up @@ -296,6 +338,9 @@ Blocks: {blocks}"#,
trace!("inode: {:?}; name: {:?}", child_inode, name);
let inode_offset = match &self.state {
RafsState::V5(s) => s.inodes_table.data[idx as usize] << 3,
_ => {
unimplemented!()
}
};
match op(name.as_os_str(), &child_inode, idx, inode_offset) {
Action::Break => break,
Expand Down Expand Up @@ -603,6 +648,18 @@ Blocks: {blocks}"#,
bootstrap.seek_to_offset(self.rafs_meta.blob_table_offset)?;

match &self.state {
RafsState::V6(s) => {
if self.request_mode {
let mut value = json!([]);
for (_i, b) in s.blobs_table.entries.iter().enumerate() {
let v = json!({"blob_id": b.blob_id(), "readahead_offset": b.readahead_offset(),
"readahead_size":b.readahead_size(), "decompressed_size": None::<u64>, "compressed_size": None::<u64>});
value.as_array_mut().unwrap().push(v);
}
return Ok(Some(value));
}
unimplemented!();
}
RafsState::V5(s) => {
let blobs = &s.blobs_table;
let extended = &s.extended_blobs_table;
Expand Down Expand Up @@ -658,6 +715,13 @@ Blocks: {blocks}"#,
}

impl RafsInspector {
fn load_state_v6(f: &mut RafsIoReader, meta: &RafsMeta) -> Result<RafsState> {
let mut table = RafsV6BlobTable::new();
f.seek_to_offset(meta.blob_table_offset)?;
table.load(f, meta.blob_table_size, meta.chunk_size, meta.flags)?;
Ok(RafsState::V6(RafsV6State { blobs_table: table }))
}

fn load_state_v5(f: &mut RafsIoReader, meta: &RafsMeta) -> Result<RafsState> {
let mut inodes_table = RafsV5InodeTable::new(meta.inode_table_entries as usize);
f.seek_to_offset(meta.inode_table_offset)?;
Expand Down Expand Up @@ -690,6 +754,12 @@ impl RafsInspector {
}))
}

fn super_block_v6(b: &mut RafsIoReader) -> Result<RafsV6SuperBlockExt> {
let mut sb = RafsV6SuperBlockExt::new();
sb.load(b)?;
_ = sb.validate()?;
Ok(sb)
}
fn super_block_v5(
b: &mut RafsIoReader,
layout_profile: &RafsLayout,
Expand All @@ -700,12 +770,19 @@ impl RafsInspector {
sb.load(b)
.map_err(|e| anyhow!("Failed in loading super block, {:?}", e))?;

if !sb.detect() {
return Err(anyhow!("invalid rafs v5 version"));
}

Ok(sb)
}

fn load_ondisk_inode_v5(&self, index: usize) -> Result<(InodeWrapper, OsString)> {
let offset = match &self.state {
RafsState::V5(s) => s.inodes_table.data[index] << 3,
_ => {
unimplemented!()
}
};

let mut ondisk_inode = RafsV5Inode::new();
Expand Down