[PATCH 34/40] btrfs: qgroup: Introduce qgroup backref cache
From: Qu Wenruo <hidden>
Date: 2020-03-23 10:26:05
Subsystem:
btrfs file system, filesystems (vfs and infrastructure), the rest · Maintainers:
Chris Mason, David Sterba, Alexander Viro, Christian Brauner, Linus Torvalds
This adds two new members for btrfs_fs_info: - struct btrfs_backref_cache *qgroup_backref_cache Only get initialized at qgroup enable time. This is to avoid further bloating up fs_info structure. - struct mutex qgroup_backref_lock This is initialized at fs_info initial time. This patch only introduces the skeleton, just initialization and cleanup for these newly introduced members, no usage of them yet. Signed-off-by: Qu Wenruo <redacted> --- fs/btrfs/ctree.h | 2 ++ fs/btrfs/disk-io.c | 1 + fs/btrfs/qgroup.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+)
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 7ee38faf91e8..974ac21dd6de 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h@@ -889,6 +889,8 @@ struct btrfs_fs_info { struct btrfs_workqueue *qgroup_rescan_workers; struct completion qgroup_rescan_completion; struct btrfs_work qgroup_rescan_work; + struct mutex qgroup_backref_lock; + struct btrfs_backref_cache *qgroup_backref_cache; bool qgroup_rescan_running; /* protected by qgroup_rescan_lock */ /* filesystem state */
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 483b54077d01..67bb6fa5ab04 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c@@ -2123,6 +2123,7 @@ static void btrfs_init_qgroup(struct btrfs_fs_info *fs_info) fs_info->qgroup_ulist = NULL; fs_info->qgroup_rescan_running = false; mutex_init(&fs_info->qgroup_rescan_lock); + mutex_init(&fs_info->qgroup_backref_lock); } static int btrfs_init_workqueues(struct btrfs_fs_info *fs_info,
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index 75bc3b686498..eeff5854c847 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c@@ -339,6 +339,19 @@ int btrfs_read_qgroup_config(struct btrfs_fs_info *fs_info) if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)) return 0; + mutex_lock(&fs_info->qgroup_backref_lock); + if (!fs_info->qgroup_backref_cache) { + fs_info->qgroup_backref_cache = kzalloc( + sizeof(struct btrfs_backref_cache), GFP_KERNEL); + if (!fs_info->qgroup_backref_cache) { + mutex_unlock(&fs_info->qgroup_backref_lock); + return -ENOMEM; + } + btrfs_backref_init_cache(fs_info, + fs_info->qgroup_backref_cache, 0); + } + mutex_unlock(&fs_info->qgroup_backref_lock); + fs_info->qgroup_ulist = ulist_alloc(GFP_KERNEL); if (!fs_info->qgroup_ulist) { ret = -ENOMEM;
@@ -528,6 +541,14 @@ void btrfs_free_qgroup_config(struct btrfs_fs_info *fs_info) */ ulist_free(fs_info->qgroup_ulist); fs_info->qgroup_ulist = NULL; + + mutex_lock(&fs_info->qgroup_backref_lock); + if (fs_info->qgroup_backref_cache) { + btrfs_backref_release_cache(fs_info->qgroup_backref_cache); + kfree(fs_info->qgroup_backref_cache); + fs_info->qgroup_backref_cache = NULL; + } + mutex_unlock(&fs_info->qgroup_backref_lock); } static int add_qgroup_relation_item(struct btrfs_trans_handle *trans, u64 src,
@@ -891,6 +912,20 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info) int slot; mutex_lock(&fs_info->qgroup_ioctl_lock); + mutex_lock(&fs_info->qgroup_backref_lock); + if (!fs_info->qgroup_backref_cache) { + fs_info->qgroup_backref_cache = kzalloc( + sizeof(struct btrfs_backref_cache), GFP_KERNEL); + if (!fs_info->qgroup_backref_cache) { + mutex_unlock(&fs_info->qgroup_backref_lock); + ret = -ENOMEM; + goto out; + } + btrfs_backref_init_cache(fs_info, fs_info->qgroup_backref_cache, + 0); + } + mutex_unlock(&fs_info->qgroup_backref_lock); + if (fs_info->quota_root) goto out;
@@ -1098,6 +1133,14 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info) goto end_trans; } + mutex_lock(&fs_info->qgroup_backref_lock); + if (fs_info->qgroup_backref_cache) { + btrfs_backref_release_cache(fs_info->qgroup_backref_cache); + kfree(fs_info->qgroup_backref_cache); + fs_info->qgroup_backref_cache = NULL; + } + mutex_unlock(&fs_info->qgroup_backref_lock); + list_del("a_root->dirty_list); btrfs_tree_lock(quota_root->node);
@@ -2566,6 +2609,16 @@ int btrfs_qgroup_account_extents(struct btrfs_trans_handle *trans) } trace_qgroup_num_dirty_extents(fs_info, trans->transid, num_dirty_extents); + + /* + * Qgroup accounting happens at commit transaction time, thus the + * backref cache will no longer be valid in next trans. + * Free it up. + */ + mutex_lock(&fs_info->qgroup_backref_lock); + if (fs_info->qgroup_backref_cache) + btrfs_backref_release_cache(fs_info->qgroup_backref_cache); + mutex_unlock(&fs_info->qgroup_backref_lock); return ret; }
--
2.25.2