Re: [PATCH v8 05/13] module: Move latched RB-tree support to a separate file

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




Le 22/02/2022 à 15:12, Aaron Tomlin a écrit :
> No functional change.
> 
> This patch migrates module latched RB-tree support
> (e.g. see __module_address()) from core module code
> into kernel/module/tree_lookup.c.
> 
> Signed-off-by: Aaron Tomlin <atomlin@xxxxxxxxxx>

Reviewed-by: Christophe Leroy <christophe.leroy@xxxxxxxxxx>

> ---
>   kernel/module/Makefile      |   1 +
>   kernel/module/internal.h    |  33 +++++++++
>   kernel/module/main.c        | 130 ++----------------------------------
>   kernel/module/tree_lookup.c | 109 ++++++++++++++++++++++++++++++
>   4 files changed, 147 insertions(+), 126 deletions(-)
>   create mode 100644 kernel/module/tree_lookup.c
> 
> diff --git a/kernel/module/Makefile b/kernel/module/Makefile
> index ed3aacb04f17..88774e386276 100644
> --- a/kernel/module/Makefile
> +++ b/kernel/module/Makefile
> @@ -11,3 +11,4 @@ obj-y += main.o
>   obj-$(CONFIG_MODULE_DECOMPRESS) += decompress.o
>   obj-$(CONFIG_MODULE_SIG) += signing.o
>   obj-$(CONFIG_LIVEPATCH) += livepatch.o
> +obj-$(CONFIG_MODULES_TREE_LOOKUP) += tree_lookup.o
> diff --git a/kernel/module/internal.h b/kernel/module/internal.h
> index ad7a444253ed..f1682e3677be 100644
> --- a/kernel/module/internal.h
> +++ b/kernel/module/internal.h
> @@ -9,6 +9,7 @@
>   #include <linux/compiler.h>
>   #include <linux/module.h>
>   #include <linux/mutex.h>
> +#include <linux/rculist.h>
>   
>   #ifndef ARCH_SHF_SMALL
>   #define ARCH_SHF_SMALL 0
> @@ -93,3 +94,35 @@ static inline void module_decompress_cleanup(struct load_info *info)
>   {
>   }
>   #endif
> +
> +#ifdef CONFIG_MODULES_TREE_LOOKUP
> +struct mod_tree_root {
> +	struct latch_tree_root root;
> +	unsigned long addr_min;
> +	unsigned long addr_max;
> +};
> +
> +extern struct mod_tree_root mod_tree;
> +
> +void mod_tree_insert(struct module *mod);
> +void mod_tree_remove_init(struct module *mod);
> +void mod_tree_remove(struct module *mod);
> +struct module *mod_find(unsigned long addr);
> +#else /* !CONFIG_MODULES_TREE_LOOKUP */
> +
> +static inline void mod_tree_insert(struct module *mod) { }
> +static inline void mod_tree_remove_init(struct module *mod) { }
> +static inline void mod_tree_remove(struct module *mod) { }
> +static inline struct module *mod_find(unsigned long addr)
> +{
> +	struct module *mod;
> +
> +	list_for_each_entry_rcu(mod, &modules, list,
> +				lockdep_is_held(&module_mutex)) {
> +		if (within_module(addr, mod))
> +			return mod;
> +	}
> +
> +	return NULL;
> +}
> +#endif /* CONFIG_MODULES_TREE_LOOKUP */
> diff --git a/kernel/module/main.c b/kernel/module/main.c
> index 3596ebf3a6c3..76b53880ad91 100644
> --- a/kernel/module/main.c
> +++ b/kernel/module/main.c
> @@ -90,138 +90,16 @@ static DECLARE_WORK(init_free_wq, do_free_init);
>   static LLIST_HEAD(init_free_list);
>   
>   #ifdef CONFIG_MODULES_TREE_LOOKUP
> -
> -/*
> - * Use a latched RB-tree for __module_address(); this allows us to use
> - * RCU-sched lookups of the address from any context.
> - *
> - * This is conditional on PERF_EVENTS || TRACING because those can really hit
> - * __module_address() hard by doing a lot of stack unwinding; potentially from
> - * NMI context.
> - */
> -
> -static __always_inline unsigned long __mod_tree_val(struct latch_tree_node *n)
> -{
> -	struct module_layout *layout = container_of(n, struct module_layout, mtn.node);
> -
> -	return (unsigned long)layout->base;
> -}
> -
> -static __always_inline unsigned long __mod_tree_size(struct latch_tree_node *n)
> -{
> -	struct module_layout *layout = container_of(n, struct module_layout, mtn.node);
> -
> -	return (unsigned long)layout->size;
> -}
> -
> -static __always_inline bool
> -mod_tree_less(struct latch_tree_node *a, struct latch_tree_node *b)
> -{
> -	return __mod_tree_val(a) < __mod_tree_val(b);
> -}
> -
> -static __always_inline int
> -mod_tree_comp(void *key, struct latch_tree_node *n)
> -{
> -	unsigned long val = (unsigned long)key;
> -	unsigned long start, end;
> -
> -	start = __mod_tree_val(n);
> -	if (val < start)
> -		return -1;
> -
> -	end = start + __mod_tree_size(n);
> -	if (val >= end)
> -		return 1;
> -
> -	return 0;
> -}
> -
> -static const struct latch_tree_ops mod_tree_ops = {
> -	.less = mod_tree_less,
> -	.comp = mod_tree_comp,
> -};
> -
> -static struct mod_tree_root {
> -	struct latch_tree_root root;
> -	unsigned long addr_min;
> -	unsigned long addr_max;
> -} mod_tree __cacheline_aligned = {
> +struct mod_tree_root mod_tree __cacheline_aligned = {
>   	.addr_min = -1UL,
>   };
>   
>   #define module_addr_min mod_tree.addr_min
>   #define module_addr_max mod_tree.addr_max
>   
> -static noinline void __mod_tree_insert(struct mod_tree_node *node)
> -{
> -	latch_tree_insert(&node->node, &mod_tree.root, &mod_tree_ops);
> -}
> -
> -static void __mod_tree_remove(struct mod_tree_node *node)
> -{
> -	latch_tree_erase(&node->node, &mod_tree.root, &mod_tree_ops);
> -}
> -
> -/*
> - * These modifications: insert, remove_init and remove; are serialized by the
> - * module_mutex.
> - */
> -static void mod_tree_insert(struct module *mod)
> -{
> -	mod->core_layout.mtn.mod = mod;
> -	mod->init_layout.mtn.mod = mod;
> -
> -	__mod_tree_insert(&mod->core_layout.mtn);
> -	if (mod->init_layout.size)
> -		__mod_tree_insert(&mod->init_layout.mtn);
> -}
> -
> -static void mod_tree_remove_init(struct module *mod)
> -{
> -	if (mod->init_layout.size)
> -		__mod_tree_remove(&mod->init_layout.mtn);
> -}
> -
> -static void mod_tree_remove(struct module *mod)
> -{
> -	__mod_tree_remove(&mod->core_layout.mtn);
> -	mod_tree_remove_init(mod);
> -}
> -
> -static struct module *mod_find(unsigned long addr)
> -{
> -	struct latch_tree_node *ltn;
> -
> -	ltn = latch_tree_find((void *)addr, &mod_tree.root, &mod_tree_ops);
> -	if (!ltn)
> -		return NULL;
> -
> -	return container_of(ltn, struct mod_tree_node, node)->mod;
> -}
> -
> -#else /* MODULES_TREE_LOOKUP */
> -
> -static unsigned long module_addr_min = -1UL, module_addr_max = 0;
> -
> -static void mod_tree_insert(struct module *mod) { }
> -static void mod_tree_remove_init(struct module *mod) { }
> -static void mod_tree_remove(struct module *mod) { }
> -
> -static struct module *mod_find(unsigned long addr)
> -{
> -	struct module *mod;
> -
> -	list_for_each_entry_rcu(mod, &modules, list,
> -				lockdep_is_held(&module_mutex)) {
> -		if (within_module(addr, mod))
> -			return mod;
> -	}
> -
> -	return NULL;
> -}
> -
> -#endif /* MODULES_TREE_LOOKUP */
> +#else /* !CONFIG_MODULES_TREE_LOOKUP */
> +static unsigned long module_addr_min = -1UL, module_addr_max;
> +#endif /* CONFIG_MODULES_TREE_LOOKUP */
>   
>   /*
>    * Bounds of module text, for speeding up __module_address.
> diff --git a/kernel/module/tree_lookup.c b/kernel/module/tree_lookup.c
> new file mode 100644
> index 000000000000..0bc4ec3b22ce
> --- /dev/null
> +++ b/kernel/module/tree_lookup.c
> @@ -0,0 +1,109 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Modules tree lookup
> + *
> + * Copyright (C) 2015 Peter Zijlstra
> + * Copyright (C) 2015 Rusty Russell
> + */
> +
> +#include <linux/module.h>
> +#include <linux/rbtree_latch.h>
> +#include "internal.h"
> +
> +/*
> + * Use a latched RB-tree for __module_address(); this allows us to use
> + * RCU-sched lookups of the address from any context.
> + *
> + * This is conditional on PERF_EVENTS || TRACING because those can really hit
> + * __module_address() hard by doing a lot of stack unwinding; potentially from
> + * NMI context.
> + */
> +
> +static __always_inline unsigned long __mod_tree_val(struct latch_tree_node *n)
> +{
> +	struct module_layout *layout = container_of(n, struct module_layout, mtn.node);
> +
> +	return (unsigned long)layout->base;
> +}
> +
> +static __always_inline unsigned long __mod_tree_size(struct latch_tree_node *n)
> +{
> +	struct module_layout *layout = container_of(n, struct module_layout, mtn.node);
> +
> +	return (unsigned long)layout->size;
> +}
> +
> +static __always_inline bool
> +mod_tree_less(struct latch_tree_node *a, struct latch_tree_node *b)
> +{
> +	return __mod_tree_val(a) < __mod_tree_val(b);
> +}
> +
> +static __always_inline int
> +mod_tree_comp(void *key, struct latch_tree_node *n)
> +{
> +	unsigned long val = (unsigned long)key;
> +	unsigned long start, end;
> +
> +	start = __mod_tree_val(n);
> +	if (val < start)
> +		return -1;
> +
> +	end = start + __mod_tree_size(n);
> +	if (val >= end)
> +		return 1;
> +
> +	return 0;
> +}
> +
> +static const struct latch_tree_ops mod_tree_ops = {
> +	.less = mod_tree_less,
> +	.comp = mod_tree_comp,
> +};
> +
> +static noinline void __mod_tree_insert(struct mod_tree_node *node)
> +{
> +	latch_tree_insert(&node->node, &mod_tree.root, &mod_tree_ops);
> +}
> +
> +static void __mod_tree_remove(struct mod_tree_node *node)
> +{
> +	latch_tree_erase(&node->node, &mod_tree.root, &mod_tree_ops);
> +}
> +
> +/*
> + * These modifications: insert, remove_init and remove; are serialized by the
> + * module_mutex.
> + */
> +void mod_tree_insert(struct module *mod)
> +{
> +	mod->core_layout.mtn.mod = mod;
> +	mod->init_layout.mtn.mod = mod;
> +
> +	__mod_tree_insert(&mod->core_layout.mtn);
> +	if (mod->init_layout.size)
> +		__mod_tree_insert(&mod->init_layout.mtn);
> +}
> +
> +void mod_tree_remove_init(struct module *mod)
> +{
> +	if (mod->init_layout.size)
> +		__mod_tree_remove(&mod->init_layout.mtn);
> +}
> +
> +void mod_tree_remove(struct module *mod)
> +{
> +	__mod_tree_remove(&mod->core_layout.mtn);
> +	mod_tree_remove_init(mod);
> +}
> +
> +struct module *mod_find(unsigned long addr)
> +{
> +	struct latch_tree_node *ltn;
> +
> +	ltn = latch_tree_find((void *)addr, &mod_tree.root, &mod_tree_ops);
> +	if (!ltn)
> +		return NULL;
> +
> +	return container_of(ltn, struct mod_tree_node, node)->mod;
> +}




[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux