Skip to content

Commit 4254b0b

Browse files
Christoph HellwigFelix Blyakher
authored andcommitted
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>
1 parent 0b48db8 commit 4254b0b

File tree

1 file changed

+138
-153
lines changed

1 file changed

+138
-153
lines changed

fs/xfs/xfs_ialloc.c

Lines changed: 138 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,37 @@ xfs_ialloc_ag_select(
589589
}
590590
}
591591

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;
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+
592623

593624
/*
594625
* Visible inode allocation functions.
@@ -644,8 +675,8 @@ xfs_dialloc(
644675
int j; /* result code */
645676
xfs_mount_t *mp; /* file system mount structure */
646677
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 */
649680
xfs_inobt_rec_incore_t rec; /* inode allocation record */
650681
xfs_agnumber_t tagno; /* testing allocation group number */
651682
xfs_btree_cur_t *tcur; /* temp cursor */
@@ -781,186 +812,140 @@ xfs_dialloc(
781812
goto error0;
782813

783814
/*
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.
785816
*/
786817
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)
823+
goto error0;
824+
XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
825+
826+
error = xfs_inobt_get_rec(cur, &rec, &j);
827+
if (error)
788828
goto error0;
789-
if (i != 0 &&
790-
(error = xfs_inobt_get_rec(cur, &rec, &j)) == 0 &&
791-
j == 1 &&
792-
rec.ir_freecount > 0) {
829+
XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
830+
831+
if (rec.ir_freecount > 0) {
793832
/*
794833
* Found a free inode in the same chunk
795-
* as parent, done.
834+
* as the parent, done.
796835
*/
836+
goto alloc_inode;
797837
}
838+
839+
798840
/*
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.
800842
*/
801-
else {
802-
int doneleft; /* done, to the left */
803-
int doneright; /* done, to the right */
804843

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;
826872
}
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;
838880
}
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 */
846881

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;
921886
}
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;
923898
}
899+
ASSERT(!doneleft || !doneright);
924900
}
901+
925902
/*
926-
* In a different a.g. from the parent.
903+
* In a different AG from the parent.
927904
* See if the most recently allocated block has any free.
928905
*/
929906
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)
932910
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+
}
941924
}
925+
942926
/*
943-
* None left in the last group, search the whole a.g.
927+
* None left in the last group, search the whole AG
944928
*/
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);
946936
if (error)
947937
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)
949943
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);
962945
}
963946
}
947+
948+
alloc_inode:
964949
offset = xfs_ialloc_find_free(&rec.ir_free);
965950
ASSERT(offset >= 0);
966951
ASSERT(offset < XFS_INODES_PER_CHUNK);

0 commit comments

Comments
 (0)