From d48589bfad0e60bff0aa3f9e4875983f607bd44b Mon Sep 17 00:00:00 2001 From: Mingming Cao Date: Sun, 26 Mar 2006 01:37:59 -0800 Subject: [PATCH] ext3_get_blocks: Adjust reservation window size for mblocks Optimize the block reservation and the multiple block allocation: with the knowledge of the total number of blocks ahead, set or adjust the reservation window size properly (based on the number of blocks needed) before block allocation happens: if there isn't any reservation yet, make sure the reservation window equals to or greater than the number of blocks needed, before create an reservation window; if a reservation window is already exists, try to extends the window size to match the number of blocks to allocate. This could increase the possibility of completing multiple blocks allocation in a single request, as blocks are only allocated in the range of the inode's reservation window. Signed-off-by: Mingming Cao Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/balloc.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) (limited to 'fs/ext3') diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index 7a2c7198b059..77927d6938f6 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -1011,6 +1011,31 @@ retry: goto retry; } +static void try_to_extend_reservation(struct ext3_reserve_window_node *my_rsv, + struct super_block *sb, int size) +{ + struct ext3_reserve_window_node *next_rsv; + struct rb_node *next; + spinlock_t *rsv_lock = &EXT3_SB(sb)->s_rsv_window_lock; + + if (!spin_trylock(rsv_lock)) + return; + + next = rb_next(&my_rsv->rsv_node); + + if (!next) + my_rsv->rsv_end += size; + else { + next_rsv = list_entry(next, struct ext3_reserve_window_node, rsv_node); + + if ((next_rsv->rsv_start - my_rsv->rsv_end - 1) >= size) + my_rsv->rsv_end += size; + else + my_rsv->rsv_end = next_rsv->rsv_start - 1; + } + spin_unlock(rsv_lock); +} + /* * This is the main function used to allocate a new block and its reservation * window. @@ -1095,6 +1120,8 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, while (1) { if (rsv_is_empty(&my_rsv->rsv_window) || (ret < 0) || !goal_in_my_reservation(&my_rsv->rsv_window, goal, group, sb)) { + if (my_rsv->rsv_goal_size < *count) + my_rsv->rsv_goal_size = *count; ret = alloc_new_reservation(my_rsv, goal, sb, group, bitmap_bh); if (ret < 0) @@ -1102,7 +1129,10 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, if (!goal_in_my_reservation(&my_rsv->rsv_window, goal, group, sb)) goal = -1; - } + } else if (goal > 0 && (my_rsv->rsv_end-goal+1) < *count) + try_to_extend_reservation(my_rsv, sb, + *count-my_rsv->rsv_end + goal - 1); + if ((my_rsv->rsv_start >= group_first_block + EXT3_BLOCKS_PER_GROUP(sb)) || (my_rsv->rsv_end < group_first_block)) BUG(); -- cgit v1.2.2