From afebe4e0b040746bd202fc556e1c5d89a89aad33 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Thu, 28 Sep 2006 11:01:46 +1000 Subject: [PATCH] --- yaml --- r: 37139 b: refs/heads/master c: 8b56f083c2a6bd0a88271225f0bcf1d81db20d3c h: refs/heads/master i: 37137: d52fa352b84008b530695fb1d9c6c82212fcb05a 37135: cd6010c0e641b8cfabae2ad9c3da7c60939957b7 v: v3 --- [refs] | 2 +- trunk/fs/xfs/xfs_itable.c | 65 +++++++++++++++++++++++++++++++++------ trunk/fs/xfs/xfs_itable.h | 11 ++++--- 3 files changed, 62 insertions(+), 16 deletions(-) diff --git a/[refs] b/[refs] index d3b98014edf5..1e4f2a53740b 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 726801ba067410a1d38518823f2c253a087f6c6f +refs/heads/master: 8b56f083c2a6bd0a88271225f0bcf1d81db20d3c diff --git a/trunk/fs/xfs/xfs_itable.c b/trunk/fs/xfs/xfs_itable.c index 7521f301ee58..305a9d0436f4 100644 --- a/trunk/fs/xfs/xfs_itable.c +++ b/trunk/fs/xfs/xfs_itable.c @@ -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. diff --git a/trunk/fs/xfs/xfs_itable.h b/trunk/fs/xfs/xfs_itable.h index be5f12e07d22..6926c373a0a9 100644 --- a/trunk/fs/xfs/xfs_itable.h +++ b/trunk/fs/xfs/xfs_itable.h @@ -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.