btrfs-progs: check: add progress indicator
authorSilvio Fricke <silvio.fricke@gmail.com>
Thu, 24 Sep 2015 06:13:05 +0000 (08:13 +0200)
committerDavid Sterba <dsterba@suse.com>
Wed, 21 Oct 2015 12:29:26 +0000 (14:29 +0200)
Signed-off-by: Silvio Fricke <silvio.fricke@gmail.com>
[minor updates]
Signed-off-by: David Sterba <dsterba@suse.com>
Documentation/btrfs-check.asciidoc
cmds-check.c

index f8d8ab4..a929862 100644 (file)
@@ -33,6 +33,8 @@ create a new CRC tree and recalculate all checksums
 create a new extent tree
 --check-data-csum::
 verify checkums of data blocks
+-p|--progress::
+indicate progress at various checking phases
 --qgroup-report::
 verify qgroup accounting and compare against filesystem accounting
 --subvol-extents <subvolid>::
index 43d4815..0b14b61 100644 (file)
@@ -30,6 +30,7 @@
 #include "repair.h"
 #include "disk-io.h"
 #include "print-tree.h"
+#include "task-utils.h"
 #include "transaction.h"
 #include "utils.h"
 #include "commands.h"
 #include "backref.h"
 #include "ulist.h"
 
+enum task_position {
+       TASK_EXTENTS,
+       TASK_FREE_SPACE,
+       TASK_FS_ROOTS,
+       TASK_NOTHING, /* have to be the last element */
+};
+
+struct task_ctx {
+       int progress_enabled;
+       enum task_position tp;
+
+       struct task_info *info;
+};
+
 static u64 bytes_used = 0;
 static u64 total_csum_bytes = 0;
 static u64 total_btree_bytes = 0;
@@ -56,6 +71,41 @@ static int no_holes = 0;
 static int init_extent_tree = 0;
 static int check_data_csum = 0;
 static struct btrfs_fs_info *global_info;
+static struct task_ctx ctx = { 0 };
+
+static void *print_status_check(void *p)
+{
+       struct task_ctx *priv = p;
+       const char work_indicator[] = { '.', 'o', 'O', 'o' };
+       uint32_t count = 0;
+       static char *task_position_string[] = {
+               "checking extents",
+               "checking free space cache",
+               "checking fs roots",
+       };
+
+       task_period_start(priv->info, 1000 /* 1s */);
+
+       if (priv->tp == TASK_NOTHING)
+               return NULL;
+
+       while (1) {
+               printf("%s [%c]\r", task_position_string[priv->tp],
+                               work_indicator[count % 4]);
+               count++;
+               fflush(stdout);
+               task_period_wait(priv->info);
+       }
+       return NULL;
+}
+
+static int print_status_return(void *p)
+{
+       printf("\n");
+       fflush(stdout);
+
+       return 0;
+}
 
 struct extent_backref {
        struct list_head list;
@@ -3522,6 +3572,11 @@ static int check_fs_roots(struct btrfs_root *root,
        int ret;
        int err = 0;
 
+       if (ctx.progress_enabled) {
+               ctx.tp = TASK_FS_ROOTS;
+               task_start(ctx.info);
+       }
+
        /*
         * Just in case we made any changes to the extent tree that weren't
         * reflected into the free space cache yet.
@@ -3598,6 +3653,8 @@ out:
        if (!cache_tree_empty(&wc.shared))
                fprintf(stderr, "warning line %d\n", __LINE__);
 
+       task_stop(ctx.info);
+
        return err;
 }
 
@@ -5326,6 +5383,11 @@ static int check_space_cache(struct btrfs_root *root)
                return 0;
        }
 
+       if (ctx.progress_enabled) {
+               ctx.tp = TASK_FREE_SPACE;
+               task_start(ctx.info);
+       }
+
        while (1) {
                cache = btrfs_lookup_first_block_group(root->fs_info, start);
                if (!cache)
@@ -5354,6 +5416,8 @@ static int check_space_cache(struct btrfs_root *root)
                }
        }
 
+       task_stop(ctx.info);
+
        return error ? -EINVAL : 0;
 }
 
@@ -8036,6 +8100,11 @@ static int check_chunks_and_extents(struct btrfs_root *root)
                exit(1);
        }
 
+       if (ctx.progress_enabled) {
+               ctx.tp = TASK_EXTENTS;
+               task_start(ctx.info);
+       }
+
 again:
        root1 = root->fs_info->tree_root;
        level = btrfs_header_level(root1->node);
@@ -8152,6 +8221,7 @@ again:
                ret = err;
 
 out:
+       task_stop(ctx.info);
        if (repair) {
                free_corrupt_blocks_tree(root->fs_info->corrupt_blocks);
                extent_io_tree_cleanup(&excluded_extents);
@@ -9314,6 +9384,7 @@ const char * const cmd_check_usage[] = {
        "--qgroup-report             print a report on qgroup consistency",
        "--subvol-extents <subvolid> print subvolume extents and sharing state",
        "--tree-root <bytenr>        use the given bytenr for the tree root",
+       "-p|--progress               indicate progress",
        NULL
 };
 
@@ -9348,10 +9419,11 @@ int cmd_check(int argc, char **argv)
                        { "subvol-extents", required_argument, NULL, 'E' },
                        { "qgroup-report", no_argument, NULL, 'Q' },
                        { "tree-root", required_argument, NULL, 'r' },
+                       { "progress", no_argument, NULL, 'p' },
                        { NULL, 0, NULL, 0}
                };
 
-               c = getopt_long(argc, argv, "as:br:", long_options, NULL);
+               c = getopt_long(argc, argv, "as:br:p", long_options, NULL);
                if (c < 0)
                        break;
                switch(c) {
@@ -9380,6 +9452,9 @@ int cmd_check(int argc, char **argv)
                        case 'r':
                                tree_root_bytenr = arg_strtou64(optarg);
                                break;
+                       case 'p':
+                               ctx.progress_enabled = true;
+                               break;
                        case '?':
                        case 'h':
                                usage(cmd_check_usage);
@@ -9413,6 +9488,11 @@ int cmd_check(int argc, char **argv)
        if (check_argc_exact(argc, 1))
                usage(cmd_check_usage);
 
+       if (ctx.progress_enabled) {
+               ctx.tp = TASK_NOTHING;
+               ctx.info = task_init(print_status_check, print_status_return, &ctx);
+       }
+
        /* This check is the only reason for --readonly to exist */
        if (readonly && repair) {
                fprintf(stderr, "Repair options are not compatible with --readonly\n");
@@ -9540,7 +9620,8 @@ int cmd_check(int argc, char **argv)
                goto close_out;
        }
 
-       fprintf(stderr, "checking extents\n");
+       if (!ctx.progress_enabled)
+               fprintf(stderr, "checking extents\n");
        ret = check_chunks_and_extents(root);
        if (ret)
                fprintf(stderr, "Errors found in extent allocation tree or chunk allocation\n");
@@ -9561,7 +9642,8 @@ int cmd_check(int argc, char **argv)
                goto close_out;
        }
 
-       fprintf(stderr, "checking free space cache\n");
+       if (!ctx.progress_enabled)
+               fprintf(stderr, "checking free space cache\n");
        ret = check_space_cache(root);
        if (ret)
                goto out;
@@ -9574,7 +9656,8 @@ int cmd_check(int argc, char **argv)
         */
        no_holes = btrfs_fs_incompat(root->fs_info,
                                     BTRFS_FEATURE_INCOMPAT_NO_HOLES);
-       fprintf(stderr, "checking fs roots\n");
+       if (!ctx.progress_enabled)
+               fprintf(stderr, "checking fs roots\n");
        ret = check_fs_roots(root, &root_cache);
        if (ret)
                goto out;
@@ -9656,5 +9739,8 @@ close_out:
        close_ctree(root);
        btrfs_close_all_devices();
 err_out:
+       if (ctx.progress_enabled)
+               task_deinit(ctx.info);
+
        return ret;
 }