提交 76719325 编写于 作者: K Ken Chen 提交者: Linus Torvalds

[PATCH] simplify shmem_aops.set_page_dirty() method

shmem backed file does not have page writeback, nor it participates in
backing device's dirty or writeback accounting.  So using generic
__set_page_dirty_nobuffers() for its .set_page_dirty aops method is a bit
overkill.  It unnecessarily prolongs shm unmap latency.

For example, on a densely populated large shm segment (sevearl GBs), the
unmapping operation becomes painfully long.  Because at unmap, kernel
transfers dirty bit in PTE into page struct and to the radix tree tag.  The
operation of tagging the radix tree is particularly expensive because it
has to traverse the tree from the root to the leaf node on every dirty
page.  What's bothering is that radix tree tag is used for page write back.
 However, shmem is memory backed and there is no page write back for such
file system.  And in the end, we spend all that time tagging radix tree and
none of that fancy tagging will be used.  So let's simplify it by introduce
a new aops __set_page_dirty_no_writeback and this will speed up shm unmap.
Signed-off-by: NKen Chen <kenchen@google.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Hugh Dickins <hugh@veritas.com>
Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
上级 bd8029b6
...@@ -785,6 +785,7 @@ extern int try_to_release_page(struct page * page, gfp_t gfp_mask); ...@@ -785,6 +785,7 @@ extern int try_to_release_page(struct page * page, gfp_t gfp_mask);
extern void do_invalidatepage(struct page *page, unsigned long offset); extern void do_invalidatepage(struct page *page, unsigned long offset);
int __set_page_dirty_nobuffers(struct page *page); int __set_page_dirty_nobuffers(struct page *page);
int __set_page_dirty_no_writeback(struct page *page);
int redirty_page_for_writepage(struct writeback_control *wbc, int redirty_page_for_writepage(struct writeback_control *wbc,
struct page *page); struct page *page);
int FASTCALL(set_page_dirty(struct page *page)); int FASTCALL(set_page_dirty(struct page *page));
......
...@@ -736,6 +736,16 @@ int write_one_page(struct page *page, int wait) ...@@ -736,6 +736,16 @@ int write_one_page(struct page *page, int wait)
} }
EXPORT_SYMBOL(write_one_page); EXPORT_SYMBOL(write_one_page);
/*
* For address_spaces which do not use buffers nor write back.
*/
int __set_page_dirty_no_writeback(struct page *page)
{
if (!PageDirty(page))
SetPageDirty(page);
return 0;
}
/* /*
* For address_spaces which do not use buffers. Just tag the page as dirty in * For address_spaces which do not use buffers. Just tag the page as dirty in
* its radix tree. * its radix tree.
......
...@@ -2316,7 +2316,7 @@ static void destroy_inodecache(void) ...@@ -2316,7 +2316,7 @@ static void destroy_inodecache(void)
static const struct address_space_operations shmem_aops = { static const struct address_space_operations shmem_aops = {
.writepage = shmem_writepage, .writepage = shmem_writepage,
.set_page_dirty = __set_page_dirty_nobuffers, .set_page_dirty = __set_page_dirty_no_writeback,
#ifdef CONFIG_TMPFS #ifdef CONFIG_TMPFS
.prepare_write = shmem_prepare_write, .prepare_write = shmem_prepare_write,
.commit_write = simple_commit_write, .commit_write = simple_commit_write,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册