diff mbox series

[1/4] e2fsck: update quota accounting after directory optimization

Message ID 20240328172940.1609-2-luis.henriques@linux.dev
State Superseded
Headers show
Series quota-related e2fsck fixes and tests | expand

Commit Message

Luis Henriques March 28, 2024, 5:29 p.m. UTC
In "Pass 3A: Optimizing directories", a directory may have it's size reduced.
If that happens and quota is enabled in the filesystem, the quota information
will be incorrect because it doesn't take the rehash into account.  This issue
was detected by running fstest ext4/014.

This patch simply updates the quota data accordingly, after the directory is
written and it's size has been updated.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=218626
Signed-off-by: Luis Henriques (SUSE) <luis.henriques@linux.dev>
---
 e2fsck/rehash.c | 27 +++++++++++++++++++++------
 1 file changed, 21 insertions(+), 6 deletions(-)

Comments

Andreas Dilger April 1, 2024, 7:52 p.m. UTC | #1
On Mar 28, 2024, at 11:29 AM, Luis Henriques (SUSE) <luis.henriques@linux.dev> wrote:
> 
> In "Pass 3A: Optimizing directories", a directory may have it's size reduced.
> If that happens and quota is enabled in the filesystem, the quota information
> will be incorrect because it doesn't take the rehash into account.  This issue
> was detected by running fstest ext4/014.
> 
> This patch simply updates the quota data accordingly, after the directory is
> written and it's size has been updated.
> 
> Link: https://bugzilla.kernel.org/show_bug.cgi?id=218626
> Signed-off-by: Luis Henriques (SUSE) <luis.henriques@linux.dev>

Reviewed-by: Andreas Dilger <adilger@dilger.ca>

> ---
> e2fsck/rehash.c | 27 +++++++++++++++++++++------
> 1 file changed, 21 insertions(+), 6 deletions(-)
> 
> diff --git a/e2fsck/rehash.c b/e2fsck/rehash.c
> index c1da7d52724e..4847d172e5fe 100644
> --- a/e2fsck/rehash.c
> +++ b/e2fsck/rehash.c
> @@ -987,14 +987,18 @@ errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino,
> {
> 	ext2_filsys 		fs = ctx->fs;
> 	errcode_t		retval;
> -	struct ext2_inode 	inode;
> +	struct ext2_inode_large	inode;
> 	char			*dir_buf = 0;
> 	struct fill_dir_struct	fd = { NULL, NULL, 0, 0, 0, NULL,
> 				       0, 0, 0, 0, 0, 0 };
> 	struct out_dir		outdir = { 0, 0, 0, 0 };
> -	struct name_cmp_ctx name_cmp_ctx = {0, NULL};
> +	struct name_cmp_ctx	name_cmp_ctx = {0, NULL};
> +	__u64			osize;
> 
> -	e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
> +	e2fsck_read_inode_full(ctx, ino, EXT2_INODE(&inode),
> +			       sizeof(inode), "rehash_dir");
> +
> +	osize = EXT2_I_SIZE(&inode);
> 
> 	if (ext2fs_has_feature_inline_data(fs->super) &&
> 	   (inode.i_flags & EXT4_INLINE_DATA_FL))
> @@ -1013,7 +1017,7 @@ errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino,
> 	fd.ino = ino;
> 	fd.ctx = ctx;
> 	fd.buf = dir_buf;
> -	fd.inode = &inode;
> +	fd.inode = EXT2_INODE(&inode);
> 	fd.dir = ino;
> 	if (!ext2fs_has_feature_dir_index(fs->super) ||
> 	    (inode.i_size / fs->blocksize) < 2)
> @@ -1092,14 +1096,25 @@ resort:
> 			goto errout;
> 	}
> 
> -	retval = write_directory(ctx, fs, &outdir, ino, &inode, fd.compress);
> +	retval = write_directory(ctx, fs, &outdir, ino, EXT2_INODE(&inode),
> +				 fd.compress);
> 	if (retval)
> 		goto errout;
> 
> +	if ((osize > EXT2_I_SIZE(&inode)) &&
> +	    (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)) {
> +		quota_data_sub(ctx->qctx, &inode,
> +			       ino, osize - EXT2_I_SIZE(&inode));
> +	}
> +
> 	if (ctx->options & E2F_OPT_CONVERT_BMAP)
> 		retval = e2fsck_rebuild_extents_later(ctx, ino);
> 	else
> -		retval = e2fsck_check_rebuild_extents(ctx, ino, &inode, pctx);
> +		retval = e2fsck_check_rebuild_extents(ctx, ino,
> +						      EXT2_INODE(&inode), pctx);
> errout:
> 	ext2fs_free_mem(&dir_buf);
> 	ext2fs_free_mem(&fd.harray);


Cheers, Andreas
diff mbox series

Patch

diff --git a/e2fsck/rehash.c b/e2fsck/rehash.c
index c1da7d52724e..4847d172e5fe 100644
--- a/e2fsck/rehash.c
+++ b/e2fsck/rehash.c
@@ -987,14 +987,18 @@  errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino,
 {
 	ext2_filsys 		fs = ctx->fs;
 	errcode_t		retval;
-	struct ext2_inode 	inode;
+	struct ext2_inode_large	inode;
 	char			*dir_buf = 0;
 	struct fill_dir_struct	fd = { NULL, NULL, 0, 0, 0, NULL,
 				       0, 0, 0, 0, 0, 0 };
 	struct out_dir		outdir = { 0, 0, 0, 0 };
-	struct name_cmp_ctx name_cmp_ctx = {0, NULL};
+	struct name_cmp_ctx	name_cmp_ctx = {0, NULL};
+	__u64			osize;
 
-	e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
+	e2fsck_read_inode_full(ctx, ino, EXT2_INODE(&inode),
+			       sizeof(inode), "rehash_dir");
+
+	osize = EXT2_I_SIZE(&inode);
 
 	if (ext2fs_has_feature_inline_data(fs->super) &&
 	   (inode.i_flags & EXT4_INLINE_DATA_FL))
@@ -1013,7 +1017,7 @@  errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino,
 	fd.ino = ino;
 	fd.ctx = ctx;
 	fd.buf = dir_buf;
-	fd.inode = &inode;
+	fd.inode = EXT2_INODE(&inode);
 	fd.dir = ino;
 	if (!ext2fs_has_feature_dir_index(fs->super) ||
 	    (inode.i_size / fs->blocksize) < 2)
@@ -1092,14 +1096,25 @@  resort:
 			goto errout;
 	}
 
-	retval = write_directory(ctx, fs, &outdir, ino, &inode, fd.compress);
+	retval = write_directory(ctx, fs, &outdir, ino, EXT2_INODE(&inode),
+				 fd.compress);
 	if (retval)
 		goto errout;
 
+	if ((osize > EXT2_I_SIZE(&inode)) &&
+	    (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)) {
+		quota_data_sub(ctx->qctx, &inode,
+			       ino, osize - EXT2_I_SIZE(&inode));
+	}
+
 	if (ctx->options & E2F_OPT_CONVERT_BMAP)
 		retval = e2fsck_rebuild_extents_later(ctx, ino);
 	else
-		retval = e2fsck_check_rebuild_extents(ctx, ino, &inode, pctx);
+		retval = e2fsck_check_rebuild_extents(ctx, ino,
+						      EXT2_INODE(&inode), pctx);
 errout:
 	ext2fs_free_mem(&dir_buf);
 	ext2fs_free_mem(&fd.harray);