aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2009-01-05 21:36:55 -0500
committerTheodore Ts'o <tytso@mit.edu>2009-01-05 21:36:55 -0500
commit7a2fcbf7f85737735fd44eb34b62315bccf6d6e4 (patch)
tree19c7dd8cc56864445dd5fbe3fd2b941d1966492d /fs
parentfb68407b0d9efba962c03f55009c797e22f024bc (diff)
ext4: don't use blocks freed but not yet committed in buddy cache init
When we generate buddy cache (especially during resize) we need to make sure we don't use the blocks freed but not yet comitted. This makes sure we have the right value of free blocks count in the group info and also in the bitmap. This also ensures the ordered mode consistency Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> Cc: stable@kernel.org
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/mballoc.c82
1 files changed, 60 insertions, 22 deletions
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index c17063ddb307..860766421fe8 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -335,6 +335,8 @@ static struct kmem_cache *ext4_ac_cachep;
335static struct kmem_cache *ext4_free_ext_cachep; 335static struct kmem_cache *ext4_free_ext_cachep;
336static void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap, 336static void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap,
337 ext4_group_t group); 337 ext4_group_t group);
338static void ext4_mb_generate_from_freelist(struct super_block *sb, void *bitmap,
339 ext4_group_t group);
338static int ext4_mb_init_per_dev_proc(struct super_block *sb); 340static int ext4_mb_init_per_dev_proc(struct super_block *sb);
339static int ext4_mb_destroy_per_dev_proc(struct super_block *sb); 341static int ext4_mb_destroy_per_dev_proc(struct super_block *sb);
340static void release_blocks_on_commit(journal_t *journal, transaction_t *txn); 342static void release_blocks_on_commit(journal_t *journal, transaction_t *txn);
@@ -858,7 +860,9 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
858 /* 860 /*
859 * incore got set to the group block bitmap below 861 * incore got set to the group block bitmap below
860 */ 862 */
863 ext4_lock_group(sb, group);
861 ext4_mb_generate_buddy(sb, data, incore, group); 864 ext4_mb_generate_buddy(sb, data, incore, group);
865 ext4_unlock_group(sb, group);
862 incore = NULL; 866 incore = NULL;
863 } else { 867 } else {
864 /* this is block of bitmap */ 868 /* this is block of bitmap */
@@ -872,6 +876,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
872 876
873 /* mark all preallocated blks used in in-core bitmap */ 877 /* mark all preallocated blks used in in-core bitmap */
874 ext4_mb_generate_from_pa(sb, data, group); 878 ext4_mb_generate_from_pa(sb, data, group);
879 ext4_mb_generate_from_freelist(sb, data, group);
875 ext4_unlock_group(sb, group); 880 ext4_unlock_group(sb, group);
876 881
877 /* set incore so that the buddy information can be 882 /* set incore so that the buddy information can be
@@ -3472,6 +3477,32 @@ ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
3472} 3477}
3473 3478
3474/* 3479/*
3480 * the function goes through all block freed in the group
3481 * but not yet committed and marks them used in in-core bitmap.
3482 * buddy must be generated from this bitmap
3483 * Need to be called with ext4 group lock (ext4_lock_group)
3484 */
3485static void ext4_mb_generate_from_freelist(struct super_block *sb, void *bitmap,
3486 ext4_group_t group)
3487{
3488 struct rb_node *n;
3489 struct ext4_group_info *grp;
3490 struct ext4_free_data *entry;
3491
3492 grp = ext4_get_group_info(sb, group);
3493 n = rb_first(&(grp->bb_free_root));
3494
3495 while (n) {
3496 entry = rb_entry(n, struct ext4_free_data, node);
3497 mb_set_bits(sb_bgl_lock(EXT4_SB(sb), group),
3498 bitmap, entry->start_blk,
3499 entry->count);
3500 n = rb_next(n);
3501 }
3502 return;
3503}
3504
3505/*
3475 * the function goes through all preallocation in this group and marks them 3506 * the function goes through all preallocation in this group and marks them
3476 * used in in-core bitmap. buddy must be generated from this bitmap 3507 * used in in-core bitmap. buddy must be generated from this bitmap
3477 * Need to be called with ext4 group lock (ext4_lock_group) 3508 * Need to be called with ext4 group lock (ext4_lock_group)
@@ -4568,12 +4599,13 @@ static int can_merge(struct ext4_free_data *entry1,
4568 4599
4569static noinline_for_stack int 4600static noinline_for_stack int
4570ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b, 4601ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
4571 ext4_group_t group, ext4_grpblk_t block, int count) 4602 struct ext4_free_data *new_entry)
4572{ 4603{
4604 ext4_grpblk_t block;
4605 struct ext4_free_data *entry;
4573 struct ext4_group_info *db = e4b->bd_info; 4606 struct ext4_group_info *db = e4b->bd_info;
4574 struct super_block *sb = e4b->bd_sb; 4607 struct super_block *sb = e4b->bd_sb;
4575 struct ext4_sb_info *sbi = EXT4_SB(sb); 4608 struct ext4_sb_info *sbi = EXT4_SB(sb);
4576 struct ext4_free_data *entry, *new_entry;
4577 struct rb_node **n = &db->bb_free_root.rb_node, *node; 4609 struct rb_node **n = &db->bb_free_root.rb_node, *node;
4578 struct rb_node *parent = NULL, *new_node; 4610 struct rb_node *parent = NULL, *new_node;
4579 4611
@@ -4581,14 +4613,9 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
4581 BUG_ON(e4b->bd_bitmap_page == NULL); 4613 BUG_ON(e4b->bd_bitmap_page == NULL);
4582 BUG_ON(e4b->bd_buddy_page == NULL); 4614 BUG_ON(e4b->bd_buddy_page == NULL);
4583 4615
4584 new_entry = kmem_cache_alloc(ext4_free_ext_cachep, GFP_NOFS);
4585 new_entry->start_blk = block;
4586 new_entry->group = group;
4587 new_entry->count = count;
4588 new_entry->t_tid = handle->h_transaction->t_tid;
4589 new_node = &new_entry->node; 4616 new_node = &new_entry->node;
4617 block = new_entry->start_blk;
4590 4618
4591 ext4_lock_group(sb, group);
4592 if (!*n) { 4619 if (!*n) {
4593 /* first free block exent. We need to 4620 /* first free block exent. We need to
4594 protect buddy cache from being freed, 4621 protect buddy cache from being freed,
@@ -4606,7 +4633,6 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
4606 else if (block >= (entry->start_blk + entry->count)) 4633 else if (block >= (entry->start_blk + entry->count))
4607 n = &(*n)->rb_right; 4634 n = &(*n)->rb_right;
4608 else { 4635 else {
4609 ext4_unlock_group(sb, group);
4610 ext4_error(sb, __func__, 4636 ext4_error(sb, __func__,
4611 "Double free of blocks %d (%d %d)", 4637 "Double free of blocks %d (%d %d)",
4612 block, entry->start_blk, entry->count); 4638 block, entry->start_blk, entry->count);
@@ -4648,7 +4674,6 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
4648 spin_lock(&sbi->s_md_lock); 4674 spin_lock(&sbi->s_md_lock);
4649 list_add(&new_entry->list, &handle->h_transaction->t_private_list); 4675 list_add(&new_entry->list, &handle->h_transaction->t_private_list);
4650 spin_unlock(&sbi->s_md_lock); 4676 spin_unlock(&sbi->s_md_lock);
4651 ext4_unlock_group(sb, group);
4652 return 0; 4677 return 0;
4653} 4678}
4654 4679
@@ -4753,15 +4778,6 @@ do_more:
4753 BUG_ON(!mb_test_bit(bit + i, bitmap_bh->b_data)); 4778 BUG_ON(!mb_test_bit(bit + i, bitmap_bh->b_data));
4754 } 4779 }
4755#endif 4780#endif
4756 mb_clear_bits(sb_bgl_lock(sbi, block_group), bitmap_bh->b_data,
4757 bit, count);
4758
4759 /* We dirtied the bitmap block */
4760 BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
4761 err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
4762 if (err)
4763 goto error_return;
4764
4765 if (ac) { 4781 if (ac) {
4766 ac->ac_b_ex.fe_group = block_group; 4782 ac->ac_b_ex.fe_group = block_group;
4767 ac->ac_b_ex.fe_start = bit; 4783 ac->ac_b_ex.fe_start = bit;
@@ -4773,11 +4789,29 @@ do_more:
4773 if (err) 4789 if (err)
4774 goto error_return; 4790 goto error_return;
4775 if (metadata && ext4_handle_valid(handle)) { 4791 if (metadata && ext4_handle_valid(handle)) {
4776 /* blocks being freed are metadata. these blocks shouldn't 4792 struct ext4_free_data *new_entry;
4777 * be used until this transaction is committed */ 4793 /*
4778 ext4_mb_free_metadata(handle, &e4b, block_group, bit, count); 4794 * blocks being freed are metadata. these blocks shouldn't
4795 * be used until this transaction is committed
4796 */
4797 new_entry = kmem_cache_alloc(ext4_free_ext_cachep, GFP_NOFS);
4798 new_entry->start_blk = bit;
4799 new_entry->group = block_group;
4800 new_entry->count = count;
4801 new_entry->t_tid = handle->h_transaction->t_tid;
4802 ext4_lock_group(sb, block_group);
4803 mb_clear_bits(sb_bgl_lock(sbi, block_group), bitmap_bh->b_data,
4804 bit, count);
4805 ext4_mb_free_metadata(handle, &e4b, new_entry);
4806 ext4_unlock_group(sb, block_group);
4779 } else { 4807 } else {
4780 ext4_lock_group(sb, block_group); 4808 ext4_lock_group(sb, block_group);
4809 /* need to update group_info->bb_free and bitmap
4810 * with group lock held. generate_buddy look at
4811 * them with group lock_held
4812 */
4813 mb_clear_bits(sb_bgl_lock(sbi, block_group), bitmap_bh->b_data,
4814 bit, count);
4781 mb_free_blocks(inode, &e4b, bit, count); 4815 mb_free_blocks(inode, &e4b, bit, count);
4782 ext4_mb_return_to_preallocation(inode, &e4b, block, count); 4816 ext4_mb_return_to_preallocation(inode, &e4b, block, count);
4783 ext4_unlock_group(sb, block_group); 4817 ext4_unlock_group(sb, block_group);
@@ -4800,6 +4834,10 @@ do_more:
4800 4834
4801 *freed += count; 4835 *freed += count;
4802 4836
4837 /* We dirtied the bitmap block */
4838 BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
4839 err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
4840
4803 /* And the group descriptor block */ 4841 /* And the group descriptor block */
4804 BUFFER_TRACE(gd_bh, "dirtied group descriptor block"); 4842 BUFFER_TRACE(gd_bh, "dirtied group descriptor block");
4805 ret = ext4_handle_dirty_metadata(handle, NULL, gd_bh); 4843 ret = ext4_handle_dirty_metadata(handle, NULL, gd_bh);