btrfs-progs: qgroup-verify: Check if qgroup limit is exceeded
PATCH 1/1 btrfs-progs: qgroup-verify: Check if qgroup limit is exceeded
For case where we exceed qgroup limits, we should also report it as an error.
Signed-off-by Qu Wenruo <[email protected]>
--- qgroup-verify.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+)
qgroup-verify.c +82 -0
@@ -54,6 +54,11 @@ struct qgroup_info {u64 exclusive_compressed; }; +struct qgroup_limit { +u64 max_rfer; +u64 max_excl; +}; +struct qgroup_count {u64 qgroupid;int subvol_exists;
@@ -63,6 +68,8 @@ struct qgroup_count {struct qgroup_info info; +struct qgroup_limit limit; +struct rb_node rb_node;/* Parents when we are a child group */
@@ -926,6 +933,48 @@ static void read_qgroup_status(struct extent_buffer *eb, int slot, counts->scan_progress =btrfs_qgroup_status_rescan (eb, status_item); } +static void read_qgroup_limit (struct extent_buffer *leaf,int slot) +{ +struct btrfs_key key; +struct btrfs_qgroup_limit_item *qli; +struct qgroup_count *count; +u64 flags; + +btrfs_item_key_to_cpu (leaf, &key, slot); + qli = btrfs_item_ptr(leaf, slot, struct btrfs_qgroup_limit_item); + flags =btrfs_qgroup_limit_flags (leaf, qli); + +/* +* Despite the deprecated LIMIT_RSV_* flags, for CMPR (compressed) +* limit it doesn't really work either. +* As qgroup works at extent level, all numbers are at compressed size +* already. +*/ +if (flags & (__BTRFS_QGROUP_LIMIT_RSV_RFER | + __BTRFS_QGROUP_LIMIT_RSV_EXCL | +BTRFS_QGROUP_LIMIT_RFER_CMPR | +BTRFS_QGROUP_LIMIT_EXCL_CMPR )) { +warning ("ignoring deprecated limit flags for qgroup %llu/%llu" , +btrfs_qgroup_level (key.offset), +btrfs_qgroup_subvid (key.offset)); + } + count =find_count (key.offset); +if (!count) { +warning ( +"found orphan QGROUP_LIMIT item, qgroup %llu/%llu doesn't exist" , +btrfs_qgroup_level (key.offset), +btrfs_qgroup_subvid (key.offset)); +return ; + } +memset (&count->limit,0 ,sizeof (struct qgroup_limit )); +if (flags &BTRFS_QGROUP_LIMIT_MAX_RFER ) + count->limit.max_rfer = +btrfs_qgroup_limit_max_referenced (leaf, qli); +if (flags &BTRFS_QGROUP_LIMIT_MAX_EXCL ) + count->limit.max_excl = +btrfs_qgroup_limit_max_exclusive (leaf, qli); +} +static int load_quota_info (struct btrfs_fs_info *info) {int ret;
@@ -979,6 +1028,10 @@ loop:continue ; } +if (key.type ==BTRFS_QGROUP_LIMIT_KEY ) { +read_qgroup_limit (leaf, i); +continue ; + }if (key.type ==BTRFS_QGROUP_STATUS_KEY ) {read_qgroup_status (leaf, i, &counts);continue ;
@@ -1308,6 +1361,31 @@ static int report_qgroup_difference(struct qgroup_count *count, int verbose)return is_different; } +bool report_qgroup_limit_error (struct qgroup_count *count) +{ +struct qgroup_info *info = &count->info; +struct qgroup_limit *limit = &count->limit; +bool ret = false; + +if (limit->max_excl && limit->max_excl < info->exclusive) { +printf ("Exclusive limit for qgroup id: %llu/%llu is exceeded\n" , +btrfs_qgroup_level (count->qgroupid), +btrfs_qgroup_subvid (count->qgroupid)); +print_fields (limit->max_excl, info->exclusive,"limit" , +"exclusive" ); + ret = true; + } +if (limit->max_rfer && limit->max_rfer < info->referenced) { +printf ("Referenced limit for qgroup id: %llu/%llu is exceeded\n" , +btrfs_qgroup_level (count->qgroupid), +btrfs_qgroup_subvid (count->qgroupid)); +print_fields (limit->max_rfer, info->referenced,"limit" , +"referenced" ); + ret = true; + } +return ret; +} +/* * Report qgroups errors * Return 0 if nothing wrong.
@@ -1352,6 +1430,10 @@ int report_qgroups(int all)list_add_tail (&c->bad_list, &bad_qgroups); found_err = true; } +if (report_qgroup_limit_error (c)) { +list_add_tail (&c->bad_list, &bad_qgroups); + found_err = true; + } node =rb_next (node); }
Signature · 1 line
2.19.1