Skip to content

Commit c806e68

Browse files
Frederic Bohetytso
authored andcommitted
ext4: fix initialization of UNINIT bitmap blocks
This fixes a bug which caused on-line resizing of filesystems with a 1k blocksize to fail. The root cause of this bug was the fact that if an uninitalized bitmap block gets read in by userspace (which e2fsprogs does try to avoid, but can happen when the blocksize is less than the pagesize and an adjacent blocks is read into memory) ext4_read_block_bitmap() was erroneously depending on the buffer uptodate flag to decide whether it needed to initialize the bitmap block in memory --- i.e., to set the standard set of blocks in use by a block group (superblock, bitmaps, inode table, etc.). Essentially, ext4_read_block_bitmap() assumed it was the only routine that might try to read a block containing a block bitmap, which is simply not true. To fix this, ext4_read_block_bitmap() and ext4_read_inode_bitmap() must always initialize uninitialized bitmap blocks. Once a block or inode is allocated out of that bitmap, it will be marked as initialized in the block group descriptor, so in general this won't result any extra unnecessary work. Signed-off-by: Frederic Bohe <frederic.bohe@bull.net> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
1 parent c2ea3fd commit c806e68

File tree

3 files changed

+9
-3
lines changed

3 files changed

+9
-3
lines changed

fs/ext4/balloc.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,9 +319,11 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
319319
block_group, bitmap_blk);
320320
return NULL;
321321
}
322-
if (bh_uptodate_or_lock(bh))
322+
if (buffer_uptodate(bh) &&
323+
!(desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)))
323324
return bh;
324325

326+
lock_buffer(bh);
325327
spin_lock(sb_bgl_lock(EXT4_SB(sb), block_group));
326328
if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
327329
ext4_init_block_bitmap(sb, bh, block_group, desc);

fs/ext4/ialloc.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,11 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
115115
block_group, bitmap_blk);
116116
return NULL;
117117
}
118-
if (bh_uptodate_or_lock(bh))
118+
if (buffer_uptodate(bh) &&
119+
!(desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)))
119120
return bh;
120121

122+
lock_buffer(bh);
121123
spin_lock(sb_bgl_lock(EXT4_SB(sb), block_group));
122124
if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) {
123125
ext4_init_inode_bitmap(sb, bh, block_group, desc);

fs/ext4/mballoc.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -782,9 +782,11 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
782782
if (bh[i] == NULL)
783783
goto out;
784784

785-
if (bh_uptodate_or_lock(bh[i]))
785+
if (buffer_uptodate(bh[i]) &&
786+
!(desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)))
786787
continue;
787788

789+
lock_buffer(bh[i]);
788790
spin_lock(sb_bgl_lock(EXT4_SB(sb), first_group + i));
789791
if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
790792
ext4_init_block_bitmap(sb, bh[i],

0 commit comments

Comments
 (0)