summaryrefslogtreecommitdiff
path: root/e2fsck/pass3.c
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2014-07-25 17:33:45 -0700
committerTheodore Ts'o <tytso@mit.edu>2014-07-26 15:45:42 -0400
commitb729b7dfabace52fb5c76d621f900e578e73bf12 (patch)
tree36d6a2fc351253513dd94d756382c538badb5101 /e2fsck/pass3.c
parent97c607b1a25e1f4e83bf246c76b679d91470f5dc (diff)
downloade2fsprogs-b729b7dfabace52fb5c76d621f900e578e73bf12.tar.gz
e2fsck: reserve blocks for root/lost+found directory repair
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. If / and/or /lost+found are corrupt and duplicate processing in pass 1b allocates all the free blocks in the FS, fsck aborts with an unusable FS since pass 3 can't recreate / or /lost+found. If either of those directories are missing, an admin can't easily mount the FS and access the directory tree to move files off the injured FS and free up space; this in turn prevents subsequent runs of e2fsck from being able to continue repairs of the FS. (One could migrate files manually with debugfs without the help of path names, but it seems easier if users can simply mount the FS and use regular FS management tools.) [ Fixed up an obvious C trap: const char * and const char [] are not the same thing when you are taking the size of the parameter. People, run your regression tests! Like spinach, it's good for you. :-) -- tytso ] Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'e2fsck/pass3.c')
-rw-r--r--e2fsck/pass3.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/e2fsck/pass3.c b/e2fsck/pass3.c
index fb217273..0274213d 100644
--- a/e2fsck/pass3.c
+++ b/e2fsck/pass3.c
@@ -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);
@@ -412,6 +429,11 @@ ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
/*
* 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;
@@ -419,6 +441,7 @@ ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
return 0;
}
ext2fs_mark_block_bitmap2(ctx->block_found_map, blk);
+skip_new_block:
ext2fs_block_alloc_stats2(fs, blk, +1);
/*