Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Sep 24, 2020. It is now read-only.

Commit cd825d8

Browse files
Yang Shigregkh
authored andcommitted
mm: mempolicy: make the behavior consistent when MPOL_MF_MOVE* and MPOL_MF_STRICT were specified
commit d883544 upstream. When both MPOL_MF_MOVE* and MPOL_MF_STRICT was specified, mbind() should try best to migrate misplaced pages, if some of the pages could not be migrated, then return -EIO. There are three different sub-cases: 1. vma is not migratable 2. vma is migratable, but there are unmovable pages 3. vma is migratable, pages are movable, but migrate_pages() fails If #1 happens, kernel would just abort immediately, then return -EIO, after a7f40cf ("mm: mempolicy: make mbind() return -EIO when MPOL_MF_STRICT is specified"). If #3 happens, kernel would set policy and migrate pages with best-effort, but won't rollback the migrated pages and reset the policy back. Before that commit, they behaves in the same way. It'd better to keep their behavior consistent. But, rolling back the migrated pages and resetting the policy back sounds not feasible, so just make #1 behave as same as #3. Userspace will know that not everything was successfully migrated (via -EIO), and can take whatever steps it deems necessary - attempt rollback, determine which exact page(s) are violating the policy, etc. Make queue_pages_range() return 1 to indicate there are unmovable pages or vma is not migratable. The #2 is not handled correctly in the current kernel, the following patch will fix it. [[email protected]: fix review comments from Vlastimil] Link: http://lkml.kernel.org/r/[email protected] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Yang Shi <[email protected]> Reviewed-by: Vlastimil Babka <[email protected]> Cc: Michal Hocko <[email protected]> Cc: Mel Gorman <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent f0fed82 commit cd825d8

File tree

1 file changed

+48
-20
lines changed

1 file changed

+48
-20
lines changed

mm/mempolicy.c

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -429,11 +429,14 @@ static inline bool queue_pages_required(struct page *page,
429429
}
430430

431431
/*
432-
* queue_pages_pmd() has three possible return values:
433-
* 1 - pages are placed on the right node or queued successfully.
434-
* 0 - THP was split.
435-
* -EIO - is migration entry or MPOL_MF_STRICT was specified and an existing
436-
* page was already on a node that does not follow the policy.
432+
* queue_pages_pmd() has four possible return values:
433+
* 0 - pages are placed on the right node or queued successfully.
434+
* 1 - there is unmovable page, and MPOL_MF_MOVE* & MPOL_MF_STRICT were
435+
* specified.
436+
* 2 - THP was split.
437+
* -EIO - is migration entry or only MPOL_MF_STRICT was specified and an
438+
* existing page was already on a node that does not follow the
439+
* policy.
437440
*/
438441
static int queue_pages_pmd(pmd_t *pmd, spinlock_t *ptl, unsigned long addr,
439442
unsigned long end, struct mm_walk *walk)
@@ -451,19 +454,17 @@ static int queue_pages_pmd(pmd_t *pmd, spinlock_t *ptl, unsigned long addr,
451454
if (is_huge_zero_page(page)) {
452455
spin_unlock(ptl);
453456
__split_huge_pmd(walk->vma, pmd, addr, false, NULL);
457+
ret = 2;
454458
goto out;
455459
}
456-
if (!queue_pages_required(page, qp)) {
457-
ret = 1;
460+
if (!queue_pages_required(page, qp))
458461
goto unlock;
459-
}
460462

461-
ret = 1;
462463
flags = qp->flags;
463464
/* go to thp migration */
464465
if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) {
465466
if (!vma_migratable(walk->vma)) {
466-
ret = -EIO;
467+
ret = 1;
467468
goto unlock;
468469
}
469470

@@ -479,6 +480,13 @@ static int queue_pages_pmd(pmd_t *pmd, spinlock_t *ptl, unsigned long addr,
479480
/*
480481
* Scan through pages checking if pages follow certain conditions,
481482
* and move them to the pagelist if they do.
483+
*
484+
* queue_pages_pte_range() has three possible return values:
485+
* 0 - pages are placed on the right node or queued successfully.
486+
* 1 - there is unmovable page, and MPOL_MF_MOVE* & MPOL_MF_STRICT were
487+
* specified.
488+
* -EIO - only MPOL_MF_STRICT was specified and an existing page was already
489+
* on a node that does not follow the policy.
482490
*/
483491
static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,
484492
unsigned long end, struct mm_walk *walk)
@@ -488,17 +496,17 @@ static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,
488496
struct queue_pages *qp = walk->private;
489497
unsigned long flags = qp->flags;
490498
int ret;
499+
bool has_unmovable = false;
491500
pte_t *pte;
492501
spinlock_t *ptl;
493502

494503
ptl = pmd_trans_huge_lock(pmd, vma);
495504
if (ptl) {
496505
ret = queue_pages_pmd(pmd, ptl, addr, end, walk);
497-
if (ret > 0)
498-
return 0;
499-
else if (ret < 0)
506+
if (ret != 2)
500507
return ret;
501508
}
509+
/* THP was split, fall through to pte walk */
502510

503511
if (pmd_trans_unstable(pmd))
504512
return 0;
@@ -519,14 +527,21 @@ static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,
519527
if (!queue_pages_required(page, qp))
520528
continue;
521529
if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) {
522-
if (!vma_migratable(vma))
530+
/* MPOL_MF_STRICT must be specified if we get here */
531+
if (!vma_migratable(vma)) {
532+
has_unmovable = true;
523533
break;
534+
}
524535
migrate_page_add(page, qp->pagelist, flags);
525536
} else
526537
break;
527538
}
528539
pte_unmap_unlock(pte - 1, ptl);
529540
cond_resched();
541+
542+
if (has_unmovable)
543+
return 1;
544+
530545
return addr != end ? -EIO : 0;
531546
}
532547

@@ -639,7 +654,13 @@ static int queue_pages_test_walk(unsigned long start, unsigned long end,
639654
*
640655
* If pages found in a given range are on a set of nodes (determined by
641656
* @nodes and @flags,) it's isolated and queued to the pagelist which is
642-
* passed via @private.)
657+
* passed via @private.
658+
*
659+
* queue_pages_range() has three possible return values:
660+
* 1 - there is unmovable page, but MPOL_MF_MOVE* & MPOL_MF_STRICT were
661+
* specified.
662+
* 0 - queue pages successfully or no misplaced page.
663+
* -EIO - there is misplaced page and only MPOL_MF_STRICT was specified.
643664
*/
644665
static int
645666
queue_pages_range(struct mm_struct *mm, unsigned long start, unsigned long end,
@@ -1168,6 +1189,7 @@ static long do_mbind(unsigned long start, unsigned long len,
11681189
struct mempolicy *new;
11691190
unsigned long end;
11701191
int err;
1192+
int ret;
11711193
LIST_HEAD(pagelist);
11721194

11731195
if (flags & ~(unsigned long)MPOL_MF_VALID)
@@ -1229,10 +1251,15 @@ static long do_mbind(unsigned long start, unsigned long len,
12291251
if (err)
12301252
goto mpol_out;
12311253

1232-
err = queue_pages_range(mm, start, end, nmask,
1254+
ret = queue_pages_range(mm, start, end, nmask,
12331255
flags | MPOL_MF_INVERT, &pagelist);
1234-
if (!err)
1235-
err = mbind_range(mm, start, end, new);
1256+
1257+
if (ret < 0) {
1258+
err = -EIO;
1259+
goto up_out;
1260+
}
1261+
1262+
err = mbind_range(mm, start, end, new);
12361263

12371264
if (!err) {
12381265
int nr_failed = 0;
@@ -1245,13 +1272,14 @@ static long do_mbind(unsigned long start, unsigned long len,
12451272
putback_movable_pages(&pagelist);
12461273
}
12471274

1248-
if (nr_failed && (flags & MPOL_MF_STRICT))
1275+
if ((ret > 0) || (nr_failed && (flags & MPOL_MF_STRICT)))
12491276
err = -EIO;
12501277
} else
12511278
putback_movable_pages(&pagelist);
12521279

1280+
up_out:
12531281
up_write(&mm->mmap_sem);
1254-
mpol_out:
1282+
mpol_out:
12551283
mpol_put(new);
12561284
return err;
12571285
}

0 commit comments

Comments
 (0)