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

Refine builder and rafs to prepare for tarfs #1144

Merged
merged 3 commits into from
Mar 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 8 additions & 8 deletions rafs/src/builder/core/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use crate::builder::{
};
use crate::metadata::chunk::ChunkWrapper;
use crate::metadata::layout::v5::RafsV5BlobTable;
use crate::metadata::layout::v6::{RafsV6BlobTable, EROFS_BLOCK_SIZE, EROFS_INODE_SLOT_SIZE};
use crate::metadata::layout::v6::{RafsV6BlobTable, EROFS_BLOCK_SIZE_4096, EROFS_INODE_SLOT_SIZE};
use crate::metadata::layout::RafsBlobTable;
use crate::metadata::{Inode, RAFS_DEFAULT_CHUNK_SIZE};
use crate::metadata::{RafsSuperFlags, RafsVersion};
Expand Down Expand Up @@ -970,11 +970,11 @@ impl BootstrapContext {
layered,
inode_map: HashMap::new(),
nodes: Vec::new(),
offset: EROFS_BLOCK_SIZE,
offset: EROFS_BLOCK_SIZE_4096,
writer,
v6_available_blocks: vec![
VecDeque::new();
EROFS_BLOCK_SIZE as usize / EROFS_INODE_SLOT_SIZE
EROFS_BLOCK_SIZE_4096 as usize / EROFS_INODE_SLOT_SIZE
],
})
}
Expand All @@ -991,17 +991,17 @@ impl BootstrapContext {
// If found it, return the offset where we can store data.
// If not, return 0.
pub(crate) fn allocate_available_block(&mut self, size: u64) -> u64 {
if size >= EROFS_BLOCK_SIZE {
if size >= EROFS_BLOCK_SIZE_4096 {
return 0;
}

let min_idx = div_round_up(size, EROFS_INODE_SLOT_SIZE as u64) as usize;
let max_idx = div_round_up(EROFS_BLOCK_SIZE, EROFS_INODE_SLOT_SIZE as u64) as usize;
let max_idx = div_round_up(EROFS_BLOCK_SIZE_4096, EROFS_INODE_SLOT_SIZE as u64) as usize;

for idx in min_idx..max_idx {
let blocks = &mut self.v6_available_blocks[idx];
if let Some(mut offset) = blocks.pop_front() {
offset += EROFS_BLOCK_SIZE - (idx * EROFS_INODE_SLOT_SIZE) as u64;
offset += EROFS_BLOCK_SIZE_4096 - (idx * EROFS_INODE_SLOT_SIZE) as u64;
self.append_available_block(offset + (min_idx * EROFS_INODE_SLOT_SIZE) as u64);
return offset;
}
Expand All @@ -1012,8 +1012,8 @@ impl BootstrapContext {

// Append the block that `offset` belongs to corresponding deque.
pub(crate) fn append_available_block(&mut self, offset: u64) {
if offset % EROFS_BLOCK_SIZE != 0 {
let avail = EROFS_BLOCK_SIZE - offset % EROFS_BLOCK_SIZE;
if offset % EROFS_BLOCK_SIZE_4096 != 0 {
let avail = EROFS_BLOCK_SIZE_4096 - offset % EROFS_BLOCK_SIZE_4096;
let idx = avail as usize / EROFS_INODE_SLOT_SIZE;
self.v6_available_blocks[idx].push_back(round_down_4k(offset));
}
Expand Down
31 changes: 9 additions & 22 deletions rafs/src/builder/core/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,15 +235,19 @@ impl Node {
return Ok(0);
} else if self.is_symlink() {
if let Some(symlink) = self.info.symlink.as_ref() {
self.inode
.set_digest(RafsDigest::from_buf(symlink.as_bytes(), ctx.digester));
if self.inode.is_v5() {
self.inode
.set_digest(RafsDigest::from_buf(symlink.as_bytes(), ctx.digester));
}
return Ok(0);
} else {
return Err(Error::msg("inode's symblink is invalid."));
}
} else if self.is_special() {
self.inode
.set_digest(RafsDigest::hasher(ctx.digester).digest_finalize());
if self.inode.is_v5() {
self.inode
.set_digest(RafsDigest::hasher(ctx.digester).digest_finalize());
}
return Ok(0);
}

Expand Down Expand Up @@ -581,7 +585,7 @@ impl Node {
// calculate it later by ourself.
if !self.is_dir() {
self.inode.set_size(meta.st_size());
self.set_inode_blocks();
self.v5_set_inode_blocks();
}
self.info = Arc::new(info);

Expand Down Expand Up @@ -736,23 +740,6 @@ impl Node {
&self.info.target
}

/// Calculate and set `i_blocks` for inode.
///
/// In order to support repeatable build, we can't reuse `i_blocks` from source filesystems,
/// so let's calculate it by ourself for stable `i_block`.
///
/// Normal filesystem includes the space occupied by Xattr into the directory size,
/// let's follow the normal behavior.
pub fn set_inode_blocks(&mut self) {
// Set inode blocks for RAFS v5 inode, v6 will calculate it at runtime.
if let InodeWrapper::V5(_) = self.inode {
self.inode.set_blocks(div_round_up(
self.inode.size() + self.info.xattrs.aligned_size_v5() as u64,
512,
));
}
}

/// Set symlink target for the node.
pub fn set_symlink(&mut self, symlink: OsString) {
let mut info = self.info.deref().clone();
Expand Down
21 changes: 19 additions & 2 deletions rafs/src/builder/core/v5.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::mem::size_of;

use anyhow::{bail, Context, Result};
use nydus_utils::digest::{DigestHasher, RafsDigest};
use nydus_utils::{root_tracer, timing_tracer, try_round_up_4k};
use nydus_utils::{div_round_up, root_tracer, timing_tracer, try_round_up_4k};

use super::bootstrap::STARGZ_DEFAULT_BLOCK_SIZE;
use super::node::Node;
Expand Down Expand Up @@ -102,7 +102,24 @@ impl Node {
// Safe to unwrap() because we have u32 for child count.
self.inode.set_size(try_round_up_4k(d_size).unwrap());
}
self.set_inode_blocks();
self.v5_set_inode_blocks();
}

/// Calculate and set `i_blocks` for inode.
///
/// In order to support repeatable build, we can't reuse `i_blocks` from source filesystems,
/// so let's calculate it by ourself for stable `i_block`.
///
/// Normal filesystem includes the space occupied by Xattr into the directory size,
/// let's follow the normal behavior.
pub fn v5_set_inode_blocks(&mut self) {
// Set inode blocks for RAFS v5 inode, v6 will calculate it at runtime.
if let InodeWrapper::V5(_) = self.inode {
self.inode.set_blocks(div_round_up(
self.inode.size() + self.info.xattrs.aligned_size_v5() as u64,
512,
));
}
}
}

Expand Down
37 changes: 19 additions & 18 deletions rafs/src/builder/core/v6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::metadata::inode::new_v6_inode;
use crate::metadata::layout::v6::{
align_offset, calculate_nid, RafsV6BlobTable, RafsV6Device, RafsV6Dirent, RafsV6InodeChunkAddr,
RafsV6InodeChunkHeader, RafsV6OndiskInode, RafsV6SuperBlock, RafsV6SuperBlockExt,
EROFS_BLOCK_SIZE, EROFS_DEVTABLE_OFFSET, EROFS_INODE_CHUNK_BASED, EROFS_INODE_FLAT_INLINE,
EROFS_BLOCK_SIZE_4096, EROFS_DEVTABLE_OFFSET, EROFS_INODE_CHUNK_BASED, EROFS_INODE_FLAT_INLINE,
EROFS_INODE_FLAT_PLAIN, EROFS_INODE_SLOT_SIZE, EROFS_SUPER_BLOCK_SIZE, EROFS_SUPER_OFFSET,
};
use crate::metadata::RafsStore;
Expand Down Expand Up @@ -162,8 +162,8 @@ impl Node {
for child in tree.children.iter() {
let len = child.node.name().as_bytes().len() + size_of::<RafsV6Dirent>();
// erofs disk format requires dirent to be aligned with 4096.
if (d_size % EROFS_BLOCK_SIZE) + len as u64 > EROFS_BLOCK_SIZE {
d_size = div_round_up(d_size as u64, EROFS_BLOCK_SIZE) * EROFS_BLOCK_SIZE;
if (d_size % EROFS_BLOCK_SIZE_4096) + len as u64 > EROFS_BLOCK_SIZE_4096 {
d_size = div_round_up(d_size as u64, EROFS_BLOCK_SIZE_4096) * EROFS_BLOCK_SIZE_4096;
}
d_size += len as u64;
}
Expand Down Expand Up @@ -217,7 +217,7 @@ impl Node {
//
//
let inode_size = self.v6_size_with_xattr();
let tail: u64 = d_size % EROFS_BLOCK_SIZE;
let tail: u64 = d_size % EROFS_BLOCK_SIZE_4096;

// We use a simple inline strategy here:
// If the inode size with xattr + tail data size <= EROFS_BLOCK_SIZE,
Expand All @@ -229,7 +229,7 @@ impl Node {
// since it contain only single blocks with some unused space, the available space can only
// be smaller than EROFS_BLOCK_SIZE, therefore we can't use our used blocks to store the
// inode plus the tail data bigger than EROFS_BLOCK_SIZE.
let should_inline = tail != 0 && (inode_size + tail) <= EROFS_BLOCK_SIZE;
let should_inline = tail != 0 && (inode_size + tail) <= EROFS_BLOCK_SIZE_4096;

// If should inline, we first try to allocate space for the inode together with tail data
// using used blocks.
Expand All @@ -240,10 +240,11 @@ impl Node {
self.v6_datalayout = if should_inline {
self.v6_offset = bootstrap_ctx.allocate_available_block(inode_size + tail);
if self.v6_offset == 0 {
let available = EROFS_BLOCK_SIZE - bootstrap_ctx.offset % EROFS_BLOCK_SIZE;
let available =
EROFS_BLOCK_SIZE_4096 - bootstrap_ctx.offset % EROFS_BLOCK_SIZE_4096;
if available < inode_size + tail {
bootstrap_ctx.append_available_block(bootstrap_ctx.offset);
bootstrap_ctx.align_offset(EROFS_BLOCK_SIZE);
bootstrap_ctx.align_offset(EROFS_BLOCK_SIZE_4096);
}

self.v6_offset = bootstrap_ctx.offset;
Expand All @@ -252,7 +253,7 @@ impl Node {

if d_size != tail {
bootstrap_ctx.append_available_block(bootstrap_ctx.offset);
bootstrap_ctx.align_offset(EROFS_BLOCK_SIZE);
bootstrap_ctx.align_offset(EROFS_BLOCK_SIZE_4096);
}
self.v6_dirents_offset = bootstrap_ctx.offset;
bootstrap_ctx.offset += round_down_4k(d_size);
Expand All @@ -269,10 +270,10 @@ impl Node {
}

bootstrap_ctx.append_available_block(bootstrap_ctx.offset);
bootstrap_ctx.align_offset(EROFS_BLOCK_SIZE);
bootstrap_ctx.align_offset(EROFS_BLOCK_SIZE_4096);
self.v6_dirents_offset = bootstrap_ctx.offset;
bootstrap_ctx.offset += d_size;
bootstrap_ctx.align_offset(EROFS_BLOCK_SIZE);
bootstrap_ctx.align_offset(EROFS_BLOCK_SIZE_4096);

EROFS_INODE_FLAT_PLAIN
};
Expand Down Expand Up @@ -336,7 +337,7 @@ impl Node {
for (offset, name, file_type) in self.v6_dirents.iter() {
let len = name.len() + size_of::<RafsV6Dirent>();
// write to bootstrap when it will exceed EROFS_BLOCK_SIZE
if used + len as u64 > EROFS_BLOCK_SIZE {
if used + len as u64 > EROFS_BLOCK_SIZE_4096 {
for (entry, name) in dirents.iter_mut() {
trace!("{:?} nameoff {}", name, nameoff);
entry.set_name_offset(nameoff as u16);
Expand All @@ -363,7 +364,7 @@ impl Node {
nameoff = 0;
used = 0;
// track where we're going to write.
dirent_off += EROFS_BLOCK_SIZE;
dirent_off += EROFS_BLOCK_SIZE_4096;
}

trace!(
Expand Down Expand Up @@ -527,7 +528,7 @@ impl Node {

impl BuildContext {
pub fn v6_block_size(&self) -> u64 {
EROFS_BLOCK_SIZE
EROFS_BLOCK_SIZE_4096
}

pub fn v6_block_addr(&self, offset: u64) -> Result<u32> {
Expand Down Expand Up @@ -609,7 +610,7 @@ impl Bootstrap {
let blob_table_size = blob_table.size() as u64;
let blob_table_offset = align_offset(
(EROFS_DEVTABLE_OFFSET as u64) + devtable_len as u64,
EROFS_BLOCK_SIZE as u64,
EROFS_BLOCK_SIZE_4096 as u64,
);
let blob_table_entries = blobs.len();
assert!(blob_table_entries < u8::MAX as usize);
Expand Down Expand Up @@ -639,11 +640,11 @@ impl Bootstrap {
// When using nid 0 as root nid,
// the root directory will not be shown by glibc's getdents/readdir.
// Because in some OS, ino == 0 represents corresponding file is deleted.
let orig_meta_addr = bootstrap_ctx.nodes[0].v6_offset - EROFS_BLOCK_SIZE;
let orig_meta_addr = bootstrap_ctx.nodes[0].v6_offset - EROFS_BLOCK_SIZE_4096;
let meta_addr = if blob_table_size > 0 {
align_offset(
blob_table_offset + blob_table_size + prefetch_table_size as u64,
EROFS_BLOCK_SIZE as u64,
EROFS_BLOCK_SIZE_4096 as u64,
)
} else {
orig_meta_addr
Expand Down Expand Up @@ -733,7 +734,7 @@ impl Bootstrap {
.writer
.seek_to_end()
.context("failed to seek to bootstrap's end for chunk table")?;
assert_eq!(pos % EROFS_BLOCK_SIZE, 0);
assert_eq!(pos % EROFS_BLOCK_SIZE_4096, 0);
let mut devtable: Vec<RafsV6Device> = Vec::new();
let mut block_count = 0u32;
let mut inlined_chunk_digest = true;
Expand Down Expand Up @@ -834,7 +835,7 @@ impl Bootstrap {
.writer
.seek_to_end()
.context("failed to seek to bootstrap's end for chunk table")?;
let padding = align_offset(pos, EROFS_BLOCK_SIZE as u64) - pos;
let padding = align_offset(pos, EROFS_BLOCK_SIZE_4096 as u64) - pos;
bootstrap_ctx
.writer
.write_all(&WRITE_PADDING_DATA[0..padding as usize])
Expand Down
Loading