[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20140718225422.31374.22565.stgit@birch.djwong.org>
Date: Fri, 18 Jul 2014 15:54:22 -0700
From: "Darrick J. Wong" <darrick.wong@...cle.com>
To: tytso@....edu, darrick.wong@...cle.com
Cc: linux-ext4@...r.kernel.org
Subject: [PATCH 17/24] 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.
Signed-off-by: Darrick J. Wong <darrick.wong@...cle.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(-)
diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h
index d6d0ba9..76d15c4 100644
--- a/e2fsck/e2fsck.h
+++ b/e2fsck/e2fsck.h
@@ -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 */
diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index eec93c3..5d93feb 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -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
diff --git a/e2fsck/pass3.c b/e2fsck/pass3.c
index 4fc390a..92e71e7 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);
@@ -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);
/*
diff --git a/tests/f_holedir/expect.1 b/tests/f_holedir/expect.1
index ad74fa6..e9cf590 100644
--- a/tests/f_holedir/expect.1
+++ b/tests/f_holedir/expect.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).
diff --git a/tests/f_holedir/expect.2 b/tests/f_holedir/expect.2
index 4c0b4f2..6ab6209 100644
--- a/tests/f_holedir/expect.2
+++ b/tests/f_holedir/expect.2
@@ -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
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists