|
@@ -1052,7 +1052,8 @@ static void ext4_mb_release_desc(struct ext4_buddy *e4b)
|
|
|
if (e4b->bd_buddy_page)
|
|
|
page_cache_release(e4b->bd_buddy_page);
|
|
|
/* Done with the buddy cache */
|
|
|
- up_read(e4b->alloc_semp);
|
|
|
+ if (e4b->alloc_semp)
|
|
|
+ up_read(e4b->alloc_semp);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -1371,7 +1372,9 @@ static void ext4_mb_use_best_found(struct ext4_allocation_context *ac,
|
|
|
get_page(ac->ac_bitmap_page);
|
|
|
ac->ac_buddy_page = e4b->bd_buddy_page;
|
|
|
get_page(ac->ac_buddy_page);
|
|
|
-
|
|
|
+ /* on allocation we use ac to track the held semaphore */
|
|
|
+ ac->alloc_semp = e4b->alloc_semp;
|
|
|
+ e4b->alloc_semp = NULL;
|
|
|
/* store last allocated for subsequent stream allocation */
|
|
|
if ((ac->ac_flags & EXT4_MB_HINT_DATA)) {
|
|
|
spin_lock(&sbi->s_md_lock);
|
|
@@ -4289,6 +4292,7 @@ ext4_mb_initialize_context(struct ext4_allocation_context *ac,
|
|
|
ac->ac_pa = NULL;
|
|
|
ac->ac_bitmap_page = NULL;
|
|
|
ac->ac_buddy_page = NULL;
|
|
|
+ ac->alloc_semp = NULL;
|
|
|
ac->ac_lg = NULL;
|
|
|
|
|
|
/* 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)
|
|
|
}
|
|
|
ext4_mb_put_pa(ac, ac->ac_sb, pa);
|
|
|
}
|
|
|
+ if (ac->alloc_semp)
|
|
|
+ up_read(ac->alloc_semp);
|
|
|
if (ac->ac_bitmap_page)
|
|
|
page_cache_release(ac->ac_bitmap_page);
|
|
|
if (ac->ac_buddy_page)
|
|
@@ -4569,10 +4575,14 @@ repeat:
|
|
|
ac->ac_o_ex.fe_len < ac->ac_b_ex.fe_len)
|
|
|
ext4_mb_new_preallocation(ac);
|
|
|
}
|
|
|
-
|
|
|
if (likely(ac->ac_status == AC_STATUS_FOUND)) {
|
|
|
*errp = ext4_mb_mark_diskspace_used(ac, handle, reserv_blks);
|
|
|
if (*errp == -EAGAIN) {
|
|
|
+ /*
|
|
|
+ * drop the reference that we took
|
|
|
+ * in ext4_mb_use_best_found
|
|
|
+ */
|
|
|
+ ext4_mb_release_context(ac);
|
|
|
ac->ac_b_ex.fe_group = 0;
|
|
|
ac->ac_b_ex.fe_start = 0;
|
|
|
ac->ac_b_ex.fe_len = 0;
|