From: Boris Burkov <boris@bur.io>
To: linux-btrfs@vger.kernel.org, kernel-team@fb.com
Subject: [PATCH v4 07/18] btrfs: function for recording simple quota deltas
Date: Wed, 26 Jul 2023 13:38:34 -0700 [thread overview]
Message-ID: <85ff3dcd358a340f89e93a09eafd02e051944bcd.1690403768.git.boris@bur.io> (raw)
In-Reply-To: <cover.1690403768.git.boris@bur.io>
Rather than re-computing shared/exclusive ownership based on backrefs
and walking roots for implicit backrefs, simple quotas does an increment
when creating an extent and a decrement when deleting it. Add the API
for the extent item code to use to track those events.
Also add a helper function to make collecting parent qgroups in a ulist
easier for functions like this.
Signed-off-by: Boris Burkov <boris@bur.io>
---
fs/btrfs/qgroup.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++
fs/btrfs/qgroup.h | 11 ++++++-
2 files changed, 83 insertions(+), 1 deletion(-)
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index 8e3a4ced3077..dedc532669f4 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -332,6 +332,35 @@ static int del_relation_rb(struct btrfs_fs_info *fs_info,
return -ENOENT;
}
+static int qgroup_collect_parents(struct btrfs_qgroup *qgroup,
+ struct ulist *ul)
+{
+ struct ulist_iterator uiter;
+ struct ulist_node *unode;
+ struct btrfs_qgroup_list *glist;
+ struct btrfs_qgroup *qg;
+ int ret = 0;
+
+ ulist_reinit(ul);
+ ret = ulist_add(ul, qgroup->qgroupid,
+ qgroup_to_aux(qgroup), GFP_ATOMIC);
+ if (ret < 0)
+ goto out;
+ ULIST_ITER_INIT(&uiter);
+ while ((unode = ulist_next(ul, &uiter))) {
+ qg = unode_aux_to_qgroup(unode);
+ list_for_each_entry(glist, &qg->groups, next_group) {
+ ret = ulist_add(ul, glist->group->qgroupid,
+ qgroup_to_aux(glist->group), GFP_ATOMIC);
+ if (ret < 0)
+ goto out;
+ }
+ }
+ ret = 0;
+out:
+ return ret;
+}
+
#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
int btrfs_verify_qgroup_counts(struct btrfs_fs_info *fs_info, u64 qgroupid,
u64 rfer, u64 excl)
@@ -4535,3 +4564,47 @@ void btrfs_qgroup_destroy_extent_records(struct btrfs_transaction *trans)
}
*root = RB_ROOT;
}
+
+int btrfs_record_simple_quota_delta(struct btrfs_fs_info *fs_info,
+ struct btrfs_simple_quota_delta *delta)
+{
+ int ret;
+ struct ulist *ul = fs_info->qgroup_ulist;
+ struct btrfs_qgroup *qgroup;
+ struct ulist_iterator uiter;
+ struct ulist_node *unode;
+ struct btrfs_qgroup *qg;
+ u64 root = delta->root;
+ u64 num_bytes = delta->num_bytes;
+ int sign = delta->is_inc ? 1 : -1;
+
+ if (btrfs_qgroup_mode(fs_info) != BTRFS_QGROUP_MODE_SIMPLE)
+ return 0;
+
+ if (!is_fstree(root))
+ return 0;
+
+ spin_lock(&fs_info->qgroup_lock);
+ qgroup = find_qgroup_rb(fs_info, root);
+ if (!qgroup) {
+ ret = -ENOENT;
+ goto out;
+ }
+ ret = qgroup_collect_parents(qgroup, ul);
+ if (ret)
+ goto out;
+
+ ULIST_ITER_INIT(&uiter);
+ while ((unode = ulist_next(ul, &uiter))) {
+ qg = unode_aux_to_qgroup(unode);
+ qg->excl += num_bytes * sign;
+ qg->rfer += num_bytes * sign;
+ qgroup_dirty(fs_info, qg);
+ }
+
+out:
+ spin_unlock(&fs_info->qgroup_lock);
+ if (!ret && delta->rsv_bytes)
+ btrfs_qgroup_free_refroot(fs_info, root, delta->rsv_bytes, BTRFS_QGROUP_RSV_DATA);
+ return ret;
+}
diff --git a/fs/btrfs/qgroup.h b/fs/btrfs/qgroup.h
index d4c4d039585f..94d85b4fbebd 100644
--- a/fs/btrfs/qgroup.h
+++ b/fs/btrfs/qgroup.h
@@ -235,6 +235,14 @@ struct btrfs_qgroup {
struct kobject kobj;
};
+struct btrfs_simple_quota_delta {
+ u64 root; /* The fstree root this delta counts against */
+ u64 num_bytes; /* The number of bytes in the extent being counted */
+ u64 rsv_bytes; /* The number of bytes reserved for this extent */
+ bool is_inc; /* Whether we are using or freeing the extent */
+ bool is_data; /* Whether the extent is data or metadata */
+};
+
static inline u64 btrfs_qgroup_subvolid(u64 qgroupid)
{
return (qgroupid & ((1ULL << BTRFS_QGROUP_LEVEL_SHIFT) - 1));
@@ -447,5 +455,6 @@ int btrfs_qgroup_trace_subtree_after_cow(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct extent_buffer *eb);
void btrfs_qgroup_destroy_extent_records(struct btrfs_transaction *trans);
bool btrfs_check_quota_leak(struct btrfs_fs_info *fs_info);
-
+int btrfs_record_simple_quota_delta(struct btrfs_fs_info *fs_info,
+ struct btrfs_simple_quota_delta *delta);
#endif
--
2.41.0
next prev parent reply other threads:[~2023-07-26 20:40 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-07-26 20:38 [PATCH v4 00/18] btrfs: simple quotas Boris Burkov
2023-07-26 20:38 ` [PATCH v4 01/18] btrfs: introduce quota mode Boris Burkov
2023-07-26 20:38 ` [PATCH v4 02/18] btrfs: add new quota mode for simple quotas Boris Burkov
2023-07-26 20:38 ` [PATCH v4 03/18] btrfs: expose quota mode via sysfs Boris Burkov
2023-07-26 20:38 ` [PATCH v4 04/18] btrfs: add simple_quota incompat feature to sysfs Boris Burkov
2023-07-26 20:38 ` [PATCH v4 05/18] btrfs: flush reservations during quota disable Boris Burkov
2023-07-26 20:38 ` [PATCH v4 06/18] btrfs: create qgroup earlier in snapshot creation Boris Burkov
2023-07-26 20:38 ` Boris Burkov [this message]
2023-07-26 20:38 ` [PATCH v4 08/18] btrfs: rename tree_ref and data_ref owning_root Boris Burkov
2023-07-26 20:38 ` [PATCH v4 09/18] btrfs: track owning root in btrfs_ref Boris Burkov
2023-07-26 20:38 ` [PATCH v4 10/18] btrfs: track original extent owner in head_ref Boris Burkov
2023-07-26 20:38 ` [PATCH v4 11/18] btrfs: new inline ref storing owning subvol of data extents Boris Burkov
2023-07-26 20:38 ` [PATCH v4 12/18] btrfs: inline owner ref lookup helper Boris Burkov
2023-07-26 20:38 ` [PATCH v4 13/18] btrfs: record simple quota deltas Boris Burkov
2023-07-26 20:38 ` [PATCH v4 14/18] btrfs: simple quota auto hierarchy for nested subvols Boris Burkov
2023-07-26 20:38 ` [PATCH v4 15/18] btrfs: check generation when recording simple quota delta Boris Burkov
2023-07-26 20:38 ` [PATCH v4 16/18] btrfs: track metadata relocation cow with simple quota Boris Burkov
2023-07-26 20:38 ` [PATCH v4 17/18] btrfs: track data relocation " Boris Burkov
2023-07-26 20:38 ` [PATCH v4 18/18] btrfs: only set QUOTA_ENABLED when done reading qgroups Boris Burkov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=85ff3dcd358a340f89e93a09eafd02e051944bcd.1690403768.git.boris@bur.io \
--to=boris@bur.io \
--cc=kernel-team@fb.com \
--cc=linux-btrfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).