mke2fs: Fix block bitmaps initalization with -O ^resize_inode
PATCH 1/1 mke2fs: Fix block bitmaps initalization with -O ^resize_inode
If we create ext4 filesystem without resize_inode feature, mke2fs command does not initialize block groups
which have backup superblock and/or group descriptor block (With meta_bg feature, backup superblock and group descriptor block are located separately).
So we have to fix block bitmaps when we run "e2fsck -b superblock device". This patch fixes the issue by initializing block bitmaps correctly.
Steps to reproduce:
1. mke2fs -t ext4 -b 4096 -O ^resize_inode device
2. e2fsck -b 32768 DEV
<snip>
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Block bitmap differences: +(32768--32769) +(98304--98305) +(163840--163841) Fix<y>?
--- lib/ext2fs/alloc_sb.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
lib/ext2fs/alloc_sb.c +6 -4
@@ -58,23 +58,25 @@ int ext2fs_reserve_super_and_bgd(ext2_filsys fs, old_desc_blocks = fs->desc_blocks + fs->super->s_reserved_gdt_blocks; -if (super_blk || (group ==0 )) +if (super_blk || (group ==0 )) { +ext2fs_bg_flags_clear (fs, group,EXT2_BG_BLOCK_UNINIT );ext2fs_mark_block_bitmap2 (bmap, super_blk); + }if ((group ==0 ) && (fs->blocksize ==1024 ) &&EXT2FS_CLUSTER_RATIO (fs) >1 )ext2fs_mark_block_bitmap2 (bmap,0 );if (old_desc_blk) { -if (fs->super->s_reserved_gdt_blocks && fs->block_map == bmap) -ext2fs_bg_flags_clear (fs, group,EXT2_BG_BLOCK_UNINIT ); num_blocks = old_desc_blocks;if (old_desc_blk + num_blocks >=ext2fs_blocks_count (fs->super)) num_blocks =ext2fs_blocks_count (fs->super) - old_desc_blk;ext2fs_mark_block_bitmap_range2 (bmap, old_desc_blk, num_blocks); } -if (new_desc_blk) +if (new_desc_blk) { +ext2fs_bg_flags_clear (fs, group,EXT2_BG_BLOCK_UNINIT );ext2fs_mark_block_bitmap2 (bmap, new_desc_blk); + } num_blocks =ext2fs_group_blocks_count (fs, group); num_blocks -=2 + fs->inode_blocks_per_group + used_blks;
Hi Ted,
Could you review this patch?
Best,
Akira Fujita
Quoted 8 lines
-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of Akira Fujita
Sent: Tuesday, October 22, 2013 4:40 PM
To: Theodore Tso; ext4 development
Subject: [PATCH] mke2fs: Fix block bitmaps initalization with -O ^resize_inodeIf we create ext4 filesystem without
resize_inodefeature, mke2fs command does not initialize
block
Quoted 1 line
groups which have backup superblock and/or group descriptor block (With
meta_bgfeature,
backup
Quoted 54 lines
superblock and group descriptor block are located separately). So we have to fix block bitmaps when we run "e2fsck -b superblock device". This patch fixes the issue by initializing block bitmaps correctly.
Steps to reproduce:
1. mke2fs -t ext4 -b 4096 -O ^resize_inode device 2. e2fsck -b 32768 DEV <snip>
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Block bitmap differences: +(32768--32769) +(98304--98305) +(163840--163841) Fix<y>?Signed-off-by Akira Fujita <[email protected]>---
lib/ext2fs/alloc_sb.c| 10 ++++++----1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/ext2fs/alloc_sb.c
b/lib/ext2fs/alloc_sb.cindex 223ec51..5419d0d 100644lib/ext2fs/alloc_sb.c +6
-5@@ -58,23 +58,25 @@ int ext2fs_reserve_super_and_bgd(ext2_filsys fs, old_desc_blocks = fs->desc_blocks + fs->super->s_reserved_gdt_blocks; -if (super_blk || (group ==0 )) +if (super_blk || (group ==0 )) { +ext2fs_bg_flags_clear (fs, group,EXT2_BG_BLOCK_UNINIT );ext2fs_mark_block_bitmap2 (bmap, super_blk); + }if ((group ==0 ) && (fs->blocksize ==1024 ) &&EXT2FS_CLUSTER_RATIO (fs) >1 )ext2fs_mark_block_bitmap2 (bmap,0 );if (old_desc_blk) { -if (fs->super->s_reserved_gdt_blocks && fs->block_map == bmap) -ext2fs_bg_flags_clear (fs, group,EXT2_BG_BLOCK_UNINIT ); num_blocks = old_desc_blocks;if (old_desc_blk + num_blocks >=ext2fs_blocks_count (fs->super)) num_blocks =ext2fs_blocks_count (fs->super) - old_desc_blk;ext2fs_mark_block_bitmap_range2 (bmap, old_desc_blk, num_blocks); } -if (new_desc_blk) +if (new_desc_blk) { +ext2fs_bg_flags_clear (fs, group,EXT2_BG_BLOCK_UNINIT );ext2fs_mark_block_bitmap2 (bmap, new_desc_blk); + } num_blocks =ext2fs_group_blocks_count (fs, group); num_blocks -=2 + fs->inode_blocks_per_group + used_blks; --
Quoted 1 line
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message
to
Quoted 1 line
[email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 29 lines · Akira Fujita
If we create ext4 filesystem without
resize_inodefeature, mke2fs command does not initialize block groups
which have backup superblock and/or group descriptor block (Withmeta_bgfeature, backup superblock and group descriptor block are located separately).
So we have to fix block bitmaps when we run "e2fsck -b superblock device". This patch fixes the issue by initializing block bitmaps correctly.Steps to reproduce:
1. mke2fs -t ext4 -b 4096 -O ^resize_inode device
2. e2fsck -b 32768 DEV
<snip>
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Block bitmap differences: +(32768--32769) +(98304--98305) +(163840--163841) Fix<y>?Signed-off-by Akira Fujita <[email protected]>--- lib/ext2fs/alloc_sb.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)lib/ext2fs/alloc_sb.c +0
-0
lib/ext2fs/alloc_sb.c int ext2fs_reserve_super_and_bgd(ext2_filsys fs, · line 62
Quoted 6 lines
lib/ext2fs/alloc_sb.c +2
-1@@ -58,23 +58,25 @@ int ext2fs_reserve_super_and_bgd(ext2_filsys fs, old_desc_blocks = fs->desc_blocks + fs->super->s_reserved_gdt_blocks; -if (super_blk || (group ==0 )) +if (super_blk || (group ==0 )) { +ext2fs_bg_flags_clear (fs, group,EXT2_BG_BLOCK_UNINIT );
I'm not sure I agree with clearing the uninit flag unconditionally. Consider the case where bmap != fs->block_map, which happens in mark_table_blocks() (e2fsck pass1) and ext2fs_check_desc (libext2fs). In these two cases, the function will mark superblock and group descriptor blocks in a separate bitmap, leaving everything under fs alone. IOW: It doesn't make sense to mess with the fs' uninit flags if we're not marking the fs' bitmap.
As you point out, however, if we /are/ being called with fs->block_bitmap == bmap, then we're probably initializing the fs and it makes sense to clear the uninit flags.
Maybe something like this, just after the call to ext2fs_super_and_bgd_loc2?
if (fs->block_map == bmap && (new_desc_block || old_desc_block || super_blk))
ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
<shrug>
I've been wondering for a while -- if we have a FS with meta_bg and s_first_meta_bg > 0, does that mean we have "old" style group descriptor layouts up to whatever block group s_first_meta_bg points to? And why do we set old_desc_blocks to s_first_meta_bg, since the former is used as a block length offset for old_desc_blk for block groups beneath s_first_meta_bg? Group descriptors aren't the same size as a block.
This all seems kinda moot since the only initialization I can find for s_first_meta_bg sets it to zero.
<confused>
lib/ext2fs/alloc_sb.c int ext2fs_reserve_super_and_bgd(ext2_filsys fs, · line 69
Quoted 9 lines
lib/ext2fs/alloc_sb.c +1
-2ext2fs_mark_block_bitmap2 (bmap, super_blk); + }if ((group ==0 ) && (fs->blocksize ==1024 ) &&EXT2FS_CLUSTER_RATIO (fs) >1 )ext2fs_mark_block_bitmap2 (bmap,0 );if (old_desc_blk) { -if (fs->super->s_reserved_gdt_blocks && fs->block_map == bmap) -ext2fs_bg_flags_clear (fs, group,EXT2_BG_BLOCK_UNINIT );
Why remove this?
lib/ext2fs/alloc_sb.c int ext2fs_reserve_super_and_bgd(ext2_filsys fs, · line 77
Quoted 9 lines
lib/ext2fs/alloc_sb.c +2
-1num_blocks = old_desc_blocks;if (old_desc_blk + num_blocks >=ext2fs_blocks_count (fs->super)) num_blocks =ext2fs_blocks_count (fs->super) - old_desc_blk;ext2fs_mark_block_bitmap_range2 (bmap, old_desc_blk, num_blocks); } -if (new_desc_blk) +if (new_desc_blk) { +ext2fs_bg_flags_clear (fs, group,EXT2_BG_BLOCK_UNINIT );
Same comment here as that first chunk of reply.
--D
Quoted 10 lines
lib/ext2fs/alloc_sb.c +1
-1ext2fs_mark_block_bitmap2 (bmap, new_desc_blk); + } num_blocks =ext2fs_group_blocks_count (fs, group); num_blocks -=2 + fs->inode_blocks_per_group + used_blks; --To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Does the following patch fix your error? I think I've started to hit it too, now that I added ^resize_inode,^meta_bg to the mix.
--D
libext2fs: clear BLOCK_UNINIT any time a group has metadata blocks
If ext2fs_reserve_super_and_bgd() is called with the filesystem's block bitmap, we clear the group's BLOCK_UNINIT flag if the group has an old-style (pre-metabg) group descriptor block with reserved descriptor blocks prior to marking the old-style descriptor blocks in use.
Unfortunately, this is not sufficient -- if the group has no reserved blocks yet isn't a meta_bg filesystem (^resize_inode,^meta_bg), we forget to clear the flag, so the filesystem thinks all blocks are free, which is disastrous.
Therefore, if we know that we're going to mark any of the bitmaps, make sure that we clear BLOCK_UNINIT.
This is based on an earlier patch by Akira Fujita.
Quoted 11 lines
Steps to reproduce:
1. mke2fs -t ext4 -b 4096 -O ^resize_inode device
2. e2fsck -b 32768 DEV
<snip>
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Block bitmap differences: +(32768--32769) +(98304--98305) +(163840--163841) Fix<y>?
--- lib/ext2fs/alloc_sb.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
lib/ext2fs/alloc_sb.c +9 -2
@@ -52,6 +52,15 @@ int ext2fs_reserve_super_and_bgd(ext2_filsys fs,ext2fs_super_and_bgd_loc2 (fs, group, &super_blk, &old_desc_blk, &new_desc_blk, &used_blks); +/* +* If we're marking blocks in the main block bitmap, be sure that we +* clear the group's BLOCK_UNINIT flag if this group has metadata +* blocks allocated. +*/ +if (fs->block_map == bmap && + (new_desc_blk || old_desc_blk || super_blk || (group ==0 ))) +ext2fs_bg_flags_clear (fs, group,EXT2_BG_BLOCK_UNINIT ); +if (fs->super->s_feature_incompat &EXT2_FEATURE_INCOMPAT_META_BG ) old_desc_blocks = fs->super->s_first_meta_bg;else
@@ -65,8 +74,6 @@ int ext2fs_reserve_super_and_bgd(ext2_filsys fs,ext2fs_mark_block_bitmap2 (bmap,0 );if (old_desc_blk) { -if (fs->super->s_reserved_gdt_blocks && fs->block_map == bmap) -ext2fs_bg_flags_clear (fs, group,EXT2_BG_BLOCK_UNINIT ); num_blocks = old_desc_blocks;if (old_desc_blk + num_blocks >=ext2fs_blocks_count (fs->super)) num_blocks = ext2fs_blocks_count(fs->super) -
Hi Darrick,
With your patch, e2fsck can't fix the filesystem created with existing mke2fs without resize_inode.
Because "fs->block_map == bmap" condition is in ext2fs_reserve_super_and_bgd().
But if the condition removed (like my previous patch) we can detect and fix filesystem inconsistency as follows.
1.Create filesystem with existing mke2fs command
# mke2fs -t ext4 -O ^resize_inode DEVICE
2. (With my patch) e2fsck removes uninit_bg flag then fixes metadata inconsistency
# ./e2fsck/e2fsck -f DEVICE e2fsck 1.43-WIP (8-Jul-2013) One or more block group descriptor checksums are invalid. Fix<y>? yes Group descriptor 1 checksum is 0x0343, should be 0xc4ba. FIXED. Group descriptor 3 checksum is 0x17f2, should be 0xd00b. FIXED. Group descriptor 5 checksum is 0xf36c, should be 0x3495. FIXED. Group descriptor 7 checksum is 0x3e90, should be 0xf969. FIXED. Group descriptor 9 checksum is 0xa31e, should be 0x64e7. FIXED. Group descriptor 25 checksum is 0x165a, should be 0xd1a3. FIXED. Group descriptor 27 checksum is 0xce4c, should be 0x09b5. FIXED. Group descriptor 49 checksum is 0x502b, should be 0x97d2. FIXED. Pass 1: Checking inodes, blocks, and sizes Pass 2: Checking directory structure Pass 3: Checking directory connectivity Pass 4: Checking reference counts Pass 5: Checking group summary information Block bitmap differences: +(32768--32769) +(98304--98305) +(163840--163841) +(229376--229377) +(294912--294913) +(819200--819201) +(884736--884737) +(1605632--1605633) Fix<y>? yes
/dev/loop0: ***** FILE SYSTEM WAS MODIFIED *****/dev/loop0: 11/656640 files (0.0% non-contiguous), 73991/2621440 blocks
Regards,
Akira Fujita
Quoted 7 lines
-----Original Message-----
From: Darrick J. Wong [mailto:[email protected]]
Sent: Tuesday, November 26, 2013 10:27 AM
To: Akira Fujita
Cc: Theodore Tso; ext4 development
Subject: Re: [PATCH] mke2fs: Fix block bitmaps initalization with -O ^resize_inode
Quoted 8 lines
Does the following patch fix your error? I think I've started to hit it too, now that I added ^resize_inode,^meta_bg to the mix.
--D
libext2fs: clear
BLOCK_UNINITany time a group has metadata blocksIf
ext2fs_reserve_super_and_bgd()is called with the filesystem's block bitmap, we clear the
group's
Quoted 1 line
BLOCK_UNINITflag if the group has an old-style (pre-metabg) group descriptor block with
reserved
Quoted 3 lines
descriptor blocks prior to marking the old-style descriptor blocks in use.
Unfortunately, this is not sufficient -- if the group has no reserved blocks yet isn't a
meta_bg
Quoted 54 lines
filesystem (^resize_inode,^meta_bg), we forget to clear the flag, so the filesystem thinks all blocks are free, which is disastrous.
Therefore, if we know that we're going to mark any of the bitmaps, make sure that we clear
BLOCK_UNINIT.This is based on an earlier patch by Akira Fujita.
Quoted 11 lines
Steps to reproduce:
1. mke2fs -t ext4 -b 4096 -O ^resize_inode device 2. e2fsck -b 32768 DEV
<snip>
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Block bitmap differences: +(32768--32769) +(98304--98305) +(163840--163841) Fix<y>?Reported-by Akira Fujita <[email protected]>Signed-off-by Darrick J. Wong <[email protected]>---
lib/ext2fs/alloc_sb.c| 11 +++++++++--1 file changed, 9 insertions(+), 2 deletions(-)lib/ext2fs/alloc_sb.c +9
-2@@ -52,6 +52,15 @@ int ext2fs_reserve_super_and_bgd(ext2_filsys fs,ext2fs_super_and_bgd_loc2 (fs, group, &super_blk, &old_desc_blk, &new_desc_blk, &used_blks); +/* +* If we're marking blocks in the main block bitmap, be sure that we +* clear the group's BLOCK_UNINIT flag if this group has metadata +* blocks allocated. +*/ +if (fs->block_map == bmap && + (new_desc_blk || old_desc_blk || super_blk || (group ==0 ))) +ext2fs_bg_flags_clear (fs, group,EXT2_BG_BLOCK_UNINIT ); +if (fs->super->s_feature_incompat &EXT2_FEATURE_INCOMPAT_META_BG ) old_desc_blocks = fs->super->s_first_meta_bg;else @@ -65,8 +74,6 @@ int ext2fs_reserve_super_and_bgd(ext2_filsys fs,ext2fs_mark_block_bitmap2 (bmap,0 );if (old_desc_blk) { -if (fs->super->s_reserved_gdt_blocks && fs->block_map == bmap) -ext2fs_bg_flags_clear (fs, group,EXT2_BG_BLOCK_UNINIT ); num_blocks = old_desc_blocks;if (old_desc_blk + num_blocks >=ext2fs_blocks_count (fs->super)) num_blocks = ext2fs_blocks_count(fs->super) -
Quoted 5 lines · Akira Fujita
Hi Darrick,
With your patch, e2fsck can't fix the filesystem created with existing mke2fs without
resize_inode.
Because "fs->block_map== bmap" condition is inext2fs_reserve_super_and_bgd().
Hmm, I think I see what's going on here.
First, I think you're arguing that BLOCK_UNINIT should only be set on a group if it's completely empty. I think you're also arguing that even if the group contains only its own superblocks, group descriptors, bitmaps, or inode tables, BLOCK_UNINIT should not be set. Let's call that condition (block group contains only group data, but BLOCK_UNINIT is set) "(1)".
Note: If a group contains some other group's metadata, BLOCK_UNINIT should not (and does not seem to) be set.
(If I'm wrong, please let me know.)
The kernel, when it needs to load a bitmap, checks for BLOCK_UNINIT; if set, it calls ext4_init_block_bitmap() to zero the bitmap and mark the relevant sb/gdt/bmap/table bits, if necessary. That takes care of (1) in the kernel.
e2fsck pass5 also checks for BLOCK_UNINIT; if it's set, then it first compares block_found_map against a zeroed bitmap (which falls back to no_optimize mode), and then it secondly compares each block individually against the ranges that ext2fs_super_and_bgd_loc2(), ext2fs_*_bitmap_loc(), and ext2fs_inode_table_loc() return. That takes care of (1) in e2fsck.
libext2fs, however, checks for BLOCK_UNINIT; if it's set, it zeroes that part of the bitmap and moves on without bothering to mark the sb/gdt/bmap/table bits. This does NOT take care of (1), and opens a window where callers can allocate blocks that already hold group metadata! (Let's call this (2).)
The fuse2fs bug that I was seeing was that if (2) happens, then fuse2fs sees a zero bitmap and blindly hands away group metadata, which is broken. With yesterday's patch, (1) doesn't happen and all seems ok.
I think in your e2fsck test, e2fsck tests block_found_map against a correctly constructed bitmap (with ext2fs_super_and_bgd_loc2) if BLOCK_UNINIT is set, which is why it can't fix (1) unless e2fsck is fed a backup superblock (or there's a corrupt a group descriptor checksum), either of which clears BLOCK_UNINIT before pass5).
So I'm wondering, is there more to the bug report than just "I ran mkfs and prodded e2fsck into reporting errors"?
Given that both the kernel and e2fsck know how to calculate the proper block bitmap when BLOCK_UNINIT is set, it doesn't seem to be an error case if BLOCK_UNINIT is set on a group that contains superblocks, group descriptors, bitmaps, or inode tables. It seems to me that if we can calculate a bitmap, then there's no need to record it, and we can use BLOCK_UNINIT.
What do you think of this solution: Change read_bitmaps to mark the location of sb/gdt/bmap/inode blocks in the in-core block bitmap for BLOCK_UNINIT groups. This fixes the problem that fs->block_bitmap doesn't accurately reflect the real state of the filesystem (as evidenced by dumpe2fs/debugfs reporting more free blocks than the summar. I think we can also eliminate the skip_group code from the block bitmap check in pass5. That should speed up pass5 since we can also use the fast bitmap compare.
I'll send out a test patch.
Of course, the tests seem coded to pass things like:
Quoted 2 lines
Group 2: (Blocks 16385-24576) [
INODE_UNINIT,BLOCK_UNINIT,ITABLE_ZEROED]
Block bitmap at 16385 (+0), Inode bitmap at 16386 (+1)
^^^^^ ^^^^^
Quoted 1 line
Inode table at 16387-16642 (+2)
^^^^^^^^^^^
Quoted 2 lines
7934 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes Free blocks: 16385-24576
^^^^^
Quoted 1 line
Free inodes: 4097-6144
<grumble>
--D
Quoted 114 lines
But if the condition removed (like my previous patch) we can detect and fix filesystem inconsistency as follows.
1.Create filesystem with existing mke2fs command
# mke2fs -t ext4 -O ^resize_inode DEVICE2. (With my patch) e2fsck removes
uninit_bgflag then fixes metadata inconsistency# ./e2fsck/e2fsck -f DEVICE e2fsck 1.43-WIP (8-Jul-2013) One or more block group descriptor checksums are invalid. Fix<y>? yes Group descriptor 1 checksum is 0x0343, should be 0xc4ba. FIXED. Group descriptor 3 checksum is 0x17f2, should be 0xd00b. FIXED. Group descriptor 5 checksum is 0xf36c, should be 0x3495. FIXED. Group descriptor 7 checksum is 0x3e90, should be 0xf969. FIXED. Group descriptor 9 checksum is 0xa31e, should be 0x64e7. FIXED. Group descriptor 25 checksum is 0x165a, should be 0xd1a3. FIXED. Group descriptor 27 checksum is 0xce4c, should be 0x09b5. FIXED. Group descriptor 49 checksum is 0x502b, should be 0x97d2. FIXED. Pass 1: Checking inodes, blocks, and sizes Pass 2: Checking directory structure Pass 3: Checking directory connectivity Pass 4: Checking reference counts Pass 5: Checking group summary information Block bitmap differences: +(32768--32769) +(98304--98305) +(163840--163841) +(229376--229377) +(294912--294913) +(819200--819201) +(884736--884737) +(1605632--1605633) Fix<y>? yes
/dev/loop0: ***** FILE SYSTEM WAS MODIFIED *****/dev/loop0: 11/656640 files (0.0% non-contiguous), 73991/2621440 blocksRegards,
Akira FujitaQuoted 7 lines
-----Original Message-----
From: Darrick J. Wong [mailto:[email protected]]
Sent: Tuesday, November 26, 2013 10:27 AM
To: Akira Fujita
Cc: Theodore Tso; ext4 development
Subject: Re: [PATCH] mke2fs: Fix block bitmaps initalization with -O ^resize_inodeQuoted 8 lines
Does the following patch fix your error? I think I've started to hit it too, now that I added ^resize_inode,^meta_bg to the mix.
--D
libext2fs: clear
BLOCK_UNINITany time a group has metadata blocksIf
ext2fs_reserve_super_and_bgd()is called with the filesystem's block bitmap, we clear thegroup's
Quoted 1 line
BLOCK_UNINITflag if the group has an old-style (pre-metabg) group descriptor block withreserved
Quoted 3 lines
descriptor blocks prior to marking the old-style descriptor blocks in use.
Unfortunately, this is not sufficient -- if the group has no reserved blocks yet isn't a
meta_bgQuoted 46 lines
filesystem (^resize_inode,^meta_bg), we forget to clear the flag, so the filesystem thinks all blocks are free, which is disastrous.
Therefore, if we know that we're going to mark any of the bitmaps, make sure that we clear
BLOCK_UNINIT.This is based on an earlier patch by Akira Fujita.
Quoted 11 lines
Steps to reproduce:
1. mke2fs -t ext4 -b 4096 -O ^resize_inode device 2. e2fsck -b 32768 DEV
<snip>
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Block bitmap differences: +(32768--32769) +(98304--98305) +(163840--163841) Fix<y>?Reported-by Akira Fujita <[email protected]>Signed-off-by Darrick J. Wong <[email protected]>---
lib/ext2fs/alloc_sb.c| 11 +++++++++--1 file changed, 9 insertions(+), 2 deletions(-)lib/ext2fs/alloc_sb.c +9
-0@@ -52,6 +52,15 @@ int ext2fs_reserve_super_and_bgd(ext2_filsys fs,ext2fs_super_and_bgd_loc2 (fs, group, &super_blk, &old_desc_blk, &new_desc_blk, &used_blks); +/* +* If we're marking blocks in the main block bitmap, be sure that we +* clear the group's BLOCK_UNINIT flag if this group has metadata +* blocks allocated. +*/ +if (fs->block_map == bmap && + (new_desc_blk || old_desc_blk || super_blk || (group ==0 ))) +ext2fs_bg_flags_clear (fs, group,EXT2_BG_BLOCK_UNINIT ); +if (fs->super->s_feature_incompat &EXT2_FEATURE_INCOMPAT_META_BG ) old_desc_blocks = fs->super->s_first_meta_bg;else lib/ext2fs/alloc_sb.c int ext2fs_reserve_super_and_bgd(ext2_filsys fs, · line 79
Quoted 8 lines
lib/ext2fs/alloc_sb.c +0
-2@@ -65,8 +74,6 @@ int ext2fs_reserve_super_and_bgd(ext2_filsys fs,ext2fs_mark_block_bitmap2 (bmap,0 );if (old_desc_blk) { -if (fs->super->s_reserved_gdt_blocks && fs->block_map == bmap) -ext2fs_bg_flags_clear (fs, group,EXT2_BG_BLOCK_UNINIT ); num_blocks = old_desc_blocks;if (old_desc_blk + num_blocks >=ext2fs_blocks_count (fs->super)) num_blocks = ext2fs_blocks_count(fs->super) ---
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 10 lines · Akira Fujita
Quoted 5 lines
Hi Darrick,
With your patch, e2fsck can't fix the filesystem created with existing mke2fs without
resize_inode.
Because "fs->block_map== bmap" condition is inext2fs_reserve_super_and_bgd().Hmm, I think I see what's going on here.
First, I think you're arguing that
BLOCK_UNINITshould only be set on a group if it's
completely
Quoted 1 line
empty. I think you're also arguing that even if the group contains only its own superblocks,
group
Quoted 1 line
descriptors, bitmaps, or inode tables,
BLOCK_UNINITshould not be set. Let's call that
condition
Quoted 3 lines
(block group contains only group data, but
BLOCK_UNINITis set) "(1)".Note: If a group contains some other group's metadata,
BLOCK_UNINITshould not (and does not
seem
Quoted 3 lines
to) be set.
(If I'm wrong, please let me know.)
Yes. Current ext4, it seems to me that BLOCK_UNINIT is set under the following rules:
1 sb(backup sb)/gdt/bitmap/itable exist (e.g. #BG0) -> BLOCK_UNINIT off 2 backup sb/gdt exist (e.g. #BG5) -> BLOCK_UNINIT off 3 bitmap/itable exist (e.g. #BG16) -> BLOCK_UNINIT off 4 Completely empty (e.g. #BG6) -> BLOCK_UNINIT on
Note: #BGN is in ext4 created by default option
And there is a bug that block group which has backup super block and group descriptor block are not write out to device in wrtie_bitmaps() when BLOCK_UNINIT is set.
So at this time, I attempted to fix this by cleaning BLOCK_UNIIT.
Quoted 6 lines
The kernel, when it needs to load a bitmap, checks for
BLOCK_UNINIT; if set, it callsext4_init_block_bitmap()to zero the bitmap and mark the relevant sb/gdt/bmap/table bits, if necessary. That takes care of (1) in the kernel.e2fsck pass5 also checks for
BLOCK_UNINIT; if it's set, then it first comparesblock_found_mapagainst a zeroed bitmap (which falls back tono_optimizemode), and then it secondly compares
each
Quoted 1 line
block individually against the ranges that
ext2fs_super_and_bgd_loc2(), ext2fs_*_bitmap_loc(),
and
Quoted 3 lines
ext2fs_inode_table_loc()return. That takes care of (1) in e2fsck.libext2fs, however, checks for
BLOCK_UNINIT; if it's set, it zeroes that part of the bitmap
and
Quoted 1 line
moves on without bothering to mark the sb/gdt/bmap/table bits. This does NOT take care of
(1),
Quoted 1 line
and opens a window where callers can allocate blocks that already hold group metadata! (Let's
call
Quoted 3 lines
this (2).)
The fuse2fs bug that I was seeing was that if (2) happens, then fuse2fs sees a zero bitmap and
blindly
Quoted 1 line
hands away group metadata, which is broken. With yesterday's patch, (1) doesn't happen and
all
Quoted 3 lines
seems ok.
I think in your e2fsck test, e2fsck tests
block_found_mapagainst a correctly constructed
bitmap
Quoted 1 line
(with
ext2fs_super_and_bgd_loc2) ifBLOCK_UNINITis set, which is why it can't fix (1) unless
e2fsck
Quoted 1 line
is fed a backup superblock (or there's a corrupt a group descriptor checksum), either of which
clears
Quoted 3 lines
BLOCK_UNINITbefore pass5).So I'm wondering, is there more to the bug report than just "I ran mkfs and prodded e2fsck
into
Quoted 1 line
reporting errors"?
I guess there is another bug.
Quoted 1 line
Given that both the kernel and e2fsck know how to calculate the proper block bitmap when
BLOCK_UNINIT
Quoted 1 line
is set, it doesn't seem to be an error case if
BLOCK_UNINITis set on a group that contains
superblocks,
Quoted 1 line
group descriptors, bitmaps, or inode tables. It seems to me that if we can calculate a
bitmap,
Quoted 3 lines
then there's no need to record it, and we can use
BLOCK_UNINIT.What do you think of this solution: Change
read_bitmapsto mark the location of
sb/gdt/bmap/inode
Quoted 3 lines
blocks in the in-core block bitmap for
BLOCK_UNINITgroups.
This fixes the problem thatfs->block_bitmapdoesn't accurately reflect the real state of the filesystem (as evidenced by dumpe2fs/debugfs reporting more free blocks than the summar. I
think
Quoted 1 line
we can also eliminate the
skip_groupcode from the block bitmap check in pass5. That should
speed
Quoted 1 line
up pass5 since we can also use the fast bitmap compare.
Speeding up bitmap check in pass5 sounds nice,
but setting BLOCK_UNINIT for block groups which have metadata means we'll change the definition of BLOCK_UNIIT... :s
Regards,
Akira Fujita
Quoted 137 lines
I'll send out a test patch.
Of course, the tests seem coded to pass things like:
Quoted 2 lines
Group 2: (Blocks 16385-24576) [
INODE_UNINIT,BLOCK_UNINIT,ITABLE_ZEROED]
Block bitmap at 16385 (+0), Inode bitmap at 16386 (+1)^^^^^ ^^^^^Quoted 1 line
Inode table at 16387-16642 (+2)
^^^^^^^^^^^Quoted 2 lines
7934 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes Free blocks: 16385-24576
^^^^^Quoted 1 line
Free inodes: 4097-6144
<grumble>
--D
Quoted 108 lines
But if the condition removed (like my previous patch) we can detect and fix filesystem inconsistency as follows.
1.Create filesystem with existing mke2fs command # mke2fs -t ext4 -O ^resize_inode DEVICE
2. (With my patch) e2fsck removes
uninit_bgflag then fixes metadata inconsistency # ./e2fsck/e2fsck -f DEVICE e2fsck 1.43-WIP (8-Jul-2013) One or more block group descriptor checksums are invalid. Fix<y>? yesGroup descriptor 1 checksum is 0x0343, should be 0xc4ba. FIXED. Group descriptor 3 checksum is 0x17f2, should be 0xd00b. FIXED. Group descriptor 5 checksum is 0xf36c, should be 0x3495. FIXED. Group descriptor 7 checksum is 0x3e90, should be 0xf969. FIXED. Group descriptor 9 checksum is 0xa31e, should be 0x64e7. FIXED. Group descriptor 25 checksum is 0x165a, should be 0xd1a3. FIXED. Group descriptor 27 checksum is 0xce4c, should be 0x09b5. FIXED. Group descriptor 49 checksum is 0x502b, should be 0x97d2. FIXED.Pass 1: Checking inodes, blocks, and sizes Pass 2: Checking directory structure Pass 3: Checking directory connectivity Pass 4: Checking reference counts Pass 5: Checking group summary information Block bitmap differences: +(32768--32769) +(98304--98305) +(163840--163841)
(quoted diff) +3
-0+(229376--229377) +(294912--294913) +(819200--819201) +(884736--884737) ++(1605632--1605633)Fix<y>? yes
/dev/loop0: ***** FILE SYSTEM WAS MODIFIED *****/dev/loop0: 11/656640 files (0.0% non-contiguous), 73991/2621440 blocksRegards,
Akira FujitaQuoted 11 lines
-----Original Message-----
From: Darrick J. Wong [mailto:[email protected]]
Sent: Tuesday, November 26, 2013 10:27 AM
To: Akira Fujita
Cc: Theodore Tso; ext4 development
Subject: Re: [PATCH] mke2fs: Fix block bitmaps initalization with -O ^resize_inodeDoes the following patch fix your error? I think I've started to hit it too, now that I added ^resize_inode,^meta_bg to the mix.
Quoted 6 lines
--D
libext2fs: clear
BLOCK_UNINITany time a group has metadata blocksIf
ext2fs_reserve_super_and_bgd()is called with the filesystem's block bitmap, we clear thegroup's
Quoted 2 lines
BLOCK_UNINITflag if the group has an old-style (pre-metabg) group descriptor block withreserved
Quoted 4 lines
descriptor blocks prior to marking the old-style descriptor blocks in use.
Unfortunately, this is not sufficient -- if the group has no reserved blocks yet isn't a
meta_bgQuoted 49 lines
filesystem (^resize_inode,^meta_bg), we forget to clear the flag, so the filesystem thinks all blocks are free, which is disastrous.
Therefore, if we know that we're going to mark any of the bitmaps, make sure that we clear
BLOCK_UNINIT.This is based on an earlier patch by Akira Fujita.
Quoted 11 lines
Steps to reproduce:
1. mke2fs -t ext4 -b 4096 -O ^resize_inode device 2. e2fsck -b 32768 DEV
<snip>
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Block bitmap differences: +(32768--32769) +(98304--98305) +(163840--163841) Fix<y>?Reported-by Akira Fujita <[email protected]>Signed-off-by Darrick J. Wong <[email protected]>---
lib/ext2fs/alloc_sb.c| 11 +++++++++--1 file changed, 9 insertions(+), 2 deletions(-)lib/ext2fs/alloc_sb.c index renamed from lib/ext2fs/alloc_sb.c +0
-0223ec51..f1898df 100644
lib/ext2fs/alloc_sb.c +9
-0@@ -52,6 +52,15 @@ int ext2fs_reserve_super_and_bgd(ext2_filsys fs,ext2fs_super_and_bgd_loc2 (fs, group, &super_blk, &old_desc_blk, &new_desc_blk, &used_blks); +/* +* If we're marking blocks in the main block bitmap, be sure that we +* clear the group's BLOCK_UNINIT flag if this group has metadata +* blocks allocated. +*/ +if (fs->block_map == bmap && + (new_desc_blk || old_desc_blk || super_blk || (group ==0 ))) +ext2fs_bg_flags_clear (fs, group,EXT2_BG_BLOCK_UNINIT ); +if (fs->super->s_feature_incompat &EXT2_FEATURE_INCOMPAT_META_BG ) old_desc_blocks = fs->super->s_first_meta_bg;else @@ -65,8 +74,6 @@ int ext2fs_reserve_super_and_bgd(ext2_filsys fs,ext2fs_mark_block_bitmap2 (bmap,0 );Quoted 11 lines
lib/ext2fs/alloc_sb.c int ext2fs_reserve_super_and_bgd(ext2_filsys fs, · line 79
Quoted 6 lines
lib/ext2fs/alloc_sb.c +0
-2if (old_desc_blk) { -if (fs->super->s_reserved_gdt_blocks && fs->block_map == bmap) -ext2fs_bg_flags_clear (fs, group,EXT2_BG_BLOCK_UNINIT ); num_blocks = old_desc_blocks;if (old_desc_blk + num_blocks >=ext2fs_blocks_count (fs->super)) num_blocks = ext2fs_blocks_count(fs->super) ---
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 2 lines
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message
to
Quoted 1 line
[email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Ted, I was hoping you might resolve a question for us:
(please scroll down a bit)
Quoted 29 lines · Akira Fujita
Quoted 10 lines · Akira Fujita
Quoted 5 lines
Hi Darrick,
With your patch, e2fsck can't fix the filesystem created with existing mke2fs without
resize_inode.
Because "fs->block_map== bmap" condition is inext2fs_reserve_super_and_bgd().Hmm, I think I see what's going on here.
First, I think you're arguing that
BLOCK_UNINITshould only be set on a group if it'scompletely
Quoted 1 line
empty. I think you're also arguing that even if the group contains only its own superblocks,
group
Quoted 1 line
descriptors, bitmaps, or inode tables,
BLOCK_UNINITshould not be set. Let's call thatcondition
Quoted 3 lines
(block group contains only group data, but
BLOCK_UNINITis set) "(1)".Note: If a group contains some other group's metadata,
BLOCK_UNINITshould not (and does notseem
Quoted 3 lines
to) be set.
(If I'm wrong, please let me know.)
Yes. Current ext4, it seems to me that
BLOCK_UNINITis set under the following rules:1 sb(backup sb)/gdt/bitmap/itable exist (e.g. #BG0) -> BLOCK_UNINIT off 2 backup sb/gdt exist (e.g. #BG5) -> BLOCK_UNINIT off 3 bitmap/itable exist (e.g. #BG16) -> BLOCK_UNINIT off 4 Completely empty (e.g. #BG6) -> BLOCK_UNINIT on
Quoted 6 lines
Note: #BGN is in ext4 created by default option
And there is a bug that block group which has backup super block and group descriptor block are not write out to device in
wrtie_bitmaps()whenBLOCK_UNINITis set.
So at this time, I attempted to fix this by cleaningBLOCK_UNIIT.
Is it the case that a group should only have BLOCK_UNINIT set if the group is totally empty (no group metadata, no blocks allocated to files) as Akira says?
Or is it the case that a group can have BLOCK_UNINIT set if the group contains group metadata but no blocks are allocated to files?
The kernel and e2fsck contain code to construct bitmaps at run time with the group metadata blocks marked in-use (thus handling case #2). Unfortunately, libext2fs does not do this; it stuffs in a zeroed bitmap any time it sees BLOCK_UNINIT (case #1).
It seems that you can mkfs -O ^resize_inode and it'll produce an fs containing groups that have superblocks/group descriptors but BLOCK_UNINIT set. The kernel handles it correctly, but things like debugfs report that every block in that group is free.
For sure I'd like to fix libext2fs to ensure that it marks the group metadata blocks in-use in the in-memory bitmap when it's loading the block bitmap for a BLOCK_UNINIT group.
As for whether or not a group can contain group data and have BLOCK_UNINIT set, well, I defer to you. :)
--D
Quoted 208 lines
Quoted 8 lines
The kernel, when it needs to load a bitmap, checks for
BLOCK_UNINIT; if set, it callsext4_init_block_bitmap()to zero the bitmap and mark the relevant sb/gdt/bmap/table bits, if necessary. That takes care of (1) in the kernel.e2fsck pass5 also checks for
BLOCK_UNINIT; if it's set, then it first comparesblock_found_mapagainst a zeroed bitmap (which falls back tono_optimizemode), and then it secondly compareseach
Quoted 1 line
block individually against the ranges that
ext2fs_super_and_bgd_loc2(), ext2fs_*_bitmap_loc(),and
Quoted 3 lines
ext2fs_inode_table_loc()return. That takes care of (1) in e2fsck.libext2fs, however, checks for
BLOCK_UNINIT; if it's set, it zeroes that part of the bitmapand
Quoted 1 line
moves on without bothering to mark the sb/gdt/bmap/table bits. This does NOT take care of
(1),
Quoted 1 line
and opens a window where callers can allocate blocks that already hold group metadata! (Let's
call
Quoted 3 lines
this (2).)
The fuse2fs bug that I was seeing was that if (2) happens, then fuse2fs sees a zero bitmap and
blindly
Quoted 1 line
hands away group metadata, which is broken. With yesterday's patch, (1) doesn't happen and
all
Quoted 3 lines
seems ok.
I think in your e2fsck test, e2fsck tests
block_found_mapagainst a correctly constructedbitmap
Quoted 1 line
(with
ext2fs_super_and_bgd_loc2) ifBLOCK_UNINITis set, which is why it can't fix (1) unlesse2fsck
Quoted 1 line
is fed a backup superblock (or there's a corrupt a group descriptor checksum), either of which
clears
Quoted 3 lines
BLOCK_UNINITbefore pass5).So I'm wondering, is there more to the bug report than just "I ran mkfs and prodded e2fsck
into
Quoted 1 line
reporting errors"?
I guess there is another bug.
Quoted 1 line
Given that both the kernel and e2fsck know how to calculate the proper block bitmap when
BLOCK_UNINITQuoted 1 line
is set, it doesn't seem to be an error case if
BLOCK_UNINITis set on a group that containssuperblocks,
Quoted 1 line
group descriptors, bitmaps, or inode tables. It seems to me that if we can calculate a
bitmap,
Quoted 3 lines
then there's no need to record it, and we can use
BLOCK_UNINIT.What do you think of this solution: Change
read_bitmapsto mark the location ofsb/gdt/bmap/inode
Quoted 3 lines
blocks in the in-core block bitmap for
BLOCK_UNINITgroups.
This fixes the problem thatfs->block_bitmapdoesn't accurately reflect the real state of the filesystem (as evidenced by dumpe2fs/debugfs reporting more free blocks than the summar. Ithink
Quoted 1 line
we can also eliminate the
skip_groupcode from the block bitmap check in pass5. That shouldspeed
Quoted 1 line
up pass5 since we can also use the fast bitmap compare.
Speeding up bitmap check in pass5 sounds nice,
but settingBLOCK_UNINITfor block groups which have metadata means we'll change the definition ofBLOCK_UNIIT... :sRegards,
Akira FujitaQuoted 137 lines
I'll send out a test patch.
Of course, the tests seem coded to pass things like:
Quoted 2 lines
Group 2: (Blocks 16385-24576) [
INODE_UNINIT,BLOCK_UNINIT,ITABLE_ZEROED]
Block bitmap at 16385 (+0), Inode bitmap at 16386 (+1)^^^^^ ^^^^^Quoted 1 line
Inode table at 16387-16642 (+2)
^^^^^^^^^^^Quoted 2 lines
7934 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes Free blocks: 16385-24576
^^^^^Quoted 1 line
Free inodes: 4097-6144
<grumble>
--D
Quoted 108 lines
But if the condition removed (like my previous patch) we can detect and fix filesystem inconsistency as follows.
1.Create filesystem with existing mke2fs command # mke2fs -t ext4 -O ^resize_inode DEVICE
2. (With my patch) e2fsck removes
uninit_bgflag then fixes metadata inconsistency # ./e2fsck/e2fsck -f DEVICE e2fsck 1.43-WIP (8-Jul-2013) One or more block group descriptor checksums are invalid. Fix<y>? yesGroup descriptor 1 checksum is 0x0343, should be 0xc4ba. FIXED. Group descriptor 3 checksum is 0x17f2, should be 0xd00b. FIXED. Group descriptor 5 checksum is 0xf36c, should be 0x3495. FIXED. Group descriptor 7 checksum is 0x3e90, should be 0xf969. FIXED. Group descriptor 9 checksum is 0xa31e, should be 0x64e7. FIXED. Group descriptor 25 checksum is 0x165a, should be 0xd1a3. FIXED. Group descriptor 27 checksum is 0xce4c, should be 0x09b5. FIXED. Group descriptor 49 checksum is 0x502b, should be 0x97d2. FIXED.Pass 1: Checking inodes, blocks, and sizes Pass 2: Checking directory structure Pass 3: Checking directory connectivity Pass 4: Checking reference counts Pass 5: Checking group summary information Block bitmap differences: +(32768--32769) +(98304--98305) +(163840--163841)
(quoted diff) +3
-0+(229376--229377) +(294912--294913) +(819200--819201) +(884736--884737) ++(1605632--1605633)Fix<y>? yes
/dev/loop0: ***** FILE SYSTEM WAS MODIFIED *****/dev/loop0: 11/656640 files (0.0% non-contiguous), 73991/2621440 blocksRegards,
Akira FujitaQuoted 11 lines
-----Original Message-----
From: Darrick J. Wong [mailto:[email protected]]
Sent: Tuesday, November 26, 2013 10:27 AM
To: Akira Fujita
Cc: Theodore Tso; ext4 development
Subject: Re: [PATCH] mke2fs: Fix block bitmaps initalization with -O ^resize_inodeDoes the following patch fix your error? I think I've started to hit it too, now that I added ^resize_inode,^meta_bg to the mix.
Quoted 6 lines
--D
libext2fs: clear
BLOCK_UNINITany time a group has metadata blocksIf
ext2fs_reserve_super_and_bgd()is called with the filesystem's block bitmap, we clear thegroup's
Quoted 2 lines
BLOCK_UNINITflag if the group has an old-style (pre-metabg) group descriptor block withreserved
Quoted 4 lines
descriptor blocks prior to marking the old-style descriptor blocks in use.
Unfortunately, this is not sufficient -- if the group has no reserved blocks yet isn't a
meta_bgQuoted 49 lines
filesystem (^resize_inode,^meta_bg), we forget to clear the flag, so the filesystem thinks all blocks are free, which is disastrous.
Therefore, if we know that we're going to mark any of the bitmaps, make sure that we clear
BLOCK_UNINIT.This is based on an earlier patch by Akira Fujita.
Quoted 11 lines
Steps to reproduce:
1. mke2fs -t ext4 -b 4096 -O ^resize_inode device 2. e2fsck -b 32768 DEV
<snip>
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Block bitmap differences: +(32768--32769) +(98304--98305) +(163840--163841) Fix<y>?Reported-by Akira Fujita <[email protected]>Signed-off-by Darrick J. Wong <[email protected]>---
lib/ext2fs/alloc_sb.c| 11 +++++++++--1 file changed, 9 insertions(+), 2 deletions(-)lib/ext2fs/alloc_sb.c index renamed from lib/ext2fs/alloc_sb.c +0
-0223ec51..f1898df 100644
lib/ext2fs/alloc_sb.c +9
-0@@ -52,6 +52,15 @@ int ext2fs_reserve_super_and_bgd(ext2_filsys fs,ext2fs_super_and_bgd_loc2 (fs, group, &super_blk, &old_desc_blk, &new_desc_blk, &used_blks); +/* +* If we're marking blocks in the main block bitmap, be sure that we +* clear the group's BLOCK_UNINIT flag if this group has metadata +* blocks allocated. +*/ +if (fs->block_map == bmap && + (new_desc_blk || old_desc_blk || super_blk || (group ==0 ))) +ext2fs_bg_flags_clear (fs, group,EXT2_BG_BLOCK_UNINIT ); +if (fs->super->s_feature_incompat &EXT2_FEATURE_INCOMPAT_META_BG ) old_desc_blocks = fs->super->s_first_meta_bg;else @@ -65,8 +74,6 @@ int ext2fs_reserve_super_and_bgd(ext2_filsys fs,ext2fs_mark_block_bitmap2 (bmap,0 );Quoted 11 lines
lib/ext2fs/alloc_sb.c int ext2fs_reserve_super_and_bgd(ext2_filsys fs, · line 79
Quoted 6 lines
lib/ext2fs/alloc_sb.c +0
-2if (old_desc_blk) { -if (fs->super->s_reserved_gdt_blocks && fs->block_map == bmap) -ext2fs_bg_flags_clear (fs, group,EXT2_BG_BLOCK_UNINIT ); num_blocks = old_desc_blocks;if (old_desc_blk + num_blocks >=ext2fs_blocks_count (fs->super)) num_blocks = ext2fs_blocks_count(fs->super) ---
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.htmlQuoted 2 lines
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a messageto
Quoted 1 line
[email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 11 lines · Darrick J. Wong
Hi Ted, I was hoping you might resolve a question for us:
Quoted 4 lines
And there is a bug that block group which has backup super block and group descriptor block are not write out to device in
wrtie_bitmaps()whenBLOCK_UNINITis set.
So at this time, I attempted to fix this by cleaningBLOCK_UNIIT.Is it the case that a group should only have
BLOCK_UNINITset if the group is totally empty (no group metadata, no blocks allocated to files) as Akira says?Or is it the case that a group can have
BLOCK_UNINITset if the group contains group metadata but no blocks are allocated to files?
The meaning of BLOCK_UNINIT is that the contents of that block group's block allocation bitmap is not initialized. This causes libext2fs to skip writing the block allocation bitmap, and to also skip reading the block allocation bitmap (which is why it substitutes all zero's instead of reading the allocation bitmap block).
Before allocating a block from a block group that has the BLOCK_UNINIT flag set, it is important that the kernel or the userspace library first initialize the block allocation bitmap and clear the BLOCK_UNINIT flag.
When allocating blocks, implementations MUST be able to initiaize the allocation bitmap for block groups which has the block group's own metadata blocks (backup superblock and bg descriptor blocks if any, reserved bg blocks, the allocation bitmaps, and inode table blocks) in use.
Implementations SHOULD be able to initialize bitmaps for block groups that have metadata blocks from other block groups if the case of flex_bg. However, historically there were some implementations that didn't handle this correctly, which is why mke2fs initializes the block bitmap and clears BLOCK_UNINIT in block groups that have metadata blocks for other block groups.
Optionally, implementations MAY set the BLOCK_UNINIT bit after data blocks have been deallocated from a block group such that the only blocks in use are the block group's metadata groups.
Also, some implementations MAY clear the BLOCK_UNINIT bit and initialize the block allocation bitmap early --- for example, when allocating an inode in the block group. This shouldn't be required, however, and so implementations SHOULD correctly handle a situation where an inode has been allocated in the inode table, but BLOCK_UNINIT is set.
All of this basically boils down to the two rules of thumb:
1) The BLOCK_UNINIT bit is fundamentally about whether the block allocation bitmap is valid, and whether mke2fs can skip needing to initialize the block, and whether e2fsck, dumpe2fs, debugfs, etc. can skip reading said allocation bitmap.
2) The IETF rule of "be conservative in what you send, and liberal in what you accept" applies.
Does that help?
Thanks,
- Ted
Hi Ted, thank you for providing some historical context. :)
Quoted 24 lines · Theodore Ts'o
Quoted 11 lines · Darrick J. Wong
Hi Ted, I was hoping you might resolve a question for us:
Quoted 4 lines
And there is a bug that block group which has backup super block and group descriptor block are not write out to device in
wrtie_bitmaps()whenBLOCK_UNINITis set.
So at this time, I attempted to fix this by cleaningBLOCK_UNIIT.Is it the case that a group should only have
BLOCK_UNINITset if the group is totally empty (no group metadata, no blocks allocated to files) as Akira says?Or is it the case that a group can have
BLOCK_UNINITset if the group contains group metadata but no blocks are allocated to files?The meaning of
BLOCK_UNINITis that the contents of that block group's block allocation bitmap is not initialized. This causes libext2fs to skip writing the block allocation bitmap, and to also skip reading the block allocation bitmap (which is why it substitutes all zero's instead of reading the allocation bitmap block).Before allocating a block from a block group that has the
BLOCK_UNINITflag set, it is important that the kernel or the userspace library first initialize the block allocation bitmap and clear theBLOCK_UNINITflag.
Quoted 5 lines
When allocating blocks, implementations MUST be able to initiaize the allocation bitmap for block groups which has the block group's own metadata blocks (backup superblock and bg descriptor blocks if any, reserved bg blocks, the allocation bitmaps, and inode table blocks) in use.
I'll call this ^^^^^ (B).
Quoted 10 lines
Implementations SHOULD be able to initialize bitmaps for block groups that have metadata blocks from other block groups if the case of
flex_bg. However, historically there were some implementations that didn't handle this correctly, which is why mke2fs initializes the block bitmap and clearsBLOCK_UNINITin block groups that have metadata blocks for other block groups.Optionally, implementations MAY set the
BLOCK_UNINITbit after data blocks have been deallocated from a block group such that the only blocks in use are the block group's metadata groups.
For the record, neither e2fsprogs nor the kernel do this -- the only code that sets BLOCK_UNINIT is the fs grow code in resize2fs.
Quoted 7 lines
Also, some implementations MAY clear the
BLOCK_UNINITbit and initialize the block allocation bitmap early --- for example, when allocating an inode in the block group. This shouldn't be required, however, and so implementations SHOULD correctly handle a situation where an inode has been allocated in the inode table, butBLOCK_UNINITis set.
Quoted 6 lines
All of this basically boils down to the two rules of thumb:
1) The
BLOCK_UNINITbit is fundamentally about whether the block allocation bitmap is valid, and whether mke2fs can skip needing to initialize the block, and whether e2fsck, dumpe2fs, debugfs, etc. can skip reading said allocation bitmap.
Right now, e2fsck and resize2fs take care of (B) on their own.
One of my patches fixes everything else (debugfs, dumpe2fs, fuse2fs, tune2fs) to take care of (B) by doing it in the library. I can't think of a scenario where it'd be useful to run around with something like this:
# mke2fs -t ext4 /dev/vda -O ^resize_inode,meta_bg
# dumpe2fs /dev/vda
<snip>
Group 1: (Blocks 32768-65535) [INODE_UNINIT, BLOCK_UNINIT]
Checksum 0xa85c, unused inodes 8192
Backup superblock at 32768, Group descriptor at 32769
^^^^^ ^^^^^
Block bitmap at 3 (bg #0 + 3), Inode bitmap at 19 (bg #0 + 19)
Inode table at 546-1057 (bg #0 + 546)
32766 free blocks, 8192 free inodes, 0 directories, 8192 unused inodes
Free blocks: 32768-65535
^^^^^ <------------------ HEY!
Free inodes: 8193-16384
<snip>
# debugfs /dev/vda -R 'testb 32768'
Block 32768 not in useNotice that blocks 32768-32769 are claimed by the group, but fs->block_map thinks those blocks are free. ext2fs_open() hands back to client programs a fs handle in which the block bitmap is in that broken state.
Quoted 2 lines
2) The IETF rule of "be conservative in what you send, and liberal in what you accept" applies.
I'm not convinced that we /need/ Akira's patch to clear BLOCK_UNINIT on any group containing its own metadata, but I doubt it'd harm anything other than make e2fsck slower.
It would certainly be the conservative-send route though.
--D
Quoted 6 lines
Does that help?
Thanks,
- Ted
Quoted 8 lines · Darrick J. Wong
Quoted 2 lines
2) The IETF rule of "be conservative in what you send, and liberal in what you accept" applies.
I'm not convinced that we /need/ Akira's patch to clear
BLOCK_UNINITon any group containing its own metadata, but I doubt it'd harm anything other than make e2fsck slower.It would certainly be the conservative-send route though.
The place where we are being conserviative what we send is that we clear BLOCK_UNINIT for block groups that don't have any data blocks, but which has metadata blocks belonging to *other* block groups, because there were some kernel implementations in the past that didn't handle this correctly.
But if you have a block group that has only its metadata, that's perfectly fine. And that's easy to test; if you create a file system like this:
touch /tmp/foo.img
mke2fs -t ext2 -O uninit_bg /tmp/foo.img 1800000... then by definition every single block group has its own metadata, and if there were problems with block groups that had its own metadata blocks, we wouldn't be able to set BLOCK_UNINIT on any block group at all.
It looks like we are currently clearing BLOCK_UNINIT for block groups that contain superblocks and backup superblocs. To be honest, I don't remember why we are currently doing this. I *think* the kernel and all modern e2fsprogs should be able to do the right thing, if we set BLOCK_UNINIT on all block groups.
- Ted
[resend without accidentally dropping the cc's]
Quoted 23 lines · Theodore Ts'o
Quoted 8 lines · Darrick J. Wong
Quoted 2 lines
2) The IETF rule of "be conservative in what you send, and liberal in what you accept" applies.
I'm not convinced that we /need/ Akira's patch to clear
BLOCK_UNINITon any group containing its own metadata, but I doubt it'd harm anything other than make e2fsck slower.It would certainly be the conservative-send route though.
The place where we are being conserviative what we send is that we clear
BLOCK_UNINITfor block groups that don't have any data blocks, but which has metadata blocks belonging to *other* block groups, because there were some kernel implementations in the past that didn't handle this correctly.But if you have a block group that has only its metadata, that's perfectly fine. And that's easy to test; if you create a file system like this:
touch /tmp/foo.img mke2fs -t ext2 -O uninit_bg /tmp/foo.img 1800000
Quoted 8 lines
... then by definition every single block group has its own metadata, and if there were problems with block groups that had its own metadata blocks, we wouldn't be able to set
BLOCK_UNINITon any block group at all.It looks like we are currently clearing
BLOCK_UNINITfor block groups that contain superblocks and backup superblocs. To be honest, I don't remember why we are currently doing this. I *think* the kernel and
Looking at the git history, that chunk of ext2fs_reserve_super_and_bgd() landed there when you were trying to clean up libext2fs, though there's no obvious reason why we need to unset BLOCK_UNINIT there too. Oh well, it can't hurt.
Quoted 2 lines
all modern e2fsprogs should be able to do the right thing, if we set
BLOCK_UNINITon all block groups.
Fortunately, they do, and have since the initial ext4dev code in 2006-7.
--D
Quoted 2 lines
- Ted
Quoted 20 lines · Darrick J. Wong
Right now, e2fsck and resize2fs take care of (B) on their own.
One of my patches fixes everything else (debugfs, dumpe2fs, fuse2fs, tune2fs) to take care of (B) by doing it in the library. I can't think of a scenario where it'd be useful to run around with something like this:
# mke2fs -t ext4 /dev/vda -O ^resize_inode,meta_bg # dumpe2fs /dev/vda <snip> Group 1: (Blocks 32768-65535) [INODE_UNINIT, BLOCK_UNINIT] Checksum 0xa85c, unused inodes 8192 Backup superblock at 32768, Group descriptor at 32769 ^^^^^ ^^^^^ Block bitmap at 3 (bg #0 + 3), Inode bitmap at 19 (bg #0 + 19) Inode table at 546-1057 (bg #0 + 546) 32766 free blocks, 8192 free inodes, 0 directories, 8192 unused inodes Free blocks: 32768-65535 ^^^^^ <------------------ HEY! Free inodes: 8193-16384
Quoted 3 lines
<snip>
# debugfs /dev/vda -R 'testb 32768' Block 32768 not in use
I'm not that concerned about dumpe2fs and debugfs, since that's just a display issue. What's more important is that lib/ext2fs/alloc.c correctly handles allocations --- see check_block_uninit() and check_inode_uninit() in lib/ext2fs/alloc.c. We do take care of initializing the portion of the allocation bitmap.
This is good, because it means that e2tools will do the right thing when it writes files to an ext4 file system that has BLOCK_UNINIT set in a block group.
- Ted
Quoted 21 lines · Theodore Ts'o
Quoted 20 lines · Darrick J. Wong
Right now, e2fsck and resize2fs take care of (B) on their own.
One of my patches fixes everything else (debugfs, dumpe2fs, fuse2fs, tune2fs) to take care of (B) by doing it in the library. I can't think of a scenario where it'd be useful to run around with something like this:
# mke2fs -t ext4 /dev/vda -O ^resize_inode,meta_bg # dumpe2fs /dev/vda <snip> Group 1: (Blocks 32768-65535) [INODE_UNINIT, BLOCK_UNINIT] Checksum 0xa85c, unused inodes 8192 Backup superblock at 32768, Group descriptor at 32769 ^^^^^ ^^^^^ Block bitmap at 3 (bg #0 + 3), Inode bitmap at 19 (bg #0 + 19) Inode table at 546-1057 (bg #0 + 546) 32766 free blocks, 8192 free inodes, 0 directories, 8192 unused inodes Free blocks: 32768-65535 ^^^^^ <------------------ HEY! Free inodes: 8193-16384
Quoted 6 lines
Quoted 3 lines
<snip>
# debugfs /dev/vda -R 'testb 32768' Block 32768 not in useI'm not that concerned about dumpe2fs and debugfs, since that's just a display issue. What's more important is that
lib/ext2fs/alloc.c
I disagree that testb returning wrong results is a merely display issue. I wasn't expecting to ffb a block I know is free and have other blocks suddenly "become" in use:
debugfs: testb 32768
Block 32768 not in use
debugfs: ffb 1 65500 Free blocks found: 65500 debugfs: testb 32768
Block 32768 marked in use
debugfs: qext2fs_write_block_bitmap: Attempt to write to filesystem opened read-onlyext2fs_close: Attempt to write to filesystem opened read-only
I shouldn't have to make debugfs modify the fs just to have testb return correct results. I don't think this qualifies as "least surprise".
Anyway, I'll send the patch along and see what everyone thinks of it.
Quoted 7 lines
correctly handles allocations --- see
check_block_uninit()andcheck_inode_uninit()inlib/ext2fs/alloc.c. We do take care of initializing the portion of the allocation bitmap.This is good, because it means that e2tools will do the right thing when it writes files to an ext4 file system that has
BLOCK_UNINITset in a block group.
I agree that doing the initialization late is better than not doing it at all, so at least we're surprising and not broken. :)
--D