Whamcloud - gitweb
e2fsck: update mmp block in one thread
[tools/e2fsprogs.git] / e2fsck / unix.c
index 84224c1..fb1c419 100644 (file)
@@ -75,13 +75,16 @@ int journal_enable_debug = -1;
 static void usage(e2fsck_t ctx)
 {
        fprintf(stderr,
-               _("Usage: %s [-panyrcdfktvDFV] [-b superblock] [-B blocksize]\n"
+               _("Usage: %s [-pamnyrcdfktvDFV] [-b superblock] [-B blocksize]\n"
                "\t\t[-l|-L bad_blocks_file] [-C fd] [-j external_journal]\n"
                "\t\t[-E extended-options] [-z undo_file] device\n"),
                ctx->program_name);
 
        fprintf(stderr, "%s", _("\nEmergency help:\n"
                " -p                   Automatic repair (no questions)\n"
+#ifdef HAVE_PTHREAD
+               " -m                   multiple threads to speedup fsck\n"
+#endif
                " -n                   Make no changes to the filesystem\n"
                " -y                   Assume \"yes\" to all questions\n"
                " -c                   Check for bad blocks and add them to the badblock list\n"
@@ -138,7 +141,8 @@ static void show_stats(e2fsck_t     ctx)
                               "%llu/%llu blocks\n"),
                        ctx->device_name, inodes_used, inodes,
                        frag_percent_total / 10, frag_percent_total % 10,
-                       blocks_used, blocks);
+                       (unsigned long long) blocks_used,
+                       (unsigned long long) blocks);
                return;
        }
        profile_get_boolean(ctx->profile, "options", "report_features", 0, 0,
@@ -194,7 +198,8 @@ static void show_stats(e2fsck_t     ctx)
        log_out(ctx, P_("%12llu block used (%2.2f%%, out of %llu)\n",
                        "%12llu blocks used (%2.2f%%, out of %llu)\n",
                   blocks_used),
-               blocks_used, 100.0 * blocks_used / blocks, blocks);
+               (unsigned long long) blocks_used, 100.0 * blocks_used / blocks,
+               (unsigned long long) blocks);
        log_out(ctx, P_("%12u bad block\n", "%12u bad blocks\n",
                        ctx->fs_badblocks_count), ctx->fs_badblocks_count);
        log_out(ctx, P_("%12u large file\n", "%12u large files\n",
@@ -444,9 +449,9 @@ static void check_if_skip(e2fsck_t ctx)
                ctx->device_name,
                fs->super->s_inodes_count - fs->super->s_free_inodes_count,
                fs->super->s_inodes_count,
-               ext2fs_blocks_count(fs->super) -
+               (unsigned long long) ext2fs_blocks_count(fs->super) -
                ext2fs_free_blocks_count(fs->super),
-               ext2fs_blocks_count(fs->super));
+               (unsigned long long) ext2fs_blocks_count(fs->super));
        next_check = 100000;
        if (fs->super->s_max_mnt_count > 0) {
                next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
@@ -753,6 +758,9 @@ static void parse_extended_opts(e2fsck_t ctx, const char *opts)
                        ctx->options |= E2F_OPT_UNSHARE_BLOCKS;
                        ctx->options |= E2F_OPT_FORCE;
                        continue;
+               } else if (strcmp(token, "check_encoding") == 0) {
+                       ctx->options |= E2F_OPT_CHECK_ENCODING;
+                       continue;
 #ifdef CONFIG_DEVELOPER_FEATURES
                } else if (strcmp(token, "clear_all_uninit_bits") == 0) {
                        ctx->options |= E2F_OPT_CLEAR_UNINIT;
@@ -784,6 +792,7 @@ static void parse_extended_opts(e2fsck_t ctx, const char *opts)
                fputs("\tbmap2extent\n", stderr);
                fputs("\tunshare_blocks\n", stderr);
                fputs("\tfixes_only\n", stderr);
+               fputs("\tcheck_encoding\n", stderr);
                fputc('\n', stderr);
                exit(1);
        }
@@ -817,7 +826,11 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
 #ifdef CONFIG_JBD_DEBUG
        char            *jbd_debug;
 #endif
-       unsigned long long phys_mem_kb;
+#ifdef HAVE_PTHREAD
+       char            *pm;
+       unsigned long   thread_num;
+#endif
+       unsigned long long phys_mem_kb, blk;
 
        retval = e2fsck_allocate_context(&ctx);
        if (retval)
@@ -847,7 +860,12 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
 
        phys_mem_kb = get_memory_size() / 1024;
        ctx->readahead_kb = ~0ULL;
+
+#ifdef HAVE_PTHREAD
+       while ((c = getopt(argc, argv, "pam:nyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDkz:")) != EOF)
+#else
        while ((c = getopt(argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDkz:")) != EOF)
+#endif
                switch (c) {
                case 'C':
                        ctx->progress = e2fsck_update_progress;
@@ -888,6 +906,22 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
                        }
                        ctx->options |= E2F_OPT_PREEN;
                        break;
+#ifdef HAVE_PTHREAD
+               case 'm':
+                       thread_num = strtoul(optarg, &pm, 0);
+                       if (*pm)
+                               fatal_error(ctx,
+                                       _("Invalid multiple thread num.\n"));
+                       if (thread_num > E2FSCK_MAX_THREADS) {
+                               fprintf(stderr,
+                                       _("threads %lu too large (max %lu)\n"),
+                                       thread_num, E2FSCK_MAX_THREADS);
+                               fatal_error(ctx, 0);
+                       }
+                       ctx->options |= E2F_OPT_MULTITHREAD;
+                       ctx->fs_num_threads = thread_num;
+                       break;
+#endif
                case 'n':
                        if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
                                goto conflict_opt;
@@ -918,7 +952,8 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
                        /* What we do by default, anyway! */
                        break;
                case 'b':
-                       res = sscanf(optarg, "%llu", &ctx->use_superblock);
+                       res = sscanf(optarg, "%llu", &blk);
+                       ctx->use_superblock = blk;
                        if (res != 1)
                                goto sscanf_err;
                        ctx->flags |= E2F_FLAG_SB_SPECIFIED;
@@ -1006,6 +1041,20 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
                        _("The -n and -l/-L options are incompatible."));
                fatal_error(ctx, 0);
        }
+#ifdef HAVE_PTHREAD
+       if (ctx->options & E2F_OPT_MULTITHREAD) {
+               if ((ctx->options & (E2F_OPT_YES|E2F_OPT_NO|E2F_OPT_PREEN)) == 0) {
+                       com_err(ctx->program_name, 0, "%s",
+                               _("The -m option should be used together with one of -p/-y/-n options."));
+                       fatal_error(ctx, 0);
+               }
+               if (ctx->progress) {
+                       com_err(ctx->program_name, 0, "%s",
+                               _("Only one of the options -C or -m may be specified."));
+                       fatal_error(ctx, 0);
+               }
+       }
+#endif
        if (ctx->options & E2F_OPT_NO)
                ctx->options |= E2F_OPT_READONLY;
 
@@ -1112,10 +1161,12 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
 #ifdef SA_RESTART
        sa.sa_flags = SA_RESTART;
 #endif
-       sa.sa_handler = signal_progress_on;
-       sigaction(SIGUSR1, &sa, 0);
-       sa.sa_handler = signal_progress_off;
-       sigaction(SIGUSR2, &sa, 0);
+       if ((ctx->options & E2F_OPT_MULTITHREAD) == 0) {
+               sa.sa_handler = signal_progress_on;
+               sigaction(SIGUSR1, &sa, 0);
+               sa.sa_handler = signal_progress_off;
+               sigaction(SIGUSR2, &sa, 0);
+       }
 #endif
 
        /* Update our PATH to include /sbin if we need to run badblocks  */
@@ -1427,6 +1478,7 @@ int main (int argc, char *argv[])
        }
        reserve_stdio_fds();
 
+       ctx->global_ctx = NULL;
        set_up_logging(ctx);
        if (ctx->logf) {
                int i;
@@ -1506,6 +1558,7 @@ restart:
        }
 
        ctx->openfs_flags = flags;
+       ctx->io_manager = io_ptr;
        retval = try_open_fs(ctx, flags, io_ptr, &fs);
 
        if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
@@ -1699,7 +1752,7 @@ failure:
         * or informational messages to the user.
         */
        if (ctx->device_name == 0 && sb->s_volume_name[0])
-               ctx->device_name = string_copy(ctx, sb->s_volume_name,
+               ctx->device_name = string_copy(ctx, (char *) sb->s_volume_name,
                                               sizeof(sb->s_volume_name));
 
        if (ctx->device_name == 0)