diff options
author | Nick Piggin <npiggin@suse.de> | 2008-07-25 22:45:30 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-26 15:00:06 -0400 |
commit | e286781d5f2e9c846e012a39653a166e9d31777d (patch) | |
tree | 14958fe6d8f3e0459c96c68b3034ea2433ab85ac /mm/shmem.c | |
parent | 47feff2c8eefe85099f87c43d3096855f0085ca0 (diff) |
mm: speculative page references
If we can be sure that elevating the page_count on a pagecache page will
pin it, we can speculatively run this operation, and subsequently check to
see if we hit the right page rather than relying on holding a lock or
otherwise pinning a reference to the page.
This can be done if get_page/put_page behaves consistently throughout the
whole tree (ie. if we "get" the page after it has been used for something
else, we must be able to free it with a put_page).
Actually, there is a period where the count behaves differently: when the
page is free or if it is a constituent page of a compound page. We need
an atomic_inc_not_zero operation to ensure we don't try to grab the page
in either case.
This patch introduces the core locking protocol to the pagecache (ie.
adds page_cache_get_speculative, and tweaks some update-side code to make
it work).
Thanks to Hugh for pointing out an improvement to the algorithm setting
page_count to zero when we have control of all references, in order to
hold off speculative getters.
[kamezawa.hiroyu@jp.fujitsu.com: fix migration_entry_wait()]
[hugh@veritas.com: fix add_to_page_cache]
[akpm@linux-foundation.org: repair a comment]
Signed-off-by: Nick Piggin <npiggin@suse.de>
Cc: Jeff Garzik <jeff@garzik.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Hugh Dickins <hugh@veritas.com>
Cc: "Paul E. McKenney" <paulmck@us.ibm.com>
Reviewed-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Signed-off-by: Hugh Dickins <hugh@veritas.com>
Acked-by: Nick Piggin <npiggin@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/shmem.c')
-rw-r--r-- | mm/shmem.c | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/mm/shmem.c b/mm/shmem.c index f92fea94d037..1089092aecaf 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -936,7 +936,7 @@ found: | |||
936 | spin_lock(&info->lock); | 936 | spin_lock(&info->lock); |
937 | ptr = shmem_swp_entry(info, idx, NULL); | 937 | ptr = shmem_swp_entry(info, idx, NULL); |
938 | if (ptr && ptr->val == entry.val) { | 938 | if (ptr && ptr->val == entry.val) { |
939 | error = add_to_page_cache(page, inode->i_mapping, | 939 | error = add_to_page_cache_locked(page, inode->i_mapping, |
940 | idx, GFP_NOWAIT); | 940 | idx, GFP_NOWAIT); |
941 | /* does mem_cgroup_uncharge_cache_page on error */ | 941 | /* does mem_cgroup_uncharge_cache_page on error */ |
942 | } else /* we must compensate for our precharge above */ | 942 | } else /* we must compensate for our precharge above */ |
@@ -1301,8 +1301,8 @@ repeat: | |||
1301 | SetPageUptodate(filepage); | 1301 | SetPageUptodate(filepage); |
1302 | set_page_dirty(filepage); | 1302 | set_page_dirty(filepage); |
1303 | swap_free(swap); | 1303 | swap_free(swap); |
1304 | } else if (!(error = add_to_page_cache( | 1304 | } else if (!(error = add_to_page_cache_locked(swappage, mapping, |
1305 | swappage, mapping, idx, GFP_NOWAIT))) { | 1305 | idx, GFP_NOWAIT))) { |
1306 | info->flags |= SHMEM_PAGEIN; | 1306 | info->flags |= SHMEM_PAGEIN; |
1307 | shmem_swp_set(info, entry, 0); | 1307 | shmem_swp_set(info, entry, 0); |
1308 | shmem_swp_unmap(entry); | 1308 | shmem_swp_unmap(entry); |