@@ -2845,12 +2845,56 @@ void ext4_mb_prefetch_fini(struct super_block *sb, ext4_group_t group,
28452845 }
28462846}
28472847
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+
28482892static noinline_for_stack int
28492893ext4_mb_regular_allocator (struct ext4_allocation_context * ac )
28502894{
28512895 ext4_group_t ngroups , group , i ;
28522896 enum criteria new_cr , cr = CR_GOAL_LEN_FAST ;
2853- int err = 0 , first_err = 0 ;
2897+ int err = 0 ;
28542898 struct ext4_sb_info * sbi ;
28552899 struct super_block * sb ;
28562900 struct ext4_buddy e4b ;
@@ -2912,6 +2956,7 @@ ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
29122956
29132957 ac -> ac_e4b = & e4b ;
29142958 ac -> ac_prefetch_ios = 0 ;
2959+ ac -> ac_first_err = 0 ;
29152960repeat :
29162961 for (; cr < EXT4_MB_NUM_CRS && ac -> ac_status == AC_STATUS_CONTINUE ; cr ++ ) {
29172962 ac -> ac_criteria = cr ;
@@ -2926,57 +2971,17 @@ ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
29262971
29272972 for (i = 0 , new_cr = cr ; i < ngroups ; i ++ ,
29282973 ext4_mb_choose_next_group (ac , & new_cr , & group , ngroups )) {
2929- int ret = 0 ;
29302974
29312975 cond_resched ();
29322976 if (new_cr != cr ) {
29332977 cr = new_cr ;
29342978 goto repeat ;
29352979 }
29362980
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 );
29532982 if (err )
29542983 goto out ;
29552984
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-
29802985 if (ac -> ac_status != AC_STATUS_CONTINUE )
29812986 break ;
29822987 }
@@ -3025,8 +3030,8 @@ ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
30253030 atomic_inc (& sbi -> s_bal_stream_goals );
30263031 }
30273032out :
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 ;
30303035
30313036 mb_debug (sb , "Best len %d, origin len %d, ac_status %u, ac_flags 0x%x, cr %d ret %d\n" ,
30323037 ac -> ac_b_ex .fe_len , ac -> ac_o_ex .fe_len , ac -> ac_status ,
0 commit comments