UPSTREAM: clk: rockchip: add clock-id for rk3036 emac pll source clock
[firefly-linux-kernel-4.4.55.git] / mm / mlock.c
index fbd8c03f7b37985542977575fabca53b54355a1d..d843bc9d32ddb077aa4aadfb156a4e2017ee94d5 100644 (file)
@@ -172,7 +172,7 @@ static void __munlock_isolation_failed(struct page *page)
  */
 unsigned int munlock_vma_page(struct page *page)
 {
-       unsigned int nr_pages;
+       int nr_pages;
        struct zone *zone = page_zone(page);
 
        /* For try_to_munlock() and to serialize with page migration */
@@ -422,7 +422,7 @@ static unsigned long __munlock_pagevec_fill(struct pagevec *pvec,
 void munlock_vma_pages_range(struct vm_area_struct *vma,
                             unsigned long start, unsigned long end)
 {
-       vma->vm_flags &= ~VM_LOCKED;
+       vma->vm_flags &= VM_LOCKED_CLEAR_MASK;
 
        while (start < end) {
                struct page *page = NULL;
@@ -506,12 +506,13 @@ static int mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev,
 
        if (newflags == vma->vm_flags || (vma->vm_flags & VM_SPECIAL) ||
            is_vm_hugetlb_page(vma) || vma == get_gate_vma(current->mm))
-               goto out;       /* don't set VM_LOCKED,  don't count */
+               /* don't set VM_LOCKED or VM_LOCKONFAULT and don't count */
+               goto out;
 
        pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
        *prev = vma_merge(mm, *prev, start, end, newflags, vma->anon_vma,
                          vma->vm_file, pgoff, vma_policy(vma),
-                         vma->vm_userfaultfd_ctx);
+                         vma->vm_userfaultfd_ctx, vma_get_anon_name(vma));
        if (*prev) {
                vma = *prev;
                goto success;
@@ -577,7 +578,7 @@ static int apply_vma_lock_flags(unsigned long start, size_t len,
                prev = vma;
 
        for (nstart = start ; ; ) {
-               vm_flags_t newflags = vma->vm_flags & ~VM_LOCKED;
+               vm_flags_t newflags = vma->vm_flags & VM_LOCKED_CLEAR_MASK;
 
                newflags |= flags;
 
@@ -644,6 +645,19 @@ SYSCALL_DEFINE2(mlock, unsigned long, start, size_t, len)
        return do_mlock(start, len, VM_LOCKED);
 }
 
+SYSCALL_DEFINE3(mlock2, unsigned long, start, size_t, len, int, flags)
+{
+       vm_flags_t vm_flags = VM_LOCKED;
+
+       if (flags & ~MLOCK_ONFAULT)
+               return -EINVAL;
+
+       if (flags & MLOCK_ONFAULT)
+               vm_flags |= VM_LOCKONFAULT;
+
+       return do_mlock(start, len, vm_flags);
+}
+
 SYSCALL_DEFINE2(munlock, unsigned long, start, size_t, len)
 {
        int ret;
@@ -658,24 +672,43 @@ SYSCALL_DEFINE2(munlock, unsigned long, start, size_t, len)
        return ret;
 }
 
+/*
+ * Take the MCL_* flags passed into mlockall (or 0 if called from munlockall)
+ * and translate into the appropriate modifications to mm->def_flags and/or the
+ * flags for all current VMAs.
+ *
+ * There are a couple of subtleties with this.  If mlockall() is called multiple
+ * times with different flags, the values do not necessarily stack.  If mlockall
+ * is called once including the MCL_FUTURE flag and then a second time without
+ * it, VM_LOCKED and VM_LOCKONFAULT will be cleared from mm->def_flags.
+ */
 static int apply_mlockall_flags(int flags)
 {
        struct vm_area_struct * vma, * prev = NULL;
+       vm_flags_t to_add = 0;
 
-       if (flags & MCL_FUTURE)
+       current->mm->def_flags &= VM_LOCKED_CLEAR_MASK;
+       if (flags & MCL_FUTURE) {
                current->mm->def_flags |= VM_LOCKED;
-       else
-               current->mm->def_flags &= ~VM_LOCKED;
 
-       if (flags == MCL_FUTURE)
-               goto out;
+               if (flags & MCL_ONFAULT)
+                       current->mm->def_flags |= VM_LOCKONFAULT;
+
+               if (!(flags & MCL_CURRENT))
+                       goto out;
+       }
+
+       if (flags & MCL_CURRENT) {
+               to_add |= VM_LOCKED;
+               if (flags & MCL_ONFAULT)
+                       to_add |= VM_LOCKONFAULT;
+       }
 
        for (vma = current->mm->mmap; vma ; vma = prev->vm_next) {
                vm_flags_t newflags;
 
-               newflags = vma->vm_flags & ~VM_LOCKED;
-               if (flags & MCL_CURRENT)
-                       newflags |= VM_LOCKED;
+               newflags = vma->vm_flags & VM_LOCKED_CLEAR_MASK;
+               newflags |= to_add;
 
                /* Ignore errors */
                mlock_fixup(vma, &prev, vma->vm_start, vma->vm_end, newflags);
@@ -690,7 +723,7 @@ SYSCALL_DEFINE1(mlockall, int, flags)
        unsigned long lock_limit;
        int ret;
 
-       if (!flags || (flags & ~(MCL_CURRENT | MCL_FUTURE)))
+       if (!flags || (flags & ~(MCL_CURRENT | MCL_FUTURE | MCL_ONFAULT)))
                return -EINVAL;
 
        if (!can_do_mlock())