xfs: create helper to check whether to free eofblocks on inode
This check is used in multiple places to determine whether we should check for (and potentially free) post EOF blocks on an inode. Add a helper to consolidate the check. Note that when we remove an inode from the cache (xfs_inactive()), we are required to trim post-EOF blocks even if the inode is marked preallocated or append-only to maintain correct space accounting. The 'force' parameter to xfs_can_free_eofblocks() specifies whether we should ignore the prealloc/append-only status of the inode. Signed-off-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Mark Tinguely <tinguely@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
This commit is contained in:
parent
a454f7428f
commit
72b53efa4a
|
@ -3912,3 +3912,40 @@ xfs_iext_irec_update_extoffs(
|
|||
ifp->if_u1.if_ext_irec[i].er_extoff += ext_diff;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether it is appropriate to check an inode for and free post EOF
|
||||
* blocks. The 'force' parameter determines whether we should also consider
|
||||
* regular files that are marked preallocated or append-only.
|
||||
*/
|
||||
bool
|
||||
xfs_can_free_eofblocks(struct xfs_inode *ip, bool force)
|
||||
{
|
||||
/* prealloc/delalloc exists only on regular files */
|
||||
if (!S_ISREG(ip->i_d.di_mode))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Zero sized files with no cached pages and delalloc blocks will not
|
||||
* have speculative prealloc/delalloc blocks to remove.
|
||||
*/
|
||||
if (VFS_I(ip)->i_size == 0 &&
|
||||
VN_CACHED(VFS_I(ip)) == 0 &&
|
||||
ip->i_delayed_blks == 0)
|
||||
return false;
|
||||
|
||||
/* If we haven't read in the extent list, then don't do it now. */
|
||||
if (!(ip->i_df.if_flags & XFS_IFEXTENTS))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Do not free real preallocated or append-only files unless the file
|
||||
* has delalloc blocks and we are forced to remove them.
|
||||
*/
|
||||
if (ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND))
|
||||
if (!force || ip->i_delayed_blks == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -585,6 +585,7 @@ void xfs_iext_irec_compact(xfs_ifork_t *);
|
|||
void xfs_iext_irec_compact_pages(xfs_ifork_t *);
|
||||
void xfs_iext_irec_compact_full(xfs_ifork_t *);
|
||||
void xfs_iext_irec_update_extoffs(xfs_ifork_t *, int, int);
|
||||
bool xfs_can_free_eofblocks(struct xfs_inode *, bool);
|
||||
|
||||
#define xfs_ipincount(ip) ((unsigned int) atomic_read(&ip->i_pincount))
|
||||
|
||||
|
|
|
@ -436,11 +436,7 @@ xfs_release(
|
|||
if (ip->i_d.di_nlink == 0)
|
||||
return 0;
|
||||
|
||||
if ((S_ISREG(ip->i_d.di_mode) &&
|
||||
(VFS_I(ip)->i_size > 0 ||
|
||||
(VN_CACHED(VFS_I(ip)) > 0 || ip->i_delayed_blks > 0)) &&
|
||||
(ip->i_df.if_flags & XFS_IFEXTENTS)) &&
|
||||
(!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) {
|
||||
if (xfs_can_free_eofblocks(ip, false)) {
|
||||
|
||||
/*
|
||||
* If we can't get the iolock just skip truncating the blocks
|
||||
|
@ -516,13 +512,12 @@ xfs_inactive(
|
|||
goto out;
|
||||
|
||||
if (ip->i_d.di_nlink != 0) {
|
||||
if ((S_ISREG(ip->i_d.di_mode) &&
|
||||
(VFS_I(ip)->i_size > 0 ||
|
||||
(VN_CACHED(VFS_I(ip)) > 0 || ip->i_delayed_blks > 0)) &&
|
||||
(ip->i_df.if_flags & XFS_IFEXTENTS) &&
|
||||
(!(ip->i_d.di_flags &
|
||||
(XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) ||
|
||||
ip->i_delayed_blks != 0))) {
|
||||
/*
|
||||
* force is true because we are evicting an inode from the
|
||||
* cache. Post-eof blocks must be freed, lest we end up with
|
||||
* broken free space accounting.
|
||||
*/
|
||||
if (xfs_can_free_eofblocks(ip, true)) {
|
||||
error = xfs_free_eofblocks(mp, ip, false);
|
||||
if (error)
|
||||
return VN_INACTIVE_CACHE;
|
||||
|
|
Loading…
Reference in New Issue