@@ -2845,12 +2845,56 @@ void ext4_mb_prefetch_fini(struct super_block *sb, ext4_group_t group,
2845
2845
}
2846
2846
}
2847
2847
2848
+ static int ext4_mb_scan_group (struct ext4_allocation_context * ac ,
2849
+ ext4_group_t group )
2850
+ {
2851
+ int ret ;
2852
+ struct super_block * sb = ac -> ac_sb ;
2853
+ enum criteria cr = ac -> ac_criteria ;
2854
+
2855
+ ext4_mb_might_prefetch (ac , group );
2856
+
2857
+ /* prevent unnecessary buddy loading. */
2858
+ if (cr < CR_ANY_FREE && spin_is_locked (ext4_group_lock_ptr (sb , group )))
2859
+ return 0 ;
2860
+
2861
+ /* This now checks without needing the buddy page */
2862
+ ret = ext4_mb_good_group_nolock (ac , group , cr );
2863
+ if (ret <= 0 ) {
2864
+ if (!ac -> ac_first_err )
2865
+ ac -> ac_first_err = ret ;
2866
+ return 0 ;
2867
+ }
2868
+
2869
+ ret = ext4_mb_load_buddy (sb , group , ac -> ac_e4b );
2870
+ if (ret )
2871
+ return ret ;
2872
+
2873
+ /* skip busy group */
2874
+ if (cr >= CR_ANY_FREE )
2875
+ ext4_lock_group (sb , group );
2876
+ else if (!ext4_try_lock_group (sb , group ))
2877
+ goto out_unload ;
2878
+
2879
+ /* We need to check again after locking the block group. */
2880
+ if (unlikely (!ext4_mb_good_group (ac , group , cr )))
2881
+ goto out_unlock ;
2882
+
2883
+ __ext4_mb_scan_group (ac );
2884
+
2885
+ out_unlock :
2886
+ ext4_unlock_group (sb , group );
2887
+ out_unload :
2888
+ ext4_mb_unload_buddy (ac -> ac_e4b );
2889
+ return ret ;
2890
+ }
2891
+
2848
2892
static noinline_for_stack int
2849
2893
ext4_mb_regular_allocator (struct ext4_allocation_context * ac )
2850
2894
{
2851
2895
ext4_group_t ngroups , group , i ;
2852
2896
enum criteria new_cr , cr = CR_GOAL_LEN_FAST ;
2853
- int err = 0 , first_err = 0 ;
2897
+ int err = 0 ;
2854
2898
struct ext4_sb_info * sbi ;
2855
2899
struct super_block * sb ;
2856
2900
struct ext4_buddy e4b ;
@@ -2912,6 +2956,7 @@ ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
2912
2956
2913
2957
ac -> ac_e4b = & e4b ;
2914
2958
ac -> ac_prefetch_ios = 0 ;
2959
+ ac -> ac_first_err = 0 ;
2915
2960
repeat :
2916
2961
for (; cr < EXT4_MB_NUM_CRS && ac -> ac_status == AC_STATUS_CONTINUE ; cr ++ ) {
2917
2962
ac -> ac_criteria = cr ;
@@ -2926,57 +2971,17 @@ ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
2926
2971
2927
2972
for (i = 0 , new_cr = cr ; i < ngroups ; i ++ ,
2928
2973
ext4_mb_choose_next_group (ac , & new_cr , & group , ngroups )) {
2929
- int ret = 0 ;
2930
2974
2931
2975
cond_resched ();
2932
2976
if (new_cr != cr ) {
2933
2977
cr = new_cr ;
2934
2978
goto repeat ;
2935
2979
}
2936
2980
2937
- ext4_mb_might_prefetch (ac , group );
2938
-
2939
- /* prevent unnecessary buddy loading. */
2940
- if (cr < CR_ANY_FREE &&
2941
- spin_is_locked (ext4_group_lock_ptr (sb , group )))
2942
- continue ;
2943
-
2944
- /* This now checks without needing the buddy page */
2945
- ret = ext4_mb_good_group_nolock (ac , group , cr );
2946
- if (ret <= 0 ) {
2947
- if (!first_err )
2948
- first_err = ret ;
2949
- continue ;
2950
- }
2951
-
2952
- err = ext4_mb_load_buddy (sb , group , & e4b );
2981
+ err = ext4_mb_scan_group (ac , group );
2953
2982
if (err )
2954
2983
goto out ;
2955
2984
2956
- /* skip busy group */
2957
- if (cr >= CR_ANY_FREE ) {
2958
- ext4_lock_group (sb , group );
2959
- } else if (!ext4_try_lock_group (sb , group )) {
2960
- ext4_mb_unload_buddy (& e4b );
2961
- continue ;
2962
- }
2963
-
2964
- /*
2965
- * We need to check again after locking the
2966
- * block group
2967
- */
2968
- ret = ext4_mb_good_group (ac , group , cr );
2969
- if (ret == 0 ) {
2970
- ext4_unlock_group (sb , group );
2971
- ext4_mb_unload_buddy (& e4b );
2972
- continue ;
2973
- }
2974
-
2975
- __ext4_mb_scan_group (ac );
2976
-
2977
- ext4_unlock_group (sb , group );
2978
- ext4_mb_unload_buddy (& e4b );
2979
-
2980
2985
if (ac -> ac_status != AC_STATUS_CONTINUE )
2981
2986
break ;
2982
2987
}
@@ -3025,8 +3030,8 @@ ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
3025
3030
atomic_inc (& sbi -> s_bal_stream_goals );
3026
3031
}
3027
3032
out :
3028
- if (!err && ac -> ac_status != AC_STATUS_FOUND && first_err )
3029
- err = first_err ;
3033
+ if (!err && ac -> ac_status != AC_STATUS_FOUND && ac -> ac_first_err )
3034
+ err = ac -> ac_first_err ;
3030
3035
3031
3036
mb_debug (sb , "Best len %d, origin len %d, ac_status %u, ac_flags 0x%x, cr %d ret %d\n" ,
3032
3037
ac -> ac_b_ex .fe_len , ac -> ac_o_ex .fe_len , ac -> ac_status ,
0 commit comments