mm: add a call to flush_cache_vmap() in vmap_pfn()
[platform/kernel/linux-starfive.git] / mm / madvise.c
index 2baa93c..d03e149 100644 (file)
@@ -772,8 +772,8 @@ static int madvise_free_single_vma(struct vm_area_struct *vma,
  * Application no longer needs these pages.  If the pages are dirty,
  * it's OK to just throw them away.  The app will be more careful about
  * data it wants to keep.  Be sure to free swap resources too.  The
- * zap_page_range call sets things up for shrink_active_list to actually free
- * these pages later if no one else has touched them in the meantime,
+ * zap_page_range_single call sets things up for shrink_active_list to actually
+ * free these pages later if no one else has touched them in the meantime,
  * although we could add these pages to a global reuse list for
  * shrink_active_list to pick up before reclaiming other pages.
  *
@@ -790,7 +790,7 @@ static int madvise_free_single_vma(struct vm_area_struct *vma,
 static long madvise_dontneed_single_vma(struct vm_area_struct *vma,
                                        unsigned long start, unsigned long end)
 {
-       zap_page_range(vma, start, end - start);
+       zap_page_range_single(vma, start, end - start, NULL);
        return 0;
 }
 
@@ -813,7 +813,14 @@ static bool madvise_dontneed_free_valid_vma(struct vm_area_struct *vma,
        if (start & ~huge_page_mask(hstate_vma(vma)))
                return false;
 
-       *end = ALIGN(*end, huge_page_size(hstate_vma(vma)));
+       /*
+        * Madvise callers expect the length to be rounded up to PAGE_SIZE
+        * boundaries, and may be unaware that this VMA uses huge pages.
+        * Avoid unexpected data loss by rounding down the number of
+        * huge pages freed.
+        */
+       *end = ALIGN_DOWN(*end, huge_page_size(hstate_vma(vma)));
+
        return true;
 }
 
@@ -828,6 +835,9 @@ static long madvise_dontneed_free(struct vm_area_struct *vma,
        if (!madvise_dontneed_free_valid_vma(vma, start, &end, behavior))
                return -EINVAL;
 
+       if (start == end)
+               return 0;
+
        if (!userfaultfd_remove(vma, start, end)) {
                *prev = NULL; /* mmap_lock has been dropped, prev is stale */
 
@@ -1449,7 +1459,7 @@ SYSCALL_DEFINE5(process_madvise, int, pidfd, const struct iovec __user *, vec,
                goto out;
        }
 
-       ret = import_iovec(READ, vec, vlen, ARRAY_SIZE(iovstack), &iov, &iter);
+       ret = import_iovec(ITER_DEST, vec, vlen, ARRAY_SIZE(iovstack), &iov, &iter);
        if (ret < 0)
                goto out;