aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/xfs_itable.c97
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. 603next_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}