From: Mingming Cao Found that in the current reservation code, if there is a need to allocate a new window to replace the old window to satisfy the new allocation goal, no matter where is the allocation goal, the new window will be allocated _after_ the old window. So, if the allocation goal block is smaller than the start block of the old reservation window, the goal block will _not_ be satisfied. This happens due to we adjusted the goal block to the block next to the end of the old reservation window, and then start from the old reservation, we search for a space to make a new reservation window. This is not our intention, as we always want to grant the goal block. Though the bug present with/without recent red-black tree changes, here is the fix based on red-black tree change: we will do a red-black tree search from the old reservation window , to locate a window nearest the allocation goal. Signed-off-by: Andrew Morton --- 25-akpm/fs/ext3/balloc.c | 26 ++++++-------------------- 1 files changed, 6 insertions(+), 20 deletions(-) diff -puN fs/ext3/balloc.c~ext3-reservations-window-allocation-fix fs/ext3/balloc.c --- 25/fs/ext3/balloc.c~ext3-reservations-window-allocation-fix Tue Sep 14 18:47:29 2004 +++ 25-akpm/fs/ext3/balloc.c Tue Sep 14 18:47:29 2004 @@ -184,10 +184,9 @@ goal_in_my_reservation(struct reserve_wi * if the goal is not in any window. * Returns NULL if there are no windows or if all windows start after the goal. */ -static struct reserve_window_node *search_reserve_window(struct rb_root *root, +static struct reserve_window_node *search_reserve_window(struct rb_node *n, unsigned long goal) { - struct rb_node *n = root->rb_node; struct reserve_window_node *rsv; if (!n) @@ -767,19 +766,11 @@ static struct reserve_window_node *find_ /** * alloc_new_reservation()--allocate a new reservation window - * if there is an existing reservation, discard it first - * then allocate the new one from there - * otherwise allocate the new reservation from the given - * start block, or the beginning of the group, if a goal - * is not given. * * To make a new reservation, we search part of the filesystem - * reservation list (the list that inside the group). - * - * If we have a old reservation, the search goal is the end of - * last reservation. If we do not have a old reservation, then we - * start from a given goal, or the first block of the group, if - * the goal is not given. + * reservation list (the list that inside the group). We try to + * allocate a new reservation window near the allocation goal, + * or the beginning of the group, if there is no goal. * * We first find a reservable space after the goal, then from * there, we check the bitmap for the first free block after @@ -801,8 +792,6 @@ static struct reserve_window_node *find_ * * @goal: The goal (group-relative). It is where the search for a * free reservable space should start from. - * if we have a old reservation, start_block is the end of - * old reservation. Otherwise, * if we have a goal(goal >0 ), then start from there, * no goal(goal = -1), we start from the first block * of the group. @@ -852,10 +841,7 @@ static int alloc_new_reservation(struct (my_rsv->rsv_end > group_end_block)) return -1; - /* remember where we are before we discard the old one */ - if (my_rsv->rsv_end + 1 > start_block) - start_block = my_rsv->rsv_end + 1; - search_head = my_rsv; + search_head = search_reserve_window(&my_rsv->rsv_node, start_block); if ((atomic_read(&my_rsv->rsv_alloc_hit) > (my_rsv->rsv_end - my_rsv->rsv_start + 1) / 2)) { /* @@ -875,7 +861,7 @@ static int alloc_new_reservation(struct * we set our goal(start_block) and * the list head for the search */ - search_head = search_reserve_window(fs_rsv_root, start_block); + search_head = search_reserve_window(fs_rsv_root->rb_node, start_block); } /* _