|
@@ -92,14 +92,28 @@ static long madvise_behavior(struct vm_area_struct *vma,
|
|
case MADV_MERGEABLE:
|
|
case MADV_MERGEABLE:
|
|
case MADV_UNMERGEABLE:
|
|
case MADV_UNMERGEABLE:
|
|
error = ksm_madvise(vma, start, end, behavior, &new_flags);
|
|
error = ksm_madvise(vma, start, end, behavior, &new_flags);
|
|
- if (error)
|
|
|
|
|
|
+ if (error) {
|
|
|
|
+ /*
|
|
|
|
+ * madvise() returns EAGAIN if kernel resources, such as
|
|
|
|
+ * slab, are temporarily unavailable.
|
|
|
|
+ */
|
|
|
|
+ if (error == -ENOMEM)
|
|
|
|
+ error = -EAGAIN;
|
|
goto out;
|
|
goto out;
|
|
|
|
+ }
|
|
break;
|
|
break;
|
|
case MADV_HUGEPAGE:
|
|
case MADV_HUGEPAGE:
|
|
case MADV_NOHUGEPAGE:
|
|
case MADV_NOHUGEPAGE:
|
|
error = hugepage_madvise(vma, &new_flags, behavior);
|
|
error = hugepage_madvise(vma, &new_flags, behavior);
|
|
- if (error)
|
|
|
|
|
|
+ if (error) {
|
|
|
|
+ /*
|
|
|
|
+ * madvise() returns EAGAIN if kernel resources, such as
|
|
|
|
+ * slab, are temporarily unavailable.
|
|
|
|
+ */
|
|
|
|
+ if (error == -ENOMEM)
|
|
|
|
+ error = -EAGAIN;
|
|
goto out;
|
|
goto out;
|
|
|
|
+ }
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -120,15 +134,37 @@ static long madvise_behavior(struct vm_area_struct *vma,
|
|
*prev = vma;
|
|
*prev = vma;
|
|
|
|
|
|
if (start != vma->vm_start) {
|
|
if (start != vma->vm_start) {
|
|
- error = split_vma(mm, vma, start, 1);
|
|
|
|
- if (error)
|
|
|
|
|
|
+ if (unlikely(mm->map_count >= sysctl_max_map_count)) {
|
|
|
|
+ error = -ENOMEM;
|
|
goto out;
|
|
goto out;
|
|
|
|
+ }
|
|
|
|
+ error = __split_vma(mm, vma, start, 1);
|
|
|
|
+ if (error) {
|
|
|
|
+ /*
|
|
|
|
+ * madvise() returns EAGAIN if kernel resources, such as
|
|
|
|
+ * slab, are temporarily unavailable.
|
|
|
|
+ */
|
|
|
|
+ if (error == -ENOMEM)
|
|
|
|
+ error = -EAGAIN;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
if (end != vma->vm_end) {
|
|
if (end != vma->vm_end) {
|
|
- error = split_vma(mm, vma, end, 0);
|
|
|
|
- if (error)
|
|
|
|
|
|
+ if (unlikely(mm->map_count >= sysctl_max_map_count)) {
|
|
|
|
+ error = -ENOMEM;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ error = __split_vma(mm, vma, end, 0);
|
|
|
|
+ if (error) {
|
|
|
|
+ /*
|
|
|
|
+ * madvise() returns EAGAIN if kernel resources, such as
|
|
|
|
+ * slab, are temporarily unavailable.
|
|
|
|
+ */
|
|
|
|
+ if (error == -ENOMEM)
|
|
|
|
+ error = -EAGAIN;
|
|
goto out;
|
|
goto out;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
success:
|
|
success:
|
|
@@ -136,10 +172,7 @@ success:
|
|
* vm_flags is protected by the mmap_sem held in write mode.
|
|
* vm_flags is protected by the mmap_sem held in write mode.
|
|
*/
|
|
*/
|
|
vma->vm_flags = new_flags;
|
|
vma->vm_flags = new_flags;
|
|
-
|
|
|
|
out:
|
|
out:
|
|
- if (error == -ENOMEM)
|
|
|
|
- error = -EAGAIN;
|
|
|
|
return error;
|
|
return error;
|
|
}
|
|
}
|
|
|
|
|