xfs: don't over-report free space or inodes in statvfs
[ Upstream commit4b8d867ca6
] Emmanual Florac reports a strange occurrence when project quota limits are enabled, free space is lower than the remaining quota, and someone runs statvfs: # mkfs.xfs -f /dev/sda # mount /dev/sda /mnt -o prjquota # xfs_quota -x -c 'limit -p bhard=2G 55' /mnt # mkdir /mnt/dir # xfs_io -c 'chproj 55' -c 'chattr +P' -c 'stat -vvvv' /mnt/dir # fallocate -l 19g /mnt/a # df /mnt /mnt/dir Filesystem Size Used Avail Use% Mounted on /dev/sda 20G 20G 345M 99% /mnt /dev/sda 2.0G 0 2.0G 0% /mnt I think the bug here is that xfs_fill_statvfs_from_dquot unconditionally assigns to f_bfree without checking that the filesystem has enough free space to fill the remaining project quota. However, this is a longstanding behavior of xfs so it's unclear what to do here. Cc: <stable@vger.kernel.org> # v2.6.18 Fixes:932f2c3231
("[XFS] statvfs component of directory/project quota support, code originally by Glen.") Reported-by: Emmanuel Florac <eflorac@intellique.com> Signed-off-by: "Darrick J. Wong" <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Sasha Levin <sashal@kernel.org> (cherry picked from commit 4534162e0916accc7bfc974a08865bebae0b5c56)
This commit is contained in:
parent
14ec905fcf
commit
a6323d0567
|
@ -32,21 +32,28 @@ xfs_fill_statvfs_from_dquot(
|
|||
limit = blkres->softlimit ?
|
||||
blkres->softlimit :
|
||||
blkres->hardlimit;
|
||||
if (limit && statp->f_blocks > limit) {
|
||||
statp->f_blocks = limit;
|
||||
statp->f_bfree = statp->f_bavail =
|
||||
(statp->f_blocks > blkres->reserved) ?
|
||||
(statp->f_blocks - blkres->reserved) : 0;
|
||||
if (limit) {
|
||||
uint64_t remaining = 0;
|
||||
|
||||
if (limit > blkres->reserved)
|
||||
remaining = limit - blkres->reserved;
|
||||
|
||||
statp->f_blocks = min(statp->f_blocks, limit);
|
||||
statp->f_bfree = min(statp->f_bfree, remaining);
|
||||
statp->f_bavail = min(statp->f_bavail, remaining);
|
||||
}
|
||||
|
||||
limit = dqp->q_ino.softlimit ?
|
||||
dqp->q_ino.softlimit :
|
||||
dqp->q_ino.hardlimit;
|
||||
if (limit && statp->f_files > limit) {
|
||||
statp->f_files = limit;
|
||||
statp->f_ffree =
|
||||
(statp->f_files > dqp->q_ino.reserved) ?
|
||||
(statp->f_files - dqp->q_ino.reserved) : 0;
|
||||
if (limit) {
|
||||
uint64_t remaining = 0;
|
||||
|
||||
if (limit > dqp->q_ino.reserved)
|
||||
remaining = limit - dqp->q_ino.reserved;
|
||||
|
||||
statp->f_files = min(statp->f_files, limit);
|
||||
statp->f_ffree = min(statp->f_ffree, remaining);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue