summaryrefslogtreecommitdiff
path: root/qgroup-verify.c
diff options
context:
space:
mode:
authorDimitri John Ledkov <xnox@ubuntu.com>2016-05-10 10:13:23 +0100
committerDimitri John Ledkov <xnox@ubuntu.com>2016-05-10 10:13:23 +0100
commit58e631d01823afd60e52f3a09887f270a91889a0 (patch)
tree6afbca5492c1ad1040608e01fe0c9d909482adeb /qgroup-verify.c
parentcec572daccafa1e912cbed363df6f84687778c6f (diff)
New upstream release 4.5.2.
* Thanks for NMU of package rename. * New upstream release 4.5.2. * Upload using dgit. * Source-only upload. * btrfs-convert should not be included in the initramfs, but should be compiled. Using btrfs-convert is not a trivial operation, and especially not from a minimal shell. Also it is known to fail, and for a sophisticated user it is trivial to include it in the initramfs. Thus won't fix Closes: #801192 * No sponsorship required Closes: #823474 * Add Provides btrfs-tools-udeb to the -progs-udeb package.
Diffstat (limited to 'qgroup-verify.c')
-rw-r--r--qgroup-verify.c51
1 files changed, 42 insertions, 9 deletions
diff --git a/qgroup-verify.c b/qgroup-verify.c
index 7e3afda8..1a0d38c3 100644
--- a/qgroup-verify.c
+++ b/qgroup-verify.c
@@ -59,6 +59,8 @@ struct qgroup_count {
static struct counts_tree {
struct rb_root root;
unsigned int num_groups;
+ unsigned int rescan_running:1;
+ unsigned int qgroup_inconsist:1;
} counts = { .root = RB_ROOT };
static struct rb_root by_bytenr = RB_ROOT;
@@ -544,8 +546,7 @@ static int travel_tree(struct btrfs_fs_info *info, struct btrfs_root *root,
nr = btrfs_header_nritems(eb);
for (i = 0; i < nr; i++) {
new_bytenr = btrfs_node_blockptr(eb, i);
- new_num_bytes = btrfs_level_size(root,
- btrfs_header_level(eb) - 1);
+ new_num_bytes = root->nodesize;
ret = travel_tree(info, root, new_bytenr, new_num_bytes,
ref_parent);
@@ -701,6 +702,19 @@ static void add_bytes(u64 root_objectid, u64 num_bytes, int exclusive)
}
}
+static void read_qgroup_status(struct btrfs_path *path,
+ struct counts_tree *counts)
+{
+ struct btrfs_qgroup_status_item *status_item;
+ u64 flags;
+
+ status_item = btrfs_item_ptr(path->nodes[0], path->slots[0],
+ struct btrfs_qgroup_status_item);
+ flags = btrfs_qgroup_status_flags(path->nodes[0], status_item);
+ counts->qgroup_inconsist = flags & BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
+ counts->rescan_running = flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN;
+}
+
static int load_quota_info(struct btrfs_fs_info *info)
{
int ret;
@@ -735,13 +749,17 @@ static int load_quota_info(struct btrfs_fs_info *info)
btrfs_item_key(leaf, &disk_key, i);
btrfs_disk_key_to_cpu(&key, &disk_key);
+ if (key.type == BTRFS_QGROUP_STATUS_KEY) {
+ read_qgroup_status(&path, &counts);
+ continue;
+ }
if (key.type == BTRFS_QGROUP_RELATION_KEY)
printf("Ignoring qgroup relation key %llu\n",
key.objectid);
/*
- * Ignore: BTRFS_QGROUP_STATUS_KEY,
- * BTRFS_QGROUP_LIMIT_KEY, BTRFS_QGROUP_RELATION_KEY
+ * Ignore: BTRFS_QGROUP_LIMIT_KEY,
+ * BTRFS_QGROUP_RELATION_KEY
*/
if (key.type != BTRFS_QGROUP_INFO_KEY)
continue;
@@ -762,7 +780,7 @@ static int load_quota_info(struct btrfs_fs_info *info)
tmproot = btrfs_read_fs_root_no_cache(info, &root_key);
if (tmproot && !IS_ERR(tmproot)) {
count->subvol_exists = 1;
- free(tmproot);
+ btrfs_free_fs_root(tmproot);
}
}
@@ -944,7 +962,7 @@ static int scan_extents(struct btrfs_fs_info *info,
bytenr = key.objectid;
num_bytes = key.offset;
if (key.type == BTRFS_METADATA_ITEM_KEY) {
- num_bytes = info->extent_root->leafsize;
+ num_bytes = info->extent_root->nodesize;
meta = 1;
}
@@ -1017,7 +1035,7 @@ static void print_fields_signed(long long bytes,
prefix, type, bytes, type, bytes_compressed);
}
-static void print_qgroup_difference(struct qgroup_count *count, int verbose)
+static int report_qgroup_difference(struct qgroup_count *count, int verbose)
{
int is_different;
struct qgroup_info *info = &count->info;
@@ -1047,19 +1065,34 @@ static void print_qgroup_difference(struct qgroup_count *count, int verbose)
print_fields_signed(excl_diff, excl_diff,
"diff:", "exclusive");
}
+ return (is_different && count->subvol_exists);
}
-void print_qgroup_report(int all)
+int report_qgroups(int all)
{
struct rb_node *node;
struct qgroup_count *c;
+ int ret = 0;
+ if (counts.rescan_running) {
+ if (all) {
+ printf(
+ "Qgroup rescan is running, qgroup counts difference is expected\n");
+ } else {
+ printf(
+ "Qgroup rescan is running, ignore qgroup check\n");
+ return ret;
+ }
+ }
+ if (counts.qgroup_inconsist && !counts.rescan_running)
+ fprintf(stderr, "Qgroup is already inconsistent before checking\n");
node = rb_first(&counts.root);
while (node) {
c = rb_entry(node, struct qgroup_count, rb_node);
- print_qgroup_difference(c, all);
+ ret |= report_qgroup_difference(c, all);
node = rb_next(node);
}
+ return ret;
}
int qgroup_verify_all(struct btrfs_fs_info *info)