diff options
author | Brian Foster <bfoster@redhat.com> | 2014-07-24 19:40:22 +1000 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2014-07-24 19:40:22 +1000 |
commit | 5400da7dc0862d73523691038c044535f518a57f (patch) | |
tree | 574a664859a18888f8d3d6cf2b108c8c61d76736 /fs/xfs/xfs_icache.c | |
parent | 2451337dd043901b5270b7586942abe564443e3d (diff) | |
download | op-kernel-dev-5400da7dc0862d73523691038c044535f518a57f.zip op-kernel-dev-5400da7dc0862d73523691038c044535f518a57f.tar.gz |
xfs: add scan owner field to xfs_eofblocks
From: Brian Foster <bfoster@redhat.com>
The scan owner field represents an optional inode number that is
responsible for the current scan. The purpose is to identify that an
inode is under iolock and as such, the iolock shouldn't be attempted
when trimming eofblocks. This is an internal only field.
Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs/xfs_icache.c')
-rw-r--r-- | fs/xfs/xfs_icache.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index 08ba4c6..6e522ff 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -1211,6 +1211,9 @@ xfs_inode_free_eofblocks( { int ret; struct xfs_eofblocks *eofb = args; + bool need_iolock = true; + + ASSERT(!eofb || (eofb && eofb->eof_scan_owner != 0)); if (!xfs_can_free_eofblocks(ip, false)) { /* inode could be preallocated or append-only */ @@ -1235,9 +1238,17 @@ xfs_inode_free_eofblocks( if (eofb->eof_flags & XFS_EOF_FLAGS_MINFILESIZE && XFS_ISIZE(ip) < eofb->eof_min_file_size) return 0; + + /* + * A scan owner implies we already hold the iolock. Skip it in + * xfs_free_eofblocks() to avoid deadlock. This also eliminates + * the possibility of EAGAIN being returned. + */ + if (eofb->eof_scan_owner == ip->i_ino) + need_iolock = false; } - ret = xfs_free_eofblocks(ip->i_mount, ip, true); + ret = xfs_free_eofblocks(ip->i_mount, ip, need_iolock); /* don't revisit the inode if we're not waiting */ if (ret == -EAGAIN && !(flags & SYNC_WAIT)) |