aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2010-09-24 05:51:50 -0400
committerAlex Elder <aelder@sgi.com>2010-10-18 16:07:54 -0400
commite3a20c0b02e1704ab115dfa9d012caf0fbc45ed0 (patch)
tree77cd4c9129b8b6fc85b0e9005a82088df9ed752f /fs/xfs
parent78ae5256768b91f25ce7a4eb9f56d563e302cc10 (diff)
xfs: batch inode reclaim lookup
Batch and optimise the per-ag inode lookup for reclaim to minimise scanning overhead. This involves gang lookups on the radix trees to get multiple inodes during each tree walk, and tighter validation of what inodes can be reclaimed without blocking befor we take any locks. This is based on ideas suggested in a proof-of-concept patch posted by Nick Piggin. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.c110
1 files changed, 77 insertions, 33 deletions
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c
index 0ed3d0ae3c28..754bc591a247 100644
--- a/fs/xfs/linux-2.6/xfs_sync.c
+++ b/fs/xfs/linux-2.6/xfs_sync.c
@@ -631,6 +631,43 @@ __xfs_inode_clear_reclaim_tag(
631} 631}
632 632
633/* 633/*
634 * Grab the inode for reclaim exclusively.
635 * Return 0 if we grabbed it, non-zero otherwise.
636 */
637STATIC int
638xfs_reclaim_inode_grab(
639 struct xfs_inode *ip,
640 int flags)
641{
642
643 /*
644 * do some unlocked checks first to avoid unnecceary lock traffic.
645 * The first is a flush lock check, the second is a already in reclaim
646 * check. Only do these checks if we are not going to block on locks.
647 */
648 if ((flags & SYNC_TRYLOCK) &&
649 (!ip->i_flush.done || __xfs_iflags_test(ip, XFS_IRECLAIM))) {
650 return 1;
651 }
652
653 /*
654 * The radix tree lock here protects a thread in xfs_iget from racing
655 * with us starting reclaim on the inode. Once we have the
656 * XFS_IRECLAIM flag set it will not touch us.
657 */
658 spin_lock(&ip->i_flags_lock);
659 ASSERT_ALWAYS(__xfs_iflags_test(ip, XFS_IRECLAIMABLE));
660 if (__xfs_iflags_test(ip, XFS_IRECLAIM)) {
661 /* ignore as it is already under reclaim */
662 spin_unlock(&ip->i_flags_lock);
663 return 1;
664 }
665 __xfs_iflags_set(ip, XFS_IRECLAIM);
666 spin_unlock(&ip->i_flags_lock);
667 return 0;
668}
669
670/*
634 * Inodes in different states need to be treated differently, and the return 671 * Inodes in different states need to be treated differently, and the return
635 * value of xfs_iflush is not sufficient to get this right. The following table 672 * value of xfs_iflush is not sufficient to get this right. The following table
636 * lists the inode states and the reclaim actions necessary for non-blocking 673 * lists the inode states and the reclaim actions necessary for non-blocking
@@ -688,23 +725,6 @@ xfs_reclaim_inode(
688{ 725{
689 int error = 0; 726 int error = 0;
690 727
691 /*
692 * The radix tree lock here protects a thread in xfs_iget from racing
693 * with us starting reclaim on the inode. Once we have the
694 * XFS_IRECLAIM flag set it will not touch us.
695 */
696 spin_lock(&ip->i_flags_lock);
697 ASSERT_ALWAYS(__xfs_iflags_test(ip, XFS_IRECLAIMABLE));
698 if (__xfs_iflags_test(ip, XFS_IRECLAIM)) {
699 /* ignore as it is already under reclaim */
700 spin_unlock(&ip->i_flags_lock);
701 write_unlock(&pag->pag_ici_lock);
702 return 0;
703 }
704 __xfs_iflags_set(ip, XFS_IRECLAIM);
705 spin_unlock(&ip->i_flags_lock);
706 write_unlock(&pag->pag_ici_lock);
707
708 xfs_ilock(ip, XFS_ILOCK_EXCL); 728 xfs_ilock(ip, XFS_ILOCK_EXCL);
709 if (!xfs_iflock_nowait(ip)) { 729 if (!xfs_iflock_nowait(ip)) {
710 if (!(sync_mode & SYNC_WAIT)) 730 if (!(sync_mode & SYNC_WAIT))
@@ -822,16 +842,19 @@ xfs_reclaim_inodes_ag(
822 while ((pag = xfs_perag_get_tag(mp, ag, XFS_ICI_RECLAIM_TAG))) { 842 while ((pag = xfs_perag_get_tag(mp, ag, XFS_ICI_RECLAIM_TAG))) {
823 unsigned long first_index = 0; 843 unsigned long first_index = 0;
824 int done = 0; 844 int done = 0;
845 int nr_found = 0;
825 846
826 ag = pag->pag_agno + 1; 847 ag = pag->pag_agno + 1;
827 848
828 do { 849 do {
829 struct xfs_inode *ip; 850 struct xfs_inode *batch[XFS_LOOKUP_BATCH];
830 int nr_found; 851 int i;
831 852
832 write_lock(&pag->pag_ici_lock); 853 write_lock(&pag->pag_ici_lock);
833 nr_found = radix_tree_gang_lookup_tag(&pag->pag_ici_root, 854 nr_found = radix_tree_gang_lookup_tag(
834 (void **)&ip, first_index, 1, 855 &pag->pag_ici_root,
856 (void **)batch, first_index,
857 XFS_LOOKUP_BATCH,
835 XFS_ICI_RECLAIM_TAG); 858 XFS_ICI_RECLAIM_TAG);
836 if (!nr_found) { 859 if (!nr_found) {
837 write_unlock(&pag->pag_ici_lock); 860 write_unlock(&pag->pag_ici_lock);
@@ -839,20 +862,41 @@ xfs_reclaim_inodes_ag(
839 } 862 }
840 863
841 /* 864 /*
842 * Update the index for the next lookup. Catch overflows 865 * Grab the inodes before we drop the lock. if we found
843 * into the next AG range which can occur if we have inodes 866 * nothing, nr == 0 and the loop will be skipped.
844 * in the last block of the AG and we are currently
845 * pointing to the last inode.
846 */ 867 */
847 first_index = XFS_INO_TO_AGINO(mp, ip->i_ino + 1); 868 for (i = 0; i < nr_found; i++) {
848 if (first_index < XFS_INO_TO_AGINO(mp, ip->i_ino)) 869 struct xfs_inode *ip = batch[i];
849 done = 1; 870
871 if (done || xfs_reclaim_inode_grab(ip, flags))
872 batch[i] = NULL;
873
874 /*
875 * Update the index for the next lookup. Catch
876 * overflows into the next AG range which can
877 * occur if we have inodes in the last block of
878 * the AG and we are currently pointing to the
879 * last inode.
880 */
881 first_index = XFS_INO_TO_AGINO(mp, ip->i_ino + 1);
882 if (first_index < XFS_INO_TO_AGINO(mp, ip->i_ino))
883 done = 1;
884 }
850 885
851 error = xfs_reclaim_inode(ip, pag, flags); 886 /* unlock now we've grabbed the inodes. */
852 if (error && last_error != EFSCORRUPTED) 887 write_unlock(&pag->pag_ici_lock);
853 last_error = error; 888
889 for (i = 0; i < nr_found; i++) {
890 if (!batch[i])
891 continue;
892 error = xfs_reclaim_inode(batch[i], pag, flags);
893 if (error && last_error != EFSCORRUPTED)
894 last_error = error;
895 }
896
897 *nr_to_scan -= XFS_LOOKUP_BATCH;
854 898
855 } while (!done && (*nr_to_scan)--); 899 } while (nr_found && !done && *nr_to_scan > 0);
856 900
857 xfs_perag_put(pag); 901 xfs_perag_put(pag);
858 } 902 }
@@ -888,7 +932,7 @@ xfs_reclaim_inode_shrink(
888 if (!(gfp_mask & __GFP_FS)) 932 if (!(gfp_mask & __GFP_FS))
889 return -1; 933 return -1;
890 934
891 xfs_reclaim_inodes_ag(mp, 0, &nr_to_scan); 935 xfs_reclaim_inodes_ag(mp, SYNC_TRYLOCK, &nr_to_scan);
892 /* terminate if we don't exhaust the scan */ 936 /* terminate if we don't exhaust the scan */
893 if (nr_to_scan > 0) 937 if (nr_to_scan > 0)
894 return -1; 938 return -1;