arm64: kaslr: support randomized module area with KASAN_VMALLOC
[linux-2.6-microblaze.git] / mm / memory-failure.c
index e948163..24210c9 100644 (file)
@@ -243,9 +243,13 @@ static int kill_proc(struct to_kill *tk, unsigned long pfn, int flags)
                        pfn, t->comm, t->pid);
 
        if (flags & MF_ACTION_REQUIRED) {
-               WARN_ON_ONCE(t != current);
-               ret = force_sig_mceerr(BUS_MCEERR_AR,
+               if (t == current)
+                       ret = force_sig_mceerr(BUS_MCEERR_AR,
                                         (void __user *)tk->addr, addr_lsb);
+               else
+                       /* Signal other processes sharing the page if they have PF_MCE_EARLY set. */
+                       ret = send_sig_mceerr(BUS_MCEERR_AO, (void __user *)tk->addr,
+                               addr_lsb, t);
        } else {
                /*
                 * Don't use force here, it's convenient if the signal
@@ -440,26 +444,26 @@ static struct task_struct *find_early_kill_thread(struct task_struct *tsk)
  * Determine whether a given process is "early kill" process which expects
  * to be signaled when some page under the process is hwpoisoned.
  * Return task_struct of the dedicated thread (main thread unless explicitly
- * specified) if the process is "early kill," and otherwise returns NULL.
+ * specified) if the process is "early kill" and otherwise returns NULL.
  *
- * Note that the above is true for Action Optional case, but not for Action
- * Required case where SIGBUS should sent only to the current thread.
+ * Note that the above is true for Action Optional case. For Action Required
+ * case, it's only meaningful to the current thread which need to be signaled
+ * with SIGBUS, this error is Action Optional for other non current
+ * processes sharing the same error page,if the process is "early kill", the
+ * task_struct of the dedicated thread will also be returned.
  */
 static struct task_struct *task_early_kill(struct task_struct *tsk,
                                           int force_early)
 {
        if (!tsk->mm)
                return NULL;
-       if (force_early) {
-               /*
-                * Comparing ->mm here because current task might represent
-                * a subthread, while tsk always points to the main thread.
-                */
-               if (tsk->mm == current->mm)
-                       return current;
-               else
-                       return NULL;
-       }
+       /*
+        * Comparing ->mm here because current task might represent
+        * a subthread, while tsk always points to the main thread.
+        */
+       if (force_early && tsk->mm == current->mm)
+               return current;
+
        return find_early_kill_thread(tsk);
 }
 
@@ -1308,6 +1312,12 @@ static int memory_failure_dev_pagemap(unsigned long pfn, int flags,
                 */
                put_page(page);
 
+       /* device metadata space is not recoverable */
+       if (!pgmap_pfn_valid(pgmap, pfn)) {
+               rc = -ENXIO;
+               goto out;
+       }
+
        /*
         * Prevent the inode from being freed while we are interrogating
         * the address_space, typically this would be handled by