diff options
Diffstat (limited to 'mm/mempolicy.c')
-rw-r--r-- | mm/mempolicy.c | 33 |
1 files changed, 31 insertions, 2 deletions
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 | ||
137 | static inline int mpol_store_user_nodemask(const struct mempolicy *pol) | 137 | static 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 | |||
142 | static 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)) { |