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
Darrick J. Wong 2014-07-26 17:14:40 -04:00 committed by Theodore Ts'o
parent 17641bf208
commit eb89a6287d
5 changed files with 364 additions and 40 deletions

View File

@ -204,28 +204,6 @@ skip_new_block:
ext2fs_mark_block_bitmap2(fs->block_map, blk);
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
*/
@ -248,6 +226,30 @@ skip_new_block:
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...
*/
@ -471,24 +473,6 @@ skip_new_block:
ext2fs_mark_inode_bitmap2(ctx->inode_dir_map, ino);
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
*/
@ -509,6 +493,27 @@ skip_new_block:
fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
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
*/

View File

@ -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

View File

@ -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.

View File

@ -0,0 +1 @@
force fsck to rebuild a corrupted rootdir w/ metadata_csum