diff options
Diffstat (limited to 'fs/xfs/xfs_sync.c')
-rw-r--r-- | fs/xfs/xfs_sync.c | 29 |
1 files changed, 15 insertions, 14 deletions
diff --git a/fs/xfs/xfs_sync.c b/fs/xfs/xfs_sync.c index 7b2bccc4d67b..468c3c0a4f9f 100644 --- a/fs/xfs/xfs_sync.c +++ b/fs/xfs/xfs_sync.c | |||
@@ -648,10 +648,6 @@ xfs_reclaim_inode_grab( | |||
648 | * (*) dgc: I don't think the clean, pinned state is possible but it gets | 648 | * (*) dgc: I don't think the clean, pinned state is possible but it gets |
649 | * handled anyway given the order of checks implemented. | 649 | * handled anyway given the order of checks implemented. |
650 | * | 650 | * |
651 | * As can be seen from the table, the return value of xfs_iflush() is not | ||
652 | * sufficient to correctly decide the reclaim action here. The checks in | ||
653 | * xfs_iflush() might look like duplicates, but they are not. | ||
654 | * | ||
655 | * Also, because we get the flush lock first, we know that any inode that has | 651 | * Also, because we get the flush lock first, we know that any inode that has |
656 | * been flushed delwri has had the flush completed by the time we check that | 652 | * been flushed delwri has had the flush completed by the time we check that |
657 | * the inode is clean. | 653 | * the inode is clean. |
@@ -679,7 +675,8 @@ xfs_reclaim_inode( | |||
679 | struct xfs_perag *pag, | 675 | struct xfs_perag *pag, |
680 | int sync_mode) | 676 | int sync_mode) |
681 | { | 677 | { |
682 | int error; | 678 | struct xfs_buf *bp = NULL; |
679 | int error; | ||
683 | 680 | ||
684 | restart: | 681 | restart: |
685 | error = 0; | 682 | error = 0; |
@@ -728,29 +725,33 @@ restart: | |||
728 | /* | 725 | /* |
729 | * Now we have an inode that needs flushing. | 726 | * Now we have an inode that needs flushing. |
730 | * | 727 | * |
731 | * We do a nonblocking flush here even if we are doing a SYNC_WAIT | 728 | * Note that xfs_iflush will never block on the inode buffer lock, as |
732 | * reclaim as we can deadlock with inode cluster removal. | ||
733 | * xfs_ifree_cluster() can lock the inode buffer before it locks the | 729 | * xfs_ifree_cluster() can lock the inode buffer before it locks the |
734 | * ip->i_lock, and we are doing the exact opposite here. As a result, | 730 | * ip->i_lock, and we are doing the exact opposite here. As a result, |
735 | * doing a blocking xfs_itobp() to get the cluster buffer will result | 731 | * doing a blocking xfs_itobp() to get the cluster buffer would result |
736 | * in an ABBA deadlock with xfs_ifree_cluster(). | 732 | * in an ABBA deadlock with xfs_ifree_cluster(). |
737 | * | 733 | * |
738 | * As xfs_ifree_cluser() must gather all inodes that are active in the | 734 | * As xfs_ifree_cluser() must gather all inodes that are active in the |
739 | * cache to mark them stale, if we hit this case we don't actually want | 735 | * cache to mark them stale, if we hit this case we don't actually want |
740 | * to do IO here - we want the inode marked stale so we can simply | 736 | * to do IO here - we want the inode marked stale so we can simply |
741 | * reclaim it. Hence if we get an EAGAIN error on a SYNC_WAIT flush, | 737 | * reclaim it. Hence if we get an EAGAIN error here, just unlock the |
742 | * just unlock the inode, back off and try again. Hopefully the next | 738 | * inode, back off and try again. Hopefully the next pass through will |
743 | * pass through will see the stale flag set on the inode. | 739 | * see the stale flag set on the inode. |
744 | */ | 740 | */ |
745 | error = xfs_iflush(ip, SYNC_TRYLOCK | sync_mode); | 741 | error = xfs_iflush(ip, &bp); |
746 | if (error == EAGAIN) { | 742 | if (error == EAGAIN) { |
747 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 743 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
748 | /* backoff longer than in xfs_ifree_cluster */ | 744 | /* backoff longer than in xfs_ifree_cluster */ |
749 | delay(2); | 745 | delay(2); |
750 | goto restart; | 746 | goto restart; |
751 | } | 747 | } |
752 | xfs_iflock(ip); | ||
753 | 748 | ||
749 | if (!error) { | ||
750 | error = xfs_bwrite(bp); | ||
751 | xfs_buf_relse(bp); | ||
752 | } | ||
753 | |||
754 | xfs_iflock(ip); | ||
754 | reclaim: | 755 | reclaim: |
755 | xfs_ifunlock(ip); | 756 | xfs_ifunlock(ip); |
756 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 757 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |