diff mbox series

[2/3] mm/mempolicy: Use flags lookup array in mpol_to_str

Message ID 20240705143218.21258-3-tursulin@igalia.com (mailing list archive)
State New
Headers show
Series One fix for /proc/<pid>/numa_maps and two RFCs | expand

Commit Message

Tvrtko Ursulin July 5, 2024, 2:32 p.m. UTC
From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>

Generalise displaying of flags in mpol_to_str() with the benefit of
removing the knowledge of which flags are mutually exclusive and which are
not.

Also add a warning for unknown flags which slightly "hardens" against
possible future omissions to add handling for new stuff, as had happened
in bda420b98505.

Simplify by switching to scnprintf while at it.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
References: bda420b98505 ("numa balancing: migrate on fault among multiple bound nodes")
Cc: Huang Ying <ying.huang@intel.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
---
 mm/mempolicy.c | 58 +++++++++++++++++++++++++++++++++-----------------
 1 file changed, 39 insertions(+), 19 deletions(-)
diff mbox series

Patch

diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 1bfb6c73a39c..77488878d8ca 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -3150,6 +3150,17 @@  static const char * const policy_modes[] =
 	[MPOL_PREFERRED_MANY]  = "prefer (many)",
 };
 
+/*
+ * Lookup array containing only uapi flags where the lowest user flag starts at
+ * array index zero.
+ */
+#define MPOL_FLAG_STR_INDEX(f) (ilog2(f) - __builtin_ffs(MPOL_MODE_FLAGS) + 1)
+static const char * const policy_flags[] = {
+	[MPOL_FLAG_STR_INDEX(MPOL_F_STATIC_NODES)] = "static",
+	[MPOL_FLAG_STR_INDEX(MPOL_F_RELATIVE_NODES)] = "relative",
+	[MPOL_FLAG_STR_INDEX(MPOL_F_NUMA_BALANCING)] = "balancing",
+};
+
 #ifdef CONFIG_TMPFS
 /**
  * mpol_parse_str - parse string to mempolicy, for tmpfs mpol mount option.
@@ -3302,14 +3313,21 @@  void mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol)
 	char *p = buffer;
 	nodemask_t nodes = NODE_MASK_NONE;
 	unsigned short mode = MPOL_DEFAULT;
-	unsigned short flags = 0;
+	unsigned int bit, cnt;
+	unsigned long flags = 0;
+	int res;
 
 	if (pol &&
 	    pol != &default_policy &&
 	    !(pol >= &preferred_node_policy[0] &&
 	      pol <= &preferred_node_policy[MAX_NUMNODES - 1])) {
 		mode = pol->mode;
-		flags = pol->flags;
+		/*
+		 * Filter out internal flags and also move user flags to lsb for
+		 * easy lookup, matching the policy_flags[] indices.
+		 */
+		flags = (pol->flags & MPOL_MODE_FLAGS) >>
+			__ffs(MPOL_MODE_FLAGS);
 	}
 
 	switch (mode) {
@@ -3329,29 +3347,31 @@  void mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol)
 		return;
 	}
 
-	p += snprintf(p, maxlen, "%s", policy_modes[mode]);
+	res = scnprintf(p, maxlen, "%s", policy_modes[mode]);
+	p += res;
+	maxlen -= res;
 
-	if (flags & MPOL_MODE_FLAGS) {
-		p += snprintf(p, buffer + maxlen - p, "=");
+	cnt = 0;
+	for_each_set_bit(bit, &flags,
+			 __fls(MPOL_MODE_FLAGS) - __ffs(MPOL_MODE_FLAGS) + 1) {
+		char prefix;
 
-		/*
-		 * Static and relative are mutually exclusive.
-		 */
-		if (flags & MPOL_F_STATIC_NODES)
-			p += snprintf(p, buffer + maxlen - p, "static");
-		else if (flags & MPOL_F_RELATIVE_NODES)
-			p += snprintf(p, buffer + maxlen - p, "relative");
+		if (WARN_ON_ONCE(bit >= ARRAY_SIZE(policy_flags) ||
+				 !policy_flags[bit]))
+			continue;
 
-		if (flags & MPOL_F_NUMA_BALANCING) {
-			if (hweight16(flags & MPOL_MODE_FLAGS) > 1)
-				p += snprintf(p, buffer + maxlen - p, "|");
-			p += snprintf(p, buffer + maxlen - p, "balancing");
-		}
+		if (cnt++ == 0)
+			prefix = '=';
+		else
+			prefix = '|';
+
+		res = scnprintf(p, maxlen, "%c%s", prefix, policy_flags[bit]);
+		p += res;
+		maxlen -= res;
 	}
 
 	if (!nodes_empty(nodes))
-		p += scnprintf(p, buffer + maxlen - p, ":%*pbl",
-			       nodemask_pr_args(&nodes));
+		scnprintf(p, maxlen, ":%*pbl", nodemask_pr_args(&nodes));
 }
 
 #ifdef CONFIG_SYSFS