diff options
-rw-r--r-- | cmds-check.c | 12 | ||||
-rw-r--r-- | qgroup-verify.c | 81 | ||||
-rw-r--r-- | qgroup-verify.h | 2 |
3 files changed, 92 insertions, 3 deletions
diff --git a/cmds-check.c b/cmds-check.c index b2e69672..e2060cba 100644 --- a/cmds-check.c +++ b/cmds-check.c @@ -6545,6 +6545,7 @@ static struct option long_options[] = { { "init-extent-tree", 0, NULL, 0 }, { "check-data-csum", 0, NULL, 0 }, { "backup", 0, NULL, 0 }, + { "subvol-extents", 1, NULL, 'E' }, { "qgroup-report", 0, NULL, 'Q' }, { NULL, 0, NULL, 0} }; @@ -6560,6 +6561,7 @@ const char * const cmd_check_usage[] = { "--init-extent-tree create a new extent tree", "--check-data-csum verify checkums of data blocks", "--qgroup-report print a report on qgroup consistency", + "--subvol-extents print subvolume extents and sharing state", NULL }; @@ -6569,6 +6571,7 @@ int cmd_check(int argc, char **argv) struct btrfs_root *root; struct btrfs_fs_info *info; u64 bytenr = 0; + u64 subvolid = 0; char uuidbuf[BTRFS_UUID_UNPARSED_SIZE]; int ret; u64 num; @@ -6604,6 +6607,9 @@ int cmd_check(int argc, char **argv) case 'Q': qgroup_report = 1; break; + case 'E': + subvolid = arg_strtou64(optarg); + break; case '?': case 'h': usage(cmd_check_usage); @@ -6660,6 +6666,12 @@ int cmd_check(int argc, char **argv) print_qgroup_report(1); goto close_out; } + if (subvolid) { + printf("Print extent state for subvolume %llu on %s\nUUID: %s\n", + subvolid, argv[optind], uuidbuf); + ret = print_extent_state(info, subvolid); + goto close_out; + } printf("Checking filesystem on %s\nUUID: %s\n", argv[optind], uuidbuf); if (!extent_buffer_uptodate(info->tree_root->node) || diff --git a/qgroup-verify.c b/qgroup-verify.c index f7692f94..81a16512 100644 --- a/qgroup-verify.c +++ b/qgroup-verify.c @@ -296,6 +296,8 @@ static void find_parent_roots(struct ulist *roots, u64 parent) } while (node && ref->bytenr == parent); } +static void print_subvol_info(u64 subvolid, u64 bytenr, u64 num_bytes, + struct ulist *roots); /* * Account each ref. Walk the refs, for each set of refs in a * given bytenr: @@ -308,7 +310,7 @@ static void find_parent_roots(struct ulist *roots, u64 parent) * - Walk ref_roots ulist, adding extent bytes to each qgroup count that * cooresponds to a found root. */ -static void account_all_refs(void) +static void account_all_refs(int do_qgroups, u64 search_subvol) { int exclusive; struct ref *ref; @@ -358,11 +360,15 @@ static void account_all_refs(void) else exclusive = 0; + if (search_subvol) + print_subvol_info(search_subvol, bytenr, num_bytes, + roots); + ULIST_ITER_INIT(&uiter); while ((unode = ulist_next(roots, &uiter))) { BUG_ON(unode->val == 0ULL); /* We only want to account fs trees */ - if (is_fstree(unode->val)) + if (is_fstree(unode->val) && do_qgroups) add_bytes(unode->val, num_bytes, exclusive); } } @@ -1072,7 +1078,7 @@ int qgroup_verify_all(struct btrfs_fs_info *info) goto out; } - account_all_refs(); + account_all_refs(1, 0); out: /* @@ -1083,3 +1089,72 @@ out: free_ref_tree(&by_bytenr); return ret; } + +static void __print_subvol_info(u64 bytenr, u64 num_bytes, struct ulist *roots) +{ + int n = roots->nnodes; + struct ulist_iterator uiter; + struct ulist_node *unode; + + printf("%llu\t%llu\t%d\t", bytenr, num_bytes, n); + + ULIST_ITER_INIT(&uiter); + while ((unode = ulist_next(roots, &uiter))) { + printf("%llu ", unode->val); + } + printf("\n"); +} + +static void print_subvol_info(u64 subvolid, u64 bytenr, u64 num_bytes, + struct ulist *roots) +{ + struct ulist_iterator uiter; + struct ulist_node *unode; + + ULIST_ITER_INIT(&uiter); + while ((unode = ulist_next(roots, &uiter))) { + BUG_ON(unode->val == 0ULL); + if (unode->val == subvolid) { + __print_subvol_info(bytenr, num_bytes, roots); + return; + } + } + + +} + +int print_extent_state(struct btrfs_fs_info *info, u64 subvol) +{ + int ret; + + tree_blocks = ulist_alloc(0); + if (!tree_blocks) { + fprintf(stderr, + "ERROR: Out of memory while allocating ulist.\n"); + return ENOMEM; + } + + /* + * Put all extent refs into our rbtree + */ + ret = scan_extents(info, 0, ~0ULL); + if (ret) { + fprintf(stderr, "ERROR: while scanning extent tree: %d\n", ret); + goto out; + } + + ret = map_implied_refs(info); + if (ret) { + fprintf(stderr, "ERROR: while mapping refs: %d\n", ret); + goto out; + } + + printf("Offset\t\tLen\tRoot Refs\tRoots\n"); + account_all_refs(0, subvol); + +out: + free_tree_blocks(); + free_ref_tree(&by_bytenr); + return ret; +} + diff --git a/qgroup-verify.h b/qgroup-verify.h index a222c175..9201407a 100644 --- a/qgroup-verify.h +++ b/qgroup-verify.h @@ -22,4 +22,6 @@ int qgroup_verify_all(struct btrfs_fs_info *info); void print_qgroup_report(int all); +int print_extent_state(struct btrfs_fs_info *info, u64 subvol); + #endif /* _BTRFS_QGROUP_VERIFY_H */ |