From: Shaohua Li <shli@kernel.org>
To: linux-mm@kvack.org
Cc: sjenning@linux.vnet.ibm.com, bob.liu@oracle.com,
dan.magenheimer@oracle.com
Subject: [RFC 1/4] cleancache: make put_page async possible
Date: Thu, 26 Sep 2013 22:14:29 +0800 [thread overview]
Message-ID: <20130926141551.554966674@kernel.org> (raw)
In-Reply-To: 20130926141428.392345308@kernel.org
[-- Attachment #1: cleancache-async-put_page.patch --]
[-- Type: text/plain, Size: 5061 bytes --]
Previously put_page must store page in sync way. This patch makes it possible
that put_page stores page in async way. To store page in async way, put_page
just increases the page reference, stores the page in other context, and
finally free the page at proper time.
In the page reclaim code path, put_page is called with page reference 0. Since
I need increase page reference, some page reference checks are relieved.
Signed-off-by: Shaohua Li <shli@kernel.org>
---
include/linux/mm.h | 5 -----
include/linux/pagemap.h | 1 -
mm/filemap.c | 7 ++++++-
mm/vmscan.c | 21 ++++++++++++++++-----
4 files changed, 22 insertions(+), 12 deletions(-)
Index: linux/include/linux/mm.h
===================================================================
--- linux.orig/include/linux/mm.h 2013-09-26 21:12:15.479396069 +0800
+++ linux/include/linux/mm.h 2013-09-26 21:12:15.471392582 +0800
@@ -414,11 +414,6 @@ static inline void get_page(struct page
if (unlikely(PageTail(page)))
if (likely(__get_page_tail(page)))
return;
- /*
- * Getting a normal page or the head of a compound page
- * requires to already have an elevated page->_count.
- */
- VM_BUG_ON(atomic_read(&page->_count) <= 0);
atomic_inc(&page->_count);
}
Index: linux/include/linux/pagemap.h
===================================================================
--- linux.orig/include/linux/pagemap.h 2013-09-26 21:12:15.479396069 +0800
+++ linux/include/linux/pagemap.h 2013-09-26 21:12:15.475394311 +0800
@@ -210,7 +210,6 @@ static inline int page_freeze_refs(struc
static inline void page_unfreeze_refs(struct page *page, int count)
{
- VM_BUG_ON(page_count(page) != 0);
VM_BUG_ON(count == 0);
atomic_set(&page->_count, count);
Index: linux/mm/filemap.c
===================================================================
--- linux.orig/mm/filemap.c 2013-09-26 21:12:15.479396069 +0800
+++ linux/mm/filemap.c 2013-09-26 21:12:15.475394311 +0800
@@ -117,17 +117,22 @@ void __delete_from_page_cache(struct pag
struct address_space *mapping = page->mapping;
trace_mm_filemap_delete_from_page_cache(page);
+
+ radix_tree_delete(&mapping->page_tree, page->index);
+
/*
* if we're uptodate, flush out into the cleancache, otherwise
* invalidate any existing cleancache entries. We can't leave
* stale data around in the cleancache once our page is gone
+ * Do this after page is removed from radix tree. put_page might
+ * increase refcnt, we don't want to break speculative get page
+ * protocol.
*/
if (PageUptodate(page) && PageMappedToDisk(page))
cleancache_put_page(page);
else
cleancache_invalidate_page(mapping, page);
- radix_tree_delete(&mapping->page_tree, page->index);
page->mapping = NULL;
/* Leave page->index set: truncation lookup relies upon it */
mapping->nrpages--;
Index: linux/mm/vmscan.c
===================================================================
--- linux.orig/mm/vmscan.c 2013-09-26 21:12:15.479396069 +0800
+++ linux/mm/vmscan.c 2013-09-26 21:12:15.475394311 +0800
@@ -570,8 +570,7 @@ cannot_free:
/*
* Attempt to detach a locked page from its ->mapping. If it is dirty or if
* someone else has a ref on the page, abort and return 0. If it was
- * successfully detached, return 1. Assumes the caller has a single ref on
- * this page.
+ * successfully detached, return 1.
*/
int remove_mapping(struct address_space *mapping, struct page *page)
{
@@ -581,7 +580,7 @@ int remove_mapping(struct address_space
* drops the pagecache ref for us without requiring another
* atomic operation.
*/
- page_unfreeze_refs(page, 1);
+ page_unfreeze_refs(page, 1 + page_count(page));
return 1;
}
return 0;
@@ -782,7 +781,7 @@ static unsigned long shrink_page_list(st
struct page *page;
int may_enter_fs;
enum page_references references = PAGEREF_RECLAIM_CLEAN;
- bool dirty, writeback;
+ bool dirty, writeback, free_page = true;
cond_resched();
@@ -1049,16 +1048,28 @@ static unsigned long shrink_page_list(st
goto keep_locked;
/*
+ * there is a case cleancache eats this page, it will free this
+ * page after the page is unlocked
+ */
+ free_page = page_count(page) == 0;
+
+ /*
* At this point, we have no other references and there is
* no way to pick any more up (removed from LRU, removed
* from pagecache). Can use non-atomic bitops now (and
* we obviously don't have to worry about waking up a process
* waiting on the page lock, because there are no references.
*/
- __clear_page_locked(page);
+ if (free_page)
+ __clear_page_locked(page);
+ else
+ unlock_page(page);
free_it:
nr_reclaimed++;
+ if (!free_page)
+ continue;
+
/*
* Is there need to periodically free_page_list? It would
* appear not as the counts should be low
--
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>
next prev parent reply other threads:[~2013-09-26 14:16 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-09-26 14:14 [RFC 0/4] cleancache: SSD backed cleancache backend Shaohua Li
2013-09-26 14:14 ` Shaohua Li [this message]
2013-09-26 14:14 ` [RFC 2/4] cleancache: make get_page async possible Shaohua Li
2013-09-26 14:14 ` [RFC 3/4] cleancache: invalidate cache at dirty page Shaohua Li
2013-09-26 14:14 ` [RFC 4/4] cleancache: SSD backed cleancache backend Shaohua Li
2013-09-26 16:14 ` [RFC 0/4] " Seth Jennings
2013-09-29 9:19 ` Shaohua Li
2013-10-09 11:52 ` Theodore Ts'o
2013-10-10 10:24 ` Alex Elsayed
2013-10-10 10:38 ` Bob Liu
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=20130926141551.554966674@kernel.org \
--to=shli@kernel.org \
--cc=bob.liu@oracle.com \
--cc=dan.magenheimer@oracle.com \
--cc=linux-mm@kvack.org \
--cc=sjenning@linux.vnet.ibm.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.