diff options
author | Shaohua Li <shli@kernel.org> | 2012-10-08 19:32:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-09 03:22:47 -0400 |
commit | 45cac65b0fcd287ebb877b141d40ba9bbe8e5da7 (patch) | |
tree | 30ed25c91aaeed153de51a78d171cb14582e383f | |
parent | e79bee24fd6134f90af4228cfebd010136d67631 (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.c | 1 | ||||
-rw-r--r-- | arch/avr32/mm/fault.c | 1 | ||||
-rw-r--r-- | arch/cris/mm/fault.c | 1 | ||||
-rw-r--r-- | arch/hexagon/mm/vm_fault.c | 1 | ||||
-rw-r--r-- | arch/ia64/mm/fault.c | 1 | ||||
-rw-r--r-- | arch/m68k/mm/fault.c | 1 | ||||
-rw-r--r-- | arch/microblaze/mm/fault.c | 1 | ||||
-rw-r--r-- | arch/mips/mm/fault.c | 1 | ||||
-rw-r--r-- | arch/openrisc/mm/fault.c | 1 | ||||
-rw-r--r-- | arch/powerpc/mm/fault.c | 1 | ||||
-rw-r--r-- | arch/s390/mm/fault.c | 1 | ||||
-rw-r--r-- | arch/sh/mm/fault.c | 1 | ||||
-rw-r--r-- | arch/sparc/mm/fault_32.c | 1 | ||||
-rw-r--r-- | arch/sparc/mm/fault_64.c | 1 | ||||
-rw-r--r-- | arch/tile/mm/fault.c | 1 | ||||
-rw-r--r-- | arch/um/kernel/trap.c | 1 | ||||
-rw-r--r-- | arch/x86/mm/fault.c | 1 | ||||
-rw-r--r-- | arch/xtensa/mm/fault.c | 1 | ||||
-rw-r--r-- | include/linux/mm.h | 1 | ||||
-rw-r--r-- | mm/filemap.c | 4 |
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); |