Commit 76485b68 authored by Ma Wupeng's avatar Ma Wupeng Committed by Wupeng Ma
Browse files

hwpoison, memory_hotplug: lock page before unmap for hwpoisoned page

hulk inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IB8TSF



--------------------------------

Commit b15c8726 ("hwpoison, memory_hotplug: allow hwpoisoned pages to
be offlined) add page poison checks in do_migrate_range in order to make
offline hwpoisoned page possible by introducing isolate_lru_page and
try_to_unmap for hwpoisoned page. However page lock must be held before
calling try_to_unmap. Add it to fix this problem.

Without page lock, kernel will BUG_ON with the following log:

  ------------[ cut here ]------------
  kernel BUG at include/linux/swapops.h:326!
  Internal error: Oops - BUG: 00000000f2000800 [#1] SMP
  CPU: 55 PID: 59981 Comm: sh Kdump: loaded Tainted: G        W  OE     5.10.0 #1
  pstate: 60400009 (nZCv daif +PAN -UAO -TCO BTYPE=--)
  pc : try_to_unmap_one+0xdfc/0x1380
  lr : try_to_unmap_one+0x4f4/0x1380
  Call trace:
   try_to_unmap_one+0xdfc/0x1380
   rmap_walk_anon+0x150/0x45c
   rmap_walk+0x50/0xfc
   try_to_unmap+0x108/0x1b0
   do_migrate_range+0x3bc/0x6d0
   offline_pages+0x450/0x5b0
   memory_subsys_offline+0x4c/0x9c
   device_offline+0xfc/0x14c
   state_store+0x98/0x110
   dev_attr_store+0x1c/0x40
   sysfs_kf_write+0x48/0x70
   kernfs_fop_write_iter+0x128/0x1d0
   new_sync_write+0xec/0x1a0
   vfs_write+0x208/0x2b0
   ksys_write+0x70/0x110
   __arm64_sys_write+0x20/0x40
   invoke_syscall+0x4c/0x124
   el0_svc_common.constprop.0+0x140/0x15c
   do_el0_svc+0x30/0xd0
   el0_svc+0x1c/0x2c
   el0_sync_handler+0xb0/0xb4
   el0_sync+0x168/0x180
  Code: 17ffffde d1000400 f9400000 3707a240 (d4210000)
  SMP: stopping secondary CPUs

Fixes: b15c8726 ("hwpoison, memory_hotplug: allow hwpoisoned pages to be offlined")
Signed-off-by: default avatarMa Wupeng <mawupeng1@huawei.com>
parent 74e85e88
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -1160,8 +1160,11 @@ int do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
		if (PageHWPoison(page)) {
			if (WARN_ON(PageLRU(page)))
				isolate_lru_page(page);
			if (page_mapped(page))
			if (page_mapped(page)) {
				lock_page(page);
				try_to_unmap(page, TTU_IGNORE_MLOCK);
				unlock_page(page);
			}
			continue;
		}