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 | } |