mm: implement find_get_pages_range_tag()
[sfrench/cifs-2.6.git] / mm / filemap.c
index 594d73fef8b43bae852f4f7ace1e8cfc46b23690..cf74d0dacc6a93b1b7ae7dcdbd8e6070821d0c62 100644 (file)
@@ -1754,9 +1754,10 @@ repeat:
 EXPORT_SYMBOL(find_get_pages_contig);
 
 /**
- * find_get_pages_tag - find and return pages that match @tag
+ * find_get_pages_range_tag - find and return pages in given range matching @tag
  * @mapping:   the address_space to search
  * @index:     the starting page index
+ * @end:       The final page index (inclusive)
  * @tag:       the tag index
  * @nr_pages:  the maximum number of pages
  * @pages:     where the resulting pages are placed
@@ -1764,8 +1765,9 @@ EXPORT_SYMBOL(find_get_pages_contig);
  * Like find_get_pages, except we only return pages which are tagged with
  * @tag.   We update @index to index the next page for the traversal.
  */
-unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index,
-                       int tag, unsigned int nr_pages, struct page **pages)
+unsigned find_get_pages_range_tag(struct address_space *mapping, pgoff_t *index,
+                       pgoff_t end, int tag, unsigned int nr_pages,
+                       struct page **pages)
 {
        struct radix_tree_iter iter;
        void **slot;
@@ -1778,6 +1780,9 @@ unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index,
        radix_tree_for_each_tagged(slot, &mapping->page_tree,
                                   &iter, *index, tag) {
                struct page *head, *page;
+
+               if (iter.index > end)
+                       break;
 repeat:
                page = radix_tree_deref_slot(slot);
                if (unlikely(!page))
@@ -1819,18 +1824,28 @@ repeat:
                }
 
                pages[ret] = page;
-               if (++ret == nr_pages)
-                       break;
+               if (++ret == nr_pages) {
+                       *index = pages[ret - 1]->index + 1;
+                       goto out;
+               }
        }
 
+       /*
+        * We come here when we got at @end. We take care to not overflow the
+        * index @index as it confuses some of the callers. This breaks the
+        * iteration when there is page at index -1 but that is already broken
+        * anyway.
+        */
+       if (end == (pgoff_t)-1)
+               *index = (pgoff_t)-1;
+       else
+               *index = end + 1;
+out:
        rcu_read_unlock();
 
-       if (ret)
-               *index = pages[ret - 1]->index + 1;
-
        return ret;
 }
-EXPORT_SYMBOL(find_get_pages_tag);
+EXPORT_SYMBOL(find_get_pages_range_tag);
 
 /**
  * find_get_entries_tag - find and return entries that match @tag