Commit 4254b0bbb1c0826b7443ffa593576696bc591aa2

Authored by Christoph Hellwig
Committed by Felix Blyakher
1 parent 0b48db80ba

xfs: untangle xfs_dialloc

Clarify the control flow in xfs_dialloc.  Factor out a helper to go to the
next node from the current one and improve the control flow by expanding
composite if statements and using gotos.

The xfs_ialloc_next_rec helper is borrowed from Dave Chinners dynamic
allocation policy patches.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Alex Elder <aelder@sgi.com>
Signed-off-by: Felix Blyakher <felixb@sgi.com>

Showing 1 changed file with 138 additions and 153 deletions Side-by-side Diff

... ... @@ -589,7 +589,38 @@
589 589 }
590 590 }
591 591  
  592 +/*
  593 + * Try to retrieve the next record to the left/right from the current one.
  594 + */
  595 +STATIC int
  596 +xfs_ialloc_next_rec(
  597 + struct xfs_btree_cur *cur,
  598 + xfs_inobt_rec_incore_t *rec,
  599 + int *done,
  600 + int left)
  601 +{
  602 + int error;
  603 + int i;
592 604  
  605 + if (left)
  606 + error = xfs_btree_decrement(cur, 0, &i);
  607 + else
  608 + error = xfs_btree_increment(cur, 0, &i);
  609 +
  610 + if (error)
  611 + return error;
  612 + *done = !i;
  613 + if (i) {
  614 + error = xfs_inobt_get_rec(cur, rec, &i);
  615 + if (error)
  616 + return error;
  617 + XFS_WANT_CORRUPTED_RETURN(i == 1);
  618 + }
  619 +
  620 + return 0;
  621 +}
  622 +
  623 +
593 624 /*
594 625 * Visible inode allocation functions.
595 626 */
... ... @@ -644,8 +675,8 @@
644 675 int j; /* result code */
645 676 xfs_mount_t *mp; /* file system mount structure */
646 677 int offset; /* index of inode in chunk */
647   - xfs_agino_t pagino; /* parent's a.g. relative inode # */
648   - xfs_agnumber_t pagno; /* parent's allocation group number */
  678 + xfs_agino_t pagino; /* parent's AG relative inode # */
  679 + xfs_agnumber_t pagno; /* parent's AG number */
649 680 xfs_inobt_rec_incore_t rec; /* inode allocation record */
650 681 xfs_agnumber_t tagno; /* testing allocation group number */
651 682 xfs_btree_cur_t *tcur; /* temp cursor */
652 683  
653 684  
654 685  
655 686  
656 687  
657 688  
658 689  
659 690  
660 691  
661 692  
662 693  
663 694  
664 695  
665 696  
666 697  
667 698  
668 699  
669 700  
670 701  
671 702  
672 703  
673 704  
674 705  
... ... @@ -781,186 +812,140 @@
781 812 goto error0;
782 813  
783 814 /*
784   - * If in the same a.g. as the parent, try to get near the parent.
  815 + * If in the same AG as the parent, try to get near the parent.
785 816 */
786 817 if (pagno == agno) {
787   - if ((error = xfs_inobt_lookup_le(cur, pagino, 0, 0, &i)))
  818 + int doneleft; /* done, to the left */
  819 + int doneright; /* done, to the right */
  820 +
  821 + error = xfs_inobt_lookup_le(cur, pagino, 0, 0, &i);
  822 + if (error)
788 823 goto error0;
789   - if (i != 0 &&
790   - (error = xfs_inobt_get_rec(cur, &rec, &j)) == 0 &&
791   - j == 1 &&
792   - rec.ir_freecount > 0) {
  824 + XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
  825 +
  826 + error = xfs_inobt_get_rec(cur, &rec, &j);
  827 + if (error)
  828 + goto error0;
  829 + XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
  830 +
  831 + if (rec.ir_freecount > 0) {
793 832 /*
794 833 * Found a free inode in the same chunk
795   - * as parent, done.
  834 + * as the parent, done.
796 835 */
  836 + goto alloc_inode;
797 837 }
  838 +
  839 +
798 840 /*
799   - * In the same a.g. as parent, but parent's chunk is full.
  841 + * In the same AG as parent, but parent's chunk is full.
800 842 */
801   - else {
802   - int doneleft; /* done, to the left */
803   - int doneright; /* done, to the right */
804 843  
805   - if (error)
806   - goto error0;
807   - ASSERT(i == 1);
808   - ASSERT(j == 1);
809   - /*
810   - * Duplicate the cursor, search left & right
811   - * simultaneously.
812   - */
813   - if ((error = xfs_btree_dup_cursor(cur, &tcur)))
814   - goto error0;
815   - /*
816   - * Search left with tcur, back up 1 record.
817   - */
818   - if ((error = xfs_btree_decrement(tcur, 0, &i)))
819   - goto error1;
820   - doneleft = !i;
821   - if (!doneleft) {
822   - error = xfs_inobt_get_rec(tcur, &trec, &i);
823   - if (error)
824   - goto error1;
825   - XFS_WANT_CORRUPTED_GOTO(i == 1, error1);
  844 + /* duplicate the cursor, search left & right simultaneously */
  845 + error = xfs_btree_dup_cursor(cur, &tcur);
  846 + if (error)
  847 + goto error0;
  848 +
  849 + /* search left with tcur, back up 1 record */
  850 + error = xfs_ialloc_next_rec(tcur, &trec, &doneleft, 1);
  851 + if (error)
  852 + goto error1;
  853 +
  854 + /* search right with cur, go forward 1 record. */
  855 + error = xfs_ialloc_next_rec(cur, &rec, &doneright, 0);
  856 + if (error)
  857 + goto error1;
  858 +
  859 + /*
  860 + * Loop until we find an inode chunk with a free inode.
  861 + */
  862 + while (!doneleft || !doneright) {
  863 + int useleft; /* using left inode chunk this time */
  864 +
  865 + /* figure out the closer block if both are valid. */
  866 + if (!doneleft && !doneright) {
  867 + useleft = pagino -
  868 + (trec.ir_startino + XFS_INODES_PER_CHUNK - 1) <
  869 + rec.ir_startino - pagino;
  870 + } else {
  871 + useleft = !doneleft;
826 872 }
827   - /*
828   - * Search right with cur, go forward 1 record.
829   - */
830   - if ((error = xfs_btree_increment(cur, 0, &i)))
831   - goto error1;
832   - doneright = !i;
833   - if (!doneright) {
834   - error = xfs_inobt_get_rec(cur, &rec, &i);
835   - if (error)
836   - goto error1;
837   - XFS_WANT_CORRUPTED_GOTO(i == 1, error1);
  873 +
  874 + /* free inodes to the left? */
  875 + if (useleft && trec.ir_freecount) {
  876 + rec = trec;
  877 + xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
  878 + cur = tcur;
  879 + goto alloc_inode;
838 880 }
839   - /*
840   - * Loop until we find the closest inode chunk
841   - * with a free one.
842   - */
843   - while (!doneleft || !doneright) {
844   - int useleft; /* using left inode
845   - chunk this time */
846 881  
847   - /*
848   - * Figure out which block is closer,
849   - * if both are valid.
850   - */
851   - if (!doneleft && !doneright)
852   - useleft =
853   - pagino -
854   - (trec.ir_startino +
855   - XFS_INODES_PER_CHUNK - 1) <
856   - rec.ir_startino - pagino;
857   - else
858   - useleft = !doneleft;
859   - /*
860   - * If checking the left, does it have
861   - * free inodes?
862   - */
863   - if (useleft && trec.ir_freecount) {
864   - /*
865   - * Yes, set it up as the chunk to use.
866   - */
867   - rec = trec;
868   - xfs_btree_del_cursor(cur,
869   - XFS_BTREE_NOERROR);
870   - cur = tcur;
871   - break;
872   - }
873   - /*
874   - * If checking the right, does it have
875   - * free inodes?
876   - */
877   - if (!useleft && rec.ir_freecount) {
878   - /*
879   - * Yes, it's already set up.
880   - */
881   - xfs_btree_del_cursor(tcur,
882   - XFS_BTREE_NOERROR);
883   - break;
884   - }
885   - /*
886   - * If used the left, get another one
887   - * further left.
888   - */
889   - if (useleft) {
890   - if ((error = xfs_btree_decrement(tcur, 0,
891   - &i)))
892   - goto error1;
893   - doneleft = !i;
894   - if (!doneleft) {
895   - error = xfs_inobt_get_rec(
896   - tcur, &trec, &i);
897   - if (error)
898   - goto error1;
899   - XFS_WANT_CORRUPTED_GOTO(i == 1,
900   - error1);
901   - }
902   - }
903   - /*
904   - * If used the right, get another one
905   - * further right.
906   - */
907   - else {
908   - if ((error = xfs_btree_increment(cur, 0,
909   - &i)))
910   - goto error1;
911   - doneright = !i;
912   - if (!doneright) {
913   - error = xfs_inobt_get_rec(
914   - cur, &rec, &i);
915   - if (error)
916   - goto error1;
917   - XFS_WANT_CORRUPTED_GOTO(i == 1,
918   - error1);
919   - }
920   - }
  882 + /* free inodes to the right? */
  883 + if (!useleft && rec.ir_freecount) {
  884 + xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
  885 + goto alloc_inode;
921 886 }
922   - ASSERT(!doneleft || !doneright);
  887 +
  888 + /* get next record to check */
  889 + if (useleft) {
  890 + error = xfs_ialloc_next_rec(tcur, &trec,
  891 + &doneleft, 1);
  892 + } else {
  893 + error = xfs_ialloc_next_rec(cur, &rec,
  894 + &doneright, 0);
  895 + }
  896 + if (error)
  897 + goto error1;
923 898 }
  899 + ASSERT(!doneleft || !doneright);
924 900 }
  901 +
925 902 /*
926   - * In a different a.g. from the parent.
  903 + * In a different AG from the parent.
927 904 * See if the most recently allocated block has any free.
928 905 */
929 906 else if (be32_to_cpu(agi->agi_newino) != NULLAGINO) {
930   - if ((error = xfs_inobt_lookup_eq(cur,
931   - be32_to_cpu(agi->agi_newino), 0, 0, &i)))
  907 + error = xfs_inobt_lookup_eq(cur, be32_to_cpu(agi->agi_newino),
  908 + 0, 0, &i);
  909 + if (error)
932 910 goto error0;
933   - if (i == 1 &&
934   - (error = xfs_inobt_get_rec(cur, &rec, &j)) == 0 &&
935   - j == 1 &&
936   - rec.ir_freecount > 0) {
937   - /*
938   - * The last chunk allocated in the group still has
939   - * a free inode.
940   - */
  911 +
  912 + if (i == 1) {
  913 + error = xfs_inobt_get_rec(cur, &rec, &j);
  914 + if (error)
  915 + goto error0;
  916 +
  917 + if (j == 1 && rec.ir_freecount > 0) {
  918 + /*
  919 + * The last chunk allocated in the group
  920 + * still has a free inode.
  921 + */
  922 + goto alloc_inode;
  923 + }
941 924 }
  925 +
942 926 /*
943   - * None left in the last group, search the whole a.g.
  927 + * None left in the last group, search the whole AG
944 928 */
945   - else {
  929 + error = xfs_inobt_lookup_ge(cur, 0, 0, 0, &i);
  930 + if (error)
  931 + goto error0;
  932 + XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
  933 +
  934 + for (;;) {
  935 + error = xfs_inobt_get_rec(cur, &rec, &i);
946 936 if (error)
947 937 goto error0;
948   - if ((error = xfs_inobt_lookup_ge(cur, 0, 0, 0, &i)))
  938 + XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
  939 + if (rec.ir_freecount > 0)
  940 + break;
  941 + error = xfs_btree_increment(cur, 0, &i);
  942 + if (error)
949 943 goto error0;
950   - ASSERT(i == 1);
951   - for (;;) {
952   - error = xfs_inobt_get_rec(cur, &rec, &i);
953   - if (error)
954   - goto error0;
955   - XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
956   - if (rec.ir_freecount > 0)
957   - break;
958   - if ((error = xfs_btree_increment(cur, 0, &i)))
959   - goto error0;
960   - XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
961   - }
  944 + XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
962 945 }
963 946 }
  947 +
  948 +alloc_inode:
964 949 offset = xfs_ialloc_find_free(&rec.ir_free);
965 950 ASSERT(offset >= 0);
966 951 ASSERT(offset < XFS_INODES_PER_CHUNK);