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

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

 



From: Tvrtko Ursulin <tvrtko.ursulin@xxxxxxxxxx>

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@xxxxxxxxxx>
References: bda420b98505 ("numa balancing: migrate on fault among multiple bound nodes")
Cc: Huang Ying <ying.huang@xxxxxxxxx>
Cc: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
---
 mm/mempolicy.c | 58 +++++++++++++++++++++++++++++++++-----------------
 1 file changed, 39 insertions(+), 19 deletions(-)

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
-- 
2.44.0





[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux