readahead: fault retry breaks mmap file read random detection
authorShaohua Li <shli@kernel.org>
Mon, 8 Oct 2012 23:32:19 +0000 (16:32 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 9 Oct 2012 07:22:47 +0000 (16:22 +0900)
.fault now can retry.  The retry can break state machine of .fault.  In
filemap_fault, if page is miss, ra->mmap_miss is increased.  In the second
try, since the page is in page cache now, ra->mmap_miss is decreased.  And
these are done in one fault, so we can't detect random mmap file access.

Add a new flag to indicate .fault is tried once.  In the second try, skip
ra->mmap_miss decreasing.  The filemap_fault state machine is ok with it.

I only tested x86, didn't test other archs, but looks the change for other
archs is obvious, but who knows :)

Signed-off-by: Shaohua Li <shaohua.li@fusionio.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
20 files changed:
arch/arm/mm/fault.c
arch/avr32/mm/fault.c
arch/cris/mm/fault.c
arch/hexagon/mm/vm_fault.c
arch/ia64/mm/fault.c
arch/m68k/mm/fault.c
arch/microblaze/mm/fault.c
arch/mips/mm/fault.c
arch/openrisc/mm/fault.c
arch/powerpc/mm/fault.c
arch/s390/mm/fault.c
arch/sh/mm/fault.c
arch/sparc/mm/fault_32.c
arch/sparc/mm/fault_64.c
arch/tile/mm/fault.c
arch/um/kernel/trap.c
arch/x86/mm/fault.c
arch/xtensa/mm/fault.c
include/linux/mm.h
mm/filemap.c

index c3bd8345022780e45e3135228329a56dda91cee4..5dbf13f954f6f493aaae525d4f3b93282ac88f75 100644 (file)
@@ -336,6 +336,7 @@ retry:
                        /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
                        * of starvation. */
                        flags &= ~FAULT_FLAG_ALLOW_RETRY;
+                       flags |= FAULT_FLAG_TRIED;
                        goto retry;
                }
        }
index b92e60958617eb25ff90481989f494c3625f5a98..b2f2d2d668491905dbbc37c385449852a9e7fdde 100644 (file)
@@ -152,6 +152,7 @@ good_area:
                        tsk->min_flt++;
                if (fault & VM_FAULT_RETRY) {
                        flags &= ~FAULT_FLAG_ALLOW_RETRY;
+                       flags |= FAULT_FLAG_TRIED;
 
                        /*
                         * No need to up_read(&mm->mmap_sem) as we would have
index 45fd542cf173df075c556d3fb1586d740298b426..73312ab6c696c160f7fd58df02a50890390ad650 100644 (file)
@@ -186,6 +186,7 @@ retry:
                        tsk->min_flt++;
                if (fault & VM_FAULT_RETRY) {
                        flags &= ~FAULT_FLAG_ALLOW_RETRY;
+                       flags |= FAULT_FLAG_TRIED;
 
                        /*
                         * No need to up_read(&mm->mmap_sem) as we would
index 06695cc4fe58f09f61d73c0e28803de8b9dfbda3..513b74cb397eb4dffab84d240367f2e71d8a4263 100644 (file)
@@ -113,6 +113,7 @@ good_area:
                                current->min_flt++;
                        if (fault & VM_FAULT_RETRY) {
                                flags &= ~FAULT_FLAG_ALLOW_RETRY;
+                               flags |= FAULT_FLAG_TRIED;
                                goto retry;
                        }
                }
index 8443daf4f515777ca3cd6d710bef4a92b6373608..6cf0341f978e59ddf235c44e70dcf615799390ed 100644 (file)
@@ -184,6 +184,7 @@ retry:
                        current->min_flt++;
                if (fault & VM_FAULT_RETRY) {
                        flags &= ~FAULT_FLAG_ALLOW_RETRY;
+                       flags |= FAULT_FLAG_TRIED;
 
                         /* No need to up_read(&mm->mmap_sem) as we would
                         * have already released it in __lock_page_or_retry
index aeebbb7b30f0b6ca7348740a6a374ef475066a82..a563727806bf922b5b3315559b9b46b5bbb9d7fc 100644 (file)
@@ -170,6 +170,7 @@ good_area:
                        /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
                         * of starvation. */
                        flags &= ~FAULT_FLAG_ALLOW_RETRY;
+                       flags |= FAULT_FLAG_TRIED;
 
                        /*
                         * No need to up_read(&mm->mmap_sem) as we would
index eb365d6795fa80448fbe4fe391b8b3211c0f4156..714b35a9c4f7b156ac59476debad57426988f849 100644 (file)
@@ -233,6 +233,7 @@ good_area:
                        current->min_flt++;
                if (fault & VM_FAULT_RETRY) {
                        flags &= ~FAULT_FLAG_ALLOW_RETRY;
+                       flags |= FAULT_FLAG_TRIED;
 
                        /*
                         * No need to up_read(&mm->mmap_sem) as we would
index c14f6dfed9958008a60daf1447b9d7013e01aa8e..9f513486af10b829596eb22efcf44bc65e18ee7c 100644 (file)
@@ -171,6 +171,7 @@ good_area:
                }
                if (fault & VM_FAULT_RETRY) {
                        flags &= ~FAULT_FLAG_ALLOW_RETRY;
+                       flags |= FAULT_FLAG_TRIED;
 
                        /*
                         * No need to up_read(&mm->mmap_sem) as we would
index 40f850e9766c78a0d790a040937b2d053b8ac4bd..e2bfafce66c53661064e2cf5e4b0d5d036e2c6a7 100644 (file)
@@ -183,6 +183,7 @@ good_area:
                        tsk->min_flt++;
                if (fault & VM_FAULT_RETRY) {
                        flags &= ~FAULT_FLAG_ALLOW_RETRY;
+                       flags |= FAULT_FLAG_TRIED;
 
                         /* No need to up_read(&mm->mmap_sem) as we would
                         * have already released it in __lock_page_or_retry
index 5495ebe983a23489403be6fc8388e7434a47f769..0a6b28336eb0791354c1dc4439ddddcc4e2b35d7 100644 (file)
@@ -451,6 +451,7 @@ good_area:
                        /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
                         * of starvation. */
                        flags &= ~FAULT_FLAG_ALLOW_RETRY;
+                       flags |= FAULT_FLAG_TRIED;
                        goto retry;
                }
        }
index ac9122ca11529217e3843483042306a7a09a74cb..04ad4001a289e05c89d30b5d6aaad9573b2ca388 100644 (file)
@@ -367,6 +367,7 @@ retry:
                        /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
                         * of starvation. */
                        flags &= ~FAULT_FLAG_ALLOW_RETRY;
+                       flags |= FAULT_FLAG_TRIED;
                        down_read(&mm->mmap_sem);
                        goto retry;
                }
index 3bdc1ad9a341f4418a1724dfcd8cd3ac4388a011..cbbdcad8fcb357cc7fc383820a6f0c7dc1537be9 100644 (file)
@@ -504,6 +504,7 @@ good_area:
                }
                if (fault & VM_FAULT_RETRY) {
                        flags &= ~FAULT_FLAG_ALLOW_RETRY;
+                       flags |= FAULT_FLAG_TRIED;
 
                        /*
                         * No need to up_read(&mm->mmap_sem) as we would
index 77ac917be15295f787977715ea8f63c43bbb1697..e98bfda205a2beb97bcaa49a27d5a9412bf03dc3 100644 (file)
@@ -265,6 +265,7 @@ good_area:
                }
                if (fault & VM_FAULT_RETRY) {
                        flags &= ~FAULT_FLAG_ALLOW_RETRY;
+                       flags |= FAULT_FLAG_TRIED;
 
                        /* No need to up_read(&mm->mmap_sem) as we would
                         * have already released it in __lock_page_or_retry
index 1fe0429b6314257faa40d80b07f7d4e3b77538c6..413d292633046a62d51b342b6de85bc04125affd 100644 (file)
@@ -452,6 +452,7 @@ good_area:
                }
                if (fault & VM_FAULT_RETRY) {
                        flags &= ~FAULT_FLAG_ALLOW_RETRY;
+                       flags |= FAULT_FLAG_TRIED;
 
                        /* No need to up_read(&mm->mmap_sem) as we would
                         * have already released it in __lock_page_or_retry
index 84ce7abbf5afb80c5d82648244349bf7d746a9c0..fe811fa5f1b96f682633e2c54f6be6bbdd525095 100644 (file)
@@ -454,6 +454,7 @@ good_area:
                        tsk->min_flt++;
                if (fault & VM_FAULT_RETRY) {
                        flags &= ~FAULT_FLAG_ALLOW_RETRY;
+                       flags |= FAULT_FLAG_TRIED;
 
                         /*
                          * No need to up_read(&mm->mmap_sem) as we would
index 0353b98ae35a28208c695816bd9b7883ad6fb22e..0f00e9c82080f644030191cb31bc7ae3e0937f49 100644 (file)
@@ -89,6 +89,7 @@ good_area:
                                current->min_flt++;
                        if (fault & VM_FAULT_RETRY) {
                                flags &= ~FAULT_FLAG_ALLOW_RETRY;
+                               flags |= FAULT_FLAG_TRIED;
 
                                goto retry;
                        }
index a530b230e7d7e3d71c5183edf4575c143ed914fe..8e13ecb41bee020a438739bd32eaaf1a5841ee6e 100644 (file)
@@ -1220,6 +1220,7 @@ good_area:
                        /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
                         * of starvation. */
                        flags &= ~FAULT_FLAG_ALLOW_RETRY;
+                       flags |= FAULT_FLAG_TRIED;
                        goto retry;
                }
        }
index 5a74c53bc69c132cfad6231d9294e49f5cedef93..2c2f710ed1dc905a8c9e0509d36cd76ed073e0ce 100644 (file)
@@ -126,6 +126,7 @@ good_area:
                        current->min_flt++;
                if (fault & VM_FAULT_RETRY) {
                        flags &= ~FAULT_FLAG_ALLOW_RETRY;
+                       flags |= FAULT_FLAG_TRIED;
 
                         /* No need to up_read(&mm->mmap_sem) as we would
                         * have already released it in __lock_page_or_retry
index b01e585ab4b538e26b7aba4daca7b57d31c37f59..bcaab4e6fe913ac6e3f2ef0a6c83ea24d8972867 100644 (file)
@@ -161,6 +161,7 @@ extern pgprot_t protection_map[16];
 #define FAULT_FLAG_ALLOW_RETRY 0x08    /* Retry fault if blocking */
 #define FAULT_FLAG_RETRY_NOWAIT        0x10    /* Don't drop mmap_sem and wait when retrying */
 #define FAULT_FLAG_KILLABLE    0x20    /* The fault task is in SIGKILL killable region */
+#define FAULT_FLAG_TRIED       0x40    /* second try */
 
 /*
  * vm_fault is filled by the the pagefault handler and passed to the vma's
index a9827b42556ed5fb3838f78989e193b39837c517..83efee76a5c0b12c577903346eca32f7ca49be18 100644 (file)
@@ -1607,13 +1607,13 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
         * Do we have something in the page cache already?
         */
        page = find_get_page(mapping, offset);
-       if (likely(page)) {
+       if (likely(page) && !(vmf->flags & FAULT_FLAG_TRIED)) {
                /*
                 * We found the page, so try async readahead before
                 * waiting for the lock.
                 */
                do_async_mmap_readahead(vma, ra, file, page, offset);
-       } else {
+       } else if (!page) {
                /* No page in the page cache at all */
                do_sync_mmap_readahead(vma, ra, file, offset);
                count_vm_event(PGMAJFAULT);