Commit 767193253bbac889e176f90b6f17b7015f986551

Authored by Ken Chen
Committed by Linus Torvalds
1 parent bd8029b660

[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: Ken Chen <kenchen@google.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 3 changed files with 12 additions and 1 deletions Side-by-side Diff

... ... @@ -785,6 +785,7 @@
785 785 extern void do_invalidatepage(struct page *page, unsigned long offset);
786 786  
787 787 int __set_page_dirty_nobuffers(struct page *page);
  788 +int __set_page_dirty_no_writeback(struct page *page);
788 789 int redirty_page_for_writepage(struct writeback_control *wbc,
789 790 struct page *page);
790 791 int FASTCALL(set_page_dirty(struct page *page));
... ... @@ -737,6 +737,16 @@
737 737 EXPORT_SYMBOL(write_one_page);
738 738  
739 739 /*
  740 + * For address_spaces which do not use buffers nor write back.
  741 + */
  742 +int __set_page_dirty_no_writeback(struct page *page)
  743 +{
  744 + if (!PageDirty(page))
  745 + SetPageDirty(page);
  746 + return 0;
  747 +}
  748 +
  749 +/*
740 750 * For address_spaces which do not use buffers. Just tag the page as dirty in
741 751 * its radix tree.
742 752 *
... ... @@ -2316,7 +2316,7 @@
2316 2316  
2317 2317 static const struct address_space_operations shmem_aops = {
2318 2318 .writepage = shmem_writepage,
2319   - .set_page_dirty = __set_page_dirty_nobuffers,
  2319 + .set_page_dirty = __set_page_dirty_no_writeback,
2320 2320 #ifdef CONFIG_TMPFS
2321 2321 .prepare_write = shmem_prepare_write,
2322 2322 .commit_write = simple_commit_write,