linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Yang Shi <shy828301@gmail.com>
To: Matthew Wilcox <willy@infradead.org>
Cc: linux-mm@kvack.org, Hugh Dickins <hughd@google.com>,
	 David Hildenbrand <david@redhat.com>
Subject: Re: Avoiding allocation of unused shmem page
Date: Thu, 20 Oct 2022 15:17:22 -0700	[thread overview]
Message-ID: <CAHbLzkr_ZpB2V8GVDVaOOkU9r=jpzHq6H1=CtTEZsHgQA4qW3Q@mail.gmail.com> (raw)
In-Reply-To: <Y1GsEdsQS9XrqZjF@casper.infradead.org>

On Thu, Oct 20, 2022 at 1:14 PM Matthew Wilcox <willy@infradead.org> wrote:
>
> In yesterday's call, David brought up the case where we fallocate a file
> in shmem, call mmap(MAP_PRIVATE) and then store to a page which is over
> a hole.  That currently causes shmem to allocate a page, zero-fill it,
> then COW it, resulting in two pages being allocated when only the
> COW page really needs to be allocated.
>
> The path we currently take through the MM when we take the page fault
> looks like this (correct me if I'm wrong ...):
>
> handle_mm_fault()
> __handle_mm_fault()
> handle_pte_fault()
> do_fault()
> do_cow_fault()
> __do_fault()
> vm_ops->fault()
>
> ... which is where we come into shmem_fault().  Apart from the
> horrendous hole-punch handling case, shmem_fault() is quite simple:
>
>         err = shmem_get_folio_gfp(inode, vmf->pgoff, &folio, SGP_CACHE,
>                                   gfp, vma, vmf, &ret);
>         if (err)
>                 return vmf_error(err);
>         vmf->page = folio_file_page(folio, vmf->pgoff);
>         return ret;
>
> What we could do here is detect this case.  Something like:
>
>         enum sgp_type sgp = SGP_CACHE;
>
>         if ((vmf->flags & FAULT_FLAG_WRITE) && !(vma->vm_flags & VM_SHARED))
>                 sgp = SGP_READ;
>         err = shmem_get_folio_gfp(inode, vmf->pgoff, &folio, sgp, gfp,
>                                 vma, vmf, &ret);
>         if (err)
>                 return vmf_error(err);
>         if (folio)
>                 vmf->page = folio_file_page(folio, vmf->pgoff);
>         else
>                 vmf->page = NULL;
>         return ret;
>
> and change do_cow_fault() like this:
>
> +++ b/mm/memory.c
> @@ -4575,12 +4575,17 @@ static vm_fault_t do_cow_fault(struct vm_fault *vmf)
>         if (ret & VM_FAULT_DONE_COW)
>                 return ret;
>
> -       copy_user_highpage(vmf->cow_page, vmf->page, vmf->address, vma);
> +       if (vmf->page)
> +               copy_user_highpage(vmf->cow_page, vmf->page, vmf->address, vma);
> +       else
> +               clear_user_highpage(vmf->cow_page, vmf->address);
>         __SetPageUptodate(vmf->cow_page);
>
>         ret |= finish_fault(vmf);
> -       unlock_page(vmf->page);
> -       put_page(vmf->page);
> +       if (vmf->page) {
> +               unlock_page(vmf->page);
> +               put_page(vmf->page);
> +       }
>         if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE | VM_FAULT_RETRY)))
>                 goto uncharge_out;
>         return ret;
>
> ... I wrote the code directly in my email client; definitely not
> compile-tested.  But if this situation is causing a real problem for
> someone, this would be a quick fix for them.
>
> Is this a real problem or just intellectual curiosity?  Also, does
> this need support for THPs being created directly, or is khugepaged
> fixing it up afterwards good enough?

AFAIK, THP is not supported for private mapping.

>


      parent reply	other threads:[~2022-10-20 22:17 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-20 20:14 Matthew Wilcox
2022-10-20 21:10 ` Peter Xu
2022-10-21  7:23   ` David Hildenbrand
2022-10-21 14:01     ` Peter Xu
2022-10-21 14:10       ` David Hildenbrand
2022-10-21 14:28         ` Peter Xu
2022-10-21 14:45           ` David Hildenbrand
2022-10-21 15:08             ` Peter Xu
2022-10-21 15:17               ` David Hildenbrand
2022-10-21 16:01                 ` Peter Xu
2022-10-21 16:19                   ` David Hildenbrand
2022-10-21 16:26                     ` David Hildenbrand
2022-10-20 22:17 ` Yang Shi [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAHbLzkr_ZpB2V8GVDVaOOkU9r=jpzHq6H1=CtTEZsHgQA4qW3Q@mail.gmail.com' \
    --to=shy828301@gmail.com \
    --cc=david@redhat.com \
    --cc=hughd@google.com \
    --cc=linux-mm@kvack.org \
    --cc=willy@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox