diff options
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/xfs_itable.c | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index e6dbe6ba6fbd..315c9bcd3be3 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c | |||
@@ -324,6 +324,8 @@ xfs_bulkstat( | |||
324 | xfs_agino_t gino; /* current btree rec's start inode */ | 324 | xfs_agino_t gino; /* current btree rec's start inode */ |
325 | int i; /* loop index */ | 325 | int i; /* loop index */ |
326 | int icount; /* count of inodes good in irbuf */ | 326 | int icount; /* count of inodes good in irbuf */ |
327 | int irbsize; /* size of irec buffer in bytes */ | ||
328 | unsigned int kmflags; /* flags for allocating irec buffer */ | ||
327 | xfs_ino_t ino; /* inode number (filesystem) */ | 329 | xfs_ino_t ino; /* inode number (filesystem) */ |
328 | xfs_inobt_rec_incore_t *irbp; /* current irec buffer pointer */ | 330 | xfs_inobt_rec_incore_t *irbp; /* current irec buffer pointer */ |
329 | xfs_inobt_rec_incore_t *irbuf; /* start of irec buffer */ | 331 | xfs_inobt_rec_incore_t *irbuf; /* start of irec buffer */ |
@@ -369,12 +371,20 @@ xfs_bulkstat( | |||
369 | nimask = ~(nicluster - 1); | 371 | nimask = ~(nicluster - 1); |
370 | nbcluster = nicluster >> mp->m_sb.sb_inopblog; | 372 | nbcluster = nicluster >> mp->m_sb.sb_inopblog; |
371 | /* | 373 | /* |
372 | * Allocate a page-sized buffer for inode btree records. | 374 | * Allocate a local buffer for inode cluster btree records. |
373 | * We could try allocating something smaller, but for normal | 375 | * This caps our maximum readahead window (so don't be stingy) |
374 | * calls we'll always (potentially) need the whole page. | 376 | * but we must handle the case where we can't get a contiguous |
377 | * multi-page buffer, so we drop back toward pagesize; the end | ||
378 | * case we ensure succeeds, via appropriate allocation flags. | ||
375 | */ | 379 | */ |
376 | irbuf = kmem_alloc(NBPC, KM_SLEEP); | 380 | irbsize = NBPP * 4; |
377 | nirbuf = NBPC / sizeof(*irbuf); | 381 | kmflags = KM_SLEEP | KM_MAYFAIL; |
382 | while (!(irbuf = kmem_alloc(irbsize, kmflags))) { | ||
383 | if ((irbsize >>= 1) <= NBPP) | ||
384 | kmflags = KM_SLEEP; | ||
385 | } | ||
386 | nirbuf = irbsize / sizeof(*irbuf); | ||
387 | |||
378 | /* | 388 | /* |
379 | * Loop over the allocation groups, starting from the last | 389 | * Loop over the allocation groups, starting from the last |
380 | * inode returned; 0 means start of the allocation group. | 390 | * inode returned; 0 means start of the allocation group. |
@@ -672,7 +682,7 @@ xfs_bulkstat( | |||
672 | /* | 682 | /* |
673 | * Done, we're either out of filesystem or space to put the data. | 683 | * Done, we're either out of filesystem or space to put the data. |
674 | */ | 684 | */ |
675 | kmem_free(irbuf, NBPC); | 685 | kmem_free(irbuf, irbsize); |
676 | *ubcountp = ubelem; | 686 | *ubcountp = ubelem; |
677 | if (agno >= mp->m_sb.sb_agcount) { | 687 | if (agno >= mp->m_sb.sb_agcount) { |
678 | /* | 688 | /* |