]> Pileus Git - ~andy/linux/blobdiff - mm/madvise.c
arm64: cmpxchg: implement cmpxchg64_relaxed
[~andy/linux] / mm / madvise.c
index 7055883e6e250f2914ed5c0a7814400e4945c9d1..539eeb96b323bf649f83783e0dddcb4f907e1d6e 100644 (file)
@@ -42,11 +42,11 @@ static int madvise_need_mmap_write(int behavior)
  * We can potentially split a vm area into separate
  * areas, each area with its own behavior.
  */
-static long madvise_behavior(struct vm_area_struct * vma,
+static long madvise_behavior(struct vm_area_struct *vma,
                     struct vm_area_struct **prev,
                     unsigned long start, unsigned long end, int behavior)
 {
-       struct mm_struct * mm = vma->vm_mm;
+       struct mm_struct *mm = vma->vm_mm;
        int error = 0;
        pgoff_t pgoff;
        unsigned long new_flags = vma->vm_flags;
@@ -215,8 +215,8 @@ static void force_shm_swapin_readahead(struct vm_area_struct *vma,
 /*
  * Schedule all required I/O operations.  Do not wait for completion.
  */
-static long madvise_willneed(struct vm_area_struct * vma,
-                            struct vm_area_struct ** prev,
+static long madvise_willneed(struct vm_area_struct *vma,
+                            struct vm_area_struct **prev,
                             unsigned long start, unsigned long end)
 {
        struct file *file = vma->vm_file;
@@ -270,8 +270,8 @@ static long madvise_willneed(struct vm_area_struct * vma,
  * An interface that causes the system to free clean pages and flush
  * dirty pages is already available as msync(MS_INVALIDATE).
  */
-static long madvise_dontneed(struct vm_area_struct * vma,
-                            struct vm_area_struct ** prev,
+static long madvise_dontneed(struct vm_area_struct *vma,
+                            struct vm_area_struct **prev,
                             unsigned long start, unsigned long end)
 {
        *prev = vma;
@@ -343,29 +343,35 @@ static long madvise_remove(struct vm_area_struct *vma,
  */
 static int madvise_hwpoison(int bhv, unsigned long start, unsigned long end)
 {
-       int ret = 0;
-
+       struct page *p;
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
-       for (; start < end; start += PAGE_SIZE) {
-               struct page *p;
-               int ret = get_user_pages_fast(start, 1, 0, &p);
+       for (; start < end; start += PAGE_SIZE <<
+                               compound_order(compound_head(p))) {
+               int ret;
+
+               ret = get_user_pages_fast(start, 1, 0, &p);
                if (ret != 1)
                        return ret;
+
+               if (PageHWPoison(p)) {
+                       put_page(p);
+                       continue;
+               }
                if (bhv == MADV_SOFT_OFFLINE) {
-                       printk(KERN_INFO "Soft offlining page %lx at %lx\n",
+                       pr_info("Soft offlining page %#lx at %#lx\n",
                                page_to_pfn(p), start);
                        ret = soft_offline_page(p, MF_COUNT_INCREASED);
                        if (ret)
-                               break;
+                               return ret;
                        continue;
                }
-               printk(KERN_INFO "Injecting memory failure for page %lx at %lx\n",
+               pr_info("Injecting memory failure for page %#lx at %#lx\n",
                       page_to_pfn(p), start);
                /* Ignore return value for now */
                memory_failure(page_to_pfn(p), 0, MF_COUNT_INCREASED);
        }
-       return ret;
+       return 0;
 }
 #endif
 
@@ -459,7 +465,7 @@ madvise_behavior_valid(int behavior)
 SYSCALL_DEFINE3(madvise, unsigned long, start, size_t, len_in, int, behavior)
 {
        unsigned long end, tmp;
-       struct vm_area_struct * vma, *prev;
+       struct vm_area_struct *vma, *prev;
        int unmapped_error = 0;
        int error = -EINVAL;
        int write;