aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mm/filemap.c66
-rw-r--r--mm/mincore.c1
-rw-r--r--mm/shmem.c12
3 files changed, 53 insertions, 26 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:
700 if (unlikely(!page)) 700 if (unlikely(!page))
701 goto out; 701 goto out;
702 if (radix_tree_exception(page)) { 702 if (radix_tree_exception(page)) {
703 if (radix_tree_exceptional_entry(page)) 703 if (radix_tree_deref_retry(page))
704 goto out; 704 goto repeat;
705 /* radix_tree_deref_retry(page) */ 705 /*
706 goto repeat; 706 * Otherwise, shmem/tmpfs must be storing a swap entry
707 * here as an exceptional entry: so return it without
708 * attempting to raise page count.
709 */
710 goto out;
707 } 711 }
708 if (!page_cache_get_speculative(page)) 712 if (!page_cache_get_speculative(page))
709 goto repeat; 713 goto repeat;
@@ -838,15 +842,21 @@ repeat:
838 continue; 842 continue;
839 843
840 if (radix_tree_exception(page)) { 844 if (radix_tree_exception(page)) {
841 if (radix_tree_exceptional_entry(page)) 845 if (radix_tree_deref_retry(page)) {
842 continue; 846 /*
847 * Transient condition which can only trigger
848 * when entry at index 0 moves out of or back
849 * to root: none yet gotten, safe to restart.
850 */
851 WARN_ON(start | i);
852 goto restart;
853 }
843 /* 854 /*
844 * radix_tree_deref_retry(page): 855 * Otherwise, shmem/tmpfs must be storing a swap entry
845 * can only trigger when entry at index 0 moves out of 856 * here as an exceptional entry: so skip over it -
846 * or back to root: none yet gotten, safe to restart. 857 * we only reach this from invalidate_mapping_pages().
847 */ 858 */
848 WARN_ON(start | i); 859 continue;
849 goto restart;
850 } 860 }
851 861
852 if (!page_cache_get_speculative(page)) 862 if (!page_cache_get_speculative(page))
@@ -904,14 +914,20 @@ repeat:
904 continue; 914 continue;
905 915
906 if (radix_tree_exception(page)) { 916 if (radix_tree_exception(page)) {
907 if (radix_tree_exceptional_entry(page)) 917 if (radix_tree_deref_retry(page)) {
908 break; 918 /*
919 * Transient condition which can only trigger
920 * when entry at index 0 moves out of or back
921 * to root: none yet gotten, safe to restart.
922 */
923 goto restart;
924 }
909 /* 925 /*
910 * radix_tree_deref_retry(page): 926 * Otherwise, shmem/tmpfs must be storing a swap entry
911 * can only trigger when entry at index 0 moves out of 927 * here as an exceptional entry: so stop looking for
912 * or back to root: none yet gotten, safe to restart. 928 * contiguous pages.
913 */ 929 */
914 goto restart; 930 break;
915 } 931 }
916 932
917 if (!page_cache_get_speculative(page)) 933 if (!page_cache_get_speculative(page))
@@ -973,13 +989,19 @@ repeat:
973 continue; 989 continue;
974 990
975 if (radix_tree_exception(page)) { 991 if (radix_tree_exception(page)) {
976 BUG_ON(radix_tree_exceptional_entry(page)); 992 if (radix_tree_deref_retry(page)) {
993 /*
994 * Transient condition which can only trigger
995 * when entry at index 0 moves out of or back
996 * to root: none yet gotten, safe to restart.
997 */
998 goto restart;
999 }
977 /* 1000 /*
978 * radix_tree_deref_retry(page): 1001 * This function is never used on a shmem/tmpfs
979 * can only trigger when entry at index 0 moves out of 1002 * mapping, so a swap entry won't be found here.
980 * or back to root: none yet gotten, safe to restart.
981 */ 1003 */
982 goto restart; 1004 BUG();
983 } 1005 }
984 1006
985 if (!page_cache_get_speculative(page)) 1007 if (!page_cache_get_speculative(page))
diff --git a/mm/mincore.c b/mm/mincore.c
index 733f1829b0dc..636a86876ff2 100644
--- a/mm/mincore.c
+++ b/mm/mincore.c
@@ -72,6 +72,7 @@ static unsigned char mincore_page(struct address_space *mapping, pgoff_t pgoff)
72 */ 72 */
73 page = find_get_page(mapping, pgoff); 73 page = find_get_page(mapping, pgoff);
74#ifdef CONFIG_SWAP 74#ifdef CONFIG_SWAP
75 /* shmem/tmpfs may return swap: account for swapcache page too. */
75 if (radix_tree_exceptional_entry(page)) { 76 if (radix_tree_exceptional_entry(page)) {
76 swp_entry_t swap = radix_to_swp_entry(page); 77 swp_entry_t swap = radix_to_swp_entry(page);
77 page = find_get_page(&swapper_space, swap.val); 78 page = find_get_page(&swapper_space, swap.val);
diff --git a/mm/shmem.c b/mm/shmem.c
index 1c702f6f1241..32f6763f16fb 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -332,10 +332,14 @@ repeat:
332 if (unlikely(!page)) 332 if (unlikely(!page))
333 continue; 333 continue;
334 if (radix_tree_exception(page)) { 334 if (radix_tree_exception(page)) {
335 if (radix_tree_exceptional_entry(page)) 335 if (radix_tree_deref_retry(page))
336 goto export; 336 goto restart;
337 /* radix_tree_deref_retry(page) */ 337 /*
338 goto restart; 338 * Otherwise, we must be storing a swap entry
339 * here as an exceptional entry: so return it
340 * without attempting to raise page count.
341 */
342 goto export;
339 } 343 }
340 if (!page_cache_get_speculative(page)) 344 if (!page_cache_get_speculative(page))
341 goto repeat; 345 goto repeat;