|
@@ -700,10 +700,14 @@ repeat:
|
|
if (unlikely(!page))
|
|
if (unlikely(!page))
|
|
goto out;
|
|
goto out;
|
|
if (radix_tree_exception(page)) {
|
|
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))
|
|
if (!page_cache_get_speculative(page))
|
|
goto repeat;
|
|
goto repeat;
|
|
@@ -838,15 +842,21 @@ repeat:
|
|
continue;
|
|
continue;
|
|
|
|
|
|
if (radix_tree_exception(page)) {
|
|
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))
|
|
if (!page_cache_get_speculative(page))
|
|
@@ -904,14 +914,20 @@ repeat:
|
|
continue;
|
|
continue;
|
|
|
|
|
|
if (radix_tree_exception(page)) {
|
|
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))
|
|
if (!page_cache_get_speculative(page))
|
|
@@ -973,13 +989,19 @@ repeat:
|
|
continue;
|
|
continue;
|
|
|
|
|
|
if (radix_tree_exception(page)) {
|
|
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))
|
|
if (!page_cache_get_speculative(page))
|