Skip to content

Commit c549212

Browse files
author
CKI Backport Bot
committed
xfs: fix freeing speculative preallocations for preallocated files
JIRA: https://issues.redhat.com/browse/RHEL-56816 commit 610b291 Author: Christoph Hellwig <[email protected]> Date: Wed Jun 19 10:32:43 2024 -0700 xfs: fix freeing speculative preallocations for preallocated files xfs_can_free_eofblocks returns false for files that have persistent preallocations unless the force flag is passed and there are delayed blocks. This means it won't free delalloc reservations for files with persistent preallocations unless the force flag is set, and it will also free the persistent preallocations if the force flag is set and the file happens to have delayed allocations. Both of these are bad, so do away with the force flag and always free only post-EOF delayed allocations for files with the XFS_DIFLAG_PREALLOC or APPEND flags set. Signed-off-by: Christoph Hellwig <[email protected]> Reviewed-by: Darrick J. Wong <[email protected]> Signed-off-by: Chandan Babu R <[email protected]> Signed-off-by: CKI Backport Bot <[email protected]>
1 parent c7149de commit c549212

File tree

4 files changed

+28
-20
lines changed

4 files changed

+28
-20
lines changed

fs/xfs/xfs_bmap_util.c

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -630,13 +630,11 @@ xfs_bmap_punch_delalloc_range(
630630

631631
/*
632632
* Test whether it is appropriate to check an inode for and free post EOF
633-
* blocks. The 'force' parameter determines whether we should also consider
634-
* regular files that are marked preallocated or append-only.
633+
* blocks.
635634
*/
636635
bool
637636
xfs_can_free_eofblocks(
638-
struct xfs_inode *ip,
639-
bool force)
637+
struct xfs_inode *ip)
640638
{
641639
struct xfs_bmbt_irec imap;
642640
struct xfs_mount *mp = ip->i_mount;
@@ -670,11 +668,11 @@ xfs_can_free_eofblocks(
670668
return false;
671669

672670
/*
673-
* Do not free real preallocated or append-only files unless the file
674-
* has delalloc blocks and we are forced to remove them.
671+
* Only free real extents for inodes with persistent preallocations or
672+
* the append-only flag.
675673
*/
676674
if (ip->i_diflags & (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND))
677-
if (!force || ip->i_delayed_blks == 0)
675+
if (ip->i_delayed_blks == 0)
678676
return false;
679677

680678
/*
@@ -728,6 +726,22 @@ xfs_free_eofblocks(
728726
/* Wait on dio to ensure i_size has settled. */
729727
inode_dio_wait(VFS_I(ip));
730728

729+
/*
730+
* For preallocated files only free delayed allocations.
731+
*
732+
* Note that this means we also leave speculative preallocations in
733+
* place for preallocated files.
734+
*/
735+
if (ip->i_diflags & (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) {
736+
if (ip->i_delayed_blks) {
737+
xfs_bmap_punch_delalloc_range(ip,
738+
round_up(XFS_ISIZE(ip), mp->m_sb.sb_blocksize),
739+
LLONG_MAX);
740+
}
741+
xfs_inode_clear_eofblocks_tag(ip);
742+
return 0;
743+
}
744+
731745
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
732746
if (error) {
733747
ASSERT(xfs_is_shutdown(mp));
@@ -1041,7 +1055,7 @@ xfs_prepare_shift(
10411055
* Trim eofblocks to avoid shifting uninitialized post-eof preallocation
10421056
* into the accessible region of the file.
10431057
*/
1044-
if (xfs_can_free_eofblocks(ip, true)) {
1058+
if (xfs_can_free_eofblocks(ip)) {
10451059
error = xfs_free_eofblocks(ip);
10461060
if (error)
10471061
return error;

fs/xfs/xfs_bmap_util.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ int xfs_insert_file_space(struct xfs_inode *, xfs_off_t offset,
6363
xfs_off_t len);
6464

6565
/* EOF block manipulation functions */
66-
bool xfs_can_free_eofblocks(struct xfs_inode *ip, bool force);
66+
bool xfs_can_free_eofblocks(struct xfs_inode *ip);
6767
int xfs_free_eofblocks(struct xfs_inode *ip);
6868

6969
int xfs_swap_extents(struct xfs_inode *ip, struct xfs_inode *tip,

fs/xfs/xfs_icache.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1147,7 +1147,7 @@ xfs_inode_free_eofblocks(
11471147
}
11481148
*lockflags |= XFS_IOLOCK_EXCL;
11491149

1150-
if (xfs_can_free_eofblocks(ip, false))
1150+
if (xfs_can_free_eofblocks(ip))
11511151
return xfs_free_eofblocks(ip);
11521152

11531153
/* inode could be preallocated or append-only */

fs/xfs/xfs_inode.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1463,7 +1463,7 @@ xfs_release(
14631463
if (!xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL))
14641464
return 0;
14651465

1466-
if (xfs_can_free_eofblocks(ip, false)) {
1466+
if (xfs_can_free_eofblocks(ip)) {
14671467
/*
14681468
* Check if the inode is being opened, written and closed
14691469
* frequently and we have delayed allocation blocks outstanding
@@ -1679,15 +1679,13 @@ xfs_inode_needs_inactive(
16791679

16801680
/*
16811681
* This file isn't being freed, so check if there are post-eof blocks
1682-
* to free. @force is true because we are evicting an inode from the
1683-
* cache. Post-eof blocks must be freed, lest we end up with broken
1684-
* free space accounting.
1682+
* to free.
16851683
*
16861684
* Note: don't bother with iolock here since lockdep complains about
16871685
* acquiring it in reclaim context. We have the only reference to the
16881686
* inode at this point anyways.
16891687
*/
1690-
return xfs_can_free_eofblocks(ip, true);
1688+
return xfs_can_free_eofblocks(ip);
16911689
}
16921690

16931691
/*
@@ -1735,15 +1733,11 @@ xfs_inactive(
17351733

17361734
if (VFS_I(ip)->i_nlink != 0) {
17371735
/*
1738-
* force is true because we are evicting an inode from the
1739-
* cache. Post-eof blocks must be freed, lest we end up with
1740-
* broken free space accounting.
1741-
*
17421736
* Note: don't bother with iolock here since lockdep complains
17431737
* about acquiring it in reclaim context. We have the only
17441738
* reference to the inode at this point anyways.
17451739
*/
1746-
if (xfs_can_free_eofblocks(ip, true))
1740+
if (xfs_can_free_eofblocks(ip))
17471741
error = xfs_free_eofblocks(ip);
17481742

17491743
goto out;

0 commit comments

Comments
 (0)