diff mbox series

[v2] mm/memory-failure: fix VM_BUG_ON_PAGE(PagePoisoned(page)) when unpoison memory

Message ID 20241219115209.574065-1-linmiaohe@huawei.com (mailing list archive)
State New
Headers show
Series [v2] mm/memory-failure: fix VM_BUG_ON_PAGE(PagePoisoned(page)) when unpoison memory | expand

Commit Message

Miaohe Lin Dec. 19, 2024, 11:52 a.m. UTC
When I did memory failure tests recently, below panic occurs:

page dumped because: VM_BUG_ON_PAGE(PagePoisoned(page))
kernel BUG at include/linux/page-flags.h:616!
Oops: invalid opcode: 0000 [#1] PREEMPT SMP NOPTI
CPU: 3 PID: 720 Comm: bash Not tainted 6.10.0-rc1-00195-g148743902568 #40
RIP: 0010:unpoison_memory+0x2f3/0x590
RSP: 0018:ffffa57fc8787d60 EFLAGS: 00000246
RAX: 0000000000000037 RBX: 0000000000000009 RCX: ffff9be25fcdc9c8
RDX: 0000000000000000 RSI: 0000000000000027 RDI: ffff9be25fcdc9c0
RBP: 0000000000300000 R08: ffffffffb4956f88 R09: 0000000000009ffb
R10: 0000000000000284 R11: ffffffffb4926fa0 R12: ffffe6b00c000000
R13: ffff9bdb453dfd00 R14: 0000000000000000 R15: fffffffffffffffe
FS:  00007f08f04e4740(0000) GS:ffff9be25fcc0000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000564787a30410 CR3: 000000010d4e2000 CR4: 00000000000006f0
Call Trace:
 <TASK>
 unpoison_memory+0x2f3/0x590
 simple_attr_write_xsigned.constprop.0.isra.0+0xb3/0x110
 debugfs_attr_write+0x42/0x60
 full_proxy_write+0x5b/0x80
 vfs_write+0xd5/0x540
 ksys_write+0x64/0xe0
 do_syscall_64+0xb9/0x1d0
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f08f0314887
RSP: 002b:00007ffece710078 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 0000000000000009 RCX: 00007f08f0314887
RDX: 0000000000000009 RSI: 0000564787a30410 RDI: 0000000000000001
RBP: 0000564787a30410 R08: 000000000000fefe R09: 000000007fffffff
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000009
R13: 00007f08f041b780 R14: 00007f08f0417600 R15: 00007f08f0416a00
 </TASK>
Modules linked in: hwpoison_inject
---[ end trace 0000000000000000 ]---
RIP: 0010:unpoison_memory+0x2f3/0x590
RSP: 0018:ffffa57fc8787d60 EFLAGS: 00000246
RAX: 0000000000000037 RBX: 0000000000000009 RCX: ffff9be25fcdc9c8
RDX: 0000000000000000 RSI: 0000000000000027 RDI: ffff9be25fcdc9c0
RBP: 0000000000300000 R08: ffffffffb4956f88 R09: 0000000000009ffb
R10: 0000000000000284 R11: ffffffffb4926fa0 R12: ffffe6b00c000000
R13: ffff9bdb453dfd00 R14: 0000000000000000 R15: fffffffffffffffe
FS:  00007f08f04e4740(0000) GS:ffff9be25fcc0000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000564787a30410 CR3: 000000010d4e2000 CR4: 00000000000006f0
Kernel panic - not syncing: Fatal exception
Kernel Offset: 0x31c00000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
---[ end Kernel panic - not syncing: Fatal exception ]---

The root cause is that unpoison_memory() tries to check the PG_HWPoison
flags of an uninitialized page. So VM_BUG_ON_PAGE(PagePoisoned(page)) is
triggered. This can be reproduced by below steps:
1.Offline memory block:
 echo offline > /sys/devices/system/memory/memory12/state
2.Get offlined memory pfn:
 page-types -b n -rlN
3.Write pfn to unpoison-pfn
 echo <pfn> > /sys/kernel/debug/hwpoison/unpoison-pfn

Signed-off-by: Miaohe Lin <linmiaohe@huawei.com>
---
v2: Use pfn_to_online_page per David. Thanks.
---
 mm/memory-failure.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

Comments

David Hildenbrand Dec. 19, 2024, 12:18 p.m. UTC | #1
On 19.12.24 12:52, Miaohe Lin wrote:
> When I did memory failure tests recently, below panic occurs:
> 
> page dumped because: VM_BUG_ON_PAGE(PagePoisoned(page))
> kernel BUG at include/linux/page-flags.h:616!
> Oops: invalid opcode: 0000 [#1] PREEMPT SMP NOPTI
> CPU: 3 PID: 720 Comm: bash Not tainted 6.10.0-rc1-00195-g148743902568 #40
> RIP: 0010:unpoison_memory+0x2f3/0x590
> RSP: 0018:ffffa57fc8787d60 EFLAGS: 00000246
> RAX: 0000000000000037 RBX: 0000000000000009 RCX: ffff9be25fcdc9c8
> RDX: 0000000000000000 RSI: 0000000000000027 RDI: ffff9be25fcdc9c0
> RBP: 0000000000300000 R08: ffffffffb4956f88 R09: 0000000000009ffb
> R10: 0000000000000284 R11: ffffffffb4926fa0 R12: ffffe6b00c000000
> R13: ffff9bdb453dfd00 R14: 0000000000000000 R15: fffffffffffffffe
> FS:  00007f08f04e4740(0000) GS:ffff9be25fcc0000(0000) knlGS:0000000000000000
> CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 0000564787a30410 CR3: 000000010d4e2000 CR4: 00000000000006f0
> Call Trace:
>   <TASK>
>   unpoison_memory+0x2f3/0x590
>   simple_attr_write_xsigned.constprop.0.isra.0+0xb3/0x110
>   debugfs_attr_write+0x42/0x60
>   full_proxy_write+0x5b/0x80
>   vfs_write+0xd5/0x540
>   ksys_write+0x64/0xe0
>   do_syscall_64+0xb9/0x1d0
>   entry_SYSCALL_64_after_hwframe+0x77/0x7f
> RIP: 0033:0x7f08f0314887
> RSP: 002b:00007ffece710078 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
> RAX: ffffffffffffffda RBX: 0000000000000009 RCX: 00007f08f0314887
> RDX: 0000000000000009 RSI: 0000564787a30410 RDI: 0000000000000001
> RBP: 0000564787a30410 R08: 000000000000fefe R09: 000000007fffffff
> R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000009
> R13: 00007f08f041b780 R14: 00007f08f0417600 R15: 00007f08f0416a00
>   </TASK>
> Modules linked in: hwpoison_inject
> ---[ end trace 0000000000000000 ]---
> RIP: 0010:unpoison_memory+0x2f3/0x590
> RSP: 0018:ffffa57fc8787d60 EFLAGS: 00000246
> RAX: 0000000000000037 RBX: 0000000000000009 RCX: ffff9be25fcdc9c8
> RDX: 0000000000000000 RSI: 0000000000000027 RDI: ffff9be25fcdc9c0
> RBP: 0000000000300000 R08: ffffffffb4956f88 R09: 0000000000009ffb
> R10: 0000000000000284 R11: ffffffffb4926fa0 R12: ffffe6b00c000000
> R13: ffff9bdb453dfd00 R14: 0000000000000000 R15: fffffffffffffffe
> FS:  00007f08f04e4740(0000) GS:ffff9be25fcc0000(0000) knlGS:0000000000000000
> CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 0000564787a30410 CR3: 000000010d4e2000 CR4: 00000000000006f0
> Kernel panic - not syncing: Fatal exception
> Kernel Offset: 0x31c00000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
> ---[ end Kernel panic - not syncing: Fatal exception ]---
> 
> The root cause is that unpoison_memory() tries to check the PG_HWPoison
> flags of an uninitialized page. So VM_BUG_ON_PAGE(PagePoisoned(page)) is
> triggered. This can be reproduced by below steps:
> 1.Offline memory block:
>   echo offline > /sys/devices/system/memory/memory12/state
> 2.Get offlined memory pfn:
>   page-types -b n -rlN
> 3.Write pfn to unpoison-pfn
>   echo <pfn> > /sys/kernel/debug/hwpoison/unpoison-pfn
> 
> Signed-off-by: Miaohe Lin <linmiaohe@huawei.com>
> ---
> v2: Use pfn_to_online_page per David. Thanks.
> ---
>   mm/memory-failure.c | 14 +++++++++++---
>   1 file changed, 11 insertions(+), 3 deletions(-)
> 
> diff --git a/mm/memory-failure.c b/mm/memory-failure.c
> index a7b8ccd29b6f..02be0596ce67 100644
> --- a/mm/memory-failure.c
> +++ b/mm/memory-failure.c
> @@ -2556,10 +2556,18 @@ int unpoison_memory(unsigned long pfn)
>   	static DEFINE_RATELIMIT_STATE(unpoison_rs, DEFAULT_RATELIMIT_INTERVAL,
>   					DEFAULT_RATELIMIT_BURST);
>   
> -	if (!pfn_valid(pfn))
> -		return -ENXIO;
> +	p = pfn_to_online_page(pfn);
> +	if (!p) {
> +		struct dev_pagemap *pgmap;
>   
> -	p = pfn_to_page(pfn);
> +		if (!pfn_valid(pfn))
> +			return -ENXIO;
> +		pgmap = get_dev_pagemap(pfn, NULL);
> +		if (!pgmap)
> +			return -ENXIO;
> +		put_dev_pagemap(pgmap);
> +		p = pfn_to_page(pfn);
> +	}

Hm, I wonder if we can do anything reasonable with ZONE_DEVICE pages here?

CCing Dan, maybe he knows if this interface used to do something 
reasonable with ZONE_DEVICE pages.

Also, I'm not sure about using the page after doing the 
put_dev_pagemap(). Likely we would have to do that at the before exiting 
from this function.
Miaohe Lin Dec. 20, 2024, 2:35 a.m. UTC | #2
On 2024/12/19 20:18, David Hildenbrand wrote:
> On 19.12.24 12:52, Miaohe Lin wrote:
>> When I did memory failure tests recently, below panic occurs:
>>
>> page dumped because: VM_BUG_ON_PAGE(PagePoisoned(page))
>> kernel BUG at include/linux/page-flags.h:616!
>> Oops: invalid opcode: 0000 [#1] PREEMPT SMP NOPTI
>> CPU: 3 PID: 720 Comm: bash Not tainted 6.10.0-rc1-00195-g148743902568 #40
>> RIP: 0010:unpoison_memory+0x2f3/0x590
>> RSP: 0018:ffffa57fc8787d60 EFLAGS: 00000246
>> RAX: 0000000000000037 RBX: 0000000000000009 RCX: ffff9be25fcdc9c8
>> RDX: 0000000000000000 RSI: 0000000000000027 RDI: ffff9be25fcdc9c0
>> RBP: 0000000000300000 R08: ffffffffb4956f88 R09: 0000000000009ffb
>> R10: 0000000000000284 R11: ffffffffb4926fa0 R12: ffffe6b00c000000
>> R13: ffff9bdb453dfd00 R14: 0000000000000000 R15: fffffffffffffffe
>> FS:  00007f08f04e4740(0000) GS:ffff9be25fcc0000(0000) knlGS:0000000000000000
>> CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
>> CR2: 0000564787a30410 CR3: 000000010d4e2000 CR4: 00000000000006f0
>> Call Trace:
>>   <TASK>
>>   unpoison_memory+0x2f3/0x590
>>   simple_attr_write_xsigned.constprop.0.isra.0+0xb3/0x110
>>   debugfs_attr_write+0x42/0x60
>>   full_proxy_write+0x5b/0x80
>>   vfs_write+0xd5/0x540
>>   ksys_write+0x64/0xe0
>>   do_syscall_64+0xb9/0x1d0
>>   entry_SYSCALL_64_after_hwframe+0x77/0x7f
>> RIP: 0033:0x7f08f0314887
>> RSP: 002b:00007ffece710078 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
>> RAX: ffffffffffffffda RBX: 0000000000000009 RCX: 00007f08f0314887
>> RDX: 0000000000000009 RSI: 0000564787a30410 RDI: 0000000000000001
>> RBP: 0000564787a30410 R08: 000000000000fefe R09: 000000007fffffff
>> R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000009
>> R13: 00007f08f041b780 R14: 00007f08f0417600 R15: 00007f08f0416a00
>>   </TASK>
>> Modules linked in: hwpoison_inject
>> ---[ end trace 0000000000000000 ]---
>> RIP: 0010:unpoison_memory+0x2f3/0x590
>> RSP: 0018:ffffa57fc8787d60 EFLAGS: 00000246
>> RAX: 0000000000000037 RBX: 0000000000000009 RCX: ffff9be25fcdc9c8
>> RDX: 0000000000000000 RSI: 0000000000000027 RDI: ffff9be25fcdc9c0
>> RBP: 0000000000300000 R08: ffffffffb4956f88 R09: 0000000000009ffb
>> R10: 0000000000000284 R11: ffffffffb4926fa0 R12: ffffe6b00c000000
>> R13: ffff9bdb453dfd00 R14: 0000000000000000 R15: fffffffffffffffe
>> FS:  00007f08f04e4740(0000) GS:ffff9be25fcc0000(0000) knlGS:0000000000000000
>> CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
>> CR2: 0000564787a30410 CR3: 000000010d4e2000 CR4: 00000000000006f0
>> Kernel panic - not syncing: Fatal exception
>> Kernel Offset: 0x31c00000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
>> ---[ end Kernel panic - not syncing: Fatal exception ]---
>>
>> The root cause is that unpoison_memory() tries to check the PG_HWPoison
>> flags of an uninitialized page. So VM_BUG_ON_PAGE(PagePoisoned(page)) is
>> triggered. This can be reproduced by below steps:
>> 1.Offline memory block:
>>   echo offline > /sys/devices/system/memory/memory12/state
>> 2.Get offlined memory pfn:
>>   page-types -b n -rlN
>> 3.Write pfn to unpoison-pfn
>>   echo <pfn> > /sys/kernel/debug/hwpoison/unpoison-pfn
>>
>> Signed-off-by: Miaohe Lin <linmiaohe@huawei.com>
>> ---
>> v2: Use pfn_to_online_page per David. Thanks.
>> ---
>>   mm/memory-failure.c | 14 +++++++++++---
>>   1 file changed, 11 insertions(+), 3 deletions(-)
>>
>> diff --git a/mm/memory-failure.c b/mm/memory-failure.c
>> index a7b8ccd29b6f..02be0596ce67 100644
>> --- a/mm/memory-failure.c
>> +++ b/mm/memory-failure.c
>> @@ -2556,10 +2556,18 @@ int unpoison_memory(unsigned long pfn)
>>       static DEFINE_RATELIMIT_STATE(unpoison_rs, DEFAULT_RATELIMIT_INTERVAL,
>>                       DEFAULT_RATELIMIT_BURST);
>>   -    if (!pfn_valid(pfn))
>> -        return -ENXIO;
>> +    p = pfn_to_online_page(pfn);
>> +    if (!p) {
>> +        struct dev_pagemap *pgmap;
>>   -    p = pfn_to_page(pfn);
>> +        if (!pfn_valid(pfn))
>> +            return -ENXIO;
>> +        pgmap = get_dev_pagemap(pfn, NULL);
>> +        if (!pgmap)
>> +            return -ENXIO;
>> +        put_dev_pagemap(pgmap);
>> +        p = pfn_to_page(pfn);
>> +    }
> 
> Hm, I wonder if we can do anything reasonable with ZONE_DEVICE pages here?

All I can see in unpoison_memory() is folio_test_clear_hwpoison() for ZONE_DEVICE pages.

> 
> CCing Dan, maybe he knows if this interface used to do something reasonable with ZONE_DEVICE pages.
> 
> Also, I'm not sure about using the page after doing the put_dev_pagemap(). Likely we would have to do that at the before exiting from this function.

IMHO, the page can be used after doing put_dev_pagemap(). The page should still be
available while it has HWPoison set. Or are you worrying about memory offline? That
might not be the scope of this problem. But I might be miss something.

Thanks.
.
David Hildenbrand Dec. 20, 2024, 8:50 a.m. UTC | #3
On 20.12.24 03:35, Miaohe Lin wrote:
> On 2024/12/19 20:18, David Hildenbrand wrote:
>> On 19.12.24 12:52, Miaohe Lin wrote:
>>> When I did memory failure tests recently, below panic occurs:
>>>
>>> page dumped because: VM_BUG_ON_PAGE(PagePoisoned(page))
>>> kernel BUG at include/linux/page-flags.h:616!
>>> Oops: invalid opcode: 0000 [#1] PREEMPT SMP NOPTI
>>> CPU: 3 PID: 720 Comm: bash Not tainted 6.10.0-rc1-00195-g148743902568 #40
>>> RIP: 0010:unpoison_memory+0x2f3/0x590
>>> RSP: 0018:ffffa57fc8787d60 EFLAGS: 00000246
>>> RAX: 0000000000000037 RBX: 0000000000000009 RCX: ffff9be25fcdc9c8
>>> RDX: 0000000000000000 RSI: 0000000000000027 RDI: ffff9be25fcdc9c0
>>> RBP: 0000000000300000 R08: ffffffffb4956f88 R09: 0000000000009ffb
>>> R10: 0000000000000284 R11: ffffffffb4926fa0 R12: ffffe6b00c000000
>>> R13: ffff9bdb453dfd00 R14: 0000000000000000 R15: fffffffffffffffe
>>> FS:  00007f08f04e4740(0000) GS:ffff9be25fcc0000(0000) knlGS:0000000000000000
>>> CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
>>> CR2: 0000564787a30410 CR3: 000000010d4e2000 CR4: 00000000000006f0
>>> Call Trace:
>>>    <TASK>
>>>    unpoison_memory+0x2f3/0x590
>>>    simple_attr_write_xsigned.constprop.0.isra.0+0xb3/0x110
>>>    debugfs_attr_write+0x42/0x60
>>>    full_proxy_write+0x5b/0x80
>>>    vfs_write+0xd5/0x540
>>>    ksys_write+0x64/0xe0
>>>    do_syscall_64+0xb9/0x1d0
>>>    entry_SYSCALL_64_after_hwframe+0x77/0x7f
>>> RIP: 0033:0x7f08f0314887
>>> RSP: 002b:00007ffece710078 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
>>> RAX: ffffffffffffffda RBX: 0000000000000009 RCX: 00007f08f0314887
>>> RDX: 0000000000000009 RSI: 0000564787a30410 RDI: 0000000000000001
>>> RBP: 0000564787a30410 R08: 000000000000fefe R09: 000000007fffffff
>>> R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000009
>>> R13: 00007f08f041b780 R14: 00007f08f0417600 R15: 00007f08f0416a00
>>>    </TASK>
>>> Modules linked in: hwpoison_inject
>>> ---[ end trace 0000000000000000 ]---
>>> RIP: 0010:unpoison_memory+0x2f3/0x590
>>> RSP: 0018:ffffa57fc8787d60 EFLAGS: 00000246
>>> RAX: 0000000000000037 RBX: 0000000000000009 RCX: ffff9be25fcdc9c8
>>> RDX: 0000000000000000 RSI: 0000000000000027 RDI: ffff9be25fcdc9c0
>>> RBP: 0000000000300000 R08: ffffffffb4956f88 R09: 0000000000009ffb
>>> R10: 0000000000000284 R11: ffffffffb4926fa0 R12: ffffe6b00c000000
>>> R13: ffff9bdb453dfd00 R14: 0000000000000000 R15: fffffffffffffffe
>>> FS:  00007f08f04e4740(0000) GS:ffff9be25fcc0000(0000) knlGS:0000000000000000
>>> CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
>>> CR2: 0000564787a30410 CR3: 000000010d4e2000 CR4: 00000000000006f0
>>> Kernel panic - not syncing: Fatal exception
>>> Kernel Offset: 0x31c00000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
>>> ---[ end Kernel panic - not syncing: Fatal exception ]---
>>>
>>> The root cause is that unpoison_memory() tries to check the PG_HWPoison
>>> flags of an uninitialized page. So VM_BUG_ON_PAGE(PagePoisoned(page)) is
>>> triggered. This can be reproduced by below steps:
>>> 1.Offline memory block:
>>>    echo offline > /sys/devices/system/memory/memory12/state
>>> 2.Get offlined memory pfn:
>>>    page-types -b n -rlN
>>> 3.Write pfn to unpoison-pfn
>>>    echo <pfn> > /sys/kernel/debug/hwpoison/unpoison-pfn
>>>
>>> Signed-off-by: Miaohe Lin <linmiaohe@huawei.com>
>>> ---
>>> v2: Use pfn_to_online_page per David. Thanks.
>>> ---
>>>    mm/memory-failure.c | 14 +++++++++++---
>>>    1 file changed, 11 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/mm/memory-failure.c b/mm/memory-failure.c
>>> index a7b8ccd29b6f..02be0596ce67 100644
>>> --- a/mm/memory-failure.c
>>> +++ b/mm/memory-failure.c
>>> @@ -2556,10 +2556,18 @@ int unpoison_memory(unsigned long pfn)
>>>        static DEFINE_RATELIMIT_STATE(unpoison_rs, DEFAULT_RATELIMIT_INTERVAL,
>>>                        DEFAULT_RATELIMIT_BURST);
>>>    -    if (!pfn_valid(pfn))
>>> -        return -ENXIO;
>>> +    p = pfn_to_online_page(pfn);
>>> +    if (!p) {
>>> +        struct dev_pagemap *pgmap;
>>>    -    p = pfn_to_page(pfn);
>>> +        if (!pfn_valid(pfn))
>>> +            return -ENXIO;
>>> +        pgmap = get_dev_pagemap(pfn, NULL);
>>> +        if (!pgmap)
>>> +            return -ENXIO;
>>> +        put_dev_pagemap(pgmap);
>>> +        p = pfn_to_page(pfn);
>>> +    }
>>
>> Hm, I wonder if we can do anything reasonable with ZONE_DEVICE pages here?
> 
> All I can see in unpoison_memory() is folio_test_clear_hwpoison() for ZONE_DEVICE pages.

IIRC, it can only be triggered via debugfs in special kernel configs. So 
chances are this was never ever actually run against a ZONE_DEVICE page.

> 
>>
>> CCing Dan, maybe he knows if this interface used to do something reasonable with ZONE_DEVICE pages.
>>
>> Also, I'm not sure about using the page after doing the put_dev_pagemap(). Likely we would have to do that at the before exiting from this function.
> 
> IMHO, the page can be used after doing put_dev_pagemap(). The page should still be
> available while it has HWPoison set.

1) Why do you think it can be used afterwards? :)

2) At that point in time you don't even know yet if the page is
    HWPoisoned! That check is performed later

3) From GUP code, I recall that we must keep the pagemap referenced
    until we grabbed a page/folio reference.

Or are you worrying about memory offline? That
> might not be the scope of this problem. But I might be miss something.

I suspect unpoison_memory() doesn't do with ZONE_DEVICE pages what it 
should be doing. Maybe I'm wrong, it would be great to get feedback from 
Dan.
diff mbox series

Patch

diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index a7b8ccd29b6f..02be0596ce67 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -2556,10 +2556,18 @@  int unpoison_memory(unsigned long pfn)
 	static DEFINE_RATELIMIT_STATE(unpoison_rs, DEFAULT_RATELIMIT_INTERVAL,
 					DEFAULT_RATELIMIT_BURST);
 
-	if (!pfn_valid(pfn))
-		return -ENXIO;
+	p = pfn_to_online_page(pfn);
+	if (!p) {
+		struct dev_pagemap *pgmap;
 
-	p = pfn_to_page(pfn);
+		if (!pfn_valid(pfn))
+			return -ENXIO;
+		pgmap = get_dev_pagemap(pfn, NULL);
+		if (!pgmap)
+			return -ENXIO;
+		put_dev_pagemap(pgmap);
+		p = pfn_to_page(pfn);
+	}
 	folio = page_folio(p);
 
 	mutex_lock(&mf_mutex);