unsigned filemap_get_folios(struct address_space *mapping, pgoff_t *start,
                pgoff_t end, struct folio_batch *fbatch);
+unsigned filemap_get_folios_contig(struct address_space *mapping,
+               pgoff_t *start, pgoff_t end, struct folio_batch *fbatch);
 unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t start,
                               unsigned int nr_pages, struct page **pages);
 unsigned find_get_pages_range_tag(struct address_space *mapping, pgoff_t *index,
 
        return index < folio->index + folio_nr_pages(folio) - 1;
 }
 
+/**
+ * filemap_get_folios_contig - Get a batch of contiguous folios
+ * @mapping:   The address_space to search
+ * @start:     The starting page index
+ * @end:       The final page index (inclusive)
+ * @fbatch:    The batch to fill
+ *
+ * filemap_get_folios_contig() works exactly like filemap_get_folios(),
+ * except the returned folios are guaranteed to be contiguous. This may
+ * not return all contiguous folios if the batch gets filled up.
+ *
+ * Return: The number of folios found.
+ * Also update @start to be positioned for traversal of the next folio.
+ */
+
+unsigned filemap_get_folios_contig(struct address_space *mapping,
+               pgoff_t *start, pgoff_t end, struct folio_batch *fbatch)
+{
+       XA_STATE(xas, &mapping->i_pages, *start);
+       unsigned long nr;
+       struct folio *folio;
+
+       rcu_read_lock();
+
+       for (folio = xas_load(&xas); folio && xas.xa_index <= end;
+                       folio = xas_next(&xas)) {
+               if (xas_retry(&xas, folio))
+                       continue;
+               /*
+                * If the entry has been swapped out, we can stop looking.
+                * No current caller is looking for DAX entries.
+                */
+               if (xa_is_value(folio))
+                       goto update_start;
+
+               if (!folio_try_get_rcu(folio))
+                       goto retry;
+
+               if (unlikely(folio != xas_reload(&xas)))
+                       goto put_folio;
+
+               if (!folio_batch_add(fbatch, folio)) {
+                       nr = folio_nr_pages(folio);
+
+                       if (folio_test_hugetlb(folio))
+                               nr = 1;
+                       *start = folio->index + nr;
+                       goto out;
+               }
+               continue;
+put_folio:
+               folio_put(folio);
+
+retry:
+               xas_reset(&xas);
+       }
+
+update_start:
+       nr = folio_batch_count(fbatch);
+
+       if (nr) {
+               folio = fbatch->folios[nr - 1];
+               if (folio_test_hugetlb(folio))
+                       *start = folio->index + 1;
+               else
+                       *start = folio->index + folio_nr_pages(folio);
+       }
+out:
+       rcu_read_unlock();
+       return folio_batch_count(fbatch);
+}
+EXPORT_SYMBOL(filemap_get_folios_contig);
+
 /**
  * find_get_pages_contig - gang contiguous pagecache lookup
  * @mapping:   The address_space to search