@@ -587,6 +587,30 @@ xfs_ialloc_next_rec(
587
587
return 0 ;
588
588
}
589
589
590
+ STATIC int
591
+ xfs_ialloc_get_rec (
592
+ struct xfs_btree_cur * cur ,
593
+ xfs_agino_t agino ,
594
+ xfs_inobt_rec_incore_t * rec ,
595
+ int * done ,
596
+ int left )
597
+ {
598
+ int error ;
599
+ int i ;
600
+
601
+ error = xfs_inobt_lookup (cur , agino , XFS_LOOKUP_EQ , & i );
602
+ if (error )
603
+ return error ;
604
+ * done = !i ;
605
+ if (i ) {
606
+ error = xfs_inobt_get_rec (cur , rec , & i );
607
+ if (error )
608
+ return error ;
609
+ XFS_WANT_CORRUPTED_RETURN (i == 1 );
610
+ }
611
+
612
+ return 0 ;
613
+ }
590
614
591
615
/*
592
616
* Visible inode allocation functions.
@@ -766,6 +790,8 @@ xfs_dialloc(
766
790
*/
767
791
agno = tagno ;
768
792
* IO_agbp = NULL ;
793
+
794
+ restart_pagno :
769
795
cur = xfs_inobt_init_cursor (mp , tp , agbp , be32_to_cpu (agi -> agi_seqno ));
770
796
/*
771
797
* If pagino is 0 (this is the root inode allocation) use newino.
@@ -782,8 +808,10 @@ xfs_dialloc(
782
808
* If in the same AG as the parent, try to get near the parent.
783
809
*/
784
810
if (pagno == agno ) {
811
+ xfs_perag_t * pag = & mp -> m_perag [agno ];
785
812
int doneleft ; /* done, to the left */
786
813
int doneright ; /* done, to the right */
814
+ int searchdistance = 10 ;
787
815
788
816
error = xfs_inobt_lookup (cur , pagino , XFS_LOOKUP_LE , & i );
789
817
if (error )
@@ -813,22 +841,51 @@ xfs_dialloc(
813
841
if (error )
814
842
goto error0 ;
815
843
816
- /* search left with tcur, back up 1 record */
817
- error = xfs_ialloc_next_rec (tcur , & trec , & doneleft , 1 );
818
- if (error )
819
- goto error1 ;
844
+ /*
845
+ * Skip to last blocks looked up if same parent inode.
846
+ */
847
+ if (pagino != NULLAGINO &&
848
+ pag -> pagl_pagino == pagino &&
849
+ pag -> pagl_leftrec != NULLAGINO &&
850
+ pag -> pagl_rightrec != NULLAGINO ) {
851
+ error = xfs_ialloc_get_rec (tcur , pag -> pagl_leftrec ,
852
+ & trec , & doneleft , 1 );
853
+ if (error )
854
+ goto error1 ;
820
855
821
- /* search right with cur, go forward 1 record. */
822
- error = xfs_ialloc_next_rec (cur , & rec , & doneright , 0 );
823
- if (error )
824
- goto error1 ;
856
+ error = xfs_ialloc_get_rec (cur , pag -> pagl_rightrec ,
857
+ & rec , & doneright , 0 );
858
+ if (error )
859
+ goto error1 ;
860
+ } else {
861
+ /* search left with tcur, back up 1 record */
862
+ error = xfs_ialloc_next_rec (tcur , & trec , & doneleft , 1 );
863
+ if (error )
864
+ goto error1 ;
865
+
866
+ /* search right with cur, go forward 1 record. */
867
+ error = xfs_ialloc_next_rec (cur , & rec , & doneright , 0 );
868
+ if (error )
869
+ goto error1 ;
870
+ }
825
871
826
872
/*
827
873
* Loop until we find an inode chunk with a free inode.
828
874
*/
829
875
while (!doneleft || !doneright ) {
830
876
int useleft ; /* using left inode chunk this time */
831
877
878
+ if (!-- searchdistance ) {
879
+ /*
880
+ * Not in range - save last search
881
+ * location and allocate a new inode
882
+ */
883
+ pag -> pagl_leftrec = trec .ir_startino ;
884
+ pag -> pagl_rightrec = rec .ir_startino ;
885
+ pag -> pagl_pagino = pagino ;
886
+ goto newino ;
887
+ }
888
+
832
889
/* figure out the closer block if both are valid. */
833
890
if (!doneleft && !doneright ) {
834
891
useleft = pagino -
@@ -843,12 +900,20 @@ xfs_dialloc(
843
900
rec = trec ;
844
901
xfs_btree_del_cursor (cur , XFS_BTREE_NOERROR );
845
902
cur = tcur ;
903
+
904
+ pag -> pagl_leftrec = trec .ir_startino ;
905
+ pag -> pagl_rightrec = rec .ir_startino ;
906
+ pag -> pagl_pagino = pagino ;
846
907
goto alloc_inode ;
847
908
}
848
909
849
910
/* free inodes to the right? */
850
911
if (!useleft && rec .ir_freecount ) {
851
912
xfs_btree_del_cursor (tcur , XFS_BTREE_NOERROR );
913
+
914
+ pag -> pagl_leftrec = trec .ir_startino ;
915
+ pag -> pagl_rightrec = rec .ir_startino ;
916
+ pag -> pagl_pagino = pagino ;
852
917
goto alloc_inode ;
853
918
}
854
919
@@ -863,14 +928,28 @@ xfs_dialloc(
863
928
if (error )
864
929
goto error1 ;
865
930
}
866
- ASSERT (!doneleft || !doneright );
931
+
932
+ /*
933
+ * We've reached the end of the btree. because
934
+ * we are only searching a small chunk of the
935
+ * btree each search, there is obviously free
936
+ * inodes closer to the parent inode than we
937
+ * are now. restart the search again.
938
+ */
939
+ pag -> pagl_pagino = NULLAGINO ;
940
+ pag -> pagl_leftrec = NULLAGINO ;
941
+ pag -> pagl_rightrec = NULLAGINO ;
942
+ xfs_btree_del_cursor (tcur , XFS_BTREE_NOERROR );
943
+ xfs_btree_del_cursor (cur , XFS_BTREE_NOERROR );
944
+ goto restart_pagno ;
867
945
}
868
946
869
947
/*
870
948
* In a different AG from the parent.
871
949
* See if the most recently allocated block has any free.
872
950
*/
873
- else if (be32_to_cpu (agi -> agi_newino ) != NULLAGINO ) {
951
+ newino :
952
+ if (be32_to_cpu (agi -> agi_newino ) != NULLAGINO ) {
874
953
error = xfs_inobt_lookup (cur , be32_to_cpu (agi -> agi_newino ),
875
954
XFS_LOOKUP_EQ , & i );
876
955
if (error )
@@ -889,27 +968,27 @@ xfs_dialloc(
889
968
goto alloc_inode ;
890
969
}
891
970
}
971
+ }
892
972
893
- /*
894
- * None left in the last group, search the whole AG
895
- */
896
- error = xfs_inobt_lookup (cur , 0 , XFS_LOOKUP_GE , & i );
973
+ /*
974
+ * None left in the last group, search the whole AG
975
+ */
976
+ error = xfs_inobt_lookup (cur , 0 , XFS_LOOKUP_GE , & i );
977
+ if (error )
978
+ goto error0 ;
979
+ XFS_WANT_CORRUPTED_GOTO (i == 1 , error0 );
980
+
981
+ for (;;) {
982
+ error = xfs_inobt_get_rec (cur , & rec , & i );
983
+ if (error )
984
+ goto error0 ;
985
+ XFS_WANT_CORRUPTED_GOTO (i == 1 , error0 );
986
+ if (rec .ir_freecount > 0 )
987
+ break ;
988
+ error = xfs_btree_increment (cur , 0 , & i );
897
989
if (error )
898
990
goto error0 ;
899
991
XFS_WANT_CORRUPTED_GOTO (i == 1 , error0 );
900
-
901
- for (;;) {
902
- error = xfs_inobt_get_rec (cur , & rec , & i );
903
- if (error )
904
- goto error0 ;
905
- XFS_WANT_CORRUPTED_GOTO (i == 1 , error0 );
906
- if (rec .ir_freecount > 0 )
907
- break ;
908
- error = xfs_btree_increment (cur , 0 , & i );
909
- if (error )
910
- goto error0 ;
911
- XFS_WANT_CORRUPTED_GOTO (i == 1 , error0 );
912
- }
913
992
}
914
993
915
994
alloc_inode :
0 commit comments