From: Mingming Cao This patch is trying to do lazy discard: keep the old reservation window temporarilly until we find the new reservation window, only do remove/add if the new reservation window locate different than the old one. (The current reservation code will discard the old one first,then search the new one). Two reasons: a. If the ext3_find_goal() does a good job, the reservation windows on the list should not very close to each other. So an inode's new reservation window is likely located just next to it's old one, it's position in the whole list is unchanged, no need to do remove and then add the new one to the list in the same location. Just update the start block and end block. b. If we failed to find a new reservation in the goal group and move on the search to the next group, having the old reservation around temporally could allow us to search the list directly after the old window. Otherwise we lost where we were and has to start from the beginning of the list. Eventually the old window will be discard when we found a new one. --- 25-akpm/fs/ext3/balloc.c | 22 +++++++++++++++------- 1 files changed, 15 insertions(+), 7 deletions(-) diff -puN fs/ext3/balloc.c~ext3-lazy-discard-reservation-window-patch fs/ext3/balloc.c --- 25/fs/ext3/balloc.c~ext3-lazy-discard-reservation-window-patch 2004-04-23 23:10:54.596005224 -0700 +++ 25-akpm/fs/ext3/balloc.c 2004-04-23 23:10:54.601004464 -0700 @@ -726,7 +726,7 @@ static int alloc_new_reservation(struct start_block = goal + group_first_block; size = atomic_read(&my_rsv->rsv_goal_size); - /* if we have a old reservation, discard it first */ + /* if we have a old reservation, start the search from the old rsv */ if (!rsv_is_empty(my_rsv)) { /* * if the old reservation is cross group boundary @@ -748,8 +748,7 @@ static int alloc_new_reservation(struct /* 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 = list_entry(my_rsv->rsv_list.prev, - struct reserve_window, rsv_list); + search_head = my_rsv; if ((my_rsv->rsv_alloc_hit > (my_rsv->rsv_end - my_rsv->rsv_start + 1) / 2)) { /* * if we previously allocation hit ration is greater than half @@ -761,7 +760,6 @@ static int alloc_new_reservation(struct size = EXT3_MAX_RESERVE_BLOCKS; atomic_set(&my_rsv->rsv_goal_size, size); } - rsv_window_remove(my_rsv); } else { /* @@ -828,9 +826,16 @@ retry: found_rsv_window: /* * great! the reservable space contains some free blocks. - * Insert it to the list. - */ - rsv_window_add(my_rsv, prev_rsv); + * if the search returns that we should add the new + * window just next to where the old window, we don't + * need to remove the old window first then add it to the + * same place, just update the new start and new end. + */ + if (my_rsv != prev_rsv) { + if (!rsv_is_empty(my_rsv)) + rsv_window_remove(my_rsv); + rsv_window_add(my_rsv, prev_rsv); + } my_rsv->rsv_start = reservable_space_start; my_rsv->rsv_end = my_rsv->rsv_start + size - 1; return 0; /* succeed */ @@ -932,6 +937,9 @@ ext3_try_to_allocate_with_rsv(struct sup if (!goal_in_my_reservation(my_rsv, goal, group, sb)) goal = -1; } + if ((my_rsv->rsv_start >= group_first_block + EXT3_BLOCKS_PER_GROUP(sb)) + || (my_rsv->rsv_end < group_first_block)) + BUG(); ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, goal, my_rsv); if (ret >= 0) _