From: Theodore Ts'o Date: Sun, 8 Dec 2024 04:31:43 +0000 (-0500) Subject: resize2fs: rewrite the checksums in the orphan file if necessary X-Git-Tag: v1.47.2~20 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ff4f46b4fdb2db5a17440252a21c7db4dfce5986;p=thirdparty%2Fe2fsprogs.git resize2fs: rewrite the checksums in the orphan file if necessary The calculation of the metadata checksum located in each block of the orphan file's inode includes the physical block number. So if any of those blocks have been moved, the checksum needs to be updated. Reported-by: Matthias Reichl Signed-off-by: Theodore Ts'o --- diff --git a/resize/resize2fs.c b/resize/resize2fs.c index e590f934..28f33d8c 100644 --- a/resize/resize2fs.c +++ b/resize/resize2fs.c @@ -49,6 +49,7 @@ static errcode_t inode_scan_and_fix(ext2_resize_t rfs); static errcode_t inode_ref_fix(ext2_resize_t rfs); static errcode_t move_itables(ext2_resize_t rfs); static errcode_t fix_resize_inode(ext2_filsys fs); +static errcode_t fix_orphan_file_inode(ext2_filsys fs); static errcode_t resize2fs_calculate_summary_stats(ext2_filsys fs); static errcode_t fix_sb_journal_backup(ext2_filsys fs); static errcode_t mark_table_blocks(ext2_filsys fs, @@ -222,6 +223,12 @@ errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags, goto errout; print_resource_track(rfs, &rtrack, fs->io); + init_resource_track(&rtrack, "fix_orphan_file_inode", fs->io); + retval = fix_orphan_file_inode(rfs->new_fs); + if (retval) + goto errout; + print_resource_track(rfs, &rtrack, fs->io); + init_resource_track(&rtrack, "fix_sb_journal_backup", fs->io); retval = fix_sb_journal_backup(rfs->new_fs); if (retval) @@ -2837,6 +2844,74 @@ errout: return retval; } +struct process_orphan_block_data { + char *buf; + errcode_t errcode; + ext2_ino_t ino; + __u32 generation; +}; + +static int process_orphan_block(ext2_filsys fs, + blk64_t *block_nr, + e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), + blk64_t ref_blk EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct process_orphan_block_data *pd = priv_data; + struct ext4_orphan_block_tail *tail; + blk64_t blk = *block_nr; + __le32 new_crc; + + pd->errcode = io_channel_read_blk64(fs->io, blk, 1, pd->buf); + if (pd->errcode) + return BLOCK_ABORT; + tail = ext2fs_orphan_block_tail(fs, pd->buf); + new_crc = ext2fs_cpu_to_le32(ext2fs_do_orphan_file_block_csum(fs, + pd->ino, pd->generation, blk, pd->buf)); + if (new_crc == tail->ob_checksum) + return 0; + tail->ob_checksum = new_crc; + pd->errcode = io_channel_write_blk64(fs->io, blk, 1, pd->buf); + if (pd->errcode) + return BLOCK_ABORT; + return 0; +} + +/* + * Fix the checksums in orphan_file inode + */ +static errcode_t fix_orphan_file_inode(ext2_filsys fs) +{ + struct process_orphan_block_data pd; + struct ext2_inode inode; + errcode_t retval; + ext2_ino_t orphan_inum; + char *orphan_buf; + + if (!ext2fs_has_feature_orphan_file(fs->super) || + !ext2fs_has_feature_metadata_csum(fs->super)) + return 0; + + orphan_inum = fs->super->s_orphan_file_inum; + retval = ext2fs_read_inode(fs, orphan_inum, &inode); + if (retval) + return retval; + orphan_buf = malloc(fs->blocksize * 4); + if (!orphan_buf) + return ENOMEM; + + pd.errcode = 0; + pd.buf = orphan_buf + 3 * fs->blocksize; + pd.ino = orphan_inum; + pd.generation = inode.i_generation; + + retval = ext2fs_block_iterate3(fs, fs->super->s_orphan_file_inum, + BLOCK_FLAG_DATA_ONLY, + orphan_buf, process_orphan_block, &pd); + return (retval ? retval : pd.errcode); +} + /* * Finally, recalculate the summary information */