aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorBrian Foster <bfoster@redhat.com>2012-11-06 09:50:40 -0500
committerBen Myers <bpm@sgi.com>2012-11-08 16:22:34 -0500
commit72b53efa4a6125a4c334871c58268c430605819a (patch)
tree8991dfdb6eb1f1abe83258cf3b6fb6617bf45fd5 /fs/xfs
parenta454f7428ffa03c8e1321124d9074101b7290be6 (diff)
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>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_inode.c37
-rw-r--r--fs/xfs/xfs_inode.h1
-rw-r--r--fs/xfs/xfs_vnodeops.c19
3 files changed, 45 insertions, 12 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 965598eb308c..7449cb943efd 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -3912,3 +3912,40 @@ xfs_iext_irec_update_extoffs(
3912 ifp->if_u1.if_ext_irec[i].er_extoff += ext_diff; 3912 ifp->if_u1.if_ext_irec[i].er_extoff += ext_diff;
3913 } 3913 }
3914} 3914}
3915
3916/*
3917 * Test whether it is appropriate to check an inode for and free post EOF
3918 * blocks. The 'force' parameter determines whether we should also consider
3919 * regular files that are marked preallocated or append-only.
3920 */
3921bool
3922xfs_can_free_eofblocks(struct xfs_inode *ip, bool force)
3923{
3924 /* prealloc/delalloc exists only on regular files */
3925 if (!S_ISREG(ip->i_d.di_mode))
3926 return false;
3927
3928 /*
3929 * Zero sized files with no cached pages and delalloc blocks will not
3930 * have speculative prealloc/delalloc blocks to remove.
3931 */
3932 if (VFS_I(ip)->i_size == 0 &&
3933 VN_CACHED(VFS_I(ip)) == 0 &&
3934 ip->i_delayed_blks == 0)
3935 return false;
3936
3937 /* If we haven't read in the extent list, then don't do it now. */
3938 if (!(ip->i_df.if_flags & XFS_IFEXTENTS))
3939 return false;
3940
3941 /*
3942 * Do not free real preallocated or append-only files unless the file
3943 * has delalloc blocks and we are forced to remove them.
3944 */
3945 if (ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND))
3946 if (!force || ip->i_delayed_blks == 0)
3947 return false;
3948
3949 return true;
3950}
3951
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 1fc2065e010b..21b4de3df716 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -585,6 +585,7 @@ void xfs_iext_irec_compact(xfs_ifork_t *);
585void xfs_iext_irec_compact_pages(xfs_ifork_t *); 585void xfs_iext_irec_compact_pages(xfs_ifork_t *);
586void xfs_iext_irec_compact_full(xfs_ifork_t *); 586void xfs_iext_irec_compact_full(xfs_ifork_t *);
587void xfs_iext_irec_update_extoffs(xfs_ifork_t *, int, int); 587void xfs_iext_irec_update_extoffs(xfs_ifork_t *, int, int);
588bool xfs_can_free_eofblocks(struct xfs_inode *, bool);
588 589
589#define xfs_ipincount(ip) ((unsigned int) atomic_read(&ip->i_pincount)) 590#define xfs_ipincount(ip) ((unsigned int) atomic_read(&ip->i_pincount))
590 591
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index e6e1d11dfdf2..c4c153900205 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -436,11 +436,7 @@ xfs_release(
436 if (ip->i_d.di_nlink == 0) 436 if (ip->i_d.di_nlink == 0)
437 return 0; 437 return 0;
438 438
439 if ((S_ISREG(ip->i_d.di_mode) && 439 if (xfs_can_free_eofblocks(ip, false)) {
440 (VFS_I(ip)->i_size > 0 ||
441 (VN_CACHED(VFS_I(ip)) > 0 || ip->i_delayed_blks > 0)) &&
442 (ip->i_df.if_flags & XFS_IFEXTENTS)) &&
443 (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) {
444 440
445 /* 441 /*
446 * If we can't get the iolock just skip truncating the blocks 442 * If we can't get the iolock just skip truncating the blocks
@@ -516,13 +512,12 @@ xfs_inactive(
516 goto out; 512 goto out;
517 513
518 if (ip->i_d.di_nlink != 0) { 514 if (ip->i_d.di_nlink != 0) {
519 if ((S_ISREG(ip->i_d.di_mode) && 515 /*
520 (VFS_I(ip)->i_size > 0 || 516 * force is true because we are evicting an inode from the
521 (VN_CACHED(VFS_I(ip)) > 0 || ip->i_delayed_blks > 0)) && 517 * cache. Post-eof blocks must be freed, lest we end up with
522 (ip->i_df.if_flags & XFS_IFEXTENTS) && 518 * broken free space accounting.
523 (!(ip->i_d.di_flags & 519 */
524 (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) || 520 if (xfs_can_free_eofblocks(ip, true)) {
525 ip->i_delayed_blks != 0))) {
526 error = xfs_free_eofblocks(mp, ip, false); 521 error = xfs_free_eofblocks(mp, ip, false);
527 if (error) 522 if (error)
528 return VN_INACTIVE_CACHE; 523 return VN_INACTIVE_CACHE;