diff options
Diffstat (limited to 'fs/ext4/mballoc.c')
| -rw-r--r-- | fs/ext4/mballoc.c | 53 |
1 files changed, 46 insertions, 7 deletions
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 865e9ddb44d4..e0e3a5eb1ddb 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
| @@ -3282,6 +3282,35 @@ static void ext4_mb_use_group_pa(struct ext4_allocation_context *ac, | |||
| 3282 | } | 3282 | } |
| 3283 | 3283 | ||
| 3284 | /* | 3284 | /* |
| 3285 | * Return the prealloc space that have minimal distance | ||
| 3286 | * from the goal block. @cpa is the prealloc | ||
| 3287 | * space that is having currently known minimal distance | ||
| 3288 | * from the goal block. | ||
| 3289 | */ | ||
| 3290 | static struct ext4_prealloc_space * | ||
| 3291 | ext4_mb_check_group_pa(ext4_fsblk_t goal_block, | ||
| 3292 | struct ext4_prealloc_space *pa, | ||
| 3293 | struct ext4_prealloc_space *cpa) | ||
| 3294 | { | ||
| 3295 | ext4_fsblk_t cur_distance, new_distance; | ||
| 3296 | |||
| 3297 | if (cpa == NULL) { | ||
| 3298 | atomic_inc(&pa->pa_count); | ||
| 3299 | return pa; | ||
| 3300 | } | ||
| 3301 | cur_distance = abs(goal_block - cpa->pa_pstart); | ||
| 3302 | new_distance = abs(goal_block - pa->pa_pstart); | ||
| 3303 | |||
| 3304 | if (cur_distance < new_distance) | ||
| 3305 | return cpa; | ||
| 3306 | |||
| 3307 | /* drop the previous reference */ | ||
| 3308 | atomic_dec(&cpa->pa_count); | ||
| 3309 | atomic_inc(&pa->pa_count); | ||
| 3310 | return pa; | ||
| 3311 | } | ||
| 3312 | |||
| 3313 | /* | ||
| 3285 | * search goal blocks in preallocated space | 3314 | * search goal blocks in preallocated space |
| 3286 | */ | 3315 | */ |
| 3287 | static noinline_for_stack int | 3316 | static noinline_for_stack int |
| @@ -3290,7 +3319,8 @@ ext4_mb_use_preallocated(struct ext4_allocation_context *ac) | |||
| 3290 | int order, i; | 3319 | int order, i; |
| 3291 | struct ext4_inode_info *ei = EXT4_I(ac->ac_inode); | 3320 | struct ext4_inode_info *ei = EXT4_I(ac->ac_inode); |
| 3292 | struct ext4_locality_group *lg; | 3321 | struct ext4_locality_group *lg; |
| 3293 | struct ext4_prealloc_space *pa; | 3322 | struct ext4_prealloc_space *pa, *cpa = NULL; |
| 3323 | ext4_fsblk_t goal_block; | ||
| 3294 | 3324 | ||
| 3295 | /* only data can be preallocated */ | 3325 | /* only data can be preallocated */ |
| 3296 | if (!(ac->ac_flags & EXT4_MB_HINT_DATA)) | 3326 | if (!(ac->ac_flags & EXT4_MB_HINT_DATA)) |
| @@ -3333,6 +3363,13 @@ ext4_mb_use_preallocated(struct ext4_allocation_context *ac) | |||
| 3333 | /* The max size of hash table is PREALLOC_TB_SIZE */ | 3363 | /* The max size of hash table is PREALLOC_TB_SIZE */ |
| 3334 | order = PREALLOC_TB_SIZE - 1; | 3364 | order = PREALLOC_TB_SIZE - 1; |
| 3335 | 3365 | ||
| 3366 | goal_block = ac->ac_g_ex.fe_group * EXT4_BLOCKS_PER_GROUP(ac->ac_sb) + | ||
| 3367 | ac->ac_g_ex.fe_start + | ||
| 3368 | le32_to_cpu(EXT4_SB(ac->ac_sb)->s_es->s_first_data_block); | ||
| 3369 | /* | ||
| 3370 | * search for the prealloc space that is having | ||
| 3371 | * minimal distance from the goal block. | ||
| 3372 | */ | ||
| 3336 | for (i = order; i < PREALLOC_TB_SIZE; i++) { | 3373 | for (i = order; i < PREALLOC_TB_SIZE; i++) { |
| 3337 | rcu_read_lock(); | 3374 | rcu_read_lock(); |
| 3338 | list_for_each_entry_rcu(pa, &lg->lg_prealloc_list[i], | 3375 | list_for_each_entry_rcu(pa, &lg->lg_prealloc_list[i], |
| @@ -3340,17 +3377,19 @@ ext4_mb_use_preallocated(struct ext4_allocation_context *ac) | |||
| 3340 | spin_lock(&pa->pa_lock); | 3377 | spin_lock(&pa->pa_lock); |
| 3341 | if (pa->pa_deleted == 0 && | 3378 | if (pa->pa_deleted == 0 && |
| 3342 | pa->pa_free >= ac->ac_o_ex.fe_len) { | 3379 | pa->pa_free >= ac->ac_o_ex.fe_len) { |
| 3343 | atomic_inc(&pa->pa_count); | 3380 | |
| 3344 | ext4_mb_use_group_pa(ac, pa); | 3381 | cpa = ext4_mb_check_group_pa(goal_block, |
| 3345 | spin_unlock(&pa->pa_lock); | 3382 | pa, cpa); |
| 3346 | ac->ac_criteria = 20; | ||
| 3347 | rcu_read_unlock(); | ||
| 3348 | return 1; | ||
| 3349 | } | 3383 | } |
| 3350 | spin_unlock(&pa->pa_lock); | 3384 | spin_unlock(&pa->pa_lock); |
| 3351 | } | 3385 | } |
| 3352 | rcu_read_unlock(); | 3386 | rcu_read_unlock(); |
| 3353 | } | 3387 | } |
| 3388 | if (cpa) { | ||
| 3389 | ext4_mb_use_group_pa(ac, cpa); | ||
| 3390 | ac->ac_criteria = 20; | ||
| 3391 | return 1; | ||
| 3392 | } | ||
| 3354 | return 0; | 3393 | return 0; |
| 3355 | } | 3394 | } |
| 3356 | 3395 | ||
