We should set s_dirt after altering the per-blockgroup free block counts -
the superblock is owed an update.



 fs/ext2/balloc.c |   33 ++++++++++++++++++++-------------
 1 files changed, 20 insertions(+), 13 deletions(-)

diff -puN fs/ext2/balloc.c~ext2-no-lock_super-set-s_dirt fs/ext2/balloc.c
--- 25/fs/ext2/balloc.c~ext2-no-lock_super-set-s_dirt	2003-03-15 13:53:15.000000000 -0800
+++ 25-akpm/fs/ext2/balloc.c	2003-03-15 13:57:38.000000000 -0800
@@ -94,11 +94,16 @@ error_out:
 	return bh;
 }
 
-static inline int
-group_reserve_blocks(struct ext2_sb_info *sbi, struct ext2_bg_info *bgi, 
+/*
+ * Set sb->s_dirt here because the superblock was "logically" altered.  We
+ * need to recalculate its free blocks count and flush it out.
+ */
+static int
+group_reserve_blocks(struct super_block *sb, struct ext2_bg_info *bgi, 
 		struct ext2_group_desc *desc, struct buffer_head *bh,
 		int count, int use_reserve)
 {
+	struct ext2_sb_info *sbi = EXT2_SB(sb);
 	unsigned free_blocks;
 	unsigned root_blocks;
 
@@ -133,14 +138,14 @@ group_reserve_blocks(struct ext2_sb_info
 	desc->bg_free_blocks_count = cpu_to_le16(free_blocks - count);
 
 	spin_unlock(&bgi->balloc_lock);
-
+	sb->s_dirt = 1;
 	mark_buffer_dirty(bh);
 	return count;
 }
 
-static inline void group_release_blocks(struct ext2_bg_info *bgi,
-					struct ext2_group_desc *desc,
-					struct buffer_head *bh, int count)
+static void group_release_blocks(struct super_block *sb,
+	struct ext2_bg_info *bgi, struct ext2_group_desc *desc,
+	struct buffer_head *bh, int count)
 {
 	if (count) {
 		unsigned free_blocks;
@@ -151,7 +156,7 @@ static inline void group_release_blocks(
 		desc->bg_free_blocks_count = cpu_to_le16(free_blocks + count);
 
 		spin_unlock(&bgi->balloc_lock);
-
+		sb->s_dirt = 1;
 		mark_buffer_dirty(bh);
 	}
 }
@@ -231,7 +236,8 @@ do_more:
 	if (sb->s_flags & MS_SYNCHRONOUS)
 		sync_dirty_buffer(bitmap_bh);
 
-	group_release_blocks(&sbi->s_bgi[block_group], desc, bh2, group_freed);
+	group_release_blocks(sb, &sbi->s_bgi[block_group],
+				desc, bh2, group_freed);
 	freed += group_freed;
 
 	if (overflow) {
@@ -349,7 +355,7 @@ int ext2_new_block(struct inode *inode, 
 	if (!desc)
 		goto io_error;
 
-	group_alloc = group_reserve_blocks(sbi, &sbi->s_bgi[group_no],
+	group_alloc = group_reserve_blocks(sb, &sbi->s_bgi[group_no],
 					desc, gdp_bh, es_alloc, 0);
 	if (group_alloc) {
 		ret_block = ((goal - le32_to_cpu(es->s_first_data_block)) %
@@ -366,8 +372,8 @@ int ext2_new_block(struct inode *inode, 
 				group_size, ret_block);
 		if (ret_block >= 0)
 			goto got_block;
-		group_release_blocks(&sbi->s_bgi[group_no], desc,
-					gdp_bh, group_alloc);
+		group_release_blocks(sb, &sbi->s_bgi[group_no],
+					desc, gdp_bh, group_alloc);
 		group_alloc = 0;
 	}
 
@@ -386,7 +392,7 @@ repeat:
 		desc = ext2_get_group_desc(sb, group_no, &gdp_bh);
 		if (!desc)
 			goto io_error;
-		group_alloc = group_reserve_blocks(sbi, &sbi->s_bgi[group_no],
+		group_alloc = group_reserve_blocks(sb, &sbi->s_bgi[group_no],
 					desc, gdp_bh, es_alloc, use_reserve);
 	}
 	if (!use_reserve) {
@@ -473,7 +479,8 @@ got_block:
 
 	*err = 0;
 out_release:
-	group_release_blocks(&sbi->s_bgi[group_no], desc, gdp_bh, group_alloc);
+	group_release_blocks(sb, &sbi->s_bgi[group_no],
+				desc, gdp_bh, group_alloc);
 	DQUOT_FREE_BLOCK(inode, dq_alloc);
 out:
 	brelse(bitmap_bh);

_