diff mbox series

mm/hwpoison: fix incorrect call put_hwpoison_page() when isolate_huge_page() return false

Message ID CAJtqMcZVQFp8U0aFqrMDD2-UGuLkWYvg3rytcCswnOT_ZMSzjQ@mail.gmail.com (mailing list archive)
State New, archived
Headers show
Series mm/hwpoison: fix incorrect call put_hwpoison_page() when isolate_huge_page() return false | expand

Commit Message

Yongkai Wu Nov. 13, 2018, 7 a.m. UTC
when isolate_huge_page() return false,it won't takes a refcount of page,
if we call put_hwpoison_page() in that case,we may hit the VM_BUG_ON_PAGE!

Signed-off-by: Yongkai Wu <nic_w@163.com>
---
 mm/memory-failure.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

  }

Comments

Naoya Horiguchi Nov. 13, 2018, 7:46 a.m. UTC | #1
On Tue, Nov 13, 2018 at 03:00:09PM +0800, Yongkai Wu wrote:
> when isolate_huge_page() return false,it won't takes a refcount of page,
> if we call put_hwpoison_page() in that case,we may hit the VM_BUG_ON_PAGE!
> 
> Signed-off-by: Yongkai Wu <nic_w@163.com>
> ---
>  mm/memory-failure.c | 13 +++++++------
>  1 file changed, 7 insertions(+), 6 deletions(-)
> 
> diff --git a/mm/memory-failure.c b/mm/memory-failure.c
> index 0cd3de3..ed09f56 100644
> --- a/mm/memory-failure.c
> +++ b/mm/memory-failure.c
> @@ -1699,12 +1699,13 @@ static int soft_offline_huge_page(struct page *page,
> int flags)
>   unlock_page(hpage);
>  
>   ret = isolate_huge_page(hpage, &pagelist);
> - /*
> - * get_any_page() and isolate_huge_page() takes a refcount each,
> - * so need to drop one here.
> - */
> - put_hwpoison_page(hpage);
> - if (!ret) {
> + if (ret) {
> +        /*
> +          * get_any_page() and isolate_huge_page() takes a refcount each,
> +          * so need to drop one here.
> +        */
> + put_hwpoison_page(hpage);
> + } else {

Hi Yongkai,

Although the current code might look odd, it's OK. We have to release
one refcount whether this isolate_huge_page() succeeds or not, because
the put_hwpoison_page() is cancelling the refcount from get_any_page()
which always succeeds when we enter soft_offline_huge_page().

Let's consider that the isolate_huge_page() fails with your patch applied,
then the refcount taken by get_any_page() is never released after returning
from soft_offline_page(). That will lead to memory leak.

I think that current code comment doesn't explaing it well, so if you
like, you can fix the comment.  (If you do that, please check coding style.
scripts/checkpatch.pl will help you.)

Thanks,
Naoya Horiguchi
Yongkai Wu Nov. 13, 2018, 9:13 a.m. UTC | #2
Dear Naoya,
Thank you for your kind reply.
You are right.The current code is ok and I am sorry for wasting your time.

Best Regards.


On Tue, Nov 13, 2018 at 3:47 PM Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
wrote:

> On Tue, Nov 13, 2018 at 03:00:09PM +0800, Yongkai Wu wrote:
> > when isolate_huge_page() return false,it won't takes a refcount of page,
> > if we call put_hwpoison_page() in that case,we may hit the
> VM_BUG_ON_PAGE!
> >
> > Signed-off-by: Yongkai Wu <nic_w@163.com>
> > ---
> >  mm/memory-failure.c | 13 +++++++------
> >  1 file changed, 7 insertions(+), 6 deletions(-)
> >
> > diff --git a/mm/memory-failure.c b/mm/memory-failure.c
> > index 0cd3de3..ed09f56 100644
> > --- a/mm/memory-failure.c
> > +++ b/mm/memory-failure.c
> > @@ -1699,12 +1699,13 @@ static int soft_offline_huge_page(struct page
> *page,
> > int flags)
> >   unlock_page(hpage);
> >
> >   ret = isolate_huge_page(hpage, &pagelist);
> > - /*
> > - * get_any_page() and isolate_huge_page() takes a refcount each,
> > - * so need to drop one here.
> > - */
> > - put_hwpoison_page(hpage);
> > - if (!ret) {
> > + if (ret) {
> > +        /*
> > +          * get_any_page() and isolate_huge_page() takes a refcount
> each,
> > +          * so need to drop one here.
> > +        */
> > + put_hwpoison_page(hpage);
> > + } else {
>
> Hi Yongkai,
>
> Although the current code might look odd, it's OK. We have to release
> one refcount whether this isolate_huge_page() succeeds or not, because
> the put_hwpoison_page() is cancelling the refcount from get_any_page()
> which always succeeds when we enter soft_offline_huge_page().
>
> Let's consider that the isolate_huge_page() fails with your patch applied,
> then the refcount taken by get_any_page() is never released after returning
> from soft_offline_page(). That will lead to memory leak.
>
> I think that current code comment doesn't explaing it well, so if you
> like, you can fix the comment.  (If you do that, please check coding style.
> scripts/checkpatch.pl will help you.)
>
> Thanks,
> Naoya Horiguchi
>
<div dir="ltr"><div dir="ltr"><div dir="ltr">Dear Naoya,<div>Thank you for your kind reply.</div><div>You are right.The current code is ok and I am sorry for wasting your time.</div><div><br></div><div>Best Regards.</div><div> </div></div></div></div><br><div class="gmail_quote"><div dir="ltr">On Tue, Nov 13, 2018 at 3:47 PM Naoya Horiguchi &lt;<a href="mailto:n-horiguchi@ah.jp.nec.com" target="_blank">n-horiguchi@ah.jp.nec.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On Tue, Nov 13, 2018 at 03:00:09PM +0800, Yongkai Wu wrote:<br>
&gt; when isolate_huge_page() return false,it won&#39;t takes a refcount of page,<br>
&gt; if we call put_hwpoison_page() in that case,we may hit the VM_BUG_ON_PAGE!<br>
&gt; <br>
&gt; Signed-off-by: Yongkai Wu &lt;<a href="mailto:nic_w@163.com" target="_blank">nic_w@163.com</a>&gt;<br>
&gt; ---<br>
&gt;  mm/memory-failure.c | 13 +++++++------<br>
&gt;  1 file changed, 7 insertions(+), 6 deletions(-)<br>
&gt; <br>
&gt; diff --git a/mm/memory-failure.c b/mm/memory-failure.c<br>
&gt; index 0cd3de3..ed09f56 100644<br>
&gt; --- a/mm/memory-failure.c<br>
&gt; +++ b/mm/memory-failure.c<br>
&gt; @@ -1699,12 +1699,13 @@ static int soft_offline_huge_page(struct page *page,<br>
&gt; int flags)<br>
&gt;   unlock_page(hpage);<br>
&gt;  <br>
&gt;   ret = isolate_huge_page(hpage, &amp;pagelist);<br>
&gt; - /*<br>
&gt; - * get_any_page() and isolate_huge_page() takes a refcount each,<br>
&gt; - * so need to drop one here.<br>
&gt; - */<br>
&gt; - put_hwpoison_page(hpage);<br>
&gt; - if (!ret) {<br>
&gt; + if (ret) {<br>
&gt; +        /*<br>
&gt; +          * get_any_page() and isolate_huge_page() takes a refcount each,<br>
&gt; +          * so need to drop one here.<br>
&gt; +        */<br>
&gt; + put_hwpoison_page(hpage);<br>
&gt; + } else {<br>
<br>
Hi Yongkai,<br>
<br>
Although the current code might look odd, it&#39;s OK. We have to release<br>
one refcount whether this isolate_huge_page() succeeds or not, because<br>
the put_hwpoison_page() is cancelling the refcount from get_any_page()<br>
which always succeeds when we enter soft_offline_huge_page().<br>
<br>
Let&#39;s consider that the isolate_huge_page() fails with your patch applied,<br>
then the refcount taken by get_any_page() is never released after returning<br>
from soft_offline_page(). That will lead to memory leak.<br>
<br>
I think that current code comment doesn&#39;t explaing it well, so if you<br>
like, you can fix the comment.  (If you do that, please check coding style.<br>
scripts/<a href="http://checkpatch.pl" rel="noreferrer" target="_blank">checkpatch.pl</a> will help you.)<br>
<br>
Thanks,<br>
Naoya Horiguchi<br>
</blockquote></div>
diff mbox series

Patch

diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 0cd3de3..ed09f56 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -1699,12 +1699,13 @@  static int soft_offline_huge_page(struct page
*page, int flags)
  unlock_page(hpage);

  ret = isolate_huge_page(hpage, &pagelist);
- /*
- * get_any_page() and isolate_huge_page() takes a refcount each,
- * so need to drop one here.
- */
- put_hwpoison_page(hpage);
- if (!ret) {
+ if (ret) {
+        /*
+          * get_any_page() and isolate_huge_page() takes a refcount each,
+          * so need to drop one here.
+        */
+ put_hwpoison_page(hpage);
+ } else {
  pr_info("soft offline: %#lx hugepage failed to isolate\n", pfn);
  return -EBUSY;