diff options
author | Minchan Kim <minchan.kim@gmail.com> | 2011-03-22 16:30:53 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-22 17:44:02 -0700 |
commit | 97cecb5a254fec22d28ef32235d888bfbfd7c783 (patch) | |
tree | 186c6bb9c1f999f807e2ec68dc6a0cf16c9d0d73 | |
parent | ef6a3c63112e865d632ff7c478ba7c7160cad0d1 (diff) |
mm: introduce delete_from_page_cache()
Presently we increase the page refcount in add_to_page_cache() but don't
decrease it in remove_from_page_cache(). Such asymmetry adds confusion,
requiring that callers notice it and a comment explaining why they release
a page reference. It's not a good API.
A long time ago, Hugh tried it (http://lkml.org/lkml/2004/10/24/140) but
gave up because reiser4's drop_page() had to unlock the page between
removing it from page cache and doing the page_cache_release(). But now
the situation is changed. I think at least things in current mainline
don't have any obstacles. The problem is for out-of-mainline filesystems
- if they have done such things as reiser4, this patch could be a problem
but they will discover this at compile time since we remove
remove_from_page_cache().
This patch:
This function works as just wrapper remove_from_page_cache(). The
difference is that it decreases page references in itself. So caller have
to make sure it has a page reference before calling.
This patch is ready for removing remove_from_page_cache().
Signed-off-by: Minchan Kim <minchan.kim@gmail.com>
Cc: Christoph Hellwig <hch@infradead.org>
Acked-by: Hugh Dickins <hughd@google.com>
Acked-by: Mel Gorman <mel@csn.ul.ie>
Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Reviewed-by: Johannes Weiner <hannes@cmpxchg.org>
Reviewed-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Edward Shishkin <edward.shishkin@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | include/linux/pagemap.h | 1 | ||||
-rw-r--r-- | mm/filemap.c | 16 |
2 files changed, 17 insertions, 0 deletions
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 26946ad483bf..0aa258f4678d 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -455,6 +455,7 @@ 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); +extern void delete_from_page_cache(struct page *page); extern void remove_from_page_cache(struct page *page); extern void __remove_from_page_cache(struct page *page); int replace_page_cache_page(struct page *old, struct page *new, gfp_t gfp_mask); diff --git a/mm/filemap.c b/mm/filemap.c index c1459f2cdb5e..e7b59785ceb9 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -155,6 +155,22 @@ void remove_from_page_cache(struct page *page) } EXPORT_SYMBOL(remove_from_page_cache); +/** + * delete_from_page_cache - delete page from page cache + * @page: the page which the kernel is trying to remove from page cache + * + * This must be called only on pages that have + * been verified to be in the page cache and locked. + * It will never put the page into the free list, + * the caller has a reference on the page. + */ +void delete_from_page_cache(struct page *page) +{ + remove_from_page_cache(page); + page_cache_release(page); +} +EXPORT_SYMBOL(delete_from_page_cache); + static int sync_page(void *word) { struct address_space *mapping; |