@@ -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,
@@ -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;
+}
@@ -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);
@@ -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();
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@effective-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(-)