hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB7V02
--------------------------------
If the xfs reserve block related ioctl takes a large input value, the input reserved size is still assigned to mp->m_resblks in xfs_reserve_blocks() even if the requested size is larger than the total free size in the filesystem. This is because the subsequent xfs_mod_fdblocks() will handle the adjustment.
However, in the current code, xfs_mod_fdblocks() calculates mp->m_resblks - mp->m_resblks_avail and casts the result to a long long type, while both mp->m_resblks and mp->m_resblks_avail are of type unsigned long long. If the difference between these two values is very large, and the most significant bit (MSB) is set to 1 (indicating a large unsigned value), the result of the cast becomes a large negative value. This causes mp->m_fdblocks to be updated to a very large value. As a result, xfs will incorrectly determine that there is always free space during foreground writes, while background writebacks may fail due to lack of space.
Modify the relevant data types in xfs_mod_fdblocks() to address this issue.
Fixes: 0d485ada404b ("xfs: use generic percpu counters for free block counter") Signed-off-by: Zizhi Wo wozizhi@huawei.com --- fs/xfs/xfs_mount.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index bc14ca674658..8481106de5f8 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -1151,7 +1151,7 @@ xfs_mod_freecounter( bool rsvd) { int64_t lcounter; - long long res_used; + uint64_t res_used; uint64_t set_aside = 0; s32 batch; bool has_resv_pool; @@ -1173,9 +1173,9 @@ xfs_mod_freecounter( }
spin_lock(&mp->m_sb_lock); - res_used = (long long)(mp->m_resblks - mp->m_resblks_avail); + res_used = mp->m_resblks - mp->m_resblks_avail;
- if (res_used > delta) { + if (res_used > (uint64_t)delta) { mp->m_resblks_avail += delta; } else { delta -= res_used;