]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob
ce1ae60a427a506a9f8bec9a518081b19045528c
[thirdparty/kernel/stable-queue.git] /
1 From d883544515aae54842c21730b880172e7894fde9 Mon Sep 17 00:00:00 2001
2 From: Yang Shi <yang.shi@linux.alibaba.com>
3 Date: Tue, 13 Aug 2019 15:37:15 -0700
4 Subject: mm: mempolicy: make the behavior consistent when MPOL_MF_MOVE* and MPOL_MF_STRICT were specified
5
6 From: Yang Shi <yang.shi@linux.alibaba.com>
7
8 commit d883544515aae54842c21730b880172e7894fde9 upstream.
9
10 When both MPOL_MF_MOVE* and MPOL_MF_STRICT was specified, mbind() should
11 try best to migrate misplaced pages, if some of the pages could not be
12 migrated, then return -EIO.
13
14 There are three different sub-cases:
15 1. vma is not migratable
16 2. vma is migratable, but there are unmovable pages
17 3. vma is migratable, pages are movable, but migrate_pages() fails
18
19 If #1 happens, kernel would just abort immediately, then return -EIO,
20 after a7f40cfe3b7a ("mm: mempolicy: make mbind() return -EIO when
21 MPOL_MF_STRICT is specified").
22
23 If #3 happens, kernel would set policy and migrate pages with
24 best-effort, but won't rollback the migrated pages and reset the policy
25 back.
26
27 Before that commit, they behaves in the same way. It'd better to keep
28 their behavior consistent. But, rolling back the migrated pages and
29 resetting the policy back sounds not feasible, so just make #1 behave as
30 same as #3.
31
32 Userspace will know that not everything was successfully migrated (via
33 -EIO), and can take whatever steps it deems necessary - attempt
34 rollback, determine which exact page(s) are violating the policy, etc.
35
36 Make queue_pages_range() return 1 to indicate there are unmovable pages
37 or vma is not migratable.
38
39 The #2 is not handled correctly in the current kernel, the following
40 patch will fix it.
41
42 [yang.shi@linux.alibaba.com: fix review comments from Vlastimil]
43 Link: http://lkml.kernel.org/r/1563556862-54056-2-git-send-email-yang.shi@linux.alibaba.com
44 Link: http://lkml.kernel.org/r/1561162809-59140-2-git-send-email-yang.shi@linux.alibaba.com
45 Signed-off-by: Yang Shi <yang.shi@linux.alibaba.com>
46 Reviewed-by: Vlastimil Babka <vbabka@suse.cz>
47 Cc: Michal Hocko <mhocko@suse.com>
48 Cc: Mel Gorman <mgorman@techsingularity.net>
49 Cc: <stable@vger.kernel.org>
50 Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
51 Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
52 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
53
54 ---
55 mm/mempolicy.c | 68 ++++++++++++++++++++++++++++++++++++++++-----------------
56 1 file changed, 48 insertions(+), 20 deletions(-)
57
58 --- a/mm/mempolicy.c
59 +++ b/mm/mempolicy.c
60 @@ -429,11 +429,14 @@ static inline bool queue_pages_required(
61 }
62
63 /*
64 - * queue_pages_pmd() has three possible return values:
65 - * 1 - pages are placed on the right node or queued successfully.
66 - * 0 - THP was split.
67 - * -EIO - is migration entry or MPOL_MF_STRICT was specified and an existing
68 - * page was already on a node that does not follow the policy.
69 + * queue_pages_pmd() has four possible return values:
70 + * 0 - pages are placed on the right node or queued successfully.
71 + * 1 - there is unmovable page, and MPOL_MF_MOVE* & MPOL_MF_STRICT were
72 + * specified.
73 + * 2 - THP was split.
74 + * -EIO - is migration entry or only MPOL_MF_STRICT was specified and an
75 + * existing page was already on a node that does not follow the
76 + * policy.
77 */
78 static int queue_pages_pmd(pmd_t *pmd, spinlock_t *ptl, unsigned long addr,
79 unsigned long end, struct mm_walk *walk)
80 @@ -451,19 +454,17 @@ static int queue_pages_pmd(pmd_t *pmd, s
81 if (is_huge_zero_page(page)) {
82 spin_unlock(ptl);
83 __split_huge_pmd(walk->vma, pmd, addr, false, NULL);
84 + ret = 2;
85 goto out;
86 }
87 - if (!queue_pages_required(page, qp)) {
88 - ret = 1;
89 + if (!queue_pages_required(page, qp))
90 goto unlock;
91 - }
92
93 - ret = 1;
94 flags = qp->flags;
95 /* go to thp migration */
96 if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) {
97 if (!vma_migratable(walk->vma)) {
98 - ret = -EIO;
99 + ret = 1;
100 goto unlock;
101 }
102
103 @@ -479,6 +480,13 @@ out:
104 /*
105 * Scan through pages checking if pages follow certain conditions,
106 * and move them to the pagelist if they do.
107 + *
108 + * queue_pages_pte_range() has three possible return values:
109 + * 0 - pages are placed on the right node or queued successfully.
110 + * 1 - there is unmovable page, and MPOL_MF_MOVE* & MPOL_MF_STRICT were
111 + * specified.
112 + * -EIO - only MPOL_MF_STRICT was specified and an existing page was already
113 + * on a node that does not follow the policy.
114 */
115 static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,
116 unsigned long end, struct mm_walk *walk)
117 @@ -488,17 +496,17 @@ static int queue_pages_pte_range(pmd_t *
118 struct queue_pages *qp = walk->private;
119 unsigned long flags = qp->flags;
120 int ret;
121 + bool has_unmovable = false;
122 pte_t *pte;
123 spinlock_t *ptl;
124
125 ptl = pmd_trans_huge_lock(pmd, vma);
126 if (ptl) {
127 ret = queue_pages_pmd(pmd, ptl, addr, end, walk);
128 - if (ret > 0)
129 - return 0;
130 - else if (ret < 0)
131 + if (ret != 2)
132 return ret;
133 }
134 + /* THP was split, fall through to pte walk */
135
136 if (pmd_trans_unstable(pmd))
137 return 0;
138 @@ -519,14 +527,21 @@ static int queue_pages_pte_range(pmd_t *
139 if (!queue_pages_required(page, qp))
140 continue;
141 if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) {
142 - if (!vma_migratable(vma))
143 + /* MPOL_MF_STRICT must be specified if we get here */
144 + if (!vma_migratable(vma)) {
145 + has_unmovable = true;
146 break;
147 + }
148 migrate_page_add(page, qp->pagelist, flags);
149 } else
150 break;
151 }
152 pte_unmap_unlock(pte - 1, ptl);
153 cond_resched();
154 +
155 + if (has_unmovable)
156 + return 1;
157 +
158 return addr != end ? -EIO : 0;
159 }
160
161 @@ -639,7 +654,13 @@ static int queue_pages_test_walk(unsigne
162 *
163 * If pages found in a given range are on a set of nodes (determined by
164 * @nodes and @flags,) it's isolated and queued to the pagelist which is
165 - * passed via @private.)
166 + * passed via @private.
167 + *
168 + * queue_pages_range() has three possible return values:
169 + * 1 - there is unmovable page, but MPOL_MF_MOVE* & MPOL_MF_STRICT were
170 + * specified.
171 + * 0 - queue pages successfully or no misplaced page.
172 + * -EIO - there is misplaced page and only MPOL_MF_STRICT was specified.
173 */
174 static int
175 queue_pages_range(struct mm_struct *mm, unsigned long start, unsigned long end,
176 @@ -1182,6 +1203,7 @@ static long do_mbind(unsigned long start
177 struct mempolicy *new;
178 unsigned long end;
179 int err;
180 + int ret;
181 LIST_HEAD(pagelist);
182
183 if (flags & ~(unsigned long)MPOL_MF_VALID)
184 @@ -1243,10 +1265,15 @@ static long do_mbind(unsigned long start
185 if (err)
186 goto mpol_out;
187
188 - err = queue_pages_range(mm, start, end, nmask,
189 + ret = queue_pages_range(mm, start, end, nmask,
190 flags | MPOL_MF_INVERT, &pagelist);
191 - if (!err)
192 - err = mbind_range(mm, start, end, new);
193 +
194 + if (ret < 0) {
195 + err = -EIO;
196 + goto up_out;
197 + }
198 +
199 + err = mbind_range(mm, start, end, new);
200
201 if (!err) {
202 int nr_failed = 0;
203 @@ -1259,13 +1286,14 @@ static long do_mbind(unsigned long start
204 putback_movable_pages(&pagelist);
205 }
206
207 - if (nr_failed && (flags & MPOL_MF_STRICT))
208 + if ((ret > 0) || (nr_failed && (flags & MPOL_MF_STRICT)))
209 err = -EIO;
210 } else
211 putback_movable_pages(&pagelist);
212
213 +up_out:
214 up_write(&mm->mmap_sem);
215 - mpol_out:
216 +mpol_out:
217 mpol_put(new);
218 return err;
219 }