mm, mempolicy: make mpol_to_str robust and always succeed
[platform/adaptation/renesas_rcar/renesas_kernel.git] / mm / mempolicy.c
index 71cb253..260b821 100644 (file)
@@ -2914,62 +2914,45 @@ out:
  * @maxlen:  length of @buffer
  * @pol:  pointer to mempolicy to be formatted
  *
- * Convert a mempolicy into a string.
- * Returns the number of characters in buffer (if positive)
- * or an error (negative)
+ * Convert @pol into a string.  If @buffer is too short, truncate the string.
+ * Recommend a @maxlen of at least 32 for the longest mode, "interleave", the
+ * longest flag, "relative", and to display at least a few node ids.
  */
-int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol)
+void mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol)
 {
        char *p = buffer;
-       int l;
-       nodemask_t nodes;
-       unsigned short mode;
-       unsigned short flags = pol ? pol->flags : 0;
-
-       /*
-        * Sanity check:  room for longest mode, flag and some nodes
-        */
-       VM_BUG_ON(maxlen < strlen("interleave") + strlen("relative") + 16);
+       nodemask_t nodes = NODE_MASK_NONE;
+       unsigned short mode = MPOL_DEFAULT;
+       unsigned short flags = 0;
 
-       if (!pol || pol == &default_policy)
-               mode = MPOL_DEFAULT;
-       else
+       if (pol && pol != &default_policy) {
                mode = pol->mode;
+               flags = pol->flags;
+       }
 
        switch (mode) {
        case MPOL_DEFAULT:
-               nodes_clear(nodes);
                break;
-
        case MPOL_PREFERRED:
-               nodes_clear(nodes);
                if (flags & MPOL_F_LOCAL)
                        mode = MPOL_LOCAL;
                else
                        node_set(pol->v.preferred_node, nodes);
                break;
-
        case MPOL_BIND:
-               /* Fall through */
        case MPOL_INTERLEAVE:
                nodes = pol->v.nodes;
                break;
-
        default:
-               return -EINVAL;
+               WARN_ON_ONCE(1);
+               snprintf(p, maxlen, "unknown");
+               return;
        }
 
-       l = strlen(policy_modes[mode]);
-       if (buffer + maxlen < p + l + 1)
-               return -ENOSPC;
-
-       strcpy(p, policy_modes[mode]);
-       p += l;
+       p += snprintf(p, maxlen, policy_modes[mode]);
 
        if (flags & MPOL_MODE_FLAGS) {
-               if (buffer + maxlen < p + 2)
-                       return -ENOSPC;
-               *p++ = '=';
+               p += snprintf(p, buffer + maxlen - p, "=");
 
                /*
                 * Currently, the only defined flags are mutually exclusive
@@ -2981,10 +2964,7 @@ int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol)
        }
 
        if (!nodes_empty(nodes)) {
-               if (buffer + maxlen < p + 2)
-                       return -ENOSPC;
-               *p++ = ':';
+               p += snprintf(p, buffer + maxlen - p, ":");
                p += nodelist_scnprintf(p, buffer + maxlen - p, nodes);
        }
-       return p - buffer;
 }