From 2bd94bd79e5bfa217714f78e5d6d7b6517ca546f Mon Sep 17 00:00:00 2001 From: Mingming Cao Date: Wed, 6 Dec 2006 20:38:18 -0800 Subject: [PATCH] ext3: fix reservation extension Hugh Dickins wrote: > Not found anything relevant, but I keep noticing these lines > in ext2_try_to_allocate_with_rsv(), ext3 and ext4 similar: > > } else if (grp_goal > 0 && > (my_rsv->rsv_end - grp_goal + 1) < *count) > try_to_extend_reservation(my_rsv, sb, > *count-my_rsv->rsv_end + grp_goal - 1); > > They're wrong, a no-op in most groups, aren't they? rsv_end is an > absolute block number, whereas grp_goal is group-relative, so the > calculation ought to bring in group_first_block? Or I'm confused. > Signed-off-by: Mingming Cao Cc: "linux-ext4@vger.kernel.org" Cc: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/balloc.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'fs/ext3/balloc.c') diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index b41a7d7e20f..f96c40a90e2 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -1307,10 +1307,14 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, if (!goal_in_my_reservation(&my_rsv->rsv_window, grp_goal, group, sb)) grp_goal = -1; - } else if (grp_goal > 0 && - (my_rsv->rsv_end-grp_goal+1) < *count) - try_to_extend_reservation(my_rsv, sb, - *count-my_rsv->rsv_end + grp_goal - 1); + } else if (grp_goal > 0) { + int curr = my_rsv->rsv_end - + (grp_goal + group_first_block) + 1; + + if (curr < *count) + try_to_extend_reservation(my_rsv, sb, + *count - curr); + } if ((my_rsv->rsv_start > group_last_block) || (my_rsv->rsv_end < group_first_block)) { -- cgit v1.2.3-70-g09d2 From ef5036782e619ab394daaec5c00876fa6b17d7a1 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 6 Dec 2006 20:41:23 -0800 Subject: [PATCH] ext3 balloc: reset windowsz when full ext3_new_blocks should reset the reservation window size to 0 when squeezing the last blocks out of an almost full filesystem, so the retry doesn't skip any groups with less than half that free, reporting ENOSPC too soon. Signed-off-by: Mingming Cao Signed-off-by: Hugh Dickins Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/balloc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs/ext3/balloc.c') diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index f96c40a90e2..db8ca34d102 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -1552,6 +1552,7 @@ retry_alloc: */ if (my_rsv) { my_rsv = NULL; + windowsz = 0; group_no = goal_group; goto retry_alloc; } -- cgit v1.2.3-70-g09d2 From 1650242324a0c19d629a8be0d5a8ecdc174d31f8 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 6 Dec 2006 20:41:25 -0800 Subject: [PATCH] ext3 balloc: fix off-by-one against grp_goal grp_goal 0 is a genuine goal (unlike -1), so ext3_try_to_allocate_with_rsv should treat it as such. Signed-off-by: Mingming Cao Signed-off-by: Hugh Dickins Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/balloc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/ext3/balloc.c') diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index db8ca34d102..0706a45d3c0 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -1271,7 +1271,7 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, } /* * grp_goal is a group relative block number (if there is a goal) - * 0 < grp_goal < EXT3_BLOCKS_PER_GROUP(sb) + * 0 <= grp_goal < EXT3_BLOCKS_PER_GROUP(sb) * first block is a filesystem wide block number * first block is the block number of the first block in this group */ @@ -1307,7 +1307,7 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, if (!goal_in_my_reservation(&my_rsv->rsv_window, grp_goal, group, sb)) grp_goal = -1; - } else if (grp_goal > 0) { + } else if (grp_goal >= 0) { int curr = my_rsv->rsv_end - (grp_goal + group_first_block) + 1; -- cgit v1.2.3-70-g09d2 From ff50dc562bf6de00fec264b11531e2745209ba12 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 6 Dec 2006 20:41:25 -0800 Subject: [PATCH] ext3 balloc: fix off-by-one against rsv_end rsv_end is the last block within the reservation, so alloc_new_reservation should accept start_block == rsv_end as success. Signed-off-by: Mingming Cao Signed-off-by: Hugh Dickins Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/balloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/ext3/balloc.c') diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index 0706a45d3c0..57cf47a9420 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -1148,7 +1148,7 @@ retry: * check if the first free block is within the * free space we just reserved */ - if (start_block >= my_rsv->rsv_start && start_block < my_rsv->rsv_end) + if (start_block >= my_rsv->rsv_start && start_block <= my_rsv->rsv_end) return 0; /* success */ /* * if the first free bit we found is out of the reservable space -- cgit v1.2.3-70-g09d2 From c56d2561f7189762c4fce854630d4f7f6d64ccee Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 6 Dec 2006 20:41:27 -0800 Subject: [PATCH] ext3 balloc: say rb_entry not list_entry The reservations tree is an rb_tree not a list, so it's less confusing to use rb_entry() than list_entry() - though they're both just container_of(). Signed-off-by: Mingming Cao Signed-off-by: Hugh Dickins Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/balloc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'fs/ext3/balloc.c') diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index 57cf47a9420..03d39b6fd30 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -144,7 +144,7 @@ restart: printk("Block Allocation Reservation Windows Map (%s):\n", fn); while (n) { - rsv = list_entry(n, struct ext3_reserve_window_node, rsv_node); + rsv = rb_entry(n, struct ext3_reserve_window_node, rsv_node); if (verbose) printk("reservation window 0x%p " "start: %lu, end: %lu\n", @@ -949,7 +949,7 @@ static int find_next_reservable_window( prev = rsv; next = rb_next(&rsv->rsv_node); - rsv = list_entry(next,struct ext3_reserve_window_node,rsv_node); + rsv = rb_entry(next,struct ext3_reserve_window_node,rsv_node); /* * Reached the last reservation, we can just append to the @@ -1193,7 +1193,7 @@ static void try_to_extend_reservation(struct ext3_reserve_window_node *my_rsv, if (!next) my_rsv->rsv_end += size; else { - next_rsv = list_entry(next, struct ext3_reserve_window_node, rsv_node); + next_rsv = rb_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; -- cgit v1.2.3-70-g09d2 From 2823b5535efad71e950ef50c2ce5f9e4dbaedc17 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 6 Dec 2006 20:41:28 -0800 Subject: [PATCH] ext3 balloc: use io_error label ext3_new_blocks has a nice io_error label for setting -EIO, so goto that in the one place that doesn't already use it. Signed-off-by: Mingming Cao Signed-off-by: Hugh Dickins Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/balloc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'fs/ext3/balloc.c') diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index 03d39b6fd30..5a2c198762f 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -1515,10 +1515,8 @@ retry_alloc: if (group_no >= ngroups) group_no = 0; gdp = ext3_get_group_desc(sb, group_no, &gdp_bh); - if (!gdp) { - *errp = -EIO; - goto out; - } + if (!gdp) + goto io_error; free_blocks = le16_to_cpu(gdp->bg_free_blocks_count); /* * skip this group if the number of -- cgit v1.2.3-70-g09d2 From 7d1c520bb57e4b5e94ec937c13553dccf473341b Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 6 Dec 2006 20:41:30 -0800 Subject: [PATCH] ext3 balloc: fix _with_rsv freeze Port fix to the off-by-one in find_next_usable_block's memscan from ext2 to ext3; but it didn't cause a serious problem for ext3 because the additional ext3_test_allocatable check rescued it from the error. Signed-off-by: Mingming Cao Signed-off-by: Hugh Dickins Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/balloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/ext3/balloc.c') diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index 5a2c198762f..22161740ba2 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -730,7 +730,7 @@ find_next_usable_block(ext3_grpblk_t start, struct buffer_head *bh, here = 0; p = ((char *)bh->b_data) + (here >> 3); - r = memscan(p, 0, (maxblocks - here + 7) >> 3); + r = memscan(p, 0, ((maxblocks + 7) >> 3) - (here >> 3)); next = (r - ((char *)bh->b_data)) << 3; if (next < maxblocks && next >= start && ext3_test_allocatable(next, bh)) -- cgit v1.2.3-70-g09d2