+
+static int e2fsck_pass1_thread_join_one(e2fsck_t global_ctx, e2fsck_t thread_ctx)
+{
+ errcode_t retval;
+ int flags = global_ctx->flags;
+ ext2_filsys thread_fs = thread_ctx->fs;
+ ext2_filsys global_fs = global_ctx->fs;
+#ifdef HAVE_SETJMP_H
+ jmp_buf old_jmp;
+
+ memcpy(old_jmp, global_ctx->abort_loc, sizeof(jmp_buf));
+#endif
+ memcpy(global_ctx, thread_ctx, sizeof(struct e2fsck_struct));
+#ifdef HAVE_SETJMP_H
+ memcpy(global_ctx->abort_loc, old_jmp, sizeof(jmp_buf));
+#endif
+ /* Keep the global singal flags*/
+ global_ctx->flags |= (flags & E2F_FLAG_SIGNAL_MASK) |
+ (global_ctx->flags & E2F_FLAG_SIGNAL_MASK);
+
+ retval = e2fsck_pass1_merge_fs(global_fs, thread_fs);
+ if (retval) {
+ com_err(global_ctx->program_name, 0, _("while merging fs\n"));
+ return retval;
+ }
+ global_fs->priv_data = global_ctx;
+ global_ctx->fs = global_fs;
+
+ if (thread_ctx->inode_used_map) {
+ retval = e2fsck_pass1_copy_bitmap(global_fs,
+ &thread_ctx->inode_used_map,
+ &global_ctx->inode_used_map);
+ if (retval)
+ return retval;
+ }
+ if (thread_ctx->inode_bad_map) {
+ retval = e2fsck_pass1_copy_bitmap(global_fs,
+ &thread_ctx->inode_bad_map,
+ &global_ctx->inode_bad_map);
+ if (retval)
+ return retval;
+ }
+ if (thread_ctx->inode_dir_map) {
+ retval = e2fsck_pass1_copy_bitmap(global_fs,
+ &thread_ctx->inode_dir_map,
+ &global_ctx->inode_dir_map);
+ if (retval)
+ return retval;
+ }
+ if (thread_ctx->inode_bb_map) {
+ retval = e2fsck_pass1_copy_bitmap(global_fs,
+ &thread_ctx->inode_bb_map,
+ &global_ctx->inode_bb_map);
+ if (retval)
+ return retval;
+ }
+ if (thread_ctx->inode_imagic_map) {
+ retval = e2fsck_pass1_copy_bitmap(global_fs,
+ &thread_ctx->inode_imagic_map,
+ &global_ctx->inode_imagic_map);
+ if (retval)
+ return retval;
+ }
+ if (thread_ctx->inode_reg_map) {
+ retval = e2fsck_pass1_copy_bitmap(global_fs,
+ &thread_ctx->inode_reg_map,
+ &global_ctx->inode_reg_map);
+ if (retval)
+ return retval;
+ }
+ if (thread_ctx->inodes_to_rebuild) {
+ retval = e2fsck_pass1_copy_bitmap(global_fs,
+ &thread_ctx->inodes_to_rebuild,
+ &global_ctx->inodes_to_rebuild);
+ if (retval)
+ return retval;
+ }
+ if (thread_ctx->block_found_map) {
+ retval = e2fsck_pass1_copy_bitmap(global_fs,
+ &thread_ctx->block_found_map,
+ &global_ctx->block_found_map);
+ if (retval)
+ return retval;
+ }
+ if (thread_ctx->block_dup_map) {
+ retval = e2fsck_pass1_copy_bitmap(global_fs,
+ &thread_ctx->block_dup_map,
+ &global_ctx->block_dup_map);
+ if (retval)
+ return retval;
+ }
+ if (thread_ctx->block_ea_map) {
+ retval = e2fsck_pass1_copy_bitmap(global_fs,
+ &thread_ctx->block_ea_map,
+ &global_ctx->block_ea_map);
+ if (retval)
+ return retval;
+ }
+ if (thread_ctx->block_metadata_map) {
+ retval = e2fsck_pass1_copy_bitmap(global_fs,
+ &thread_ctx->block_metadata_map,
+ &global_ctx->block_metadata_map);
+ if (retval)
+ return retval;
+ }
+
+ return 0;
+}
+
+static int e2fsck_pass1_thread_join(e2fsck_t global_ctx, e2fsck_t thread_ctx)
+{
+ errcode_t retval;
+
+ retval = e2fsck_pass1_thread_join_one(global_ctx, thread_ctx);
+ ext2fs_free_mem(&thread_ctx->fs);
+ ext2fs_free_mem(&thread_ctx);
+
+ return retval;
+}
+
+void e2fsck_pass1_multithread(e2fsck_t ctx)
+{
+ errcode_t retval;
+ e2fsck_t thread_ctx;
+
+ retval = e2fsck_pass1_thread_prepare(ctx, &thread_ctx);
+ if (retval) {
+ com_err(ctx->program_name, 0,
+ _("while preparing pass1 thread\n"));
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
+ }
+
+#ifdef HAVE_SETJMP_H
+ /*
+ * When fatal_error() happens, jump to here. The thread
+ * context's flags will be saved, but its abort_loc will
+ * be overwritten by original jump buffer for the later
+ * tests.
+ */
+ if (setjmp(thread_ctx->abort_loc)) {
+ thread_ctx->flags &= ~E2F_FLAG_SETJMP_OK;
+ e2fsck_pass1_thread_join(ctx, thread_ctx);
+ return;
+ }
+ thread_ctx->flags |= E2F_FLAG_SETJMP_OK;
+#endif
+
+ e2fsck_pass1_thread(thread_ctx);
+ retval = e2fsck_pass1_thread_join(ctx, thread_ctx);
+ if (retval) {
+ com_err(ctx->program_name, 0,
+ _("while joining pass1 thread\n"));
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
+ }
+}
+
+void e2fsck_pass1(e2fsck_t ctx)
+{
+ e2fsck_pass1_multithread(ctx);
+}
+