aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.c81
-rw-r--r--fs/xfs/xfs_inode.c11
-rw-r--r--fs/xfs/xfs_inode.h1
3 files changed, 64 insertions, 29 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;
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index d0d1b5a05183..8d0666dd170a 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -2493,7 +2493,7 @@ __xfs_iunpin_wait(
2493 wait_event(ip->i_ipin_wait, (atomic_read(&ip->i_pincount) == 0)); 2493 wait_event(ip->i_ipin_wait, (atomic_read(&ip->i_pincount) == 0));
2494} 2494}
2495 2495
2496static inline void 2496void
2497xfs_iunpin_wait( 2497xfs_iunpin_wait(
2498 xfs_inode_t *ip) 2498 xfs_inode_t *ip)
2499{ 2499{
@@ -2849,15 +2849,6 @@ xfs_iflush(
2849 mp = ip->i_mount; 2849 mp = ip->i_mount;
2850 2850
2851 /* 2851 /*
2852 * If the inode isn't dirty, then just release the inode flush lock and
2853 * do nothing.
2854 */
2855 if (xfs_inode_clean(ip)) {
2856 xfs_ifunlock(ip);
2857 return 0;
2858 }
2859
2860 /*
2861 * We can't flush the inode until it is unpinned, so wait for it if we 2852 * We can't flush the inode until it is unpinned, so wait for it if we
2862 * are allowed to block. We know noone new can pin it, because we are 2853 * are allowed to block. We know noone new can pin it, because we are
2863 * holding the inode lock shared and you need to hold it exclusively to 2854 * holding the inode lock shared and you need to hold it exclusively to
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index ec1f28c4fc4f..8b618ea4d692 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -483,6 +483,7 @@ int xfs_iunlink(struct xfs_trans *, xfs_inode_t *);
483void xfs_iext_realloc(xfs_inode_t *, int, int); 483void xfs_iext_realloc(xfs_inode_t *, int, int);
484void xfs_ipin(xfs_inode_t *); 484void xfs_ipin(xfs_inode_t *);
485void xfs_iunpin(xfs_inode_t *); 485void xfs_iunpin(xfs_inode_t *);
486void xfs_iunpin_wait(xfs_inode_t *);
486int xfs_iflush(xfs_inode_t *, uint); 487int xfs_iflush(xfs_inode_t *, uint);
487void xfs_ichgtime(xfs_inode_t *, int); 488void xfs_ichgtime(xfs_inode_t *, int);
488void xfs_lock_inodes(xfs_inode_t **, int, uint); 489void xfs_lock_inodes(xfs_inode_t **, int, uint);