aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6/xfs_sync.c
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2011-04-13 07:32:28 -0400
committerPatrick McHardy <kaber@trash.net>2011-04-13 07:32:28 -0400
commitb32e3dc7860d00124fa432dba09667e647cb9bcc (patch)
tree2fa6e56f389431dfb84609d3d7572cad76e88e71 /fs/xfs/linux-2.6/xfs_sync.c
parent6604271c5bc658a6067ed0c3deba4d89e0e50382 (diff)
parent96120d86fe302c006259baee9061eea9e1b9e486 (diff)
Merge branch 'master' of ssh://master.kernel.org/pub/scm/linux/kernel/git/kaber/nf-2.6
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_sync.c')
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.c35
1 files changed, 29 insertions, 6 deletions
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c
index e22f0057d21f..594cd822d84d 100644
--- a/fs/xfs/linux-2.6/xfs_sync.c
+++ b/fs/xfs/linux-2.6/xfs_sync.c
@@ -425,8 +425,7 @@ xfs_quiesce_attr(
425 /* Push the superblock and write an unmount record */ 425 /* Push the superblock and write an unmount record */
426 error = xfs_log_sbcount(mp, 1); 426 error = xfs_log_sbcount(mp, 1);
427 if (error) 427 if (error)
428 xfs_fs_cmn_err(CE_WARN, mp, 428 xfs_warn(mp, "xfs_attr_quiesce: failed to log sb changes. "
429 "xfs_attr_quiesce: failed to log sb changes. "
430 "Frozen image may not be consistent."); 429 "Frozen image may not be consistent.");
431 xfs_log_unmount_write(mp); 430 xfs_log_unmount_write(mp);
432 xfs_unmountfs_writesb(mp); 431 xfs_unmountfs_writesb(mp);
@@ -762,8 +761,10 @@ xfs_reclaim_inode(
762 struct xfs_perag *pag, 761 struct xfs_perag *pag,
763 int sync_mode) 762 int sync_mode)
764{ 763{
765 int error = 0; 764 int error;
766 765
766restart:
767 error = 0;
767 xfs_ilock(ip, XFS_ILOCK_EXCL); 768 xfs_ilock(ip, XFS_ILOCK_EXCL);
768 if (!xfs_iflock_nowait(ip)) { 769 if (!xfs_iflock_nowait(ip)) {
769 if (!(sync_mode & SYNC_WAIT)) 770 if (!(sync_mode & SYNC_WAIT))
@@ -789,9 +790,31 @@ xfs_reclaim_inode(
789 if (xfs_inode_clean(ip)) 790 if (xfs_inode_clean(ip))
790 goto reclaim; 791 goto reclaim;
791 792
792 /* Now we have an inode that needs flushing */ 793 /*
793 error = xfs_iflush(ip, sync_mode); 794 * Now we have an inode that needs flushing.
795 *
796 * We do a nonblocking flush here even if we are doing a SYNC_WAIT
797 * reclaim as we can deadlock with inode cluster removal.
798 * xfs_ifree_cluster() can lock the inode buffer before it locks the
799 * ip->i_lock, and we are doing the exact opposite here. As a result,
800 * doing a blocking xfs_itobp() to get the cluster buffer will result
801 * in an ABBA deadlock with xfs_ifree_cluster().
802 *
803 * As xfs_ifree_cluser() must gather all inodes that are active in the
804 * cache to mark them stale, if we hit this case we don't actually want
805 * to do IO here - we want the inode marked stale so we can simply
806 * reclaim it. Hence if we get an EAGAIN error on a SYNC_WAIT flush,
807 * just unlock the inode, back off and try again. Hopefully the next
808 * pass through will see the stale flag set on the inode.
809 */
810 error = xfs_iflush(ip, SYNC_TRYLOCK | sync_mode);
794 if (sync_mode & SYNC_WAIT) { 811 if (sync_mode & SYNC_WAIT) {
812 if (error == EAGAIN) {
813 xfs_iunlock(ip, XFS_ILOCK_EXCL);
814 /* backoff longer than in xfs_ifree_cluster */
815 delay(2);
816 goto restart;
817 }
795 xfs_iflock(ip); 818 xfs_iflock(ip);
796 goto reclaim; 819 goto reclaim;
797 } 820 }
@@ -806,7 +829,7 @@ xfs_reclaim_inode(
806 * pass on the error. 829 * pass on the error.
807 */ 830 */
808 if (error && error != EAGAIN && !XFS_FORCED_SHUTDOWN(ip->i_mount)) { 831 if (error && error != EAGAIN && !XFS_FORCED_SHUTDOWN(ip->i_mount)) {
809 xfs_fs_cmn_err(CE_WARN, ip->i_mount, 832 xfs_warn(ip->i_mount,
810 "inode 0x%llx background reclaim flush failed with %d", 833 "inode 0x%llx background reclaim flush failed with %d",
811 (long long)ip->i_ino, error); 834 (long long)ip->i_ino, error);
812 } 835 }