Introduce the new helper numa_nearest_nodemask() to find the closest node, in a specified nodemask and state, from a given starting node. Returns MAX_NUMNODES if no node is found. Cc: Yury Norov <yury.norov@xxxxxxxxx> Signed-off-by: Andrea Righi <arighi@xxxxxxxxxx> --- include/linux/nodemask_types.h | 6 +++++- include/linux/numa.h | 8 +++++++ mm/mempolicy.c | 38 ++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/include/linux/nodemask_types.h b/include/linux/nodemask_types.h index 6b28d97ea6ed0..8d0b7a66c3a49 100644 --- a/include/linux/nodemask_types.h +++ b/include/linux/nodemask_types.h @@ -5,6 +5,10 @@ #include <linux/bitops.h> #include <linux/numa.h> -typedef struct { DECLARE_BITMAP(bits, MAX_NUMNODES); } nodemask_t; +struct nodemask { + DECLARE_BITMAP(bits, MAX_NUMNODES); +}; + +typedef struct nodemask nodemask_t; #endif /* __LINUX_NODEMASK_TYPES_H */ diff --git a/include/linux/numa.h b/include/linux/numa.h index 3567e40329ebc..a549b87d1fca5 100644 --- a/include/linux/numa.h +++ b/include/linux/numa.h @@ -27,6 +27,8 @@ static inline bool numa_valid_node(int nid) #define __initdata_or_meminfo __initdata #endif +struct nodemask; + #ifdef CONFIG_NUMA #include <asm/sparsemem.h> @@ -38,6 +40,7 @@ void __init alloc_offline_node_data(int nid); /* Generic implementation available */ int numa_nearest_node(int node, unsigned int state); +int numa_nearest_nodemask(int node, unsigned int state, struct nodemask *mask); #ifndef memory_add_physaddr_to_nid int memory_add_physaddr_to_nid(u64 start); @@ -55,6 +58,11 @@ static inline int numa_nearest_node(int node, unsigned int state) return NUMA_NO_NODE; } +static inline int numa_nearest_nodemask(int node, unsigned int state, struct nodemask *mask) +{ + return NUMA_NO_NODE; +} + static inline int memory_add_physaddr_to_nid(u64 start) { return 0; diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 162407fbf2bc7..1cfee509c7229 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -196,6 +196,44 @@ int numa_nearest_node(int node, unsigned int state) } EXPORT_SYMBOL_GPL(numa_nearest_node); +/** + * numa_nearest_nodemask - Find the node in @mask at the nearest distance + * from @node. + * + * @node: the node to start the search from. + * @state: the node state to filter nodes by. + * @mask: a pointer to a nodemask representing the allowed nodes. + * + * This function iterates over all nodes in the given state and calculates + * the distance to the starting node. + * + * Returns the node ID in @mask that is the closest in terms of distance + * from @node, or MAX_NUMNODES if no node is found. + */ +int numa_nearest_nodemask(int node, unsigned int state, nodemask_t *mask) +{ + int dist, n, min_dist = INT_MAX, min_node = MAX_NUMNODES; + + if (node == NUMA_NO_NODE) + return MAX_NUMNODES; + + if (node_state(node, state) && node_isset(node, *mask)) + return node; + + for_each_node_state(n, state) { + if (!node_isset(n, *mask)) + continue; + dist = node_distance(node, n); + if (dist < min_dist) { + min_dist = dist; + min_node = n; + } + } + + return min_node; +} +EXPORT_SYMBOL_GPL(numa_nearest_nodemask); + struct mempolicy *get_task_policy(struct task_struct *p) { struct mempolicy *pol = p->mempolicy; -- 2.48.1