diff options
-rw-r--r-- | fs/xfs/xfs_itable.c | 65 | ||||
-rw-r--r-- | fs/xfs/xfs_itable.h | 11 |
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 | */ | ||
260 | STATIC int | ||
261 | xfs_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 | */ |
258 | int /* error status */ | 298 | int /* 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. |