diff options
Diffstat (limited to 'fs/ext4/mballoc.c')
-rw-r--r-- | fs/ext4/mballoc.c | 45 |
1 files changed, 28 insertions, 17 deletions
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index deba54f6cbed..9f61e62f435f 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
@@ -1447,7 +1447,7 @@ static void ext4_mb_measure_extent(struct ext4_allocation_context *ac, | |||
1447 | struct ext4_free_extent *gex = &ac->ac_g_ex; | 1447 | struct ext4_free_extent *gex = &ac->ac_g_ex; |
1448 | 1448 | ||
1449 | BUG_ON(ex->fe_len <= 0); | 1449 | BUG_ON(ex->fe_len <= 0); |
1450 | BUG_ON(ex->fe_len >= EXT4_BLOCKS_PER_GROUP(ac->ac_sb)); | 1450 | BUG_ON(ex->fe_len > EXT4_BLOCKS_PER_GROUP(ac->ac_sb)); |
1451 | BUG_ON(ex->fe_start >= EXT4_BLOCKS_PER_GROUP(ac->ac_sb)); | 1451 | BUG_ON(ex->fe_start >= EXT4_BLOCKS_PER_GROUP(ac->ac_sb)); |
1452 | BUG_ON(ac->ac_status != AC_STATUS_CONTINUE); | 1452 | BUG_ON(ac->ac_status != AC_STATUS_CONTINUE); |
1453 | 1453 | ||
@@ -3292,7 +3292,7 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac, | |||
3292 | } | 3292 | } |
3293 | BUG_ON(start + size <= ac->ac_o_ex.fe_logical && | 3293 | BUG_ON(start + size <= ac->ac_o_ex.fe_logical && |
3294 | start > ac->ac_o_ex.fe_logical); | 3294 | start > ac->ac_o_ex.fe_logical); |
3295 | BUG_ON(size <= 0 || size >= EXT4_BLOCKS_PER_GROUP(ac->ac_sb)); | 3295 | BUG_ON(size <= 0 || size > EXT4_BLOCKS_PER_GROUP(ac->ac_sb)); |
3296 | 3296 | ||
3297 | /* now prepare goal request */ | 3297 | /* now prepare goal request */ |
3298 | 3298 | ||
@@ -3589,6 +3589,7 @@ static void ext4_mb_put_pa(struct ext4_allocation_context *ac, | |||
3589 | struct super_block *sb, struct ext4_prealloc_space *pa) | 3589 | struct super_block *sb, struct ext4_prealloc_space *pa) |
3590 | { | 3590 | { |
3591 | ext4_group_t grp; | 3591 | ext4_group_t grp; |
3592 | ext4_fsblk_t grp_blk; | ||
3592 | 3593 | ||
3593 | if (!atomic_dec_and_test(&pa->pa_count) || pa->pa_free != 0) | 3594 | if (!atomic_dec_and_test(&pa->pa_count) || pa->pa_free != 0) |
3594 | return; | 3595 | return; |
@@ -3603,8 +3604,12 @@ static void ext4_mb_put_pa(struct ext4_allocation_context *ac, | |||
3603 | pa->pa_deleted = 1; | 3604 | pa->pa_deleted = 1; |
3604 | spin_unlock(&pa->pa_lock); | 3605 | spin_unlock(&pa->pa_lock); |
3605 | 3606 | ||
3606 | /* -1 is to protect from crossing allocation group */ | 3607 | grp_blk = pa->pa_pstart; |
3607 | ext4_get_group_no_and_offset(sb, pa->pa_pstart - 1, &grp, NULL); | 3608 | /* If linear, pa_pstart may be in the next group when pa is used up */ |
3609 | if (pa->pa_linear) | ||
3610 | grp_blk--; | ||
3611 | |||
3612 | ext4_get_group_no_and_offset(sb, grp_blk, &grp, NULL); | ||
3608 | 3613 | ||
3609 | /* | 3614 | /* |
3610 | * possible race: | 3615 | * possible race: |
@@ -3693,6 +3698,8 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac) | |||
3693 | pa->pa_free = pa->pa_len; | 3698 | pa->pa_free = pa->pa_len; |
3694 | atomic_set(&pa->pa_count, 1); | 3699 | atomic_set(&pa->pa_count, 1); |
3695 | spin_lock_init(&pa->pa_lock); | 3700 | spin_lock_init(&pa->pa_lock); |
3701 | INIT_LIST_HEAD(&pa->pa_inode_list); | ||
3702 | INIT_LIST_HEAD(&pa->pa_group_list); | ||
3696 | pa->pa_deleted = 0; | 3703 | pa->pa_deleted = 0; |
3697 | pa->pa_linear = 0; | 3704 | pa->pa_linear = 0; |
3698 | 3705 | ||
@@ -3755,6 +3762,7 @@ ext4_mb_new_group_pa(struct ext4_allocation_context *ac) | |||
3755 | atomic_set(&pa->pa_count, 1); | 3762 | atomic_set(&pa->pa_count, 1); |
3756 | spin_lock_init(&pa->pa_lock); | 3763 | spin_lock_init(&pa->pa_lock); |
3757 | INIT_LIST_HEAD(&pa->pa_inode_list); | 3764 | INIT_LIST_HEAD(&pa->pa_inode_list); |
3765 | INIT_LIST_HEAD(&pa->pa_group_list); | ||
3758 | pa->pa_deleted = 0; | 3766 | pa->pa_deleted = 0; |
3759 | pa->pa_linear = 1; | 3767 | pa->pa_linear = 1; |
3760 | 3768 | ||
@@ -4476,23 +4484,26 @@ static int ext4_mb_release_context(struct ext4_allocation_context *ac) | |||
4476 | pa->pa_free -= ac->ac_b_ex.fe_len; | 4484 | pa->pa_free -= ac->ac_b_ex.fe_len; |
4477 | pa->pa_len -= ac->ac_b_ex.fe_len; | 4485 | pa->pa_len -= ac->ac_b_ex.fe_len; |
4478 | spin_unlock(&pa->pa_lock); | 4486 | spin_unlock(&pa->pa_lock); |
4479 | /* | ||
4480 | * We want to add the pa to the right bucket. | ||
4481 | * Remove it from the list and while adding | ||
4482 | * make sure the list to which we are adding | ||
4483 | * doesn't grow big. | ||
4484 | */ | ||
4485 | if (likely(pa->pa_free)) { | ||
4486 | spin_lock(pa->pa_obj_lock); | ||
4487 | list_del_rcu(&pa->pa_inode_list); | ||
4488 | spin_unlock(pa->pa_obj_lock); | ||
4489 | ext4_mb_add_n_trim(ac); | ||
4490 | } | ||
4491 | } | 4487 | } |
4492 | ext4_mb_put_pa(ac, ac->ac_sb, pa); | ||
4493 | } | 4488 | } |
4494 | if (ac->alloc_semp) | 4489 | if (ac->alloc_semp) |
4495 | up_read(ac->alloc_semp); | 4490 | up_read(ac->alloc_semp); |
4491 | if (pa) { | ||
4492 | /* | ||
4493 | * We want to add the pa to the right bucket. | ||
4494 | * Remove it from the list and while adding | ||
4495 | * make sure the list to which we are adding | ||
4496 | * doesn't grow big. We need to release | ||
4497 | * alloc_semp before calling ext4_mb_add_n_trim() | ||
4498 | */ | ||
4499 | if (pa->pa_linear && likely(pa->pa_free)) { | ||
4500 | spin_lock(pa->pa_obj_lock); | ||
4501 | list_del_rcu(&pa->pa_inode_list); | ||
4502 | spin_unlock(pa->pa_obj_lock); | ||
4503 | ext4_mb_add_n_trim(ac); | ||
4504 | } | ||
4505 | ext4_mb_put_pa(ac, ac->ac_sb, pa); | ||
4506 | } | ||
4496 | if (ac->ac_bitmap_page) | 4507 | if (ac->ac_bitmap_page) |
4497 | page_cache_release(ac->ac_bitmap_page); | 4508 | page_cache_release(ac->ac_bitmap_page); |
4498 | if (ac->ac_buddy_page) | 4509 | if (ac->ac_buddy_page) |