diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_sync.c | 81 | ||||
| -rw-r--r-- | fs/xfs/xfs_inode.c | 11 | ||||
| -rw-r--r-- | fs/xfs/xfs_inode.h | 1 |
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 | */ | ||
| 709 | STATIC int | 738 | STATIC int |
| 710 | xfs_reclaim_inode( | 739 | xfs_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 | ||
| 797 | reclaim: | ||
| 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 | ||
| 2496 | static inline void | 2496 | void |
| 2497 | xfs_iunpin_wait( | 2497 | xfs_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 *); | |||
| 483 | void xfs_iext_realloc(xfs_inode_t *, int, int); | 483 | void xfs_iext_realloc(xfs_inode_t *, int, int); |
| 484 | void xfs_ipin(xfs_inode_t *); | 484 | void xfs_ipin(xfs_inode_t *); |
| 485 | void xfs_iunpin(xfs_inode_t *); | 485 | void xfs_iunpin(xfs_inode_t *); |
| 486 | void xfs_iunpin_wait(xfs_inode_t *); | ||
| 486 | int xfs_iflush(xfs_inode_t *, uint); | 487 | int xfs_iflush(xfs_inode_t *, uint); |
| 487 | void xfs_ichgtime(xfs_inode_t *, int); | 488 | void xfs_ichgtime(xfs_inode_t *, int); |
| 488 | void xfs_lock_inodes(xfs_inode_t **, int, uint); | 489 | void xfs_lock_inodes(xfs_inode_t **, int, uint); |
