[XFS] Rework DMAPI bulkstat calls in such a way that we can directly
authorNathan Scott <nathans@sgi.com>
Thu, 28 Sep 2006 01:01:46 +0000 (11:01 +1000)
committerTim Shimmin <tes@sgi.com>
Thu, 28 Sep 2006 01:01:46 +0000 (11:01 +1000)
extract inline attributes out of the bulkstat buffer (for that case),
rather than using an (extremely expensive for large icount filesystems)
iget for fetching attrs.

SGI-PV: 944409
SGI-Modid: xfs-linux-melb:xfs-kern:26602a

Signed-off-by: Nathan Scott <nathans@sgi.com>
Signed-off-by: Tim Shimmin <tes@sgi.com>
fs/xfs/xfs_itable.c
fs/xfs/xfs_itable.h

index 7521f301ee58116b6db501a5e3d622a0d807c7d5..305a9d0436f474baed960f317d1b698522d0d566 100644 (file)
@@ -252,6 +252,46 @@ xfs_bulkstat_one(
        return error;
 }
 
+/*
+ * Test to see whether we can use the ondisk inode directly, based
+ * on the given bulkstat flags, filling in dipp accordingly.
+ * Returns zero if the inode is dodgey.
+ */
+STATIC int
+xfs_bulkstat_use_dinode(
+       xfs_mount_t     *mp,
+       int             flags,
+       xfs_buf_t       *bp,
+       int             clustidx,
+       xfs_dinode_t    **dipp)
+{
+       xfs_dinode_t    *dip;
+       unsigned int    aformat;
+
+       *dipp = NULL;
+       if (!bp || (flags & BULKSTAT_FG_IGET))
+               return 1;
+       dip = (xfs_dinode_t *)
+                       xfs_buf_offset(bp, clustidx << mp->m_sb.sb_inodelog);
+       if (INT_GET(dip->di_core.di_magic, ARCH_CONVERT) != XFS_DINODE_MAGIC ||
+           !XFS_DINODE_GOOD_VERSION(
+                       INT_GET(dip->di_core.di_version, ARCH_CONVERT)))
+               return 0;
+       if (flags & BULKSTAT_FG_QUICK) {
+               *dipp = dip;
+               return 1;
+       }
+       /* BULKSTAT_FG_INLINE: if attr fork is local, or not there, use it */
+       aformat = INT_GET(dip->di_core.di_aformat, ARCH_CONVERT);
+       if ((XFS_CFORK_Q(&dip->di_core) == 0) ||
+           (aformat == XFS_DINODE_FMT_LOCAL) ||
+           (aformat == XFS_DINODE_FMT_EXTENTS && !dip->di_core.di_anextents)) {
+               *dipp = dip;
+               return 1;
+       }
+       return 1;
+}
+
 /*
  * Return stat information in bulk (by-inode) for the filesystem.
  */
@@ -529,7 +569,8 @@ xfs_bulkstat(
                                                ((chunkidx & nimask) >>
                                                 mp->m_sb.sb_inopblog);
 
-                                       if (flags & BULKSTAT_FG_QUICK) {
+                                       if (flags & (BULKSTAT_FG_QUICK |
+                                                    BULKSTAT_FG_INLINE)) {
                                                ino = XFS_AGINO_TO_INO(mp, agno,
                                                                       agino);
                                                bno = XFS_AGB_TO_DADDR(mp, agno,
@@ -573,21 +614,25 @@ xfs_bulkstat(
                                be32_add(&irbp->ir_freecount, 1);
                                ino = XFS_AGINO_TO_INO(mp, agno, agino);
                                bno = XFS_AGB_TO_DADDR(mp, agno, agbno);
-                               if (flags & BULKSTAT_FG_QUICK) {
-                                       dip = (xfs_dinode_t *)xfs_buf_offset(bp,
-                                             (clustidx << mp->m_sb.sb_inodelog));
-
-                                       if (INT_GET(dip->di_core.di_magic, ARCH_CONVERT)
-                                                   != XFS_DINODE_MAGIC
-                                           || !XFS_DINODE_GOOD_VERSION(
-                                                   INT_GET(dip->di_core.di_version, ARCH_CONVERT)))
-                                               continue;
+                               if (!xfs_bulkstat_use_dinode(mp, flags, bp,
+                                                            clustidx, &dip))
+                                       continue;
+                               /*
+                                * If we need to do an iget, cannot hold bp.
+                                * Drop it, until starting the next cluster.
+                                */
+                               if ((flags & BULKSTAT_FG_INLINE) && !dip) {
+                                       if (bp)
+                                               xfs_buf_relse(bp);
+                                       bp = NULL;
                                }
 
                                /*
                                 * Get the inode and fill in a single buffer.
                                 * BULKSTAT_FG_QUICK uses dip to fill it in.
                                 * BULKSTAT_FG_IGET uses igets.
+                                * BULKSTAT_FG_INLINE uses dip if we have an
+                                * inline attr fork, else igets.
                                 * See: xfs_bulkstat_one & xfs_dm_bulkstat_one.
                                 * This is also used to count inodes/blks, etc
                                 * in xfs_qm_quotacheck.
index be5f12e07d2217d98814127747d8fc9eadb40cc0..6926c373a0a91c4f541b2a8c69963aec559440e7 100644 (file)
@@ -36,15 +36,16 @@ typedef int (*bulkstat_one_pf)(struct xfs_mount     *mp,
 /*
  * Values for stat return value.
  */
-#define        BULKSTAT_RV_NOTHING     0
-#define        BULKSTAT_RV_DIDONE      1
-#define        BULKSTAT_RV_GIVEUP      2
+#define BULKSTAT_RV_NOTHING    0
+#define BULKSTAT_RV_DIDONE     1
+#define BULKSTAT_RV_GIVEUP     2
 
 /*
  * Values for bulkstat flag argument.
  */
-#define        BULKSTAT_FG_IGET        0x1     /* Go through the buffer cache */
-#define        BULKSTAT_FG_QUICK       0x2     /* No iget, walk the dinode cluster */
+#define BULKSTAT_FG_IGET       0x1     /* Go through the buffer cache */
+#define BULKSTAT_FG_QUICK      0x2     /* No iget, walk the dinode cluster */
+#define BULKSTAT_FG_INLINE     0x4     /* No iget if inline attrs */
 
 /*
  * Return stat information in bulk (by-inode) for the filesystem.