From 36c25776ee3dffae90b8b38b86883d4636937ca5 Mon Sep 17 00:00:00 2001 From: liuh Date: Wed, 19 Jun 2024 13:57:44 +0800 Subject: [PATCH] e2fsck: update quota when deallocating a bad inode (cherry picked from commit b0ae794398a139d0c0e376f931f76f089a3b6d15) --- ...-quota-when-deallocating-a-bad-inode.patch | 121 ++++++++++++++++++ e2fsprogs.spec | 7 +- 2 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 0015-e2fsck-update-quota-when-deallocating-a-bad-inode.patch diff --git a/0015-e2fsck-update-quota-when-deallocating-a-bad-inode.patch b/0015-e2fsck-update-quota-when-deallocating-a-bad-inode.patch new file mode 100644 index 0000000..b8d31c3 --- /dev/null +++ b/0015-e2fsck-update-quota-when-deallocating-a-bad-inode.patch @@ -0,0 +1,121 @@ +From eb0680deb908d7da399dd331b7aa35cc1a4dfa2d Mon Sep 17 00:00:00 2001 +From: "Luis Henriques (SUSE)" +Date: Fri, 5 Apr 2024 15:24:03 +0100 +Subject: [PATCH] e2fsck: update quota when deallocating a bad inode + +If a bad inode is found it will be deallocated. However, if the filesystem has +quota enabled, the quota information isn't being updated accordingly. This +issue was detected by running fstest ext4/019. + +This patch fixes the issue by decreasing the inode count from the +quota and, if blocks are also being released, also subtract them as well. + +While there, and as suggested by Andreas Dilger, the deallocate_inode() +function documentation is also updated by this patch to make it clear what +that function really does. + +Signed-off-by: Luis Henriques (SUSE) +Link: https://lore.kernel.org/r/20240405142405.12312-3-luis.henriques@linux.dev +Signed-off-by: Theodore Ts'o +--- + e2fsck/pass2.c | 43 ++++++++++++++++++++++++++++++++----------- + 1 file changed, 32 insertions(+), 11 deletions(-) + +diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c +index 410edd1..9bb1e32 100644 +--- a/e2fsck/pass2.c ++++ b/e2fsck/pass2.c +@@ -1842,17 +1842,26 @@ static int deallocate_inode_block(ext2_filsys fs, + } + + /* +- * This function deallocates an inode ++ * This function reverts various counters and bitmaps incremented in ++ * pass1 for the inode, blocks, and quotas before it was decided the ++ * inode was corrupt and needed to be cleared. This avoids the need ++ * to run e2fsck a second time (or have it restart itself) to repair ++ * these counters. ++ * ++ * It does not modify any on-disk state, so even if the inode is bad ++ * it _should_ reset in-memory state to before the inode was first ++ * processed. + */ + static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf) + { + ext2_filsys fs = ctx->fs; +- struct ext2_inode inode; ++ struct ext2_inode_large inode; + struct problem_context pctx; + __u32 count; + struct del_block del_block; + +- e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode"); ++ e2fsck_read_inode_full(ctx, ino, EXT2_INODE(&inode), ++ sizeof(inode), "deallocate_inode"); + clear_problem_context(&pctx); + pctx.ino = ino; + +@@ -1862,29 +1871,29 @@ static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf) + e2fsck_read_bitmaps(ctx); + ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode)); + +- if (ext2fs_file_acl_block(fs, &inode) && ++ if (ext2fs_file_acl_block(fs, EXT2_INODE(&inode)) && + ext2fs_has_feature_xattr(fs->super)) { + pctx.errcode = ext2fs_adjust_ea_refcount3(fs, +- ext2fs_file_acl_block(fs, &inode), ++ ext2fs_file_acl_block(fs, EXT2_INODE(&inode)), + block_buf, -1, &count, ino); + if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) { + pctx.errcode = 0; + count = 1; + } + if (pctx.errcode) { +- pctx.blk = ext2fs_file_acl_block(fs, &inode); ++ pctx.blk = ext2fs_file_acl_block(fs, EXT2_INODE(&inode)); + fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + return; + } + if (count == 0) { + ext2fs_block_alloc_stats2(fs, +- ext2fs_file_acl_block(fs, &inode), -1); ++ ext2fs_file_acl_block(fs, EXT2_INODE(&inode)), -1); + } +- ext2fs_file_acl_block_set(fs, &inode, 0); ++ ext2fs_file_acl_block_set(fs, EXT2_INODE(&inode), 0); + } + +- if (!ext2fs_inode_has_valid_blocks2(fs, &inode)) ++ if (!ext2fs_inode_has_valid_blocks2(fs, EXT2_INODE(&inode))) + goto clear_inode; + + /* Inline data inodes don't have blocks to iterate */ +@@ -1909,10 +1918,22 @@ static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf) + ctx->flags |= E2F_FLAG_ABORT; + return; + } ++ ++ if ((ino != quota_type2inum(PRJQUOTA, fs->super)) && ++ (ino != fs->super->s_orphan_file_inum) && ++ (ino == EXT2_ROOT_INO || ino >= EXT2_FIRST_INODE(ctx->fs->super)) && ++ !(inode.i_flags & EXT4_EA_INODE_FL)) { ++ if (del_block.num > 0) ++ quota_data_sub(ctx->qctx, &inode, ino, ++ del_block.num * EXT2_CLUSTER_SIZE(fs->super)); ++ quota_data_inodes(ctx->qctx, (struct ext2_inode_large *)&inode, ++ ino, -1); ++ } ++ + clear_inode: + /* Inode may have changed by block_iterate, so reread it */ +- e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode"); +- e2fsck_clear_inode(ctx, ino, &inode, 0, "deallocate_inode"); ++ e2fsck_read_inode(ctx, ino, EXT2_INODE(&inode), "deallocate_inode"); ++ e2fsck_clear_inode(ctx, ino, EXT2_INODE(&inode), 0, "deallocate_inode"); + } + + /* +-- +2.43.0 + diff --git a/e2fsprogs.spec b/e2fsprogs.spec index 099862f..3763542 100644 --- a/e2fsprogs.spec +++ b/e2fsprogs.spec @@ -1,6 +1,6 @@ Name: e2fsprogs Version: 1.47.0 -Release: 5 +Release: 6 Summary: Second extended file system management tools License: GPLv2+ and LGPLv2 and MIT URL: http://e2fsprogs.sourceforge.net/ @@ -21,6 +21,7 @@ Patch11: 0011-mke2fs.conf-remove-metadata_csum_seed-and-orphan_fil.patch Patch12: 0012-debugfs-fix-infinite-loop-while-dumping-the-journal.patch Patch13: 0013-e4crypt-fix-spurious-Success-error-message.patch Patch14: 0014-e2fsck-update-quota-accounting-after-directory-optim.patch +Patch15: 0015-e2fsck-update-quota-when-deallocating-a-bad-inode.patch BuildRequires: gcc pkgconfig texinfo BuildRequires: fuse-devel libblkid-devel libuuid-devel @@ -161,6 +162,10 @@ exit 0 %{_mandir}/man8/* %changelog +* Fri Jun 21 2024 liuh - 1.47.0-6 +- sync patch from community + e2fsck: update quota when deallocating a bad inode + * Wed Jun 12 2024 liuh - 1.47.0-5 - sync patch from community fix e2fsck: update quota accounting after directory optimization -- Gitee