summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2007-04-27 18:01:57 +0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2007-04-27 18:01:46 +0400
commit6c210482ae4a9a5bb9377ad250feaacec3faa3cd (patch)
tree2eb89d89a22380298d64edad59010c1d0a59e5a4
parent2fc2d1e9ffcde78af7ab63ed640d9a4901797de2 (diff)
downloadlinux-6c210482ae4a9a5bb9377ad250feaacec3faa3cd.tar.xz
[S390] split page_test_and_clear_dirty.
The page_test_and_clear_dirty primitive really consists of two operations, page_test_dirty and the page_clear_dirty. The combination of the two is not an atomic operation, so it makes more sense to have two separate operations instead of one. In addition to the improved readability of the s390 version of SetPageUptodate, it now avoids the page_test_dirty operation which is an insert-storage-key-extended (iske) instruction which is an expensive operation. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--include/asm-generic/pgtable.h11
-rw-r--r--include/asm-s390/pgtable.h15
-rw-r--r--include/linux/page-flags.h2
-rw-r--r--mm/rmap.c8
4 files changed, 24 insertions, 12 deletions
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 6d7e279b1490..dc8f99ee305f 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -139,8 +139,15 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres
#define pte_same(A,B) (pte_val(A) == pte_val(B))
#endif
-#ifndef __HAVE_ARCH_PAGE_TEST_AND_CLEAR_DIRTY
-#define page_test_and_clear_dirty(page) (0)
+#ifndef __HAVE_ARCH_PAGE_TEST_DIRTY
+#define page_test_dirty(page) (0)
+#endif
+
+#ifndef __HAVE_ARCH_PAGE_CLEAR_DIRTY
+#define page_clear_dirty(page) do { } while (0)
+#endif
+
+#ifndef __HAVE_ARCH_PAGE_TEST_DIRTY
#define pte_maybe_dirty(pte) pte_dirty(pte)
#else
#define pte_maybe_dirty(pte) (1)
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
index 13c16546eff5..8fe8d42e64c3 100644
--- a/include/asm-s390/pgtable.h
+++ b/include/asm-s390/pgtable.h
@@ -753,14 +753,14 @@ ptep_establish(struct vm_area_struct *vma,
* should therefore only be called if it is not mapped in any
* address space.
*/
-static inline int page_test_and_clear_dirty(struct page *page)
+static inline int page_test_dirty(struct page *page)
{
- unsigned long physpage = page_to_phys(page);
- int skey = page_get_storage_key(physpage);
+ return (page_get_storage_key(page_to_phys(page)) & _PAGE_CHANGED) != 0;
+}
- if (skey & _PAGE_CHANGED)
- page_set_storage_key(physpage, skey & ~_PAGE_CHANGED);
- return skey & _PAGE_CHANGED;
+static inline void page_clear_dirty(struct page *page)
+{
+ page_set_storage_key(page_to_phys(page), PAGE_DEFAULT_KEY);
}
/*
@@ -953,7 +953,8 @@ extern void memmap_init(unsigned long, int, unsigned long, unsigned long);
#define __HAVE_ARCH_PTEP_CLEAR_FLUSH
#define __HAVE_ARCH_PTEP_SET_WRPROTECT
#define __HAVE_ARCH_PTE_SAME
-#define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_DIRTY
+#define __HAVE_ARCH_PAGE_TEST_DIRTY
+#define __HAVE_ARCH_PAGE_CLEAR_DIRTY
#define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG
#include <asm-generic/pgtable.h>
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 9cd0d0eaf523..96326594e55d 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -133,7 +133,7 @@
static inline void SetPageUptodate(struct page *page)
{
if (!test_and_set_bit(PG_uptodate, &page->flags))
- page_test_and_clear_dirty(page);
+ page_clear_dirty(page);
}
#else
#define SetPageUptodate(page) set_bit(PG_uptodate, &(page)->flags)
diff --git a/mm/rmap.c b/mm/rmap.c
index b82146e6dfc9..59da5b734c80 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -498,8 +498,10 @@ int page_mkclean(struct page *page)
struct address_space *mapping = page_mapping(page);
if (mapping)
ret = page_mkclean_file(mapping, page);
- if (page_test_and_clear_dirty(page))
+ if (page_test_dirty(page)) {
+ page_clear_dirty(page);
ret = 1;
+ }
}
return ret;
@@ -605,8 +607,10 @@ void page_remove_rmap(struct page *page, struct vm_area_struct *vma)
* Leaving it set also helps swapoff to reinstate ptes
* faster for those pages still in swapcache.
*/
- if (page_test_and_clear_dirty(page))
+ if (page_test_dirty(page)) {
+ page_clear_dirty(page);
set_page_dirty(page);
+ }
__dec_zone_page_state(page,
PageAnon(page) ? NR_ANON_PAGES : NR_FILE_MAPPED);
}