aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/mempolicy.h3
-rw-r--r--mm/mempolicy.c33
-rw-r--r--mm/shmem.c6
3 files changed, 39 insertions, 3 deletions
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index 07350d7b8d96..02b11efd7066 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -25,12 +25,13 @@ enum {
25 25
26/* Flags for set_mempolicy */ 26/* Flags for set_mempolicy */
27#define MPOL_F_STATIC_NODES (1 << 15) 27#define MPOL_F_STATIC_NODES (1 << 15)
28#define MPOL_F_RELATIVE_NODES (1 << 14)
28 29
29/* 30/*
30 * MPOL_MODE_FLAGS is the union of all possible optional mode flags passed to 31 * MPOL_MODE_FLAGS is the union of all possible optional mode flags passed to
31 * either set_mempolicy() or mbind(). 32 * either set_mempolicy() or mbind().
32 */ 33 */
33#define MPOL_MODE_FLAGS (MPOL_F_STATIC_NODES) 34#define MPOL_MODE_FLAGS (MPOL_F_STATIC_NODES | MPOL_F_RELATIVE_NODES)
34 35
35/* Flags for get_mempolicy */ 36/* Flags for get_mempolicy */
36#define MPOL_F_NODE (1<<0) /* return next IL mode instead of node mask */ 37#define MPOL_F_NODE (1<<0) /* return next IL mode instead of node mask */
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index d59b1e766aee..ffd3be66b255 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -136,7 +136,15 @@ static int is_valid_nodemask(nodemask_t *nodemask)
136 136
137static inline int mpol_store_user_nodemask(const struct mempolicy *pol) 137static inline int mpol_store_user_nodemask(const struct mempolicy *pol)
138{ 138{
139 return pol->flags & MPOL_F_STATIC_NODES; 139 return pol->flags & (MPOL_F_STATIC_NODES | MPOL_F_RELATIVE_NODES);
140}
141
142static void mpol_relative_nodemask(nodemask_t *ret, const nodemask_t *orig,
143 const nodemask_t *rel)
144{
145 nodemask_t tmp;
146 nodes_fold(tmp, *orig, nodes_weight(*rel));
147 nodes_onto(*ret, tmp, *rel);
140} 148}
141 149
142/* Create a new policy */ 150/* Create a new policy */
@@ -157,7 +165,12 @@ static struct mempolicy *mpol_new(unsigned short mode, unsigned short flags,
157 return ERR_PTR(-ENOMEM); 165 return ERR_PTR(-ENOMEM);
158 atomic_set(&policy->refcnt, 1); 166 atomic_set(&policy->refcnt, 1);
159 cpuset_update_task_memory_state(); 167 cpuset_update_task_memory_state();
160 nodes_and(cpuset_context_nmask, *nodes, cpuset_current_mems_allowed); 168 if (flags & MPOL_F_RELATIVE_NODES)
169 mpol_relative_nodemask(&cpuset_context_nmask, nodes,
170 &cpuset_current_mems_allowed);
171 else
172 nodes_and(cpuset_context_nmask, *nodes,
173 cpuset_current_mems_allowed);
161 switch (mode) { 174 switch (mode) {
162 case MPOL_INTERLEAVE: 175 case MPOL_INTERLEAVE:
163 if (nodes_empty(*nodes) || nodes_empty(cpuset_context_nmask)) 176 if (nodes_empty(*nodes) || nodes_empty(cpuset_context_nmask))
@@ -873,6 +886,9 @@ asmlinkage long sys_mbind(unsigned long start, unsigned long len,
873 mode &= ~MPOL_MODE_FLAGS; 886 mode &= ~MPOL_MODE_FLAGS;
874 if (mode >= MPOL_MAX) 887 if (mode >= MPOL_MAX)
875 return -EINVAL; 888 return -EINVAL;
889 if ((mode_flags & MPOL_F_STATIC_NODES) &&
890 (mode_flags & MPOL_F_RELATIVE_NODES))
891 return -EINVAL;
876 err = get_nodes(&nodes, nmask, maxnode); 892 err = get_nodes(&nodes, nmask, maxnode);
877 if (err) 893 if (err)
878 return err; 894 return err;
@@ -891,6 +907,8 @@ asmlinkage long sys_set_mempolicy(int mode, unsigned long __user *nmask,
891 mode &= ~MPOL_MODE_FLAGS; 907 mode &= ~MPOL_MODE_FLAGS;
892 if ((unsigned int)mode >= MPOL_MAX) 908 if ((unsigned int)mode >= MPOL_MAX)
893 return -EINVAL; 909 return -EINVAL;
910 if ((flags & MPOL_F_STATIC_NODES) && (flags & MPOL_F_RELATIVE_NODES))
911 return -EINVAL;
894 err = get_nodes(&nodes, nmask, maxnode); 912 err = get_nodes(&nodes, nmask, maxnode);
895 if (err) 913 if (err)
896 return err; 914 return err;
@@ -1745,10 +1763,12 @@ static void mpol_rebind_policy(struct mempolicy *pol,
1745{ 1763{
1746 nodemask_t tmp; 1764 nodemask_t tmp;
1747 int static_nodes; 1765 int static_nodes;
1766 int relative_nodes;
1748 1767
1749 if (!pol) 1768 if (!pol)
1750 return; 1769 return;
1751 static_nodes = pol->flags & MPOL_F_STATIC_NODES; 1770 static_nodes = pol->flags & MPOL_F_STATIC_NODES;
1771 relative_nodes = pol->flags & MPOL_F_RELATIVE_NODES;
1752 if (!mpol_store_user_nodemask(pol) && 1772 if (!mpol_store_user_nodemask(pol) &&
1753 nodes_equal(pol->w.cpuset_mems_allowed, *newmask)) 1773 nodes_equal(pol->w.cpuset_mems_allowed, *newmask))
1754 return; 1774 return;
@@ -1761,6 +1781,9 @@ static void mpol_rebind_policy(struct mempolicy *pol,
1761 case MPOL_INTERLEAVE: 1781 case MPOL_INTERLEAVE:
1762 if (static_nodes) 1782 if (static_nodes)
1763 nodes_and(tmp, pol->w.user_nodemask, *newmask); 1783 nodes_and(tmp, pol->w.user_nodemask, *newmask);
1784 else if (relative_nodes)
1785 mpol_relative_nodemask(&tmp, &pol->w.user_nodemask,
1786 newmask);
1764 else { 1787 else {
1765 nodes_remap(tmp, pol->v.nodes, 1788 nodes_remap(tmp, pol->v.nodes,
1766 pol->w.cpuset_mems_allowed, *newmask); 1789 pol->w.cpuset_mems_allowed, *newmask);
@@ -1783,6 +1806,10 @@ static void mpol_rebind_policy(struct mempolicy *pol,
1783 pol->v.preferred_node = node; 1806 pol->v.preferred_node = node;
1784 else 1807 else
1785 pol->v.preferred_node = -1; 1808 pol->v.preferred_node = -1;
1809 } else if (relative_nodes) {
1810 mpol_relative_nodemask(&tmp, &pol->w.user_nodemask,
1811 newmask);
1812 pol->v.preferred_node = first_node(tmp);
1786 } else { 1813 } else {
1787 pol->v.preferred_node = node_remap(pol->v.preferred_node, 1814 pol->v.preferred_node = node_remap(pol->v.preferred_node,
1788 pol->w.cpuset_mems_allowed, *newmask); 1815 pol->w.cpuset_mems_allowed, *newmask);
@@ -1878,6 +1905,8 @@ static inline int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol)
1878 1905
1879 if (flags & MPOL_F_STATIC_NODES) 1906 if (flags & MPOL_F_STATIC_NODES)
1880 p += sprintf(p, "%sstatic", need_bar++ ? "|" : ""); 1907 p += sprintf(p, "%sstatic", need_bar++ ? "|" : "");
1908 if (flags & MPOL_F_RELATIVE_NODES)
1909 p += sprintf(p, "%srelative", need_bar++ ? "|" : "");
1881 } 1910 }
1882 1911
1883 if (!nodes_empty(nodes)) { 1912 if (!nodes_empty(nodes)) {
diff --git a/mm/shmem.c b/mm/shmem.c
index 3e9fda0ca470..9435f298dd75 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1128,6 +1128,12 @@ static int shmem_parse_mpol(char *value, unsigned short *policy,
1128 if (flags) { 1128 if (flags) {
1129 if (!strcmp(flags, "static")) 1129 if (!strcmp(flags, "static"))
1130 *mode_flags |= MPOL_F_STATIC_NODES; 1130 *mode_flags |= MPOL_F_STATIC_NODES;
1131 if (!strcmp(flags, "relative"))
1132 *mode_flags |= MPOL_F_RELATIVE_NODES;
1133
1134 if ((*mode_flags & MPOL_F_STATIC_NODES) &&
1135 (*mode_flags & MPOL_F_RELATIVE_NODES))
1136 err = 1;
1131 } 1137 }
1132out: 1138out:
1133 /* Restore string for error message */ 1139 /* Restore string for error message */