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); _