@@ -227,6 +227,20 @@ typedef struct e2fsck_struct *e2fsck_t;
#define MAX_EXTENT_DEPTH_COUNT 5
+/*
+ * Fields that used for multi-thread
+ */
+struct e2fsck_thread {
+ /* The start group number for this thread */
+ dgrp_t et_group_start;
+ /* The end (not included) group number for this thread*/
+ dgrp_t et_group_end;
+ /* The next group number to check */
+ dgrp_t et_group_next;
+ /* Thread index */
+ int et_thread_index;
+};
+
struct e2fsck_struct {
/* ---- Following fields are never updated during the pass1 ---- */
/* Global context to get the cancel flag */
@@ -380,8 +394,8 @@ struct e2fsck_struct {
*/
ext2_ino_t stashed_ino;
struct ext2_inode *stashed_inode;
- /* Thread index, if global_ctx is null, this field is useless */
- int thread_index;
+ /* if @global_ctx is null, this field is useless */
+ struct e2fsck_thread thread_info;
/*
* Directory information
@@ -311,8 +311,9 @@ static FILE *set_up_log_file(e2fsck_t ctx, const char *key, const char *fn)
expand_logfn(ctx, log_fn, &s);
if (ctx->global_ctx) {
- assert(ctx->thread_index < 1000);
- sprintf(string_index, "%03d", ctx->thread_index);
+ assert(ctx->thread_info.et_thread_index < 1000);
+ sprintf(string_index, "%03d",
+ ctx->thread_info.et_thread_index);
append_string(&s, ".", 1);
append_string(&s, string_index, 0);
}
@@ -1378,6 +1378,19 @@ void _e2fsck_pass1(e2fsck_t ctx)
/* Set up ctx->lost_and_found if possible */
(void) e2fsck_get_lost_and_found(ctx, 0);
+ if (ctx->global_ctx) {
+#if 0
+ printf("jumping to %d\n", ctx->thread_info.et_group_start);
+#endif
+ pctx.errcode = ext2fs_inode_scan_goto_blockgroup(scan,
+ ctx->thread_info.et_group_start);
+ if (pctx.errcode) {
+ fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
+ ctx->flags |= E2F_FLAG_ABORT;
+ goto endit;
+ }
+ }
+
while (1) {
if (ino % (fs->super->s_inodes_per_group * 4) == 1) {
if (e2fsck_mmp_update(fs))
@@ -1429,6 +1442,8 @@ void _e2fsck_pass1(e2fsck_t ctx)
ext2fs_mark_inode_bitmap2(ctx->inode_used_map, ino);
continue;
}
+ if (pctx.errcode == EXT2_ET_SCAN_FINISHED)
+ break;
if (pctx.errcode &&
pctx.errcode != EXT2_ET_INODE_CSUM_INVALID &&
pctx.errcode != EXT2_ET_INODE_IS_GARBAGE) {
@@ -2302,12 +2317,15 @@ static int e2fsck_pass1_merge_fs(ext2_filsys dest, ext2_filsys src)
return retval;
}
-static errcode_t e2fsck_pass1_thread_prepare(e2fsck_t global_ctx, e2fsck_t *thread_ctx)
+static errcode_t e2fsck_pass1_thread_prepare(e2fsck_t global_ctx,
+ e2fsck_t *thread_ctx,
+ int thread_index)
{
- errcode_t retval;
- e2fsck_t thread_context;
- ext2_filsys thread_fs;
- ext2_filsys global_fs = global_ctx->fs;
+ errcode_t retval;
+ e2fsck_t thread_context;
+ ext2_filsys thread_fs;
+ ext2_filsys global_fs = global_ctx->fs;
+ struct e2fsck_thread *tinfo;
assert(global_ctx->inode_used_map == NULL);
assert(global_ctx->inode_dir_map == NULL);
@@ -2343,9 +2361,15 @@ static errcode_t e2fsck_pass1_thread_prepare(e2fsck_t global_ctx, e2fsck_t *thre
}
thread_fs->priv_data = thread_context;
- thread_context->thread_index = 0;
+ thread_context->thread_info.et_thread_index = thread_index;
set_up_logging(thread_context);
+ assert(thread_index == 0);
+ tinfo = &thread_context->thread_info;
+ tinfo->et_group_start = 0;
+ tinfo->et_group_next = 0;
+ tinfo->et_group_end = thread_fs->group_desc_count;
+
thread_context->fs = thread_fs;
*thread_ctx = thread_context;
return 0;
@@ -2505,7 +2529,7 @@ static int e2fsck_pass1_threads_start(struct e2fsck_thread_info **pinfo,
for (i = 0; i < num_threads; i++) {
tmp_pinfo = &infos[i];
tmp_pinfo->eti_thread_index = i;
- retval = e2fsck_pass1_thread_prepare(global_ctx, &thread_ctx);
+ retval = e2fsck_pass1_thread_prepare(global_ctx, &thread_ctx, i);
if (retval) {
com_err(global_ctx->program_name, retval,
_("while preparing pass1 thread\n"));
@@ -2584,6 +2608,7 @@ static errcode_t scan_callback(ext2_filsys fs,
{
struct scan_callback_struct *scan_struct;
e2fsck_t ctx;
+ struct e2fsck_thread *tinfo;
scan_struct = (struct scan_callback_struct *) priv_data;
ctx = scan_struct->ctx;
@@ -2595,6 +2620,13 @@ static errcode_t scan_callback(ext2_filsys fs,
ctx->fs->group_desc_count))
return EXT2_ET_CANCEL_REQUESTED;
+ if (ctx->global_ctx) {
+ tinfo = &ctx->thread_info;
+ tinfo->et_group_next++;
+ if (tinfo->et_group_next >= tinfo->et_group_end)
+ return EXT2_ET_SCAN_FINISHED;
+ }
+
return 0;
}
@@ -1269,6 +1269,11 @@ static struct e2fsck_problem problem_table[] = {
N_("Encrypted @i %i has corrupt encryption @a.\n"),
PROMPT_CLEAR_INODE, 0, 0, 0, 0 },
+ /* Failed to goto block group */
+ { PR_1_SCAN_GOTO,
+ N_("failed to goto block group"),
+ PROMPT_NONE, PR_FATAL, 0, 0, 0 },
+
/* Pass 1b errors */
/* Pass 1B: Rescan for duplicate/bad blocks */
@@ -707,6 +707,9 @@ struct problem_context {
/* Encrypted inode has corrupt encryption extended attribute */
#define PR_1_CORRUPT_ENCRYPTION_XATTR 0x01008B
+/* Failed to goto block group */
+#define PR_1_SCAN_GOTO 0x01008C
+
/*
* Pass 1b errors
*/
@@ -548,4 +548,7 @@ ec EXT2_ET_EA_INODE_CORRUPTED,
ec EXT2_ET_NO_GDESC,
"Group descriptors not loaded"
+ec EXT2_ET_SCAN_FINISHED,
+ "Scanning finished"
+
end