diff options
Diffstat (limited to 'cmds-check.c')
-rw-r--r-- | cmds-check.c | 94 |
1 files changed, 90 insertions, 4 deletions
diff --git a/cmds-check.c b/cmds-check.c index 43d48155..0b14b61e 100644 --- a/cmds-check.c +++ b/cmds-check.c @@ -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" @@ -40,6 +41,20 @@ #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; } |