|
@@ -563,24 +563,50 @@ static int policy_vma(struct vm_area_struct *vma, struct mempolicy *new)
|
|
}
|
|
}
|
|
|
|
|
|
/* Step 2: apply policy to a range and do splits. */
|
|
/* Step 2: apply policy to a range and do splits. */
|
|
-static int mbind_range(struct vm_area_struct *vma, unsigned long start,
|
|
|
|
- unsigned long end, struct mempolicy *new)
|
|
|
|
|
|
+static int mbind_range(struct mm_struct *mm, unsigned long start,
|
|
|
|
+ unsigned long end, struct mempolicy *new_pol)
|
|
{
|
|
{
|
|
struct vm_area_struct *next;
|
|
struct vm_area_struct *next;
|
|
- int err;
|
|
|
|
|
|
+ struct vm_area_struct *prev;
|
|
|
|
+ struct vm_area_struct *vma;
|
|
|
|
+ int err = 0;
|
|
|
|
+ pgoff_t pgoff;
|
|
|
|
+ unsigned long vmstart;
|
|
|
|
+ unsigned long vmend;
|
|
|
|
|
|
- err = 0;
|
|
|
|
- for (; vma && vma->vm_start < end; vma = next) {
|
|
|
|
|
|
+ vma = find_vma_prev(mm, start, &prev);
|
|
|
|
+ if (!vma || vma->vm_start > start)
|
|
|
|
+ return -EFAULT;
|
|
|
|
+
|
|
|
|
+ for (; vma && vma->vm_start < end; prev = vma, vma = next) {
|
|
next = vma->vm_next;
|
|
next = vma->vm_next;
|
|
- if (vma->vm_start < start)
|
|
|
|
- err = split_vma(vma->vm_mm, vma, start, 1);
|
|
|
|
- if (!err && vma->vm_end > end)
|
|
|
|
- err = split_vma(vma->vm_mm, vma, end, 0);
|
|
|
|
- if (!err)
|
|
|
|
- err = policy_vma(vma, new);
|
|
|
|
|
|
+ vmstart = max(start, vma->vm_start);
|
|
|
|
+ vmend = min(end, vma->vm_end);
|
|
|
|
+
|
|
|
|
+ pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
|
|
|
|
+ prev = vma_merge(mm, prev, vmstart, vmend, vma->vm_flags,
|
|
|
|
+ vma->anon_vma, vma->vm_file, pgoff, new_pol);
|
|
|
|
+ if (prev) {
|
|
|
|
+ vma = prev;
|
|
|
|
+ next = vma->vm_next;
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ if (vma->vm_start != vmstart) {
|
|
|
|
+ err = split_vma(vma->vm_mm, vma, vmstart, 1);
|
|
|
|
+ if (err)
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ if (vma->vm_end != vmend) {
|
|
|
|
+ err = split_vma(vma->vm_mm, vma, vmend, 0);
|
|
|
|
+ if (err)
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ err = policy_vma(vma, new_pol);
|
|
if (err)
|
|
if (err)
|
|
- break;
|
|
|
|
|
|
+ goto out;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ out:
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1047,7 +1073,7 @@ static long do_mbind(unsigned long start, unsigned long len,
|
|
if (!IS_ERR(vma)) {
|
|
if (!IS_ERR(vma)) {
|
|
int nr_failed = 0;
|
|
int nr_failed = 0;
|
|
|
|
|
|
- err = mbind_range(vma, start, end, new);
|
|
|
|
|
|
+ err = mbind_range(mm, start, end, new);
|
|
|
|
|
|
if (!list_empty(&pagelist))
|
|
if (!list_empty(&pagelist))
|
|
nr_failed = migrate_pages(&pagelist, new_vma_page,
|
|
nr_failed = migrate_pages(&pagelist, new_vma_page,
|