HWPOISON: Convert pr_debugs to pr_info
[deliverable/linux.git] / mm / memory-failure.c
index 9c26eeca13425886690cddaf6dd45954fd3f0097..0a2ed9a17e8c6b435ec192a90a42b4048b1b5444 100644 (file)
@@ -7,21 +7,26 @@
  * Free Software Foundation.
  *
  * High level machine check handler. Handles pages reported by the
- * hardware as being corrupted usually due to a 2bit ECC memory or cache
+ * hardware as being corrupted usually due to a multi-bit ECC memory or cache
  * failure.
+ * 
+ * In addition there is a "soft offline" entry point that allows stop using
+ * not-yet-corrupted-by-suspicious pages without killing anything.
  *
  * Handles page cache pages in various states. The tricky part
- * here is that we can access any page asynchronous to other VM
- * users, because memory failures could happen anytime and anywhere,
- * possibly violating some of their assumptions. This is why this code
- * has to be extremely careful. Generally it tries to use normal locking
- * rules, as in get the standard locks, even if that means the
- * error handling takes potentially a long time.
- *
- * The operation to map back from RMAP chains to processes has to walk
- * the complete process list and has non linear complexity with the number
- * mappings. In short it can be quite slow. But since memory corruptions
- * are rare we hope to get away with this.
+ * here is that we can access any page asynchronously in respect to 
+ * other VM users, because memory failures could happen anytime and 
+ * anywhere. This could violate some of their assumptions. This is why 
+ * this code has to be extremely careful. Generally it tries to use 
+ * normal locking rules, as in get the standard locks, even if that means 
+ * the error handling takes potentially a long time.
+ * 
+ * There are several operations here with exponential complexity because
+ * of unsuitable VM data structures. For example the operation to map back 
+ * from RMAP chains to processes has to walk the complete process list and 
+ * has non linear complexity with the number. But since memory corruptions
+ * are rare we hope to get away with this. This avoids impacting the core 
+ * VM.
  */
 
 /*
@@ -78,7 +83,7 @@ static int hwpoison_filter_dev(struct page *p)
                return 0;
 
        /*
-        * page_mapping() does not accept slab page
+        * page_mapping() does not accept slab pages.
         */
        if (PageSlab(p))
                return -EINVAL;
@@ -183,7 +188,7 @@ EXPORT_SYMBOL_GPL(hwpoison_filter);
  * signal.
  */
 static int kill_proc_ao(struct task_struct *t, unsigned long addr, int trapno,
-                       unsigned long pfn)
+                       unsigned long pfn, struct page *page)
 {
        struct siginfo si;
        int ret;
@@ -198,7 +203,7 @@ static int kill_proc_ao(struct task_struct *t, unsigned long addr, int trapno,
 #ifdef __ARCH_SI_TRAPNO
        si.si_trapno = trapno;
 #endif
-       si.si_addr_lsb = PAGE_SHIFT;
+       si.si_addr_lsb = compound_order(compound_head(page)) + PAGE_SHIFT;
        /*
         * Don't use force here, it's convenient if the signal
         * can be temporarily blocked.
@@ -235,7 +240,7 @@ void shake_page(struct page *p, int access)
                int nr;
                do {
                        nr = shrink_slab(1000, GFP_KERNEL, 1000);
-                       if (page_count(p) == 0)
+                       if (page_count(p) == 1)
                                break;
                } while (nr > 10);
        }
@@ -309,7 +314,7 @@ static void add_to_kill(struct task_struct *tsk, struct page *p,
         * a SIGKILL because the error is not contained anymore.
         */
        if (tk->addr == -EFAULT) {
-               pr_debug("MCE: Unable to find user space address %lx in %s\n",
+               pr_info("MCE: Unable to find user space address %lx in %s\n",
                        page_to_pfn(p), tsk->comm);
                tk->addr_valid = 0;
        }
@@ -327,7 +332,7 @@ static void add_to_kill(struct task_struct *tsk, struct page *p,
  * wrong earlier.
  */
 static void kill_procs_ao(struct list_head *to_kill, int doit, int trapno,
-                         int fail, unsigned long pfn)
+                         int fail, struct page *page, unsigned long pfn)
 {
        struct to_kill *tk, *next;
 
@@ -352,7 +357,7 @@ static void kill_procs_ao(struct list_head *to_kill, int doit, int trapno,
                         * process anyways.
                         */
                        else if (kill_proc_ao(tk->tsk, tk->addr, trapno,
-                                             pfn) < 0)
+                                             pfn, page) < 0)
                                printk(KERN_ERR
                "MCE %#lx: Cannot send advisory machine check signal to %s:%d\n",
                                        pfn, tk->tsk->comm, tk->tsk->pid);
@@ -577,7 +582,7 @@ static int me_pagecache_clean(struct page *p, unsigned long pfn)
                                        pfn, err);
                } else if (page_has_private(p) &&
                                !try_to_release_page(p, GFP_NOIO)) {
-                       pr_debug("MCE %#lx: failed to release buffers\n", pfn);
+                       pr_info("MCE %#lx: failed to release buffers\n", pfn);
                } else {
                        ret = RECOVERED;
                }
@@ -928,7 +933,7 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
         * any accesses to the poisoned memory.
         */
        kill_procs_ao(&tokill, !!PageDirty(hpage), trapno,
-                     ret != SWAP_SUCCESS, pfn);
+                     ret != SWAP_SUCCESS, p, pfn);
 
        return ret;
 }
@@ -1147,7 +1152,7 @@ int unpoison_memory(unsigned long pfn)
        page = compound_head(p);
 
        if (!PageHWPoison(p)) {
-               pr_debug("MCE: Page was already unpoisoned %#lx\n", pfn);
+               pr_info("MCE: Page was already unpoisoned %#lx\n", pfn);
                return 0;
        }
 
@@ -1156,7 +1161,7 @@ int unpoison_memory(unsigned long pfn)
        if (!get_page_unless_zero(page)) {
                if (TestClearPageHWPoison(p))
                        atomic_long_sub(nr_pages, &mce_bad_pages);
-               pr_debug("MCE: Software-unpoisoned free page %#lx\n", pfn);
+               pr_info("MCE: Software-unpoisoned free page %#lx\n", pfn);
                return 0;
        }
 
@@ -1168,7 +1173,7 @@ int unpoison_memory(unsigned long pfn)
         * the free buddy page pool.
         */
        if (TestClearPageHWPoison(page)) {
-               pr_debug("MCE: Software-unpoisoned page %#lx\n", pfn);
+               pr_info("MCE: Software-unpoisoned page %#lx\n", pfn);
                atomic_long_sub(nr_pages, &mce_bad_pages);
                freeit = 1;
        }
@@ -1217,12 +1222,12 @@ static int get_any_page(struct page *p, unsigned long pfn, int flags)
        set_migratetype_isolate(p);
        if (!get_page_unless_zero(compound_head(p))) {
                if (is_free_buddy_page(p)) {
-                       pr_debug("get_any_page: %#lx free buddy page\n", pfn);
+                       pr_info("get_any_page: %#lx free buddy page\n", pfn);
                        /* Set hwpoison bit while page is still isolated */
                        SetPageHWPoison(p);
                        ret = 0;
                } else {
-                       pr_debug("get_any_page: %#lx: unknown zero refcount page type %lx\n",
+                       pr_info("get_any_page: %#lx: unknown zero refcount page type %lx\n",
                                pfn, p->flags);
                        ret = -EIO;
                }
@@ -1288,7 +1293,7 @@ int soft_offline_page(struct page *page, int flags)
                        goto done;
        }
        if (!PageLRU(page)) {
-               pr_debug("soft_offline: %#lx: unknown non LRU page type %lx\n",
+               pr_info("soft_offline: %#lx: unknown non LRU page type %lx\n",
                                pfn, page->flags);
                return -EIO;
        }
@@ -1302,7 +1307,7 @@ int soft_offline_page(struct page *page, int flags)
        if (PageHWPoison(page)) {
                unlock_page(page);
                put_page(page);
-               pr_debug("soft offline: %#lx page already poisoned\n", pfn);
+               pr_info("soft offline: %#lx page already poisoned\n", pfn);
                return -EBUSY;
        }
 
@@ -1323,7 +1328,7 @@ int soft_offline_page(struct page *page, int flags)
        put_page(page);
        if (ret == 1) {
                ret = 0;
-               pr_debug("soft_offline: %#lx: invalidated\n", pfn);
+               pr_info("soft_offline: %#lx: invalidated\n", pfn);
                goto done;
        }
 
@@ -1339,13 +1344,13 @@ int soft_offline_page(struct page *page, int flags)
                list_add(&page->lru, &pagelist);
                ret = migrate_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, 0);
                if (ret) {
-                       pr_debug("soft offline: %#lx: migration failed %d, type %lx\n",
+                       pr_info("soft offline: %#lx: migration failed %d, type %lx\n",
                                pfn, ret, page->flags);
                        if (ret > 0)
                                ret = -EIO;
                }
        } else {
-               pr_debug("soft offline: %#lx: isolation failed: %d, page count %d, type %lx\n",
+               pr_info("soft offline: %#lx: isolation failed: %d, page count %d, type %lx\n",
                                pfn, ret, page_count(page), page->flags);
        }
        if (ret)
This page took 0.042758 seconds and 5 git commands to generate.