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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).