aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShaohua Li <shli@kernel.org>2012-10-08 19:32:19 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-09 03:22:47 -0400
commit45cac65b0fcd287ebb877b141d40ba9bbe8e5da7 (patch)
tree30ed25c91aaeed153de51a78d171cb14582e383f
parente79bee24fd6134f90af4228cfebd010136d67631 (diff)
readahead: fault retry breaks mmap file read random detection
.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>
-rw-r--r--arch/arm/mm/fault.c1
-rw-r--r--arch/avr32/mm/fault.c1
-rw-r--r--arch/cris/mm/fault.c1
-rw-r--r--arch/hexagon/mm/vm_fault.c1
-rw-r--r--arch/ia64/mm/fault.c1
-rw-r--r--arch/m68k/mm/fault.c1
-rw-r--r--arch/microblaze/mm/fault.c1
-rw-r--r--arch/mips/mm/fault.c1
-rw-r--r--arch/openrisc/mm/fault.c1
-rw-r--r--arch/powerpc/mm/fault.c1
-rw-r--r--arch/s390/mm/fault.c1
-rw-r--r--arch/sh/mm/fault.c1
-rw-r--r--arch/sparc/mm/fault_32.c1
-rw-r--r--arch/sparc/mm/fault_64.c1
-rw-r--r--arch/tile/mm/fault.c1
-rw-r--r--arch/um/kernel/trap.c1
-rw-r--r--arch/x86/mm/fault.c1
-rw-r--r--arch/xtensa/mm/fault.c1
-rw-r--r--include/linux/mm.h1
-rw-r--r--mm/filemap.c4
20 files changed, 21 insertions, 2 deletions
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index c3bd83450227..5dbf13f954f6 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -336,6 +336,7 @@ retry:
336 /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk 336 /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
337 * of starvation. */ 337 * of starvation. */
338 flags &= ~FAULT_FLAG_ALLOW_RETRY; 338 flags &= ~FAULT_FLAG_ALLOW_RETRY;
339 flags |= FAULT_FLAG_TRIED;
339 goto retry; 340 goto retry;
340 } 341 }
341 } 342 }
diff --git a/arch/avr32/mm/fault.c b/arch/avr32/mm/fault.c
index b92e60958617..b2f2d2d66849 100644
--- a/arch/avr32/mm/fault.c
+++ b/arch/avr32/mm/fault.c
@@ -152,6 +152,7 @@ good_area:
152 tsk->min_flt++; 152 tsk->min_flt++;
153 if (fault & VM_FAULT_RETRY) { 153 if (fault & VM_FAULT_RETRY) {
154 flags &= ~FAULT_FLAG_ALLOW_RETRY; 154 flags &= ~FAULT_FLAG_ALLOW_RETRY;
155 flags |= FAULT_FLAG_TRIED;
155 156
156 /* 157 /*
157 * No need to up_read(&mm->mmap_sem) as we would have 158 * No need to up_read(&mm->mmap_sem) as we would have
diff --git a/arch/cris/mm/fault.c b/arch/cris/mm/fault.c
index 45fd542cf173..73312ab6c696 100644
--- a/arch/cris/mm/fault.c
+++ b/arch/cris/mm/fault.c
@@ -186,6 +186,7 @@ retry:
186 tsk->min_flt++; 186 tsk->min_flt++;
187 if (fault & VM_FAULT_RETRY) { 187 if (fault & VM_FAULT_RETRY) {
188 flags &= ~FAULT_FLAG_ALLOW_RETRY; 188 flags &= ~FAULT_FLAG_ALLOW_RETRY;
189 flags |= FAULT_FLAG_TRIED;
189 190
190 /* 191 /*
191 * No need to up_read(&mm->mmap_sem) as we would 192 * No need to up_read(&mm->mmap_sem) as we would
diff --git a/arch/hexagon/mm/vm_fault.c b/arch/hexagon/mm/vm_fault.c
index 06695cc4fe58..513b74cb397e 100644
--- a/arch/hexagon/mm/vm_fault.c
+++ b/arch/hexagon/mm/vm_fault.c
@@ -113,6 +113,7 @@ good_area:
113 current->min_flt++; 113 current->min_flt++;
114 if (fault & VM_FAULT_RETRY) { 114 if (fault & VM_FAULT_RETRY) {
115 flags &= ~FAULT_FLAG_ALLOW_RETRY; 115 flags &= ~FAULT_FLAG_ALLOW_RETRY;
116 flags |= FAULT_FLAG_TRIED;
116 goto retry; 117 goto retry;
117 } 118 }
118 } 119 }
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
index 8443daf4f515..6cf0341f978e 100644
--- a/arch/ia64/mm/fault.c
+++ b/arch/ia64/mm/fault.c
@@ -184,6 +184,7 @@ retry:
184 current->min_flt++; 184 current->min_flt++;
185 if (fault & VM_FAULT_RETRY) { 185 if (fault & VM_FAULT_RETRY) {
186 flags &= ~FAULT_FLAG_ALLOW_RETRY; 186 flags &= ~FAULT_FLAG_ALLOW_RETRY;
187 flags |= FAULT_FLAG_TRIED;
187 188
188 /* No need to up_read(&mm->mmap_sem) as we would 189 /* No need to up_read(&mm->mmap_sem) as we would
189 * have already released it in __lock_page_or_retry 190 * have already released it in __lock_page_or_retry
diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c
index aeebbb7b30f0..a563727806bf 100644
--- a/arch/m68k/mm/fault.c
+++ b/arch/m68k/mm/fault.c
@@ -170,6 +170,7 @@ good_area:
170 /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk 170 /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
171 * of starvation. */ 171 * of starvation. */
172 flags &= ~FAULT_FLAG_ALLOW_RETRY; 172 flags &= ~FAULT_FLAG_ALLOW_RETRY;
173 flags |= FAULT_FLAG_TRIED;
173 174
174 /* 175 /*
175 * No need to up_read(&mm->mmap_sem) as we would 176 * No need to up_read(&mm->mmap_sem) as we would
diff --git a/arch/microblaze/mm/fault.c b/arch/microblaze/mm/fault.c
index eb365d6795fa..714b35a9c4f7 100644
--- a/arch/microblaze/mm/fault.c
+++ b/arch/microblaze/mm/fault.c
@@ -233,6 +233,7 @@ good_area:
233 current->min_flt++; 233 current->min_flt++;
234 if (fault & VM_FAULT_RETRY) { 234 if (fault & VM_FAULT_RETRY) {
235 flags &= ~FAULT_FLAG_ALLOW_RETRY; 235 flags &= ~FAULT_FLAG_ALLOW_RETRY;
236 flags |= FAULT_FLAG_TRIED;
236 237
237 /* 238 /*
238 * No need to up_read(&mm->mmap_sem) as we would 239 * No need to up_read(&mm->mmap_sem) as we would
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
index c14f6dfed995..9f513486af10 100644
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -171,6 +171,7 @@ good_area:
171 } 171 }
172 if (fault & VM_FAULT_RETRY) { 172 if (fault & VM_FAULT_RETRY) {
173 flags &= ~FAULT_FLAG_ALLOW_RETRY; 173 flags &= ~FAULT_FLAG_ALLOW_RETRY;
174 flags |= FAULT_FLAG_TRIED;
174 175
175 /* 176 /*
176 * No need to up_read(&mm->mmap_sem) as we would 177 * No need to up_read(&mm->mmap_sem) as we would
diff --git a/arch/openrisc/mm/fault.c b/arch/openrisc/mm/fault.c
index 40f850e9766c..e2bfafce66c5 100644
--- a/arch/openrisc/mm/fault.c
+++ b/arch/openrisc/mm/fault.c
@@ -183,6 +183,7 @@ good_area:
183 tsk->min_flt++; 183 tsk->min_flt++;
184 if (fault & VM_FAULT_RETRY) { 184 if (fault & VM_FAULT_RETRY) {
185 flags &= ~FAULT_FLAG_ALLOW_RETRY; 185 flags &= ~FAULT_FLAG_ALLOW_RETRY;
186 flags |= FAULT_FLAG_TRIED;
186 187
187 /* No need to up_read(&mm->mmap_sem) as we would 188 /* No need to up_read(&mm->mmap_sem) as we would
188 * have already released it in __lock_page_or_retry 189 * have already released it in __lock_page_or_retry
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 5495ebe983a2..0a6b28336eb0 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -451,6 +451,7 @@ good_area:
451 /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk 451 /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
452 * of starvation. */ 452 * of starvation. */
453 flags &= ~FAULT_FLAG_ALLOW_RETRY; 453 flags &= ~FAULT_FLAG_ALLOW_RETRY;
454 flags |= FAULT_FLAG_TRIED;
454 goto retry; 455 goto retry;
455 } 456 }
456 } 457 }
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index ac9122ca1152..04ad4001a289 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -367,6 +367,7 @@ retry:
367 /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk 367 /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
368 * of starvation. */ 368 * of starvation. */
369 flags &= ~FAULT_FLAG_ALLOW_RETRY; 369 flags &= ~FAULT_FLAG_ALLOW_RETRY;
370 flags |= FAULT_FLAG_TRIED;
370 down_read(&mm->mmap_sem); 371 down_read(&mm->mmap_sem);
371 goto retry; 372 goto retry;
372 } 373 }
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
index 3bdc1ad9a341..cbbdcad8fcb3 100644
--- a/arch/sh/mm/fault.c
+++ b/arch/sh/mm/fault.c
@@ -504,6 +504,7 @@ good_area:
504 } 504 }
505 if (fault & VM_FAULT_RETRY) { 505 if (fault & VM_FAULT_RETRY) {
506 flags &= ~FAULT_FLAG_ALLOW_RETRY; 506 flags &= ~FAULT_FLAG_ALLOW_RETRY;
507 flags |= FAULT_FLAG_TRIED;
507 508
508 /* 509 /*
509 * No need to up_read(&mm->mmap_sem) as we would 510 * No need to up_read(&mm->mmap_sem) as we would
diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c
index 77ac917be152..e98bfda205a2 100644
--- a/arch/sparc/mm/fault_32.c
+++ b/arch/sparc/mm/fault_32.c
@@ -265,6 +265,7 @@ good_area:
265 } 265 }
266 if (fault & VM_FAULT_RETRY) { 266 if (fault & VM_FAULT_RETRY) {
267 flags &= ~FAULT_FLAG_ALLOW_RETRY; 267 flags &= ~FAULT_FLAG_ALLOW_RETRY;
268 flags |= FAULT_FLAG_TRIED;
268 269
269 /* No need to up_read(&mm->mmap_sem) as we would 270 /* No need to up_read(&mm->mmap_sem) as we would
270 * have already released it in __lock_page_or_retry 271 * have already released it in __lock_page_or_retry
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c
index 1fe0429b6314..413d29263304 100644
--- a/arch/sparc/mm/fault_64.c
+++ b/arch/sparc/mm/fault_64.c
@@ -452,6 +452,7 @@ good_area:
452 } 452 }
453 if (fault & VM_FAULT_RETRY) { 453 if (fault & VM_FAULT_RETRY) {
454 flags &= ~FAULT_FLAG_ALLOW_RETRY; 454 flags &= ~FAULT_FLAG_ALLOW_RETRY;
455 flags |= FAULT_FLAG_TRIED;
455 456
456 /* No need to up_read(&mm->mmap_sem) as we would 457 /* No need to up_read(&mm->mmap_sem) as we would
457 * have already released it in __lock_page_or_retry 458 * have already released it in __lock_page_or_retry
diff --git a/arch/tile/mm/fault.c b/arch/tile/mm/fault.c
index 84ce7abbf5af..fe811fa5f1b9 100644
--- a/arch/tile/mm/fault.c
+++ b/arch/tile/mm/fault.c
@@ -454,6 +454,7 @@ good_area:
454 tsk->min_flt++; 454 tsk->min_flt++;
455 if (fault & VM_FAULT_RETRY) { 455 if (fault & VM_FAULT_RETRY) {
456 flags &= ~FAULT_FLAG_ALLOW_RETRY; 456 flags &= ~FAULT_FLAG_ALLOW_RETRY;
457 flags |= FAULT_FLAG_TRIED;
457 458
458 /* 459 /*
459 * No need to up_read(&mm->mmap_sem) as we would 460 * No need to up_read(&mm->mmap_sem) as we would
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index 0353b98ae35a..0f00e9c82080 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -89,6 +89,7 @@ good_area:
89 current->min_flt++; 89 current->min_flt++;
90 if (fault & VM_FAULT_RETRY) { 90 if (fault & VM_FAULT_RETRY) {
91 flags &= ~FAULT_FLAG_ALLOW_RETRY; 91 flags &= ~FAULT_FLAG_ALLOW_RETRY;
92 flags |= FAULT_FLAG_TRIED;
92 93
93 goto retry; 94 goto retry;
94 } 95 }
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index a530b230e7d7..8e13ecb41bee 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -1220,6 +1220,7 @@ good_area:
1220 /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk 1220 /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
1221 * of starvation. */ 1221 * of starvation. */
1222 flags &= ~FAULT_FLAG_ALLOW_RETRY; 1222 flags &= ~FAULT_FLAG_ALLOW_RETRY;
1223 flags |= FAULT_FLAG_TRIED;
1223 goto retry; 1224 goto retry;
1224 } 1225 }
1225 } 1226 }
diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c
index 5a74c53bc69c..2c2f710ed1dc 100644
--- a/arch/xtensa/mm/fault.c
+++ b/arch/xtensa/mm/fault.c
@@ -126,6 +126,7 @@ good_area:
126 current->min_flt++; 126 current->min_flt++;
127 if (fault & VM_FAULT_RETRY) { 127 if (fault & VM_FAULT_RETRY) {
128 flags &= ~FAULT_FLAG_ALLOW_RETRY; 128 flags &= ~FAULT_FLAG_ALLOW_RETRY;
129 flags |= FAULT_FLAG_TRIED;
129 130
130 /* No need to up_read(&mm->mmap_sem) as we would 131 /* No need to up_read(&mm->mmap_sem) as we would
131 * have already released it in __lock_page_or_retry 132 * have already released it in __lock_page_or_retry
diff --git a/include/linux/mm.h b/include/linux/mm.h
index b01e585ab4b5..bcaab4e6fe91 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -161,6 +161,7 @@ extern pgprot_t protection_map[16];
161#define FAULT_FLAG_ALLOW_RETRY 0x08 /* Retry fault if blocking */ 161#define FAULT_FLAG_ALLOW_RETRY 0x08 /* Retry fault if blocking */
162#define FAULT_FLAG_RETRY_NOWAIT 0x10 /* Don't drop mmap_sem and wait when retrying */ 162#define FAULT_FLAG_RETRY_NOWAIT 0x10 /* Don't drop mmap_sem and wait when retrying */
163#define FAULT_FLAG_KILLABLE 0x20 /* The fault task is in SIGKILL killable region */ 163#define FAULT_FLAG_KILLABLE 0x20 /* The fault task is in SIGKILL killable region */
164#define FAULT_FLAG_TRIED 0x40 /* second try */
164 165
165/* 166/*
166 * vm_fault is filled by the the pagefault handler and passed to the vma's 167 * vm_fault is filled by the the pagefault handler and passed to the vma's
diff --git a/mm/filemap.c b/mm/filemap.c
index a9827b42556e..83efee76a5c0 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1607,13 +1607,13 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
1607 * Do we have something in the page cache already? 1607 * Do we have something in the page cache already?
1608 */ 1608 */
1609 page = find_get_page(mapping, offset); 1609 page = find_get_page(mapping, offset);
1610 if (likely(page)) { 1610 if (likely(page) && !(vmf->flags & FAULT_FLAG_TRIED)) {
1611 /* 1611 /*
1612 * We found the page, so try async readahead before 1612 * We found the page, so try async readahead before
1613 * waiting for the lock. 1613 * waiting for the lock.
1614 */ 1614 */
1615 do_async_mmap_readahead(vma, ra, file, page, offset); 1615 do_async_mmap_readahead(vma, ra, file, page, offset);
1616 } else { 1616 } else if (!page) {
1617 /* No page in the page cache at all */ 1617 /* No page in the page cache at all */
1618 do_sync_mmap_readahead(vma, ra, file, offset); 1618 do_sync_mmap_readahead(vma, ra, file, offset);
1619 count_vm_event(PGMAJFAULT); 1619 count_vm_event(PGMAJFAULT);