xfs: support a tag-based inode_ag_iterator
authorBrian Foster <bfoster@redhat.com>
Tue, 6 Nov 2012 14:50:39 +0000 (09:50 -0500)
committerBen Myers <bpm@sgi.com>
Thu, 8 Nov 2012 21:20:38 +0000 (15:20 -0600)
Genericize xfs_inode_ag_walk() to support an optional radix tree tag
and args argument for the execute function. Create a new wrapper
called xfs_inode_ag_iterator_tag() that performs a tag based walk
of perag's and inodes.

Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Mark Tinguely <tinguely@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
fs/xfs/xfs_icache.c
fs/xfs/xfs_icache.h
fs/xfs/xfs_qm_syscalls.c

index f9afc5ff04828fb835a2840363c07c24cd9818a1..2a96dc48ebe6cdebe1db562f792ca5cb2eafb694 100644 (file)
@@ -516,8 +516,11 @@ xfs_inode_ag_walk(
        struct xfs_mount        *mp,
        struct xfs_perag        *pag,
        int                     (*execute)(struct xfs_inode *ip,
-                                          struct xfs_perag *pag, int flags),
-       int                     flags)
+                                          struct xfs_perag *pag, int flags,
+                                          void *args),
+       int                     flags,
+       void                    *args,
+       int                     tag)
 {
        uint32_t                first_index;
        int                     last_error = 0;
@@ -536,9 +539,17 @@ restart:
                int             i;
 
                rcu_read_lock();
-               nr_found = radix_tree_gang_lookup(&pag->pag_ici_root,
+
+               if (tag == -1)
+                       nr_found = radix_tree_gang_lookup(&pag->pag_ici_root,
                                        (void **)batch, first_index,
                                        XFS_LOOKUP_BATCH);
+               else
+                       nr_found = radix_tree_gang_lookup_tag(
+                                       &pag->pag_ici_root,
+                                       (void **) batch, first_index,
+                                       XFS_LOOKUP_BATCH, tag);
+
                if (!nr_found) {
                        rcu_read_unlock();
                        break;
@@ -579,7 +590,7 @@ restart:
                for (i = 0; i < nr_found; i++) {
                        if (!batch[i])
                                continue;
-                       error = execute(batch[i], pag, flags);
+                       error = execute(batch[i], pag, flags, args);
                        IRELE(batch[i]);
                        if (error == EAGAIN) {
                                skipped++;
@@ -608,8 +619,10 @@ int
 xfs_inode_ag_iterator(
        struct xfs_mount        *mp,
        int                     (*execute)(struct xfs_inode *ip,
-                                          struct xfs_perag *pag, int flags),
-       int                     flags)
+                                          struct xfs_perag *pag, int flags,
+                                          void *args),
+       int                     flags,
+       void                    *args)
 {
        struct xfs_perag        *pag;
        int                     error = 0;
@@ -619,7 +632,36 @@ xfs_inode_ag_iterator(
        ag = 0;
        while ((pag = xfs_perag_get(mp, ag))) {
                ag = pag->pag_agno + 1;
-               error = xfs_inode_ag_walk(mp, pag, execute, flags);
+               error = xfs_inode_ag_walk(mp, pag, execute, flags, args, -1);
+               xfs_perag_put(pag);
+               if (error) {
+                       last_error = error;
+                       if (error == EFSCORRUPTED)
+                               break;
+               }
+       }
+       return XFS_ERROR(last_error);
+}
+
+int
+xfs_inode_ag_iterator_tag(
+       struct xfs_mount        *mp,
+       int                     (*execute)(struct xfs_inode *ip,
+                                          struct xfs_perag *pag, int flags,
+                                          void *args),
+       int                     flags,
+       void                    *args,
+       int                     tag)
+{
+       struct xfs_perag        *pag;
+       int                     error = 0;
+       int                     last_error = 0;
+       xfs_agnumber_t          ag;
+
+       ag = 0;
+       while ((pag = xfs_perag_get_tag(mp, ag, tag))) {
+               ag = pag->pag_agno + 1;
+               error = xfs_inode_ag_walk(mp, pag, execute, flags, args, tag);
                xfs_perag_put(pag);
                if (error) {
                        last_error = error;
index db3613075dc64d26527eec8fc28aced0bf04f55e..54c113478dfcfa4e811d843d1f2b06663d42bb0b 100644 (file)
@@ -40,7 +40,12 @@ void xfs_inode_clear_eofblocks_tag(struct xfs_inode *ip);
 
 int xfs_sync_inode_grab(struct xfs_inode *ip);
 int xfs_inode_ag_iterator(struct xfs_mount *mp,
-       int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags),
-       int flags);
+       int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag,
+               int flags, void *args),
+       int flags, void *args);
+int xfs_inode_ag_iterator_tag(struct xfs_mount *mp,
+       int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag,
+               int flags, void *args),
+       int flags, void *args, int tag);
 
 #endif
index 7a9071f8855fc85b09d324b4d9115eaad4e7da85..5f53e75409b8f45ad919aae17b24cf92c5218a06 100644 (file)
@@ -846,7 +846,8 @@ STATIC int
 xfs_dqrele_inode(
        struct xfs_inode        *ip,
        struct xfs_perag        *pag,
-       int                     flags)
+       int                     flags,
+       void                    *args)
 {
        /* skip quota inodes */
        if (ip == ip->i_mount->m_quotainfo->qi_uquotaip ||
@@ -882,5 +883,5 @@ xfs_qm_dqrele_all_inodes(
        uint             flags)
 {
        ASSERT(mp->m_quotainfo);
-       xfs_inode_ag_iterator(mp, xfs_dqrele_inode, flags);
+       xfs_inode_ag_iterator(mp, xfs_dqrele_inode, flags, NULL);
 }