Skip to content

Commit

Permalink
rafs: do not include chunk info array in the metadata blob
Browse files Browse the repository at this point in the history
Now we can reconstruct chunk info from RAFS v6 data blob with embedded
chunk digest, so no need to embed the chunk info array in the metadata
blob anymore, which helps to dramatically reduce size of metadata blob
for big images.

Signed-off-by: Jiang Liu <gerry@linux.alibaba.com>
  • Loading branch information
jiangliu committed Mar 3, 2023
1 parent 04e4349 commit 906ea0b
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 29 deletions.
51 changes: 28 additions & 23 deletions src/bin/nydus-image/core/bootstrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use nydus_utils::digest::{self, DigestHasher, RafsDigest};
use super::context::{
ArtifactStorage, BlobManager, BootstrapContext, BootstrapManager, BuildContext, ConversionType,
};
use super::feature::Feature;
use super::node::{Node, WhiteoutType, OVERLAYFS_WHITEOUT_OPAQUE};
use super::tree::Tree;

Expand Down Expand Up @@ -599,13 +600,16 @@ impl Bootstrap {
ext_sb.set_blob_table_offset(blob_table_offset);
ext_sb.set_blob_table_size(blob_table_size as u32);

// collect all chunks in this bootstrap.
// Collect all chunks in this bootstrap.
// HashChunkDict cannot be used here, because there will be duplicate chunks between layers,
// but there is no deduplication during the actual construction.
// Each layer uses the corresponding chunk in the blob of its own layer.
// If HashChunkDict is used here, it will cause duplication. The chunks are removed,
// resulting in incomplete chunk info.
let mut chunk_cache = BTreeMap::new();
// For RAFSv6 with chunk digest array, there's no need to save the chunk info array anymore.
let mut chunk_cache = if ctx.features.is_enabled(Feature::BlobToc) {
None
} else {
Some(BTreeMap::new())
};

// Dump bootstrap
timing_tracer!(
Expand All @@ -616,7 +620,7 @@ impl Bootstrap {
bootstrap_ctx.writer.as_mut(),
orig_meta_addr,
meta_addr,
&mut chunk_cache,
chunk_cache.as_mut(),
)
.context("failed to dump bootstrap")?;
}
Expand Down Expand Up @@ -644,25 +648,26 @@ impl Bootstrap {
pt.store(bootstrap_ctx.writer.as_mut()).unwrap();
}

// TODO: get rid of the chunk info array.
// Dump chunk info array.
let chunk_table_offset = bootstrap_ctx
.writer
.seek_to_end()
.context("failed to seek to bootstrap's end for chunk table")?;
let mut chunk_table_size: u64 = 0;
for (_, chunk) in chunk_cache.iter() {
let chunk_size = chunk
.store(bootstrap_ctx.writer.as_mut())
.context("failed to dump chunk table")?;
chunk_table_size += chunk_size as u64;
if let Some(chunk_cache) = chunk_cache.as_ref() {
// Dump chunk info array if needed.
let chunk_table_offset = bootstrap_ctx
.writer
.seek_to_end()
.context("failed to seek to bootstrap's end for chunk table")?;
let mut chunk_table_size: u64 = 0;
for (_, chunk) in chunk_cache.iter() {
let chunk_size = chunk
.store(bootstrap_ctx.writer.as_mut())
.context("failed to dump chunk table")?;
chunk_table_size += chunk_size as u64;
}
ext_sb.set_chunk_table(chunk_table_offset, chunk_table_size);
debug!(
"chunk_table offset {} size {}",
chunk_table_offset, chunk_table_size
);
Self::rafsv6_align_to_block(bootstrap_ctx)?;
}
ext_sb.set_chunk_table(chunk_table_offset, chunk_table_size);
debug!(
"chunk_table offset {} size {}",
chunk_table_offset, chunk_table_size
);
Self::rafsv6_align_to_block(bootstrap_ctx)?;

// Prepare device slots.
let pos = bootstrap_ctx
Expand Down
14 changes: 8 additions & 6 deletions src/bin/nydus-image/core/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -899,7 +899,7 @@ impl Node {
f_bootstrap: &mut dyn RafsIoWrite,
orig_meta_addr: u64,
meta_addr: u64,
chunk_cache: &mut BTreeMap<DigestWithBlobIndex, ChunkWrapper>,
chunk_cache: Option<&mut BTreeMap<DigestWithBlobIndex, ChunkWrapper>>,
) -> Result<()> {
let xattr_inline_count = self.xattrs.count_v6();
ensure!(
Expand Down Expand Up @@ -1273,7 +1273,7 @@ impl Node {
&mut self,
ctx: &mut BuildContext,
f_bootstrap: &mut dyn RafsIoWrite,
chunk_cache: &mut BTreeMap<DigestWithBlobIndex, ChunkWrapper>,
mut chunk_cache: Option<&mut BTreeMap<DigestWithBlobIndex, ChunkWrapper>>,
inode: &mut Box<dyn RafsV6OndiskInode>,
) -> Result<()> {
let mut is_continuous = true;
Expand All @@ -1289,10 +1289,12 @@ impl Node {
v6_chunk.set_blob_ci_index(chunk.inner.index());
v6_chunk.set_block_addr((uncompressed_offset / EROFS_BLOCK_SIZE) as u32);
chunks.extend(v6_chunk.as_ref());
chunk_cache.insert(
DigestWithBlobIndex(*chunk.inner.id(), chunk.inner.blob_index() + 1),
chunk.inner.clone(),
);
if let Some(v) = chunk_cache.as_mut() {
v.insert(
DigestWithBlobIndex(*chunk.inner.id(), chunk.inner.blob_index() + 1),
chunk.inner.clone(),
);
}

if let Some((prev_idx, prev_pos)) = prev {
if prev_pos + ctx.chunk_size as u64 != uncompressed_offset || prev_idx != blob_idx {
Expand Down

0 comments on commit 906ea0b

Please sign in to comment.