aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6/xfs_sync.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_sync.c')
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.c81
1 files changed, 62 insertions, 19 deletions
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c
index c9b863eacab7..525260c7617f 100644
--- a/fs/xfs/linux-2.6/xfs_sync.c
+++ b/fs/xfs/linux-2.6/xfs_sync.c
@@ -706,12 +706,43 @@ __xfs_inode_clear_reclaim_tag(
706 XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG); 706 XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG);
707} 707}
708 708
709/*
710 * Inodes in different states need to be treated differently, and the return
711 * value of xfs_iflush is not sufficient to get this right. The following table
712 * lists the inode states and the reclaim actions necessary for non-blocking
713 * reclaim:
714 *
715 *
716 * inode state iflush ret required action
717 * --------------- ---------- ---------------
718 * bad - reclaim
719 * shutdown EIO unpin and reclaim
720 * clean, unpinned 0 reclaim
721 * stale, unpinned 0 reclaim
722 * clean, pinned(*) 0 unpin and reclaim
723 * stale, pinned 0 unpin and reclaim
724 * dirty, async 0 block on flush lock, reclaim
725 * dirty, sync flush 0 block on flush lock, reclaim
726 *
727 * (*) dgc: I don't think the clean, pinned state is possible but it gets
728 * handled anyway given the order of checks implemented.
729 *
730 * Hence the order of actions after gaining the locks should be:
731 * bad => reclaim
732 * shutdown => unpin and reclaim
733 * pinned => unpin
734 * stale => reclaim
735 * clean => reclaim
736 * dirty => flush, wait and reclaim
737 */
709STATIC int 738STATIC int
710xfs_reclaim_inode( 739xfs_reclaim_inode(
711 struct xfs_inode *ip, 740 struct xfs_inode *ip,
712 struct xfs_perag *pag, 741 struct xfs_perag *pag,
713 int sync_mode) 742 int sync_mode)
714{ 743{
744 int error;
745
715 /* 746 /*
716 * The radix tree lock here protects a thread in xfs_iget from racing 747 * The radix tree lock here protects a thread in xfs_iget from racing
717 * with us starting reclaim on the inode. Once we have the 748 * with us starting reclaim on the inode. Once we have the
@@ -729,30 +760,42 @@ xfs_reclaim_inode(
729 spin_unlock(&ip->i_flags_lock); 760 spin_unlock(&ip->i_flags_lock);
730 write_unlock(&pag->pag_ici_lock); 761 write_unlock(&pag->pag_ici_lock);
731 762
732 /*
733 * If the inode is still dirty, then flush it out. If the inode
734 * is not in the AIL, then it will be OK to flush it delwri as
735 * long as xfs_iflush() does not keep any references to the inode.
736 * We leave that decision up to xfs_iflush() since it has the
737 * knowledge of whether it's OK to simply do a delwri flush of
738 * the inode or whether we need to wait until the inode is
739 * pulled from the AIL.
740 * We get the flush lock regardless, though, just to make sure
741 * we don't free it while it is being flushed.
742 */
743 xfs_ilock(ip, XFS_ILOCK_EXCL); 763 xfs_ilock(ip, XFS_ILOCK_EXCL);
744 xfs_iflock(ip); 764 xfs_iflock(ip);
745 765
746 /* 766 if (is_bad_inode(VFS_I(ip)))
747 * In the case of a forced shutdown we rely on xfs_iflush() to 767 goto reclaim;
748 * wait for the inode to be unpinned before returning an error. 768 if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
749 */ 769 xfs_iunpin_wait(ip);
750 if (!is_bad_inode(VFS_I(ip)) && xfs_iflush(ip, sync_mode) == 0) { 770 goto reclaim;
751 /* synchronize with xfs_iflush_done */ 771 }
752 xfs_iflock(ip); 772 if (xfs_ipincount(ip))
753 xfs_ifunlock(ip); 773 xfs_iunpin_wait(ip);
774 if (xfs_iflags_test(ip, XFS_ISTALE))
775 goto reclaim;
776 if (xfs_inode_clean(ip))
777 goto reclaim;
778
779 /* Now we have an inode that needs flushing */
780 error = xfs_iflush(ip, sync_mode);
781 if (!error) {
782 switch(sync_mode) {
783 case XFS_IFLUSH_DELWRI_ELSE_ASYNC:
784 case XFS_IFLUSH_DELWRI:
785 case XFS_IFLUSH_ASYNC:
786 case XFS_IFLUSH_DELWRI_ELSE_SYNC:
787 case XFS_IFLUSH_SYNC:
788 /* IO issued, synchronise with IO completion */
789 xfs_iflock(ip);
790 break;
791 default:
792 ASSERT(0);
793 break;
794 }
754 } 795 }
755 796
797reclaim:
798 xfs_ifunlock(ip);
756 xfs_iunlock(ip, XFS_ILOCK_EXCL); 799 xfs_iunlock(ip, XFS_ILOCK_EXCL);
757 xfs_ireclaim(ip); 800 xfs_ireclaim(ip);
758 return 0; 801 return 0;