diff options
| -rw-r--r-- | fs/xfs/xfs_itable.c | 97 |
1 files changed, 40 insertions, 57 deletions
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index df7605183aa2..ed042fff9337 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c | |||
| @@ -536,7 +536,7 @@ xfs_inumbers( | |||
| 536 | xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, *lastino); | 536 | xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, *lastino); |
| 537 | xfs_agino_t agino = XFS_INO_TO_AGINO(mp, *lastino); | 537 | xfs_agino_t agino = XFS_INO_TO_AGINO(mp, *lastino); |
| 538 | struct xfs_btree_cur *cur = NULL; | 538 | struct xfs_btree_cur *cur = NULL; |
| 539 | xfs_buf_t *agbp = NULL; | 539 | struct xfs_buf *agbp = NULL; |
| 540 | struct xfs_inogrp *buffer; | 540 | struct xfs_inogrp *buffer; |
| 541 | int bcount; | 541 | int bcount; |
| 542 | int left = *count; | 542 | int left = *count; |
| @@ -550,61 +550,40 @@ xfs_inumbers( | |||
| 550 | 550 | ||
| 551 | bcount = MIN(left, (int)(PAGE_SIZE / sizeof(*buffer))); | 551 | bcount = MIN(left, (int)(PAGE_SIZE / sizeof(*buffer))); |
| 552 | buffer = kmem_alloc(bcount * sizeof(*buffer), KM_SLEEP); | 552 | buffer = kmem_alloc(bcount * sizeof(*buffer), KM_SLEEP); |
| 553 | while (left > 0 && agno < mp->m_sb.sb_agcount) { | 553 | do { |
| 554 | struct xfs_inobt_rec_incore r; | 554 | struct xfs_inobt_rec_incore r; |
| 555 | int stat; | 555 | int stat; |
| 556 | 556 | ||
| 557 | if (agbp == NULL) { | 557 | if (!agbp) { |
| 558 | error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp); | 558 | error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp); |
| 559 | if (error) { | 559 | if (error) |
| 560 | /* | 560 | break; |
| 561 | * If we can't read the AGI of this ag, | 561 | |
| 562 | * then just skip to the next one. | ||
| 563 | */ | ||
| 564 | ASSERT(cur == NULL); | ||
| 565 | agbp = NULL; | ||
| 566 | agno++; | ||
| 567 | agino = 0; | ||
| 568 | continue; | ||
| 569 | } | ||
| 570 | cur = xfs_inobt_init_cursor(mp, NULL, agbp, agno, | 562 | cur = xfs_inobt_init_cursor(mp, NULL, agbp, agno, |
| 571 | XFS_BTNUM_INO); | 563 | XFS_BTNUM_INO); |
| 572 | error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_GE, | 564 | error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_GE, |
| 573 | &stat); | 565 | &stat); |
| 574 | if (error) { | 566 | if (error) |
| 575 | xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); | 567 | break; |
| 576 | cur = NULL; | 568 | if (!stat) |
| 577 | xfs_buf_relse(agbp); | 569 | goto next_ag; |
| 578 | agbp = NULL; | ||
| 579 | /* | ||
| 580 | * Move up the last inode in the current | ||
| 581 | * chunk. The lookup_ge will always get | ||
| 582 | * us the first inode in the next chunk. | ||
| 583 | */ | ||
| 584 | agino += XFS_INODES_PER_CHUNK - 1; | ||
| 585 | continue; | ||
| 586 | } | ||
| 587 | } | 570 | } |
| 571 | |||
| 588 | error = xfs_inobt_get_rec(cur, &r, &stat); | 572 | error = xfs_inobt_get_rec(cur, &r, &stat); |
| 589 | if (error || stat == 0) { | 573 | if (error) |
| 590 | xfs_buf_relse(agbp); | 574 | break; |
| 591 | agbp = NULL; | 575 | if (!stat) |
| 592 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); | 576 | goto next_ag; |
| 593 | cur = NULL; | 577 | |
| 594 | agno++; | ||
| 595 | agino = 0; | ||
| 596 | continue; | ||
| 597 | } | ||
| 598 | agino = r.ir_startino + XFS_INODES_PER_CHUNK - 1; | 578 | agino = r.ir_startino + XFS_INODES_PER_CHUNK - 1; |
| 599 | buffer[bufidx].xi_startino = | 579 | buffer[bufidx].xi_startino = |
| 600 | XFS_AGINO_TO_INO(mp, agno, r.ir_startino); | 580 | XFS_AGINO_TO_INO(mp, agno, r.ir_startino); |
| 601 | buffer[bufidx].xi_alloccount = | 581 | buffer[bufidx].xi_alloccount = |
| 602 | XFS_INODES_PER_CHUNK - r.ir_freecount; | 582 | XFS_INODES_PER_CHUNK - r.ir_freecount; |
| 603 | buffer[bufidx].xi_allocmask = ~r.ir_free; | 583 | buffer[bufidx].xi_allocmask = ~r.ir_free; |
| 604 | bufidx++; | 584 | if (++bufidx == bcount) { |
| 605 | left--; | 585 | long written; |
| 606 | if (bufidx == bcount) { | 586 | |
| 607 | long written; | ||
| 608 | error = formatter(ubuffer, buffer, bufidx, &written); | 587 | error = formatter(ubuffer, buffer, bufidx, &written); |
| 609 | if (error) | 588 | if (error) |
| 610 | break; | 589 | break; |
| @@ -612,36 +591,40 @@ xfs_inumbers( | |||
| 612 | *count += bufidx; | 591 | *count += bufidx; |
| 613 | bufidx = 0; | 592 | bufidx = 0; |
| 614 | } | 593 | } |
| 615 | if (left) { | 594 | if (!--left) |
| 616 | error = xfs_btree_increment(cur, 0, &stat); | 595 | break; |
| 617 | if (error) { | 596 | |
| 618 | xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); | 597 | error = xfs_btree_increment(cur, 0, &stat); |
| 619 | cur = NULL; | 598 | if (error) |
| 620 | xfs_buf_relse(agbp); | 599 | break; |
| 621 | agbp = NULL; | 600 | if (stat) |
| 622 | /* | 601 | continue; |
| 623 | * The agino value has already been bumped. | 602 | |
| 624 | * Just try to skip up to it. | 603 | next_ag: |
| 625 | */ | 604 | xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); |
| 626 | agino += XFS_INODES_PER_CHUNK; | 605 | cur = NULL; |
| 627 | continue; | 606 | xfs_buf_relse(agbp); |
| 628 | } | 607 | agbp = NULL; |
| 629 | } | 608 | agino = 0; |
| 630 | } | 609 | } while (++agno < mp->m_sb.sb_agcount); |
| 610 | |||
| 631 | if (!error) { | 611 | if (!error) { |
| 632 | if (bufidx) { | 612 | if (bufidx) { |
| 633 | long written; | 613 | long written; |
| 614 | |||
| 634 | error = formatter(ubuffer, buffer, bufidx, &written); | 615 | error = formatter(ubuffer, buffer, bufidx, &written); |
| 635 | if (!error) | 616 | if (!error) |
| 636 | *count += bufidx; | 617 | *count += bufidx; |
| 637 | } | 618 | } |
| 638 | *lastino = XFS_AGINO_TO_INO(mp, agno, agino); | 619 | *lastino = XFS_AGINO_TO_INO(mp, agno, agino); |
| 639 | } | 620 | } |
| 621 | |||
| 640 | kmem_free(buffer); | 622 | kmem_free(buffer); |
| 641 | if (cur) | 623 | if (cur) |
| 642 | xfs_btree_del_cursor(cur, (error ? XFS_BTREE_ERROR : | 624 | xfs_btree_del_cursor(cur, (error ? XFS_BTREE_ERROR : |
| 643 | XFS_BTREE_NOERROR)); | 625 | XFS_BTREE_NOERROR)); |
| 644 | if (agbp) | 626 | if (agbp) |
| 645 | xfs_buf_relse(agbp); | 627 | xfs_buf_relse(agbp); |
| 628 | |||
| 646 | return error; | 629 | return error; |
| 647 | } | 630 | } |
