summaryrefslogtreecommitdiffstats
path: root/mm/filemap.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/filemap.c')
-rw-r--r--mm/filemap.c66
1 files changed, 44 insertions, 22 deletions
diff --git a/mm/filemap.c b/mm/filemap.c
index 96778faf82d5..645a080ba4df 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -700,10 +700,14 @@ repeat:
if (unlikely(!page))
goto out;
if (radix_tree_exception(page)) {
- if (radix_tree_exceptional_entry(page))
- goto out;
- /* radix_tree_deref_retry(page) */
- goto repeat;
+ if (radix_tree_deref_retry(page))
+ goto repeat;
+ /*
+ * Otherwise, shmem/tmpfs must be storing a swap entry
+ * here as an exceptional entry: so return it without
+ * attempting to raise page count.
+ */
+ goto out;
}
if (!page_cache_get_speculative(page))
goto repeat;
@@ -838,15 +842,21 @@ repeat:
continue;
if (radix_tree_exception(page)) {
- if (radix_tree_exceptional_entry(page))
- continue;
+ if (radix_tree_deref_retry(page)) {
+ /*
+ * Transient condition which can only trigger
+ * when entry at index 0 moves out of or back
+ * to root: none yet gotten, safe to restart.
+ */
+ WARN_ON(start | i);
+ goto restart;
+ }
/*
- * radix_tree_deref_retry(page):
- * can only trigger when entry at index 0 moves out of
- * or back to root: none yet gotten, safe to restart.
+ * Otherwise, shmem/tmpfs must be storing a swap entry
+ * here as an exceptional entry: so skip over it -
+ * we only reach this from invalidate_mapping_pages().
*/
- WARN_ON(start | i);
- goto restart;
+ continue;
}
if (!page_cache_get_speculative(page))
@@ -904,14 +914,20 @@ repeat:
continue;
if (radix_tree_exception(page)) {
- if (radix_tree_exceptional_entry(page))
- break;
+ if (radix_tree_deref_retry(page)) {
+ /*
+ * Transient condition which can only trigger
+ * when entry at index 0 moves out of or back
+ * to root: none yet gotten, safe to restart.
+ */
+ goto restart;
+ }
/*
- * radix_tree_deref_retry(page):
- * can only trigger when entry at index 0 moves out of
- * or back to root: none yet gotten, safe to restart.
+ * Otherwise, shmem/tmpfs must be storing a swap entry
+ * here as an exceptional entry: so stop looking for
+ * contiguous pages.
*/
- goto restart;
+ break;
}
if (!page_cache_get_speculative(page))
@@ -973,13 +989,19 @@ repeat:
continue;
if (radix_tree_exception(page)) {
- BUG_ON(radix_tree_exceptional_entry(page));
+ if (radix_tree_deref_retry(page)) {
+ /*
+ * Transient condition which can only trigger
+ * when entry at index 0 moves out of or back
+ * to root: none yet gotten, safe to restart.
+ */
+ goto restart;
+ }
/*
- * radix_tree_deref_retry(page):
- * can only trigger when entry at index 0 moves out of
- * or back to root: none yet gotten, safe to restart.
+ * This function is never used on a shmem/tmpfs
+ * mapping, so a swap entry won't be found here.
*/
- goto restart;
+ BUG();
}
if (!page_cache_get_speculative(page))