Linux 3.1-rc7
[pandora-kernel.git] / mm / filemap.c
index 96778fa..7771871 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;
@@ -823,13 +827,14 @@ unsigned find_get_pages(struct address_space *mapping, pgoff_t start,
 {
        unsigned int i;
        unsigned int ret;
-       unsigned int nr_found;
+       unsigned int nr_found, nr_skip;
 
        rcu_read_lock();
 restart:
        nr_found = radix_tree_gang_lookup_slot(&mapping->page_tree,
                                (void ***)pages, NULL, start, nr_pages);
        ret = 0;
+       nr_skip = 0;
        for (i = 0; i < nr_found; i++) {
                struct page *page;
 repeat:
@@ -838,15 +843,22 @@ 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;
+                       nr_skip++;
+                       continue;
                }
 
                if (!page_cache_get_speculative(page))
@@ -866,7 +878,7 @@ repeat:
         * If all entries were removed before we could secure them,
         * try again, because callers stop trying once 0 is returned.
         */
-       if (unlikely(!ret && nr_found))
+       if (unlikely(!ret && nr_found > nr_skip))
                goto restart;
        rcu_read_unlock();
        return ret;
@@ -904,14 +916,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 +991,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))