tmpfs mempolicy: fix /proc/mounts corrupting memory
[~shefty/rdma-dev.git] / mm / mempolicy.c
index d1b315e9862726a7f9511615279942f144261f4d..02c914cca53d1a97e8e7e8132554fc39b2b5fccb 100644 (file)
@@ -2595,8 +2595,7 @@ void numa_default_policy(void)
  */
 
 /*
- * "local" is pseudo-policy:  MPOL_PREFERRED with MPOL_F_LOCAL flag
- * Used only for mpol_parse_str() and mpol_to_str()
+ * "local" is implemented internally by MPOL_PREFERRED with MPOL_F_LOCAL flag.
  */
 static const char * const policy_modes[] =
 {
@@ -2610,28 +2609,21 @@ static const char * const policy_modes[] =
 
 #ifdef CONFIG_TMPFS
 /**
- * mpol_parse_str - parse string to mempolicy
+ * mpol_parse_str - parse string to mempolicy, for tmpfs mpol mount option.
  * @str:  string containing mempolicy to parse
  * @mpol:  pointer to struct mempolicy pointer, returned on success.
- * @no_context:  flag whether to "contextualize" the mempolicy
+ * @unused:  redundant argument, to be removed later.
  *
  * Format of input:
  *     <mode>[=<flags>][:<nodelist>]
  *
- * if @no_context is true, save the input nodemask in w.user_nodemask in
- * the returned mempolicy.  This will be used to "clone" the mempolicy in
- * a specific context [cpuset] at a later time.  Used to parse tmpfs mpol
- * mount option.  Note that if 'static' or 'relative' mode flags were
- * specified, the input nodemask will already have been saved.  Saving
- * it again is redundant, but safe.
- *
  * On success, returns 0, else 1
  */
-int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context)
+int mpol_parse_str(char *str, struct mempolicy **mpol, int unused)
 {
        struct mempolicy *new = NULL;
        unsigned short mode;
-       unsigned short uninitialized_var(mode_flags);
+       unsigned short mode_flags;
        nodemask_t nodes;
        char *nodelist = strchr(str, ':');
        char *flags = strchr(str, '=');
@@ -2719,24 +2711,23 @@ int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context)
        if (IS_ERR(new))
                goto out;
 
-       if (no_context) {
-               /* save for contextualization */
-               new->w.user_nodemask = nodes;
-       } else {
-               int ret;
-               NODEMASK_SCRATCH(scratch);
-               if (scratch) {
-                       task_lock(current);
-                       ret = mpol_set_nodemask(new, &nodes, scratch);
-                       task_unlock(current);
-               } else
-                       ret = -ENOMEM;
-               NODEMASK_SCRATCH_FREE(scratch);
-               if (ret) {
-                       mpol_put(new);
-                       goto out;
-               }
-       }
+       /*
+        * Save nodes for mpol_to_str() to show the tmpfs mount options
+        * for /proc/mounts, /proc/pid/mounts and /proc/pid/mountinfo.
+        */
+       if (mode != MPOL_PREFERRED)
+               new->v.nodes = nodes;
+       else if (nodelist)
+               new->v.preferred_node = first_node(nodes);
+       else
+               new->flags |= MPOL_F_LOCAL;
+
+       /*
+        * Save nodes for contextualization: this will be used to "clone"
+        * the mempolicy in a specific context [cpuset] at a later time.
+        */
+       new->w.user_nodemask = nodes;
+
        err = 0;
 
 out:
@@ -2756,13 +2747,13 @@ out:
  * @buffer:  to contain formatted mempolicy string
  * @maxlen:  length of @buffer
  * @pol:  pointer to mempolicy to be formatted
- * @no_context:  "context free" mempolicy - use nodemask in w.user_nodemask
+ * @unused:  redundant argument, to be removed later.
  *
  * Convert a mempolicy into a string.
  * Returns the number of characters in buffer (if positive)
  * or an error (negative)
  */
-int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol, int no_context)
+int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol, int unused)
 {
        char *p = buffer;
        int l;
@@ -2788,7 +2779,7 @@ int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol, int no_context)
        case MPOL_PREFERRED:
                nodes_clear(nodes);
                if (flags & MPOL_F_LOCAL)
-                       mode = MPOL_LOCAL;      /* pseudo-policy */
+                       mode = MPOL_LOCAL;
                else
                        node_set(pol->v.preferred_node, nodes);
                break;
@@ -2796,10 +2787,7 @@ int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol, int no_context)
        case MPOL_BIND:
                /* Fall through */
        case MPOL_INTERLEAVE:
-               if (no_context)
-                       nodes = pol->w.user_nodemask;
-               else
-                       nodes = pol->v.nodes;
+               nodes = pol->v.nodes;
                break;
 
        default: