Whamcloud - gitweb
resize2fs: rewrite the checksums in the orphan file if necessary
authorTheodore Ts'o <tytso@mit.edu>
Sun, 8 Dec 2024 04:31:43 +0000 (23:31 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Sun, 8 Dec 2024 04:55:28 +0000 (23:55 -0500)
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 <hias@horus.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
resize/resize2fs.c

index e590f93..28f33d8 100644 (file)
@@ -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
  */