summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2025-03-14 00:38:42 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-04-10 14:44:47 +0200
commitc891bc9bbd2dd626a92cddf4a689c3150b8ed20a (patch)
tree611de78e84e29491dad3c9c5fe9e669f827c0c71
parent5a57f8eb2a17d469d65cd1186cea26b798221d4a (diff)
downloadlinux-c891bc9bbd2dd626a92cddf4a689c3150b8ed20a.tar.gz
linux-c891bc9bbd2dd626a92cddf4a689c3150b8ed20a.tar.bz2
linux-c891bc9bbd2dd626a92cddf4a689c3150b8ed20a.zip
ext4: don't over-report free space or inodes in statvfs
commit f87d3af7419307ae26e705a2b2db36140db367a2 upstream. This fixes an analogus bug that was fixed in xfs in commit 4b8d867ca6e2 ("xfs: don't over-report free space or inodes in statvfs") where statfs can report misleading / incorrect information where project quota is enabled, and the free space is less than the remaining quota. This commit will resolve a test failure in generic/762 which tests for this bug. Cc: stable@kernel.org Fixes: 689c958cbe6b ("ext4: add project quota support") Signed-off-by: Theodore Ts'o <tytso@mit.edu> Reviewed-by: "Darrick J. Wong" <djwong@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/ext4/super.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index b666ef71a034..dc46a7063f1e 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -6813,22 +6813,29 @@ static int ext4_statfs_project(struct super_block *sb,
dquot->dq_dqb.dqb_bhardlimit);
limit >>= sb->s_blocksize_bits;
- if (limit && buf->f_blocks > limit) {
+ if (limit) {
+ uint64_t remaining = 0;
+
curblock = (dquot->dq_dqb.dqb_curspace +
dquot->dq_dqb.dqb_rsvspace) >> sb->s_blocksize_bits;
- buf->f_blocks = limit;
- buf->f_bfree = buf->f_bavail =
- (buf->f_blocks > curblock) ?
- (buf->f_blocks - curblock) : 0;
+ if (limit > curblock)
+ remaining = limit - curblock;
+
+ buf->f_blocks = min(buf->f_blocks, limit);
+ buf->f_bfree = min(buf->f_bfree, remaining);
+ buf->f_bavail = min(buf->f_bavail, remaining);
}
limit = min_not_zero(dquot->dq_dqb.dqb_isoftlimit,
dquot->dq_dqb.dqb_ihardlimit);
- if (limit && buf->f_files > limit) {
- buf->f_files = limit;
- buf->f_ffree =
- (buf->f_files > dquot->dq_dqb.dqb_curinodes) ?
- (buf->f_files - dquot->dq_dqb.dqb_curinodes) : 0;
+ if (limit) {
+ uint64_t remaining = 0;
+
+ if (limit > dquot->dq_dqb.dqb_curinodes)
+ remaining = limit - dquot->dq_dqb.dqb_curinodes;
+
+ buf->f_files = min(buf->f_files, limit);
+ buf->f_ffree = min(buf->f_ffree, remaining);
}
spin_unlock(&dquot->dq_dqb_lock);