diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_sync.c | 81 |
1 files changed, 71 insertions, 10 deletions
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c index 9e7f4dccab72..bbb40e27840b 100644 --- a/fs/xfs/linux-2.6/xfs_sync.c +++ b/fs/xfs/linux-2.6/xfs_sync.c | |||
@@ -685,32 +685,93 @@ xfs_inode_clear_reclaim_tag( | |||
685 | xfs_put_perag(mp, pag); | 685 | xfs_put_perag(mp, pag); |
686 | } | 686 | } |
687 | 687 | ||
688 | int | 688 | |
689 | xfs_reclaim_inodes( | 689 | STATIC void |
690 | xfs_reclaim_inodes_ag( | ||
690 | xfs_mount_t *mp, | 691 | xfs_mount_t *mp, |
691 | int noblock, | 692 | int ag, |
693 | int noblock, | ||
692 | int mode) | 694 | int mode) |
693 | { | 695 | { |
694 | xfs_inode_t *ip, *n; | 696 | xfs_inode_t *ip = NULL; |
697 | xfs_perag_t *pag = &mp->m_perag[ag]; | ||
698 | int nr_found; | ||
699 | int first_index; | ||
700 | int skipped; | ||
695 | 701 | ||
696 | restart: | 702 | restart: |
697 | XFS_MOUNT_ILOCK(mp); | 703 | first_index = 0; |
698 | list_for_each_entry_safe(ip, n, &mp->m_del_inodes, i_reclaim) { | 704 | skipped = 0; |
705 | do { | ||
706 | /* | ||
707 | * use a gang lookup to find the next inode in the tree | ||
708 | * as the tree is sparse and a gang lookup walks to find | ||
709 | * the number of objects requested. | ||
710 | */ | ||
711 | read_lock(&pag->pag_ici_lock); | ||
712 | nr_found = radix_tree_gang_lookup_tag(&pag->pag_ici_root, | ||
713 | (void**)&ip, first_index, 1, | ||
714 | XFS_ICI_RECLAIM_TAG); | ||
715 | |||
716 | if (!nr_found) { | ||
717 | read_unlock(&pag->pag_ici_lock); | ||
718 | break; | ||
719 | } | ||
720 | |||
721 | /* update the index for the next lookup */ | ||
722 | first_index = XFS_INO_TO_AGINO(mp, ip->i_ino + 1); | ||
723 | |||
724 | ASSERT(xfs_iflags_test(ip, (XFS_IRECLAIMABLE|XFS_IRECLAIM))); | ||
725 | |||
726 | /* ignore if already under reclaim */ | ||
727 | if (xfs_iflags_test(ip, XFS_IRECLAIM)) { | ||
728 | read_unlock(&pag->pag_ici_lock); | ||
729 | continue; | ||
730 | } | ||
731 | |||
699 | if (noblock) { | 732 | if (noblock) { |
700 | if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL) == 0) | 733 | if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) { |
734 | read_unlock(&pag->pag_ici_lock); | ||
701 | continue; | 735 | continue; |
736 | } | ||
702 | if (xfs_ipincount(ip) || | 737 | if (xfs_ipincount(ip) || |
703 | !xfs_iflock_nowait(ip)) { | 738 | !xfs_iflock_nowait(ip)) { |
704 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 739 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
740 | read_unlock(&pag->pag_ici_lock); | ||
705 | continue; | 741 | continue; |
706 | } | 742 | } |
707 | } | 743 | } |
708 | XFS_MOUNT_IUNLOCK(mp); | 744 | read_unlock(&pag->pag_ici_lock); |
745 | |||
746 | /* | ||
747 | * hmmm - this is an inode already in reclaim. Do | ||
748 | * we even bother catching it here? | ||
749 | */ | ||
709 | if (xfs_reclaim_inode(ip, noblock, mode)) | 750 | if (xfs_reclaim_inode(ip, noblock, mode)) |
710 | delay(1); | 751 | skipped++; |
752 | } while (nr_found); | ||
753 | |||
754 | if (skipped) { | ||
755 | delay(1); | ||
711 | goto restart; | 756 | goto restart; |
712 | } | 757 | } |
713 | XFS_MOUNT_IUNLOCK(mp); | 758 | return; |
759 | |||
760 | } | ||
761 | |||
762 | int | ||
763 | xfs_reclaim_inodes( | ||
764 | xfs_mount_t *mp, | ||
765 | int noblock, | ||
766 | int mode) | ||
767 | { | ||
768 | int i; | ||
769 | |||
770 | for (i = 0; i < mp->m_sb.sb_agcount; i++) { | ||
771 | if (!mp->m_perag[i].pag_ici_init) | ||
772 | continue; | ||
773 | xfs_reclaim_inodes_ag(mp, i, noblock, mode); | ||
774 | } | ||
714 | return 0; | 775 | return 0; |
715 | } | 776 | } |
716 | 777 | ||