linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Nick Piggin <nickpiggin@yahoo.com.au>
To: Hugh Dickins <hugh@veritas.com>
Cc: Andrew Morton <akpm@linux-foundation.org>,
	Nick Piggin <npiggin@suse.de>,
	linux-mm@kvack.org
Subject: Re: [PATCH mm] mm: speculative page references fix add_to_page_cache
Date: Mon, 14 Jul 2008 14:57:42 +1000	[thread overview]
Message-ID: <200807141457.43179.nickpiggin@yahoo.com.au> (raw)
In-Reply-To: <Pine.LNX.4.64.0807140031220.30686@blonde.site>

Ah, thanks Hugh. I was surprised that nothing had appeared to blow up
from my pulling the lockless pagecache out of my usual series... I had
missed this case though :(

On Monday 14 July 2008 09:38, Hugh Dickins wrote:
> The speculative page references patch actually depends on another patch
> of Nick's which he hasn't supplied this time around: an atomic-avoiding
> __set_page_locked patch: see http://lkml.org/lkml/2007/11/10/5
>
> This showed up when shmem_unuse_inode's add_to_page_cache failed: the
> page was passed in locked and should remain locked, but speculative's
> add_to_page_cache had unlocked it already, so the subsequent unlock_page
> BUGged.  add_to_page_cache indeed should set and clear the page lock, but
> shmem/tmpfs needs an add_to_page_cache_locked entry point to avoid that.
>
> This fix patch below extracts and updates what's needed from Nick's
> original, including his comments, but leaving out the atomic-avoidance.
>
> (Do speculative page references actually need the page locked before
> it's entered into the page cache?  I'm not sure myself, suspect that
> if everywhere else handled PageUptodate and PageError correctly then
> it might not be necessary; but we're pretty sure there are gaps in
> that error handling, so I agree with Nick that we should lock before.
> He may well be able to supply a stronger reason why it's necessary.)

Right, I'm not sure, I'm not sure whether I could point to a real
bug if we add it unlocked, but I figure it is better to try retaining
pre-lockless-pagecache semantics where possible rather than try to
weaken them at the same time as lockless pagecache.

> I apologize for not finding this sooner, my testing coverage weaker
> than I'd thought: only hit this in checking the swap priority patch.
>
> Signed-off-by: Hugh Dickins <hugh@veritas.com>

Thanks,
Acked-by: Nick Piggin <npiggin@suse.de>


> ---
> Should follow mmotm's mm-speculative-page-references-hugh-fix3.patch
>
>  include/linux/pagemap.h |   18 +++++++++++++++++-
>  mm/filemap.c            |   19 +++++++++----------
>  mm/shmem.c              |    4 ++--
>  mm/swap_state.c         |    2 +-
>  4 files changed, 29 insertions(+), 14 deletions(-)
>
> --- mmotm.orig/include/linux/pagemap.h	2008-07-12 21:36:26.000000000 +0100
> +++ mmotm/include/linux/pagemap.h	2008-07-12 21:36:40.000000000 +0100
> @@ -227,7 +227,7 @@ static inline struct page *read_mapping_
>  	return read_cache_page(mapping, index, filler, data);
>  }
>
> -int add_to_page_cache(struct page *page, struct address_space *mapping,
> +int add_to_page_cache_locked(struct page *page, struct address_space
> *mapping, pgoff_t index, gfp_t gfp_mask);
>  int add_to_page_cache_lru(struct page *page, struct address_space
> *mapping, pgoff_t index, gfp_t gfp_mask);
> @@ -235,6 +235,22 @@ extern void remove_from_page_cache(struc
>  extern void __remove_from_page_cache(struct page *page);
>
>  /*
> + * Like add_to_page_cache_locked, but used to add newly allocated pages:
> + * the page is new, so we can just run SetPageLocked() against it.
> + */
> +static inline int add_to_page_cache(struct page *page,
> +		struct address_space *mapping, pgoff_t offset, gfp_t gfp_mask)
> +{
> +	int error;
> +
> +	SetPageLocked(page);
> +	error = add_to_page_cache_locked(page, mapping, offset, gfp_mask);
> +	if (unlikely(error))
> +		ClearPageLocked(page);
> +	return error;
> +}
> +
> +/*
>   * Return byte-offset into filesystem object for page.
>   */
>  static inline loff_t page_offset(struct page *page)
> --- mmotm.orig/mm/filemap.c	2008-07-12 21:36:26.000000000 +0100
> +++ mmotm/mm/filemap.c	2008-07-12 21:36:40.000000000 +0100
> @@ -442,22 +442,23 @@ int filemap_write_and_wait_range(struct
>  }
>
>  /**
> - * add_to_page_cache - add newly allocated pagecache pages
> + * add_to_page_cache_locked - add newly allocated pagecache pages
>   * @page:	page to add
>   * @mapping:	the page's address_space
>   * @offset:	page index
>   * @gfp_mask:	page allocation mode
>   *
> - * This function is used to add newly allocated pagecache pages;
> - * the page is new, so we can just run SetPageLocked() against it.
> - * The other page state flags were set by rmqueue().
> - *
> + * This function is used to add a page to the pagecache. It must be
> locked. * This function does not add the page to the LRU.  The caller must
> do that. */
> -int add_to_page_cache(struct page *page, struct address_space *mapping,
> +int add_to_page_cache_locked(struct page *page, struct address_space
> *mapping, pgoff_t offset, gfp_t gfp_mask)
>  {
> -	int error = mem_cgroup_cache_charge(page, current->mm,
> +	int error;
> +
> +	VM_BUG_ON(!PageLocked(page));
> +
> +	error = mem_cgroup_cache_charge(page, current->mm,
>  					gfp_mask & ~__GFP_HIGHMEM);
>  	if (error)
>  		goto out;
> @@ -465,7 +466,6 @@ int add_to_page_cache(struct page *page,
>  	error = radix_tree_preload(gfp_mask & ~__GFP_HIGHMEM);
>  	if (error == 0) {
>  		page_cache_get(page);
> -		SetPageLocked(page);
>  		page->mapping = mapping;
>  		page->index = offset;
>
> @@ -476,7 +476,6 @@ int add_to_page_cache(struct page *page,
>  			__inc_zone_page_state(page, NR_FILE_PAGES);
>  		} else {
>  			page->mapping = NULL;
> -			ClearPageLocked(page);
>  			mem_cgroup_uncharge_cache_page(page);
>  			page_cache_release(page);
>  		}
> @@ -488,7 +487,7 @@ int add_to_page_cache(struct page *page,
>  out:
>  	return error;
>  }
> -EXPORT_SYMBOL(add_to_page_cache);
> +EXPORT_SYMBOL(add_to_page_cache_locked);
>
>  int add_to_page_cache_lru(struct page *page, struct address_space
> *mapping, pgoff_t offset, gfp_t gfp_mask)
> --- mmotm.orig/mm/shmem.c	2008-07-12 21:25:56.000000000 +0100
> +++ mmotm/mm/shmem.c	2008-07-12 21:36:40.000000000 +0100
> @@ -936,7 +936,7 @@ found:
>  	spin_lock(&info->lock);
>  	ptr = shmem_swp_entry(info, idx, NULL);
>  	if (ptr && ptr->val == entry.val) {
> -		error = add_to_page_cache(page, inode->i_mapping,
> +		error = add_to_page_cache_locked(page, inode->i_mapping,
>  						idx, GFP_NOWAIT);
>  		/* does mem_cgroup_uncharge_cache_page on error */
>  	} else	/* we must compensate for our precharge above */
> @@ -1301,7 +1301,7 @@ repeat:
>  			SetPageUptodate(filepage);
>  			set_page_dirty(filepage);
>  			swap_free(swap);
> -		} else if (!(error = add_to_page_cache(
> +		} else if (!(error = add_to_page_cache_locked(
>  				swappage, mapping, idx, GFP_NOWAIT))) {
>  			info->flags |= SHMEM_PAGEIN;
>  			shmem_swp_set(info, entry, 0);
> --- mmotm.orig/mm/swap_state.c	2008-07-12 21:36:26.000000000 +0100
> +++ mmotm/mm/swap_state.c	2008-07-12 21:36:40.000000000 +0100
> @@ -64,7 +64,7 @@ void show_swap_cache_info(void)
>  }
>
>  /*
> - * add_to_swap_cache resembles add_to_page_cache on swapper_space,
> + * add_to_swap_cache resembles add_to_page_cache_locked on swapper_space,
>   * but sets SwapCache flag and private instead of mapping and index.
>   */
>  int add_to_swap_cache(struct page *page, swp_entry_t entry, gfp_t
> gfp_mask)
>
> --
> To unsubscribe, send a message with 'unsubscribe linux-mm' in
> the body to majordomo@kvack.org.  For more info on Linux MM,
> see: http://www.linux-mm.org/ .
> Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

      reply	other threads:[~2008-07-14  4:57 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-07-13 23:38 Hugh Dickins
2008-07-14  4:57 ` Nick Piggin [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=200807141457.43179.nickpiggin@yahoo.com.au \
    --to=nickpiggin@yahoo.com.au \
    --cc=akpm@linux-foundation.org \
    --cc=hugh@veritas.com \
    --cc=linux-mm@kvack.org \
    --cc=npiggin@suse.de \
    /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