Skip to content

Commit 2bc2d49

Browse files
Christoph Hellwiggregkh
authored andcommitted
xfs: fix freeing speculative preallocations for preallocated files
commit 610b291 upstream. 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 <hch@lst.de> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Chandan Babu R <chandanbabu@kernel.org> Signed-off-by: Catherine Hoang <catherine.hoang@oracle.com> Acked-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 740a427 commit 2bc2d49

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
@@ -636,13 +636,11 @@ xfs_bmap_punch_delalloc_range(
636636

637637
/*
638638
* Test whether it is appropriate to check an inode for and free post EOF
639-
* blocks. The 'force' parameter determines whether we should also consider
640-
* regular files that are marked preallocated or append-only.
639+
* blocks.
641640
*/
642641
bool
643642
xfs_can_free_eofblocks(
644-
struct xfs_inode *ip,
645-
bool force)
643+
struct xfs_inode *ip)
646644
{
647645
struct xfs_bmbt_irec imap;
648646
struct xfs_mount *mp = ip->i_mount;
@@ -676,11 +674,11 @@ xfs_can_free_eofblocks(
676674
return false;
677675

678676
/*
679-
* Do not free real preallocated or append-only files unless the file
680-
* has delalloc blocks and we are forced to remove them.
677+
* Only free real extents for inodes with persistent preallocations or
678+
* the append-only flag.
681679
*/
682680
if (ip->i_diflags & (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND))
683-
if (!force || ip->i_delayed_blks == 0)
681+
if (ip->i_delayed_blks == 0)
684682
return false;
685683

686684
/*
@@ -734,6 +732,22 @@ xfs_free_eofblocks(
734732
/* Wait on dio to ensure i_size has settled. */
735733
inode_dio_wait(VFS_I(ip));
736734

735+
/*
736+
* For preallocated files only free delayed allocations.
737+
*
738+
* Note that this means we also leave speculative preallocations in
739+
* place for preallocated files.
740+
*/
741+
if (ip->i_diflags & (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) {
742+
if (ip->i_delayed_blks) {
743+
xfs_bmap_punch_delalloc_range(ip,
744+
round_up(XFS_ISIZE(ip), mp->m_sb.sb_blocksize),
745+
LLONG_MAX);
746+
}
747+
xfs_inode_clear_eofblocks_tag(ip);
748+
return 0;
749+
}
750+
737751
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
738752
if (error) {
739753
ASSERT(xfs_is_shutdown(mp));
@@ -1048,7 +1062,7 @@ xfs_prepare_shift(
10481062
* Trim eofblocks to avoid shifting uninitialized post-eof preallocation
10491063
* into the accessible region of the file.
10501064
*/
1051-
if (xfs_can_free_eofblocks(ip, true)) {
1065+
if (xfs_can_free_eofblocks(ip)) {
10521066
error = xfs_free_eofblocks(ip);
10531067
if (error)
10541068
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
@@ -1149,7 +1149,7 @@ xfs_inode_free_eofblocks(
11491149
}
11501150
*lockflags |= XFS_IOLOCK_EXCL;
11511151

1152-
if (xfs_can_free_eofblocks(ip, false))
1152+
if (xfs_can_free_eofblocks(ip))
11531153
return xfs_free_eofblocks(ip);
11541154

11551155
/* 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
@@ -1469,7 +1469,7 @@ xfs_release(
14691469
if (!xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL))
14701470
return 0;
14711471

1472-
if (xfs_can_free_eofblocks(ip, false)) {
1472+
if (xfs_can_free_eofblocks(ip)) {
14731473
/*
14741474
* Check if the inode is being opened, written and closed
14751475
* frequently and we have delayed allocation blocks outstanding
@@ -1685,15 +1685,13 @@ xfs_inode_needs_inactive(
16851685

16861686
/*
16871687
* This file isn't being freed, so check if there are post-eof blocks
1688-
* to free. @force is true because we are evicting an inode from the
1689-
* cache. Post-eof blocks must be freed, lest we end up with broken
1690-
* free space accounting.
1688+
* to free.
16911689
*
16921690
* Note: don't bother with iolock here since lockdep complains about
16931691
* acquiring it in reclaim context. We have the only reference to the
16941692
* inode at this point anyways.
16951693
*/
1696-
return xfs_can_free_eofblocks(ip, true);
1694+
return xfs_can_free_eofblocks(ip);
16971695
}
16981696

16991697
/*
@@ -1741,15 +1739,11 @@ xfs_inactive(
17411739

17421740
if (VFS_I(ip)->i_nlink != 0) {
17431741
/*
1744-
* force is true because we are evicting an inode from the
1745-
* cache. Post-eof blocks must be freed, lest we end up with
1746-
* broken free space accounting.
1747-
*
17481742
* Note: don't bother with iolock here since lockdep complains
17491743
* about acquiring it in reclaim context. We have the only
17501744
* reference to the inode at this point anyways.
17511745
*/
1752-
if (xfs_can_free_eofblocks(ip, true))
1746+
if (xfs_can_free_eofblocks(ip))
17531747
error = xfs_free_eofblocks(ip);
17541748

17551749
goto out;

0 commit comments

Comments
 (0)