Skip to content

Commit a920196

Browse files
chaseyuJaegeuk Kim
authored andcommitted
f2fs: don't over-report free space or inodes in statvfs
This fixes an analogus bug that was fixed in modern filesystems: a) xfs in commit 4b8d867 ("xfs: don't over-report free space or inodes in statvfs") b) ext4 in commit f87d3af ("ext4: 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. generic/762 - output mismatch (see /share/git/fstests/results//generic/762.out.bad) --- tests/generic/762.out 2025-04-15 10:21:53.371067071 +0800 +++ /share/git/fstests/results//generic/762.out.bad 2025-05-13 16:13:37.000000000 +0800 @@ -6,8 +6,10 @@ root blocks2 is in range dir blocks2 is in range root bavail2 is in range -dir bavail2 is in range +dir bavail2 has value of 1539066 +dir bavail2 is NOT in range 304734.87 .. 310891.13 root blocks3 is in range ... (Run 'diff -u /share/git/fstests/tests/generic/762.out /share/git/fstests/results//generic/762.out.bad' to see the entire diff) HINT: You _MAY_ be missing kernel fix: XXXXXXXXXXXXXX xfs: don't over-report free space or inodes in statvfs Cc: stable@kernel.org Fixes: ddc34e3 ("f2fs: introduce f2fs_statfs_project") Signed-off-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
1 parent 80f31d2 commit a920196

File tree

1 file changed

+18
-12
lines changed

1 file changed

+18
-12
lines changed

fs/f2fs/super.c

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1808,26 +1808,32 @@ static int f2fs_statfs_project(struct super_block *sb,
18081808

18091809
limit = min_not_zero(dquot->dq_dqb.dqb_bsoftlimit,
18101810
dquot->dq_dqb.dqb_bhardlimit);
1811-
if (limit)
1812-
limit >>= sb->s_blocksize_bits;
1811+
limit >>= sb->s_blocksize_bits;
1812+
1813+
if (limit) {
1814+
uint64_t remaining = 0;
18131815

1814-
if (limit && buf->f_blocks > limit) {
18151816
curblock = (dquot->dq_dqb.dqb_curspace +
18161817
dquot->dq_dqb.dqb_rsvspace) >> sb->s_blocksize_bits;
1817-
buf->f_blocks = limit;
1818-
buf->f_bfree = buf->f_bavail =
1819-
(buf->f_blocks > curblock) ?
1820-
(buf->f_blocks - curblock) : 0;
1818+
if (limit > curblock)
1819+
remaining = limit - curblock;
1820+
1821+
buf->f_blocks = min(buf->f_blocks, limit);
1822+
buf->f_bfree = min(buf->f_bfree, remaining);
1823+
buf->f_bavail = min(buf->f_bavail, remaining);
18211824
}
18221825

18231826
limit = min_not_zero(dquot->dq_dqb.dqb_isoftlimit,
18241827
dquot->dq_dqb.dqb_ihardlimit);
18251828

1826-
if (limit && buf->f_files > limit) {
1827-
buf->f_files = limit;
1828-
buf->f_ffree =
1829-
(buf->f_files > dquot->dq_dqb.dqb_curinodes) ?
1830-
(buf->f_files - dquot->dq_dqb.dqb_curinodes) : 0;
1829+
if (limit) {
1830+
uint64_t remaining = 0;
1831+
1832+
if (limit > dquot->dq_dqb.dqb_curinodes)
1833+
remaining = limit - dquot->dq_dqb.dqb_curinodes;
1834+
1835+
buf->f_files = min(buf->f_files, limit);
1836+
buf->f_ffree = min(buf->f_ffree, remaining);
18311837
}
18321838

18331839
spin_unlock(&dquot->dq_dqb_lock);

0 commit comments

Comments
 (0)