aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Scott <nathans@sgi.com>2006-09-27 21:01:46 -0400
committerTim Shimmin <tes@sgi.com>2006-09-27 21:01:46 -0400
commit8b56f083c2a6bd0a88271225f0bcf1d81db20d3c (patch)
tree90acd2461a8d7a8852385711ce7ef4a771f0cebb
parent726801ba067410a1d38518823f2c253a087f6c6f (diff)
[XFS] Rework DMAPI bulkstat calls in such a way that we can directly
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>
-rw-r--r--fs/xfs/xfs_itable.c65
-rw-r--r--fs/xfs/xfs_itable.h11
2 files changed, 61 insertions, 15 deletions
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 7521f301ee58..305a9d0436f4 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -253,6 +253,46 @@ xfs_bulkstat_one(
253} 253}
254 254
255/* 255/*
256 * Test to see whether we can use the ondisk inode directly, based
257 * on the given bulkstat flags, filling in dipp accordingly.
258 * Returns zero if the inode is dodgey.
259 */
260STATIC int
261xfs_bulkstat_use_dinode(
262 xfs_mount_t *mp,
263 int flags,
264 xfs_buf_t *bp,
265 int clustidx,
266 xfs_dinode_t **dipp)
267{
268 xfs_dinode_t *dip;
269 unsigned int aformat;
270
271 *dipp = NULL;
272 if (!bp || (flags & BULKSTAT_FG_IGET))
273 return 1;
274 dip = (xfs_dinode_t *)
275 xfs_buf_offset(bp, clustidx << mp->m_sb.sb_inodelog);
276 if (INT_GET(dip->di_core.di_magic, ARCH_CONVERT) != XFS_DINODE_MAGIC ||
277 !XFS_DINODE_GOOD_VERSION(
278 INT_GET(dip->di_core.di_version, ARCH_CONVERT)))
279 return 0;
280 if (flags & BULKSTAT_FG_QUICK) {
281 *dipp = dip;
282 return 1;
283 }
284 /* BULKSTAT_FG_INLINE: if attr fork is local, or not there, use it */
285 aformat = INT_GET(dip->di_core.di_aformat, ARCH_CONVERT);
286 if ((XFS_CFORK_Q(&dip->di_core) == 0) ||
287 (aformat == XFS_DINODE_FMT_LOCAL) ||
288 (aformat == XFS_DINODE_FMT_EXTENTS && !dip->di_core.di_anextents)) {
289 *dipp = dip;
290 return 1;
291 }
292 return 1;
293}
294
295/*
256 * Return stat information in bulk (by-inode) for the filesystem. 296 * Return stat information in bulk (by-inode) for the filesystem.
257 */ 297 */
258int /* error status */ 298int /* error status */
@@ -529,7 +569,8 @@ xfs_bulkstat(
529 ((chunkidx & nimask) >> 569 ((chunkidx & nimask) >>
530 mp->m_sb.sb_inopblog); 570 mp->m_sb.sb_inopblog);
531 571
532 if (flags & BULKSTAT_FG_QUICK) { 572 if (flags & (BULKSTAT_FG_QUICK |
573 BULKSTAT_FG_INLINE)) {
533 ino = XFS_AGINO_TO_INO(mp, agno, 574 ino = XFS_AGINO_TO_INO(mp, agno,
534 agino); 575 agino);
535 bno = XFS_AGB_TO_DADDR(mp, agno, 576 bno = XFS_AGB_TO_DADDR(mp, agno,
@@ -573,21 +614,25 @@ xfs_bulkstat(
573 be32_add(&irbp->ir_freecount, 1); 614 be32_add(&irbp->ir_freecount, 1);
574 ino = XFS_AGINO_TO_INO(mp, agno, agino); 615 ino = XFS_AGINO_TO_INO(mp, agno, agino);
575 bno = XFS_AGB_TO_DADDR(mp, agno, agbno); 616 bno = XFS_AGB_TO_DADDR(mp, agno, agbno);
576 if (flags & BULKSTAT_FG_QUICK) { 617 if (!xfs_bulkstat_use_dinode(mp, flags, bp,
577 dip = (xfs_dinode_t *)xfs_buf_offset(bp, 618 clustidx, &dip))
578 (clustidx << mp->m_sb.sb_inodelog)); 619 continue;
579 620 /*
580 if (INT_GET(dip->di_core.di_magic, ARCH_CONVERT) 621 * If we need to do an iget, cannot hold bp.
581 != XFS_DINODE_MAGIC 622 * Drop it, until starting the next cluster.
582 || !XFS_DINODE_GOOD_VERSION( 623 */
583 INT_GET(dip->di_core.di_version, ARCH_CONVERT))) 624 if ((flags & BULKSTAT_FG_INLINE) && !dip) {
584 continue; 625 if (bp)
626 xfs_buf_relse(bp);
627 bp = NULL;
585 } 628 }
586 629
587 /* 630 /*
588 * Get the inode and fill in a single buffer. 631 * Get the inode and fill in a single buffer.
589 * BULKSTAT_FG_QUICK uses dip to fill it in. 632 * BULKSTAT_FG_QUICK uses dip to fill it in.
590 * BULKSTAT_FG_IGET uses igets. 633 * BULKSTAT_FG_IGET uses igets.
634 * BULKSTAT_FG_INLINE uses dip if we have an
635 * inline attr fork, else igets.
591 * See: xfs_bulkstat_one & xfs_dm_bulkstat_one. 636 * See: xfs_bulkstat_one & xfs_dm_bulkstat_one.
592 * This is also used to count inodes/blks, etc 637 * This is also used to count inodes/blks, etc
593 * in xfs_qm_quotacheck. 638 * in xfs_qm_quotacheck.
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
index be5f12e07d22..6926c373a0a9 100644
--- a/fs/xfs/xfs_itable.h
+++ b/fs/xfs/xfs_itable.h
@@ -36,15 +36,16 @@ typedef int (*bulkstat_one_pf)(struct xfs_mount *mp,
36/* 36/*
37 * Values for stat return value. 37 * Values for stat return value.
38 */ 38 */
39#define BULKSTAT_RV_NOTHING 0 39#define BULKSTAT_RV_NOTHING 0
40#define BULKSTAT_RV_DIDONE 1 40#define BULKSTAT_RV_DIDONE 1
41#define BULKSTAT_RV_GIVEUP 2 41#define BULKSTAT_RV_GIVEUP 2
42 42
43/* 43/*
44 * Values for bulkstat flag argument. 44 * Values for bulkstat flag argument.
45 */ 45 */
46#define BULKSTAT_FG_IGET 0x1 /* Go through the buffer cache */ 46#define BULKSTAT_FG_IGET 0x1 /* Go through the buffer cache */
47#define BULKSTAT_FG_QUICK 0x2 /* No iget, walk the dinode cluster */ 47#define BULKSTAT_FG_QUICK 0x2 /* No iget, walk the dinode cluster */
48#define BULKSTAT_FG_INLINE 0x4 /* No iget if inline attrs */
48 49
49/* 50/*
50 * Return stat information in bulk (by-inode) for the filesystem. 51 * Return stat information in bulk (by-inode) for the filesystem.