From 45c624eb4656a6d25e3557e453a5e27c02ffc7f5 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Tue, 22 Oct 2024 17:19:44 -0700 Subject: [PATCH] LU-8130 libcfs: don't use radix tree for xarray MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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. Lustre-change: https://review.whamcloud.com/51840 Lustre-commit: 778791dd7da107710c2311935a24cfd7e7a5fd85 LU-17052 libcfs: fix build for old kernel Fix build for kernel v4.17 to v4.19. These old kernels already have xarray.h and #include by fs.h but don't have full xarray support. It is needed to #include libcfs's xarray.h also to contain xarray support. Rename the header define macro to ensure libcfs's xarray.h will be included。 Lustre-change: https://review.whamcloud.com/52090 Lustre-commit: 778791dd7da107710c2311935a24cfd7e7a5fd85 Test-Parameters: trivial Test-Parameters: testlist=sanityn envdefinitions=ONLY=77,ONLY_REPEAT=20 Fixes: 84e12028be9a ("LU-9859 libcfs: add support for Xarray") Fixes: 778791dd7da1 ("LU-8130 libcfs: don't use radix tree for xarray") Signed-off-by: James Simmons Signed-off-by: Xinliang Liu Change-Id: I87607aa0e55a4aca039f2fef5a76fbff0bedd9b3 Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/56762 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Yang Sheng Reviewed-by: Oleg Drokin --- libcfs/include/libcfs/linux/xarray.h | 6 +++--- libcfs/libcfs/linux/linux-prim.c | 19 ++++++++++++++++--- libcfs/libcfs/linux/xarray.c | 27 +++++++++++++-------------- 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/libcfs/include/libcfs/linux/xarray.h b/libcfs/include/libcfs/linux/xarray.h index 74397ab..b252aaf 100644 --- a/libcfs/include/libcfs/linux/xarray.h +++ b/libcfs/include/libcfs/linux/xarray.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ */ -#ifndef _LINUX_XARRAY_H -#define _LINUX_XARRAY_H +#ifndef _LINUX_XARRAY_LUSTRE_H +#define _LINUX_XARRAY_LUSTRE_H /* * eXtensible Arrays * Copyright (c) 2017 Microsoft Corporation @@ -1763,4 +1763,4 @@ static inline void *xas_next(struct xa_state *xas) } #endif /* !HAVE_XARRAY_SUPPORT */ -#endif /* _LINUX_XARRAY_H */ +#endif /* _LINUX_XARRAY_LUSTRE_H */ diff --git a/libcfs/libcfs/linux/linux-prim.c b/libcfs/libcfs/linux/linux-prim.c index 5f2f6ae..7203ee3 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