aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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.