diff --git a/src/bin/nydus-image/core/bootstrap.rs b/src/bin/nydus-image/core/bootstrap.rs index cd1a5780bf9..d6f8f334186 100644 --- a/src/bin/nydus-image/core/bootstrap.rs +++ b/src/bin/nydus-image/core/bootstrap.rs @@ -168,6 +168,7 @@ impl Bootstrap { // Hardlink handle, all hardlink nodes' ino, nlink should be the same, // because the real_ino may be conflicted between different layers, // so we need to find hardlink node index list in the layer where the node is located. + let mut hardlink_v6_offset = 0; if let Some(indexes) = bootstrap_ctx.inode_map.get_mut(&( child.node.layer_idx, child.node.src_ino, @@ -182,6 +183,8 @@ impl Bootstrap { nodes[*idx as usize - 1].inode.set_nlink(nlink); } indexes.push(index); + // set offset for rafs v6 harlinks + hardlink_v6_offset = nodes[indexes[0] as usize - 1].offset; } else { child.node.inode.set_ino(index); child.node.inode.set_nlink(1); @@ -195,7 +198,7 @@ impl Bootstrap { // update bootstrap_ctx.offset for rafs v6. if !child.node.is_dir() { if ctx.fs_version.is_v6() { - child.node.set_v6_offset(bootstrap_ctx); + child.node.set_v6_offset(bootstrap_ctx, hardlink_v6_offset); } bootstrap_ctx.align_offset(EROFS_INODE_SLOT_SIZE as u64); } diff --git a/src/bin/nydus-image/core/node.rs b/src/bin/nydus-image/core/node.rs index 3efc3991e76..e28e5a63c95 100644 --- a/src/bin/nydus-image/core/node.rs +++ b/src/bin/nydus-image/core/node.rs @@ -1079,20 +1079,27 @@ impl Node { } /// Set node offset in bootstrap and return the next position. - pub(crate) fn set_v6_offset(&mut self, bootstrap_ctx: &mut BootstrapContext) { + pub(crate) fn set_v6_offset( + &mut self, + bootstrap_ctx: &mut BootstrapContext, + hardlink_v6_offset: u64, + ) { if self.is_reg() { - let size = self.size_with_xattr() as u64; - let unit = size_of::() as u64; - - // We first try to allocate space from used blocks. - // If no available used block exists, we allocate sequentially. - let total_size = round_up(size, unit) + self.inode.child_count() as u64 * unit; - self.offset = bootstrap_ctx.allocate_available_block(total_size); - if self.offset == 0 { - self.offset = bootstrap_ctx.offset; - bootstrap_ctx.offset += size; - bootstrap_ctx.align_offset(unit); - bootstrap_ctx.offset += self.inode.child_count() as u64 * unit; + if hardlink_v6_offset == 0 { + let size = self.size_with_xattr() as u64; + let unit = size_of::() as u64; + // We first try to allocate space from used blocks. + // If no available used block exists, we allocate sequentially. + let total_size = round_up(size, unit) + self.inode.child_count() as u64 * unit; + self.offset = bootstrap_ctx.allocate_available_block(total_size); + if self.offset == 0 { + self.offset = bootstrap_ctx.offset; + bootstrap_ctx.offset += size; + bootstrap_ctx.align_offset(unit); + bootstrap_ctx.offset += self.inode.child_count() as u64 * unit; + } + } else { + self.offset = hardlink_v6_offset; } self.v6_datalayout = EROFS_INODE_CHUNK_BASED; } else if self.is_symlink() { @@ -1897,7 +1904,7 @@ mod tests { // reg file. // "1" is used only for testing purpose, in practice // it's always aligned to 32 bytes. - node.set_v6_offset(&mut bootstrap_ctx); + node.set_v6_offset(&mut bootstrap_ctx, 0); assert_eq!(node.offset, 0); assert_eq!(node.v6_datalayout, EROFS_INODE_CHUNK_BASED); assert!(node.v6_compact_inode);