summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Wilcox <matthew@wil.cx>2005-03-07 17:47:28 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-03-07 17:47:28 -0800
commitbb596f367f0112c71dd5b8d278dfdb8044074d53 (patch)
tree5108fccde6208793e83e78ab55d796bafea8cdab
parent94ee039d596b1a381a1070fe091e7d0f6aea7bf2 (diff)
[PATCH] ext3: free block accounting fix
If we chose to "do_more", we would double-count the amount freed in the second and subsequent block groups. Fix it the same way as was done in ext2 a couple of years ago. Signed-off-by: Matthew Wilcox <matthew@wil.cx> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--fs/ext3/balloc.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index 0ad9c35b1350..f069d75e5da7 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -288,6 +288,7 @@ void ext3_free_blocks_sb(handle_t *handle, struct super_block *sb,
struct ext3_super_block * es;
struct ext3_sb_info *sbi;
int err = 0, ret;
+ unsigned group_freed;
*pdquot_freed_blocks = 0;
sbi = EXT3_SB(sb);
@@ -358,7 +359,7 @@ do_more:
jbd_lock_bh_state(bitmap_bh);
- for (i = 0; i < count; i++) {
+ for (i = 0, group_freed = 0; i < count; i++) {
/*
* An HJ special. This is expensive...
*/
@@ -421,15 +422,15 @@ do_more:
jbd_lock_bh_state(bitmap_bh);
BUFFER_TRACE(bitmap_bh, "bit already cleared");
} else {
- (*pdquot_freed_blocks)++;
+ group_freed++;
}
}
jbd_unlock_bh_state(bitmap_bh);
spin_lock(sb_bgl_lock(sbi, block_group));
- gdp->bg_free_blocks_count =
- cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) +
- *pdquot_freed_blocks);
+ desc->bg_free_blocks_count =
+ cpu_to_le16(le16_to_cpu(desc->bg_free_blocks_count) +
+ group_freed);
spin_unlock(sb_bgl_lock(sbi, block_group));
percpu_counter_mod(&sbi->s_freeblocks_counter, count);
@@ -441,6 +442,7 @@ do_more:
BUFFER_TRACE(gd_bh, "dirtied group descriptor block");
ret = ext3_journal_dirty_metadata(handle, gd_bh);
if (!err) err = ret;
+ *pdquot_freed_blocks += group_freed;
if (overflow && !err) {
block += count;