aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/mballoc.c
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2009-01-05 21:46:55 -0500
committerTheodore Ts'o <tytso@mit.edu>2009-01-05 21:46:55 -0500
commit8556e8f3b6c4c11601ce1e9ea8090a6d8bd5daae (patch)
tree8a0da99a4781cbde8c050d7cbcd85f31fd54e894 /fs/ext4/mballoc.c
parent648f5879f5892dddd3ba71cd0d285599f40f2512 (diff)
ext4: Don't allow new groups to be added during block allocation
After we mark the blocks in the buddy cache as allocated, we need to ensure that we don't reinit the buddy cache until the block bitmap is updated. This commit achieves this by holding the group_info alloc_semaphore till ext4_mb_release_context 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/ext4/mballoc.c')
-rw-r--r--fs/ext4/mballoc.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 7d7f6f91d555..0c7e247f714c 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -1052,7 +1052,8 @@ static void ext4_mb_release_desc(struct ext4_buddy *e4b)
1052 if (e4b->bd_buddy_page) 1052 if (e4b->bd_buddy_page)
1053 page_cache_release(e4b->bd_buddy_page); 1053 page_cache_release(e4b->bd_buddy_page);
1054 /* Done with the buddy cache */ 1054 /* Done with the buddy cache */
1055 up_read(e4b->alloc_semp); 1055 if (e4b->alloc_semp)
1056 up_read(e4b->alloc_semp);
1056} 1057}
1057 1058
1058 1059
@@ -1371,7 +1372,9 @@ static void ext4_mb_use_best_found(struct ext4_allocation_context *ac,
1371 get_page(ac->ac_bitmap_page); 1372 get_page(ac->ac_bitmap_page);
1372 ac->ac_buddy_page = e4b->bd_buddy_page; 1373 ac->ac_buddy_page = e4b->bd_buddy_page;
1373 get_page(ac->ac_buddy_page); 1374 get_page(ac->ac_buddy_page);
1374 1375 /* on allocation we use ac to track the held semaphore */
1376 ac->alloc_semp = e4b->alloc_semp;
1377 e4b->alloc_semp = NULL;
1375 /* store last allocated for subsequent stream allocation */ 1378 /* store last allocated for subsequent stream allocation */
1376 if ((ac->ac_flags & EXT4_MB_HINT_DATA)) { 1379 if ((ac->ac_flags & EXT4_MB_HINT_DATA)) {
1377 spin_lock(&sbi->s_md_lock); 1380 spin_lock(&sbi->s_md_lock);
@@ -4289,6 +4292,7 @@ ext4_mb_initialize_context(struct ext4_allocation_context *ac,
4289 ac->ac_pa = NULL; 4292 ac->ac_pa = NULL;
4290 ac->ac_bitmap_page = NULL; 4293 ac->ac_bitmap_page = NULL;
4291 ac->ac_buddy_page = NULL; 4294 ac->ac_buddy_page = NULL;
4295 ac->alloc_semp = NULL;
4292 ac->ac_lg = NULL; 4296 ac->ac_lg = NULL;
4293 4297
4294 /* we have to define context: we'll we work with a file or 4298 /* we have to define context: we'll we work with a file or
@@ -4469,6 +4473,8 @@ static int ext4_mb_release_context(struct ext4_allocation_context *ac)
4469 } 4473 }
4470 ext4_mb_put_pa(ac, ac->ac_sb, pa); 4474 ext4_mb_put_pa(ac, ac->ac_sb, pa);
4471 } 4475 }
4476 if (ac->alloc_semp)
4477 up_read(ac->alloc_semp);
4472 if (ac->ac_bitmap_page) 4478 if (ac->ac_bitmap_page)
4473 page_cache_release(ac->ac_bitmap_page); 4479 page_cache_release(ac->ac_bitmap_page);
4474 if (ac->ac_buddy_page) 4480 if (ac->ac_buddy_page)
@@ -4569,10 +4575,14 @@ repeat:
4569 ac->ac_o_ex.fe_len < ac->ac_b_ex.fe_len) 4575 ac->ac_o_ex.fe_len < ac->ac_b_ex.fe_len)
4570 ext4_mb_new_preallocation(ac); 4576 ext4_mb_new_preallocation(ac);
4571 } 4577 }
4572
4573 if (likely(ac->ac_status == AC_STATUS_FOUND)) { 4578 if (likely(ac->ac_status == AC_STATUS_FOUND)) {
4574 *errp = ext4_mb_mark_diskspace_used(ac, handle, reserv_blks); 4579 *errp = ext4_mb_mark_diskspace_used(ac, handle, reserv_blks);
4575 if (*errp == -EAGAIN) { 4580 if (*errp == -EAGAIN) {
4581 /*
4582 * drop the reference that we took
4583 * in ext4_mb_use_best_found
4584 */
4585 ext4_mb_release_context(ac);
4576 ac->ac_b_ex.fe_group = 0; 4586 ac->ac_b_ex.fe_group = 0;
4577 ac->ac_b_ex.fe_start = 0; 4587 ac->ac_b_ex.fe_start = 0;
4578 ac->ac_b_ex.fe_len = 0; 4588 ac->ac_b_ex.fe_len = 0;