Commit dc2a1cbf7d862e9d0abea1d1b4c8712dfbb5a398

Authored by Wu Fengguang
Committed by Andi Kleen
1 parent 71f72525df

HWPOISON: introduce delete_from_lru_cache()

Introduce delete_from_lru_cache() to
- clear PG_active, PG_unevictable to avoid complains at unpoison time
- move the isolate_lru_page() call back to the handlers instead of the
  entrance of __memory_failure(), this is more hwpoison filter friendly

Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Andi Kleen <ak@linux.intel.com>

Showing 1 changed file with 37 additions and 8 deletions Side-by-side Diff

... ... @@ -350,6 +350,30 @@
350 350 };
351 351  
352 352 /*
  353 + * XXX: It is possible that a page is isolated from LRU cache,
  354 + * and then kept in swap cache or failed to remove from page cache.
  355 + * The page count will stop it from being freed by unpoison.
  356 + * Stress tests should be aware of this memory leak problem.
  357 + */
  358 +static int delete_from_lru_cache(struct page *p)
  359 +{
  360 + if (!isolate_lru_page(p)) {
  361 + /*
  362 + * Clear sensible page flags, so that the buddy system won't
  363 + * complain when the page is unpoison-and-freed.
  364 + */
  365 + ClearPageActive(p);
  366 + ClearPageUnevictable(p);
  367 + /*
  368 + * drop the page count elevated by isolate_lru_page()
  369 + */
  370 + page_cache_release(p);
  371 + return 0;
  372 + }
  373 + return -EIO;
  374 +}
  375 +
  376 +/*
353 377 * Error hit kernel page.
354 378 * Do nothing, try to be lucky and not touch this instead. For a few cases we
355 379 * could be more sophisticated.
... ... @@ -393,6 +417,8 @@
393 417 int ret = FAILED;
394 418 struct address_space *mapping;
395 419  
  420 + delete_from_lru_cache(p);
  421 +
396 422 /*
397 423 * For anonymous pages we're done the only reference left
398 424 * should be the one m_f() holds.
399 425  
... ... @@ -522,14 +548,20 @@
522 548 /* Trigger EIO in shmem: */
523 549 ClearPageUptodate(p);
524 550  
525   - return DELAYED;
  551 + if (!delete_from_lru_cache(p))
  552 + return DELAYED;
  553 + else
  554 + return FAILED;
526 555 }
527 556  
528 557 static int me_swapcache_clean(struct page *p, unsigned long pfn)
529 558 {
530 559 delete_from_swap_cache(p);
531 560  
532   - return RECOVERED;
  561 + if (!delete_from_lru_cache(p))
  562 + return RECOVERED;
  563 + else
  564 + return FAILED;
533 565 }
534 566  
535 567 /*
... ... @@ -746,7 +778,6 @@
746 778  
747 779 int __memory_failure(unsigned long pfn, int trapno, int flags)
748 780 {
749   - unsigned long lru_flag;
750 781 struct page_state *ps;
751 782 struct page *p;
752 783 int res;
753 784  
... ... @@ -796,13 +827,11 @@
796 827 */
797 828 if (!PageLRU(p))
798 829 lru_add_drain_all();
799   - lru_flag = p->flags & lru;
800   - if (isolate_lru_page(p)) {
  830 + if (!PageLRU(p)) {
801 831 action_result(pfn, "non LRU", IGNORED);
802 832 put_page(p);
803 833 return -EBUSY;
804 834 }
805   - page_cache_release(p);
806 835  
807 836 /*
808 837 * Lock the page and wait for writeback to finish.
... ... @@ -825,7 +854,7 @@
825 854 /*
826 855 * Torn down by someone else?
827 856 */
828   - if ((lru_flag & lru) && !PageSwapCache(p) && p->mapping == NULL) {
  857 + if (PageLRU(p) && !PageSwapCache(p) && p->mapping == NULL) {
829 858 action_result(pfn, "already truncated LRU", IGNORED);
830 859 res = 0;
831 860 goto out;
... ... @@ -833,7 +862,7 @@
833 862  
834 863 res = -EBUSY;
835 864 for (ps = error_states;; ps++) {
836   - if (((p->flags | lru_flag)& ps->mask) == ps->res) {
  865 + if ((p->flags & ps->mask) == ps->res) {
837 866 res = page_action(ps, p, pfn);
838 867 break;
839 868 }