mm/numa: Introduce nearest_node_nodemask()
authorAndrea Righi <arighi@nvidia.com>
Fri, 14 Feb 2025 19:40:02 +0000 (20:40 +0100)
committerTejun Heo <tj@kernel.org>
Sun, 16 Feb 2025 16:52:19 +0000 (06:52 -1000)
Introduce the new helper nearest_node_nodemask() to find the closest
node in a specified nodemask from a given starting node.

Returns MAX_NUMNODES if no node is found.

Suggested-by: Yury Norov [NVIDIA] <yury.norov@gmail.com>
Signed-off-by: Andrea Righi <arighi@nvidia.com>
Acked-by: Yury Norov [NVIDIA] <yury.norov@gmail.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
include/linux/numa.h
mm/mempolicy.c

index 31d8bf8a951a749636d456b1a1977c6c9139f43e..e6baaf6051bcff6c23308d3b67f790053fbd29dc 100644 (file)
@@ -31,6 +31,8 @@ void __init alloc_offline_node_data(int nid);
 /* Generic implementation available */
 int numa_nearest_node(int node, unsigned int state);
 
+int nearest_node_nodemask(int node, nodemask_t *mask);
+
 #ifndef memory_add_physaddr_to_nid
 int memory_add_physaddr_to_nid(u64 start);
 #endif
@@ -47,6 +49,11 @@ static inline int numa_nearest_node(int node, unsigned int state)
        return NUMA_NO_NODE;
 }
 
+static inline int nearest_node_nodemask(int node, nodemask_t *mask)
+{
+       return NUMA_NO_NODE;
+}
+
 static inline int memory_add_physaddr_to_nid(u64 start)
 {
        return 0;
index 162407fbf2bc76099f5c93da1add7056fe2df009..488cad280efb3af8f3e7223700f47a47973dfefc 100644 (file)
@@ -196,6 +196,37 @@ int numa_nearest_node(int node, unsigned int state)
 }
 EXPORT_SYMBOL_GPL(numa_nearest_node);
 
+/**
+ * nearest_node_nodemask - Find the node in @mask at the nearest distance
+ *                        from @node.
+ *
+ * @node: a valid node ID to start the search from.
+ * @mask: a pointer to a nodemask representing the allowed nodes.
+ *
+ * This function iterates over all nodes in @mask and calculates the
+ * distance from the starting @node, then it returns the node ID that is
+ * the closest to @node, or MAX_NUMNODES if no node is found.
+ *
+ * Note that @node must be a valid node ID usable with node_distance(),
+ * providing an invalid node ID (e.g., NUMA_NO_NODE) may result in crashes
+ * or unexpected behavior.
+ */
+int nearest_node_nodemask(int node, nodemask_t *mask)
+{
+       int dist, n, min_dist = INT_MAX, min_node = MAX_NUMNODES;
+
+       for_each_node_mask(n, *mask) {
+               dist = node_distance(node, n);
+               if (dist < min_dist) {
+                       min_dist = dist;
+                       min_node = n;
+               }
+       }
+
+       return min_node;
+}
+EXPORT_SYMBOL_GPL(nearest_node_nodemask);
+
 struct mempolicy *get_task_policy(struct task_struct *p)
 {
        struct mempolicy *pol = p->mempolicy;