From 778791dd7da107710c2311935a24cfd7e7a5fd85 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 2 Aug 2023 14:36:11 -0400 Subject: [PATCH] LU-8130 libcfs: don't use radix tree for xarray For newer kernels the radix tree is totally based on Xarray. For Lustre support for RHEL7 we backported Xarray but it still was using the radix tree. Their is a mismatch between what the radix tree expects and using a struct xa_node when allocating and freeing memory. Instead abandon all use of the radix tree with Xarray. We use our own private kmem cache which is based on radix tree but it uses xa_node. Test-Parameters: trivial Fixes: 84e12028be9a ("LU-9859 libcfs: add support for Xarray") Change-Id: I87607aa0e55a4aca039f2fef5a76fbff0bedd9b3 Signed-off-by: James Simmons Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/51840 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Neil Brown Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin --- libcfs/libcfs/linux/linux-prim.c | 19 ++++++++++++++++--- libcfs/libcfs/linux/xarray.c | 27 +++++++++++++-------------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/libcfs/libcfs/linux/linux-prim.c b/libcfs/libcfs/linux/linux-prim.c index bf5712a..060c1ad 100644 --- a/libcfs/libcfs/linux/linux-prim.c +++ b/libcfs/libcfs/linux/linux-prim.c @@ -49,6 +49,9 @@ #include #include #include +#ifndef HAVE_XARRAY_SUPPORT +#include +#endif #ifndef HAVE_KTIME_GET_TS64 void ktime_get_ts64(struct timespec64 *ts) @@ -117,7 +120,15 @@ int cfs_apply_workqueue_attrs(struct workqueue_struct *wq, EXPORT_SYMBOL_GPL(cfs_apply_workqueue_attrs); #ifndef HAVE_XARRAY_SUPPORT -struct kmem_cache (*radix_tree_node_cachep); +struct kmem_cache *xarray_cachep; + +static void xarray_node_ctor(void *arg) +{ + struct xa_node *node = arg; + + memset(node, 0, sizeof(*node)); + INIT_LIST_HEAD(&node->private_list); +} #endif void __init cfs_arch_init(void) @@ -128,8 +139,10 @@ void __init cfs_arch_init(void) cfs_apply_workqueue_attrs_t = (void *)cfs_kallsyms_lookup_name("apply_workqueue_attrs"); #ifndef HAVE_XARRAY_SUPPORT - radix_tree_node_cachep = - (void *)cfs_kallsyms_lookup_name("radix_tree_node_cachep"); + xarray_cachep = kmem_cache_create("xarray_cache", + sizeof(struct xa_node), 0, + SLAB_PANIC | SLAB_RECLAIM_ACCOUNT, + xarray_node_ctor); #endif } diff --git a/libcfs/libcfs/linux/xarray.c b/libcfs/libcfs/linux/xarray.c index fea97fe..5bc9d76 100644 --- a/libcfs/libcfs/linux/xarray.c +++ b/libcfs/libcfs/linux/xarray.c @@ -15,7 +15,6 @@ #include #include #include -#include #include /* @@ -252,18 +251,18 @@ void *xas_load(struct xa_state *xas) EXPORT_SYMBOL_GPL(xas_load); /* Move the radix tree node cache here */ -extern struct kmem_cache *radix_tree_node_cachep; +extern struct kmem_cache *xarray_cachep; -static inline void tag_clear(struct radix_tree_node *node, unsigned int tag, +static inline void tag_clear(struct xa_node *node, unsigned int tag, int offset) { __clear_bit(offset, node->tags[tag]); } -static void radix_tree_node_rcu_free(struct rcu_head *head) +static void xarray_node_rcu_free(struct rcu_head *head) { - struct radix_tree_node *node = - container_of(head, struct radix_tree_node, rcu_head); + struct xa_node *node = + container_of(head, struct xa_node, rcu_head); int i; /* @@ -271,13 +270,13 @@ static void radix_tree_node_rcu_free(struct rcu_head *head) * can leave us with a non-NULL entry in the first slot, so clear * that here to make sure. */ - for (i = 0; i < RADIX_TREE_MAX_TAGS; i++) + for (i = 0; i < XA_MAX_MARKS; i++) tag_clear(node, i, 0); node->slots[0] = NULL; node->count = 0; - kmem_cache_free(radix_tree_node_cachep, node); + kmem_cache_free(xarray_cachep, node); } #define XA_RCU_FREE ((struct xarray *)1) @@ -286,7 +285,7 @@ static void xa_node_free(struct xa_node *node) { XA_NODE_BUG_ON(node, !list_empty(&node->private_list)); node->array = XA_RCU_FREE; - call_rcu(&node->rcu_head, radix_tree_node_rcu_free); + call_rcu(&node->rcu_head, xarray_node_rcu_free); } /* @@ -302,7 +301,7 @@ static void xas_destroy(struct xa_state *xas) if (!node) return; XA_NODE_BUG_ON(node, !list_empty(&node->private_list)); - kmem_cache_free(radix_tree_node_cachep, node); + kmem_cache_free(xarray_cachep, node); xas->xa_alloc = NULL; } @@ -334,7 +333,7 @@ bool xas_nomem(struct xa_state *xas, gfp_t gfp) if (xas->xa->xa_flags & XA_FLAGS_ACCOUNT) gfp |= __GFP_ACCOUNT; #endif - xas->xa_alloc = kmem_cache_alloc(radix_tree_node_cachep, gfp); + xas->xa_alloc = kmem_cache_alloc(xarray_cachep, gfp); if (!xas->xa_alloc) return false; XA_NODE_BUG_ON(xas->xa_alloc, !list_empty(&xas->xa_alloc->private_list)); @@ -367,10 +366,10 @@ static bool __xas_nomem(struct xa_state *xas, gfp_t gfp) #endif if (gfpflags_allow_blocking(gfp)) { xas_unlock_type(xas, lock_type); - xas->xa_alloc = kmem_cache_alloc(radix_tree_node_cachep, gfp); + xas->xa_alloc = kmem_cache_alloc(xarray_cachep, gfp); xas_lock_type(xas, lock_type); } else { - xas->xa_alloc = kmem_cache_alloc(radix_tree_node_cachep, gfp); + xas->xa_alloc = kmem_cache_alloc(xarray_cachep, gfp); } if (!xas->xa_alloc) return false; @@ -403,7 +402,7 @@ static void *xas_alloc(struct xa_state *xas, unsigned int shift) if (xas->xa->xa_flags & XA_FLAGS_ACCOUNT) gfp |= __GFP_ACCOUNT; #endif - node = kmem_cache_alloc(radix_tree_node_cachep, gfp); + node = kmem_cache_alloc(xarray_cachep, gfp); if (!node) { xas_set_err(xas, -ENOMEM); return NULL; -- 1.8.3.1