diff --git a/include/linux/xarray.h b/include/linux/xarray.h index 074ecc0ef902..6fd3f4f79261 100644 --- a/include/linux/xarray.h +++ b/include/linux/xarray.h @@ -266,7 +266,7 @@ void *___xa_clear_tag(struct xarray *, unsigned long index, xa_tag_t); * we'd get only 3 nodes per 4kB page. */ #define XA_CHUNK_SHIFT 6 -#define XA_CHUNK_SIZE (1 << XA_CHUNK_SHIFT) +#define XA_CHUNK_SIZE (1UL << XA_CHUNK_SHIFT) #define XA_CHUNK_MASK (XA_CHUNK_SIZE - 1) #define XA_MAX_TAGS 3 #define XA_TAG_LONGS (XA_CHUNK_SIZE / BITS_PER_LONG) diff --git a/mm/filemap.c b/mm/filemap.c index 78559818bdfb..d6f9e3b3d6d2 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1329,6 +1329,21 @@ struct page *pagecache_get_page(struct address_space *mapping, pgoff_t offset, } EXPORT_SYMBOL(pagecache_get_page); +static unsigned fill_page_array(struct page **pages, unsigned long *indices, + unsigned i, unsigned max, struct page *page) +{ + unsigned refs = 0; + while (!PageLastTail(page) && i < max) { + if (indices) + indices[i] = indices[i - 1] + 1; + pages[i++] = ++page; + refs++; + } + if (refs) + page_ref_add(compound_head(page), refs); + return i; +} + /** * find_get_entries - bulk pagecache lookup * @mapping: The address_space to search @@ -1368,42 +1383,33 @@ unsigned find_get_entries(struct address_space *mapping, repeat: if (xas_retry(&xas, page)) continue; - if (!xa_is_exceptional(page)) { - if (!page_cache_revalidate(&mapping->pages, &xas, - &page)) { - if (!page) - continue; - goto repeat; - } + if (xa_is_exceptional(page)) { + entries[ret] = page; + page = NULL; + goto next; + } + + if (!page_cache_revalidate(&mapping->pages, &xas, &page)) { + if (!page) + continue; + goto repeat; } -fill: - indices[ret] = xas.xa_index; entries[ret] = find_subpage(page, xas.xa_index); +next: + indices[ret] = xas.xa_index; if (++ret == nr_entries) break; - if (PageTail(++page)) { - xas.xa_index++; - goto fill; - } + if (!page || !PageCompound(page) || PageHuge(page)) + continue; + ret = fill_page_array(entries, indices, ret, nr_entries, page); + if (ret == nr_entries) + break; } rcu_read_unlock(); return ret; } -static unsigned fill_page_array(struct page **pages, unsigned i, unsigned max, - struct page *page) -{ - unsigned refs = 0; - while (!PageLastTail(page) && i < max) { - pages[i++] = ++page; - refs++; - } - if (refs) - page_ref_add(compound_head(page), refs); - return i; -} - /** * find_get_pages - gang pagecache lookup * @mapping: The address_space to search @@ -1449,7 +1455,7 @@ unsigned find_get_pages(struct address_space *mapping, pgoff_t start, break; if (!PageCompound(page) || PageHuge(page)) continue; - ret = fill_page_array(pages, ret, nr_pages, page); + ret = fill_page_array(pages, NULL, ret, nr_pages, page); if (ret == nr_pages) break; } @@ -1499,7 +1505,7 @@ unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t index, break; if (!PageCompound(page) || PageHuge(page)) continue; - ret = fill_page_array(pages, ret, nr_pages, page); + ret = fill_page_array(pages, NULL, ret, nr_pages, page); if (ret == nr_pages) break; } @@ -1548,7 +1554,7 @@ unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index, break; if (!PageCompound(page) || PageHuge(page)) continue; - ret = fill_page_array(pages, ret, nr_pages, page); + ret = fill_page_array(pages, NULL, ret, nr_pages, page); if (ret == nr_pages) break; } @@ -1613,7 +1619,7 @@ unsigned find_get_entries_tag(struct address_space *mapping, pgoff_t start, break; if (!PageCompound(page) || PageHuge(page)) continue; - ret = fill_page_array(entries, ret, nr_entries, page); + ret = fill_page_array(entries, indices, ret, nr_entries, page); if (ret == nr_entries) break; }