@@ -375,6 +375,9 @@ struct e2fsck_struct {
*/
void *priv_data;
ext2fs_block_bitmap block_metadata_map; /* Metadata blocks */
+
+ /* Reserve blocks for root and l+f re-creation */
+ blk64_t root_repair_block, lnf_repair_block;
};
/* Used by the region allocation code */
@@ -601,6 +601,42 @@ static errcode_t recheck_bad_inode_checksum(ext2_filsys fs, ext2_ino_t ino,
return 0;
}
+static void reserve_block_for_root_repair(e2fsck_t ctx)
+{
+ blk64_t blk = 0;
+ errcode_t err;
+ ext2_filsys fs = ctx->fs;
+
+ ctx->root_repair_block = 0;
+ if (ext2fs_test_inode_bitmap2(ctx->inode_used_map, EXT2_ROOT_INO))
+ return;
+
+ err = ext2fs_new_block2(fs, 0, ctx->block_found_map, &blk);
+ if (err)
+ return;
+ ext2fs_mark_block_bitmap2(ctx->block_found_map, blk);
+ ctx->root_repair_block = blk;
+}
+
+static void reserve_block_for_lnf_repair(e2fsck_t ctx)
+{
+ blk64_t blk = 0;
+ errcode_t err;
+ ext2_filsys fs = ctx->fs;
+ const char *name = "lost+found";
+ ext2_ino_t ino;
+
+ ctx->lnf_repair_block = 0;
+ if (!ext2fs_lookup(fs, EXT2_ROOT_INO, name, sizeof(name)-1, 0, &ino))
+ return;
+
+ err = ext2fs_new_block2(fs, 0, ctx->block_found_map, &blk);
+ if (err)
+ return;
+ ext2fs_mark_block_bitmap2(ctx->block_found_map, blk);
+ ctx->lnf_repair_block = blk;
+}
+
void e2fsck_pass1(e2fsck_t ctx)
{
int i;
@@ -1357,6 +1393,9 @@ endit:
if (inode)
ext2fs_free_mem(&inode);
+ reserve_block_for_root_repair(ctx);
+ reserve_block_for_lnf_repair(ctx);
+
/*
* The l+f inode may have been cleared, so zap it now and
* later passes will recalculate it if necessary
@@ -134,6 +134,17 @@ abort_exit:
inode_done_map = 0;
}
+ if (ctx->lnf_repair_block) {
+ ext2fs_unmark_block_bitmap2(ctx->block_found_map,
+ ctx->lnf_repair_block);
+ ctx->lnf_repair_block = 0;
+ }
+ if (ctx->root_repair_block) {
+ ext2fs_unmark_block_bitmap2(ctx->block_found_map,
+ ctx->root_repair_block);
+ ctx->root_repair_block = 0;
+ }
+
print_resource_track(ctx, _("Pass 3"), &rtrack, ctx->fs->io);
}
@@ -176,6 +187,11 @@ static void check_root(e2fsck_t ctx)
/*
* First, find a free block
*/
+ if (ctx->root_repair_block) {
+ blk = ctx->root_repair_block;
+ ctx->root_repair_block = 0;
+ goto skip_new_block;
+ }
pctx.errcode = ext2fs_new_block2(fs, 0, ctx->block_found_map, &blk);
if (pctx.errcode) {
pctx.str = "ext2fs_new_block";
@@ -184,6 +200,7 @@ static void check_root(e2fsck_t ctx)
return;
}
ext2fs_mark_block_bitmap2(ctx->block_found_map, blk);
+skip_new_block:
ext2fs_mark_block_bitmap2(fs->block_map, blk);
ext2fs_mark_bb_dirty(fs);
@@ -425,6 +442,11 @@ unlink:
/*
* First, find a free block
*/
+ if (ctx->lnf_repair_block) {
+ blk = ctx->lnf_repair_block;
+ ctx->lnf_repair_block = 0;
+ goto skip_new_block;
+ }
retval = ext2fs_new_block2(fs, 0, ctx->block_found_map, &blk);
if (retval) {
pctx.errcode = retval;
@@ -432,6 +454,7 @@ unlink:
return 0;
}
ext2fs_mark_block_bitmap2(ctx->block_found_map, blk);
+skip_new_block:
ext2fs_block_alloc_stats2(fs, blk, +1);
/*
@@ -18,7 +18,7 @@ Directory inode 11 has an unallocated block #6. Allocate? yes
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-Block bitmap differences: -21
+Block bitmap differences: -10
Fix? yes
Free blocks count wrong for group #0 (78, counted=79).
@@ -3,5 +3,5 @@ Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-test_filesys: 11/32 files (0.0% non-contiguous), 21/100 blocks
+test_filesys: 11/32 files (9.1% non-contiguous), 21/100 blocks
Exit status is 0
If we think we're going to need to repair either the root directory or the lost+found directory, reserve a block at the end of pass 1 to reduce the likelihood of an e2fsck abort while reconstructing root/lost+found during pass 3. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> --- e2fsck/e2fsck.h | 3 +++ e2fsck/pass1.c | 39 +++++++++++++++++++++++++++++++++++++++ e2fsck/pass3.c | 23 +++++++++++++++++++++++ tests/f_holedir/expect.1 | 2 +- tests/f_holedir/expect.2 | 2 +- 5 files changed, 67 insertions(+), 2 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html