mirror of https://github.com/vitalif/e2fsprogs
e2fsck: write dir blocks after new inode when reconstructing root/lost+found
If we trash the root directory block, e2fsck will find inode 11 (the old lost+found) and try to attach it to l+f. The lost+found checker also fails to find l+f and tries to add one to the root dir. The root dir is not found but is recreated with incorrect checksums, so linking in the l+f dir fails and the l+f '..' entry isn't set. Since both dirs now fail checksum verification, they're both referred to rehash to have that fixed, but because l+f doesn't have a '..' entry, rehash crashes because l+f has < 2 entries. On a checksumming filesystem, the routines in e2fsck that recreate /lost+found and / must write the new directory block *after* the inode has been written to disk because the checksum depends on i_generation. Add a regression test while we're at it. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>crypto
parent
17641bf208
commit
eb89a6287d
|
@ -204,28 +204,6 @@ skip_new_block:
|
||||||
ext2fs_mark_block_bitmap2(fs->block_map, blk);
|
ext2fs_mark_block_bitmap2(fs->block_map, blk);
|
||||||
ext2fs_mark_bb_dirty(fs);
|
ext2fs_mark_bb_dirty(fs);
|
||||||
|
|
||||||
/*
|
|
||||||
* Now let's create the actual data block for the inode
|
|
||||||
*/
|
|
||||||
pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
|
|
||||||
&block);
|
|
||||||
if (pctx.errcode) {
|
|
||||||
pctx.str = "ext2fs_new_dir_block";
|
|
||||||
fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
|
|
||||||
ctx->flags |= E2F_FLAG_ABORT;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pctx.errcode = ext2fs_write_dir_block4(fs, blk, block, 0,
|
|
||||||
EXT2_ROOT_INO);
|
|
||||||
if (pctx.errcode) {
|
|
||||||
pctx.str = "ext2fs_write_dir_block4";
|
|
||||||
fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
|
|
||||||
ctx->flags |= E2F_FLAG_ABORT;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ext2fs_free_mem(&block);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up the inode structure
|
* Set up the inode structure
|
||||||
*/
|
*/
|
||||||
|
@ -248,6 +226,30 @@ skip_new_block:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now let's create the actual data block for the inode.
|
||||||
|
* Due to metadata_csum, we must write the dir blocks AFTER
|
||||||
|
* the inode has been written to disk!
|
||||||
|
*/
|
||||||
|
pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
|
||||||
|
&block);
|
||||||
|
if (pctx.errcode) {
|
||||||
|
pctx.str = "ext2fs_new_dir_block";
|
||||||
|
fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
|
||||||
|
ctx->flags |= E2F_FLAG_ABORT;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pctx.errcode = ext2fs_write_dir_block4(fs, blk, block, 0,
|
||||||
|
EXT2_ROOT_INO);
|
||||||
|
ext2fs_free_mem(&block);
|
||||||
|
if (pctx.errcode) {
|
||||||
|
pctx.str = "ext2fs_write_dir_block4";
|
||||||
|
fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
|
||||||
|
ctx->flags |= E2F_FLAG_ABORT;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Miscellaneous bookkeeping...
|
* Miscellaneous bookkeeping...
|
||||||
*/
|
*/
|
||||||
|
@ -471,24 +473,6 @@ skip_new_block:
|
||||||
ext2fs_mark_inode_bitmap2(ctx->inode_dir_map, ino);
|
ext2fs_mark_inode_bitmap2(ctx->inode_dir_map, ino);
|
||||||
ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
|
ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
|
||||||
|
|
||||||
/*
|
|
||||||
* Now let's create the actual data block for the inode
|
|
||||||
*/
|
|
||||||
retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
|
|
||||||
if (retval) {
|
|
||||||
pctx.errcode = retval;
|
|
||||||
fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
retval = ext2fs_write_dir_block4(fs, blk, block, 0, ino);
|
|
||||||
ext2fs_free_mem(&block);
|
|
||||||
if (retval) {
|
|
||||||
pctx.errcode = retval;
|
|
||||||
fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up the inode structure
|
* Set up the inode structure
|
||||||
*/
|
*/
|
||||||
|
@ -509,6 +493,27 @@ skip_new_block:
|
||||||
fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
|
fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now let's create the actual data block for the inode.
|
||||||
|
* Due to metadata_csum, the directory block MUST be written
|
||||||
|
* after the inode is written to disk!
|
||||||
|
*/
|
||||||
|
retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
|
||||||
|
if (retval) {
|
||||||
|
pctx.errcode = retval;
|
||||||
|
fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = ext2fs_write_dir_block4(fs, blk, block, 0, ino);
|
||||||
|
ext2fs_free_mem(&block);
|
||||||
|
if (retval) {
|
||||||
|
pctx.errcode = retval;
|
||||||
|
fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Finally, create the directory link
|
* Finally, create the directory link
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,311 @@
|
||||||
|
Pass 1: Checking inodes, blocks, and sizes
|
||||||
|
Pass 2: Checking directory structure
|
||||||
|
Directory inode 2, block #0, offset 0: directory has no checksum.
|
||||||
|
Fix? yes
|
||||||
|
|
||||||
|
Directory inode 2, block #0, offset 0: directory corrupted
|
||||||
|
Salvage? yes
|
||||||
|
|
||||||
|
Missing '.' in directory inode 2.
|
||||||
|
Fix? yes
|
||||||
|
|
||||||
|
Setting filetype for entry '.' in ??? (2) to 2.
|
||||||
|
Missing '..' in directory inode 2.
|
||||||
|
Fix? yes
|
||||||
|
|
||||||
|
Setting filetype for entry '..' in ??? (2) to 2.
|
||||||
|
Pass 3: Checking directory connectivity
|
||||||
|
'..' in / (2) is <The NULL inode> (0), should be / (2).
|
||||||
|
Fix? yes
|
||||||
|
|
||||||
|
Unconnected directory inode 11 (/???)
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
/lost+found not found. Create? yes
|
||||||
|
|
||||||
|
Pass 3A: Optimizing directories
|
||||||
|
Pass 4: Checking reference counts
|
||||||
|
Inode 11 ref count is 3, should be 2. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 12
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 12 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 13
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 13 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 14
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 14 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 15
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 15 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 16
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 16 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 17
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 17 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 18
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 18 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 19
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 19 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 20
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 20 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 21
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 21 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 22
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 22 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 23
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 23 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 24
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 24 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 25
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 25 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 26
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 26 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 27
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 27 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 28
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 28 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 29
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 29 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 30
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 30 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 31
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 31 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 32
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 32 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 33
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 33 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 34
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 34 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 35
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 35 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 36
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 36 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 37
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 37 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 38
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 38 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 39
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 39 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 40
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 40 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 41
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 41 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 42
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 42 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 43
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 43 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 44
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 44 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 45
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 45 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 46
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 46 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 47
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 47 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 48
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 48 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 49
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 49 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 50
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 50 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 51
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 51 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 52
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 52 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 53
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 53 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 54
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 54 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 55
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 55 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 56
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 56 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 57
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 57 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 58
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 58 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 59
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 59 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 60
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 60 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 61
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 61 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 62
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 62 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 63
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 63 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 64
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 64 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached zero-length inode 65. Clear? yes
|
||||||
|
|
||||||
|
Unattached inode 66
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 66 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Unattached inode 67
|
||||||
|
Connect to /lost+found? yes
|
||||||
|
|
||||||
|
Inode 67 ref count is 2, should be 1. Fix? yes
|
||||||
|
|
||||||
|
Pass 5: Checking group summary information
|
||||||
|
|
||||||
|
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
|
||||||
|
test_filesys: 67/512 files (1.5% non-contiguous), 1127/2048 blocks
|
||||||
|
Exit status is 1
|
|
@ -0,0 +1,7 @@
|
||||||
|
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
|
||||||
|
test_filesys: 67/512 files (1.5% non-contiguous), 1127/2048 blocks
|
||||||
|
Exit status is 0
|
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
force fsck to rebuild a corrupted rootdir w/ metadata_csum
|
Loading…
Reference in New Issue