mm: clarify the radix_tree exceptional cases
Hugh Dickins [Wed, 3 Aug 2011 23:21:28 +0000 (16:21 -0700)]
Make the radix_tree exceptional cases, mostly in filemap.c, clearer.

It's hard to devise a suitable snappy name that illuminates the use by
shmem/tmpfs for swap, while keeping filemap/pagecache/radix_tree
generality.  And akpm points out that /* radix_tree_deref_retry(page) */
comments look like calls that have been commented out for unknown
reason.

Skirt the naming difficulty by rearranging these blocks to handle the
transient radix_tree_deref_retry(page) case first; then just explain the
remaining shmem/tmpfs swap case in a comment.

Signed-off-by: Hugh Dickins <hughd@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

mm/filemap.c
mm/mincore.c
mm/shmem.c

index 96778fa..645a080 100644 (file)
@@ -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))
index 733f182..636a868 100644 (file)
@@ -72,6 +72,7 @@ static unsigned char mincore_page(struct address_space *mapping, pgoff_t pgoff)
         */
        page = find_get_page(mapping, pgoff);
 #ifdef CONFIG_SWAP
+       /* shmem/tmpfs may return swap: account for swapcache page too. */
        if (radix_tree_exceptional_entry(page)) {
                swp_entry_t swap = radix_to_swp_entry(page);
                page = find_get_page(&swapper_space, swap.val);
index 1c702f6..32f6763 100644 (file)
@@ -332,10 +332,14 @@ repeat:
                if (unlikely(!page))
                        continue;
                if (radix_tree_exception(page)) {
-                       if (radix_tree_exceptional_entry(page))
-                               goto export;
-                       /* radix_tree_deref_retry(page) */
-                       goto restart;
+                       if (radix_tree_deref_retry(page))
+                               goto restart;
+                       /*
+                        * Otherwise, we must be storing a swap entry
+                        * here as an exceptional entry: so return it
+                        * without attempting to raise page count.
+                        */
+                       goto export;
                }
                if (!page_cache_get_speculative(page))
                        goto repeat;