lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20211004105533.1605-1-someguy@effective-light.com>
Date:   Mon,  4 Oct 2021 06:55:32 -0400
From:   Hamza Mahfooz <someguy@...ective-light.com>
To:     linux-kernel@...r.kernel.org
Cc:     Hamza Mahfooz <someguy@...ective-light.com>,
        Chris Mason <clm@...com>, Josef Bacik <josef@...icpanda.com>,
        David Sterba <dsterba@...e.com>, linux-btrfs@...r.kernel.org
Subject: [PATCH] btrfs: use kmem cache to allocate struct btrfs_qgroup_extent_record

Commit 3368d001ba5d ("btrfs: qgroup: Record possible quota-related extent
for qgroup.") suggests that, struct btrfs_qgroup_extent_record should be
allocated using kmem cache.

Signed-off-by: Hamza Mahfooz <someguy@...ective-light.com>
---
 fs/btrfs/delayed-ref.c |  6 +++---
 fs/btrfs/qgroup.c      | 27 +++++++++++++++++++++++----
 fs/btrfs/qgroup.h      | 17 ++++++++++++++++-
 fs/btrfs/super.c       |  9 ++++++++-
 4 files changed, 50 insertions(+), 9 deletions(-)

diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c
index ca848b183474..dbe490e0ef59 100644
--- a/fs/btrfs/delayed-ref.c
+++ b/fs/btrfs/delayed-ref.c
@@ -796,7 +796,7 @@ add_delayed_ref_head(struct btrfs_trans_handle *trans,
 	if (qrecord) {
 		if (btrfs_qgroup_trace_extent_nolock(trans->fs_info,
 					delayed_refs, qrecord))
-			kfree(qrecord);
+			btrfs_free_qgroup_extent_record(qrecord);
 		else
 			qrecord_inserted = 1;
 	}
@@ -924,7 +924,7 @@ int btrfs_add_delayed_tree_ref(struct btrfs_trans_handle *trans,
 	    is_fstree(generic_ref->real_root) &&
 	    is_fstree(generic_ref->tree_ref.root) &&
 	    !generic_ref->skip_qgroup) {
-		record = kzalloc(sizeof(*record), GFP_NOFS);
+		record = btrfs_alloc_qgroup_extent_record(GFP_NOFS);
 		if (!record) {
 			kmem_cache_free(btrfs_delayed_tree_ref_cachep, ref);
 			kmem_cache_free(btrfs_delayed_ref_head_cachep, head_ref);
@@ -1029,7 +1029,7 @@ int btrfs_add_delayed_data_ref(struct btrfs_trans_handle *trans,
 	    is_fstree(ref_root) &&
 	    is_fstree(generic_ref->real_root) &&
 	    !generic_ref->skip_qgroup) {
-		record = kzalloc(sizeof(*record), GFP_NOFS);
+		record = btrfs_alloc_qgroup_extent_record(GFP_NOFS);
 		if (!record) {
 			kmem_cache_free(btrfs_delayed_data_ref_cachep, ref);
 			kmem_cache_free(btrfs_delayed_ref_head_cachep,
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index db680f5be745..a675498ae989 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -25,6 +25,7 @@
 #include "sysfs.h"
 #include "tree-mod-log.h"
 
+struct kmem_cache *btrfs_qgroup_extent_record_cachep;
 /* TODO XXX FIXME
  *  - subvol delete -> delete when ref goes to 0? delete limits also?
  *  - reorganize keys
@@ -1764,7 +1765,7 @@ int btrfs_qgroup_trace_extent(struct btrfs_trans_handle *trans, u64 bytenr,
 	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)
 	    || bytenr == 0 || num_bytes == 0)
 		return 0;
-	record = kzalloc(sizeof(*record), gfp_flag);
+	record = btrfs_alloc_qgroup_extent_record(gfp_flag);
 	if (!record)
 		return -ENOMEM;
 
@@ -1777,7 +1778,7 @@ int btrfs_qgroup_trace_extent(struct btrfs_trans_handle *trans, u64 bytenr,
 	ret = btrfs_qgroup_trace_extent_nolock(fs_info, delayed_refs, record);
 	spin_unlock(&delayed_refs->lock);
 	if (ret > 0) {
-		kfree(record);
+		btrfs_free_qgroup_extent_record(record);
 		return 0;
 	}
 	return btrfs_qgroup_trace_extent_post(trans, record);
@@ -2687,7 +2688,7 @@ int btrfs_qgroup_account_extents(struct btrfs_trans_handle *trans)
 		ulist_free(new_roots);
 		new_roots = NULL;
 		rb_erase(node, &delayed_refs->dirty_extent_root);
-		kfree(record);
+		btrfs_free_qgroup_extent_record(record);
 
 	}
 	trace_qgroup_num_dirty_extents(fs_info, trans->transid,
@@ -4269,6 +4270,24 @@ void btrfs_qgroup_destroy_extent_records(struct btrfs_transaction *trans)
 	root = &trans->delayed_refs.dirty_extent_root;
 	rbtree_postorder_for_each_entry_safe(entry, next, root, node) {
 		ulist_free(entry->old_roots);
-		kfree(entry);
+		btrfs_free_qgroup_extent_record(entry);
 	}
 }
+
+void __cold btrfs_qgroup_exit(void)
+{
+	kmem_cache_destroy(btrfs_qgroup_extent_record_cachep);
+}
+
+int __init btrfs_qgroup_init(void)
+{
+	btrfs_qgroup_extent_record_cachep = kmem_cache_create(
+				"btrfs_qgroup_extent_record",
+				sizeof(struct btrfs_qgroup_extent_record), 0,
+				SLAB_MEM_SPREAD, NULL);
+
+	if (unlikely(!btrfs_qgroup_extent_record_cachep))
+		return -ENOMEM;
+
+	return 0;
+}
diff --git a/fs/btrfs/qgroup.h b/fs/btrfs/qgroup.h
index 880e9df0dac1..b06fb52c7cee 100644
--- a/fs/btrfs/qgroup.h
+++ b/fs/btrfs/qgroup.h
@@ -12,6 +12,7 @@
 #include "ulist.h"
 #include "delayed-ref.h"
 
+extern struct kmem_cache *btrfs_qgroup_extent_record_cachep;
 /*
  * Btrfs qgroup overview
  *
@@ -102,7 +103,6 @@
 
 /*
  * Record a dirty extent, and info qgroup to update quota on it
- * TODO: Use kmem cache to alloc it.
  */
 struct btrfs_qgroup_extent_record {
 	struct rb_node node;
@@ -231,6 +231,19 @@ struct btrfs_qgroup {
 	struct kobject kobj;
 };
 
+static inline struct btrfs_qgroup_extent_record *
+btrfs_alloc_qgroup_extent_record(gfp_t gfp_flag)
+{
+	return kmem_cache_zalloc(btrfs_qgroup_extent_record_cachep, gfp_flag);
+}
+
+static inline void
+btrfs_free_qgroup_extent_record(struct btrfs_qgroup_extent_record *record)
+{
+	if (record)
+		kmem_cache_free(btrfs_qgroup_extent_record_cachep, record);
+}
+
 static inline u64 btrfs_qgroup_subvolid(u64 qgroupid)
 {
 	return (qgroupid & ((1ULL << BTRFS_QGROUP_LEVEL_SHIFT) - 1));
@@ -243,6 +256,8 @@ static inline u64 btrfs_qgroup_subvolid(u64 qgroupid)
 #define QGROUP_RELEASE		(1<<1)
 #define QGROUP_FREE		(1<<2)
 
+void __cold btrfs_qgroup_exit(void);
+int __init btrfs_qgroup_init(void);
 int btrfs_quota_enable(struct btrfs_fs_info *fs_info);
 int btrfs_quota_disable(struct btrfs_fs_info *fs_info);
 int btrfs_qgroup_rescan(struct btrfs_fs_info *fs_info);
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 537d90bf5d84..1c9b6a13d962 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -2602,10 +2602,14 @@ static int __init init_btrfs_fs(void)
 	if (err)
 		goto free_delayed_inode;
 
-	err = btrfs_delayed_ref_init();
+	err = btrfs_qgroup_init();
 	if (err)
 		goto free_auto_defrag;
 
+	err = btrfs_delayed_ref_init();
+	if (err)
+		goto free_qgroup;
+
 	err = btrfs_prelim_ref_init();
 	if (err)
 		goto free_delayed_ref;
@@ -2638,6 +2642,8 @@ static int __init init_btrfs_fs(void)
 	btrfs_prelim_ref_exit();
 free_delayed_ref:
 	btrfs_delayed_ref_exit();
+free_qgroup:
+	btrfs_qgroup_exit();
 free_auto_defrag:
 	btrfs_auto_defrag_exit();
 free_delayed_inode:
@@ -2662,6 +2668,7 @@ static int __init init_btrfs_fs(void)
 static void __exit exit_btrfs_fs(void)
 {
 	btrfs_destroy_cachep();
+	btrfs_qgroup_exit();
 	btrfs_delayed_ref_exit();
 	btrfs_auto_defrag_exit();
 	btrfs_delayed_inode_exit();
-- 
2.33.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ