diff options
-rw-r--r-- | mm/filemap.c | 66 | ||||
-rw-r--r-- | mm/mincore.c | 1 | ||||
-rw-r--r-- | mm/shmem.c | 12 |
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; |