diff options
author | Patrick McHardy <kaber@trash.net> | 2011-04-13 07:32:28 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2011-04-13 07:32:28 -0400 |
commit | b32e3dc7860d00124fa432dba09667e647cb9bcc (patch) | |
tree | 2fa6e56f389431dfb84609d3d7572cad76e88e71 /fs/xfs/linux-2.6/xfs_sync.c | |
parent | 6604271c5bc658a6067ed0c3deba4d89e0e50382 (diff) | |
parent | 96120d86fe302c006259baee9061eea9e1b9e486 (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.c | 35 |
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 | ||
766 | restart: | ||
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 | } |