History

mm: Convert find_lock_entries() to use a folio_batch

find_lock_entries() already only returned the head page of folios, so convert it to return a folio_batch instead of a pagevec. That cascades through converting truncate_inode_pages_range() to delete_from_page_cache_batch() and page_cache_delete_batch().

Matthew Wilcox (Oracle) committed 4 years ago

Commit 51dcbda1 parent 0e499ed6 files · +69 −80Browse files

Unified · Split

6 files
  1. fs/f2fs/f2fs.h +2 −0
  2. include/linux/pagemap.h +2 −2
  3. mm/filemap.c +29 −31
  4. mm/internal.h +1 −1
  5. mm/shmem.c +6 −8
  6. mm/truncate.c +29 −38
fs/f2fs/f2fs.h+2−0
@@ -28,6 +28,8 @@ · 27 unmodified lines
28#include <linux/fscrypt.h>28#include <linux/fscrypt.h>
29#include <linux/fsverity.h>29#include <linux/fsverity.h>
30 30
31struct pagevec;
32
31#ifdef CONFIG_F2FS_CHECK_FS33#ifdef CONFIG_F2FS_CHECK_FS
32#define f2fs_bug_on(sbi, condition) BUG_ON(condition)34#define f2fs_bug_on(sbi, condition) BUG_ON(condition)
33#else35#else
include/linux/pagemap.h+2−2
@@ -16,7 +16,7 @@ · 15 unmodified lines
16#include <linux/hardirq.h> /* for in_interrupt() */16#include <linux/hardirq.h> /* for in_interrupt() */
17#include <linux/hugetlb_inline.h>17#include <linux/hugetlb_inline.h>
18 18
19struct pagevec;19struct folio_batch;
20 20
21static inline bool mapping_empty(struct address_space *mapping)21static inline bool mapping_empty(struct address_space *mapping)
22{22{
@@ -936,7 +936,7 @@ static inline void __delete_from_page_cache(struct page *page, void *shadow) · 913 unmodified lines
936}936}
937void replace_page_cache_page(struct page *old, struct page *new);937void replace_page_cache_page(struct page *old, struct page *new);
938void delete_from_page_cache_batch(struct address_space *mapping,938void delete_from_page_cache_batch(struct address_space *mapping,
939 struct pagevec *pvec);939 struct folio_batch *fbatch);
940int try_to_release_page(struct page *page, gfp_t gfp);940int try_to_release_page(struct page *page, gfp_t gfp);
941bool filemap_release_folio(struct folio *folio, gfp_t gfp);941bool filemap_release_folio(struct folio *folio, gfp_t gfp);
942loff_t mapping_seek_hole_data(struct address_space *, loff_t start, loff_t end,942loff_t mapping_seek_hole_data(struct address_space *, loff_t start, loff_t end,
mm/filemap.c+29−31
@@ -270,30 +270,29 @@ void filemap_remove_folio(struct folio *folio) · 269 unmodified lines
270}270}
271 271
272/*272/*
273 * page_cache_delete_batch - delete several pages from page cache273 * page_cache_delete_batch - delete several folios from page cache
274 * @mapping: the mapping to which pages belong274 * @mapping: the mapping to which folios belong
275 * @pvec: pagevec with pages to delete275 * @fbatch: batch of folios to delete
276 *276 *
277 * The function walks over mapping->i_pages and removes pages passed in @pvec277 * The function walks over mapping->i_pages and removes folios passed in
278 * from the mapping. The function expects @pvec to be sorted by page index278 * @fbatch from the mapping. The function expects @fbatch to be sorted
279 * and is optimised for it to be dense.279 * by page index and is optimised for it to be dense.
280 * It tolerates holes in @pvec (mapping entries at those indices are not280 * It tolerates holes in @fbatch (mapping entries at those indices are not
281 * modified). The function expects only THP head pages to be present in the281 * modified).
282 * @pvec.
283 *282 *
284 * The function expects the i_pages lock to be held.283 * The function expects the i_pages lock to be held.
285 */284 */
286static void page_cache_delete_batch(struct address_space *mapping,285static void page_cache_delete_batch(struct address_space *mapping,
287 struct pagevec *pvec)286 struct folio_batch *fbatch)
288{287{
289 XA_STATE(xas, &mapping->i_pages, pvec->pages[0]->index);288 XA_STATE(xas, &mapping->i_pages, fbatch->folios[0]->index);
290 int total_pages = 0;289 int total_pages = 0;
291 int i = 0;290 int i = 0;
292 struct folio *folio;291 struct folio *folio;
293 292
294 mapping_set_update(&xas, mapping);293 mapping_set_update(&xas, mapping);
295 xas_for_each(&xas, folio, ULONG_MAX) {294 xas_for_each(&xas, folio, ULONG_MAX) {
296 if (i >= pagevec_count(pvec))295 if (i >= folio_batch_count(fbatch))
297 break;296 break;
298 297
299 /* A swap/dax/shadow entry got inserted? Skip it. */298 /* A swap/dax/shadow entry got inserted? Skip it. */
@@ -306,9 +305,9 @@ static void page_cache_delete_batch(struct address_space *mapping, · 6 unmodified lines
306 * means our page has been removed, which shouldn't be305 * means our page has been removed, which shouldn't be
307 * possible because we're holding the PageLock.306 * possible because we're holding the PageLock.
308 */307 */
309 if (&folio->page != pvec->pages[i]) {308 if (folio != fbatch->folios[i]) {
310 VM_BUG_ON_FOLIO(folio->index >309 VM_BUG_ON_FOLIO(folio->index >
311 pvec->pages[i]->index, folio);310 fbatch->folios[i]->index, folio);
312 continue;311 continue;
313 }312 }
314 313
@@ -316,12 +315,11 @@ static void page_cache_delete_batch(struct address_space *mapping, · 1 unmodified line
316 315
317 if (folio->index == xas.xa_index)316 if (folio->index == xas.xa_index)
318 folio->mapping = NULL;317 folio->mapping = NULL;
319 /* Leave page->index set: truncation lookup relies on it */318 /* Leave folio->index set: truncation lookup relies on it */
320 319
321 /*320 /*
322 * Move to the next page in the vector if this is a regular321 * Move to the next folio in the batch if this is a regular
323 * page or the index is of the last sub-page of this compound322 * folio or the index is of the last sub-page of this folio.
324 * page.
325 */323 */
326 if (folio->index + folio_nr_pages(folio) - 1 == xas.xa_index)324 if (folio->index + folio_nr_pages(folio) - 1 == xas.xa_index)
327 i++;325 i++;
@@ -332,29 +330,29 @@ static void page_cache_delete_batch(struct address_space *mapping, · 4 unmodified lines
332}330}
333 331
334void delete_from_page_cache_batch(struct address_space *mapping,332void delete_from_page_cache_batch(struct address_space *mapping,
335 struct pagevec *pvec)333 struct folio_batch *fbatch)
336{334{
337 int i;335 int i;
338 336
339 if (!pagevec_count(pvec))337 if (!folio_batch_count(fbatch))
340 return;338 return;
341 339
342 spin_lock(&mapping->host->i_lock);340 spin_lock(&mapping->host->i_lock);
343 xa_lock_irq(&mapping->i_pages);341 xa_lock_irq(&mapping->i_pages);
344 for (i = 0; i < pagevec_count(pvec); i++) {342 for (i = 0; i < folio_batch_count(fbatch); i++) {
345 struct folio *folio = page_folio(pvec->pages[i]);343 struct folio *folio = fbatch->folios[i];
346 344
347 trace_mm_filemap_delete_from_page_cache(folio);345 trace_mm_filemap_delete_from_page_cache(folio);
348 filemap_unaccount_folio(mapping, folio);346 filemap_unaccount_folio(mapping, folio);
349 }347 }
350 page_cache_delete_batch(mapping, pvec);348 page_cache_delete_batch(mapping, fbatch);
351 xa_unlock_irq(&mapping->i_pages);349 xa_unlock_irq(&mapping->i_pages);
352 if (mapping_shrinkable(mapping))350 if (mapping_shrinkable(mapping))
353 inode_add_lru(mapping->host);351 inode_add_lru(mapping->host);
354 spin_unlock(&mapping->host->i_lock);352 spin_unlock(&mapping->host->i_lock);
355 353
356 for (i = 0; i < pagevec_count(pvec); i++)354 for (i = 0; i < folio_batch_count(fbatch); i++)
357 filemap_free_folio(mapping, page_folio(pvec->pages[i]));355 filemap_free_folio(mapping, fbatch->folios[i]);
358}356}
359 357
360int filemap_check_errors(struct address_space *mapping)358int filemap_check_errors(struct address_space *mapping)
@@ -2052,8 +2050,8 @@ unsigned find_get_entries(struct address_space *mapping, pgoff_t start, · 1691 unmodified lines
2052 * @mapping: The address_space to search.2050 * @mapping: The address_space to search.
2053 * @start: The starting page cache index.2051 * @start: The starting page cache index.
2054 * @end: The final page index (inclusive).2052 * @end: The final page index (inclusive).
2055 * @pvec: Where the resulting entries are placed.2053 * @fbatch: Where the resulting entries are placed.
2056 * @indices: The cache indices of the entries in @pvec.2054 * @indices: The cache indices of the entries in @fbatch.
2057 *2055 *
2058 * find_lock_entries() will return a batch of entries from @mapping.2056 * find_lock_entries() will return a batch of entries from @mapping.
2059 * Swap, shadow and DAX entries are included. Folios are returned2057 * Swap, shadow and DAX entries are included. Folios are returned
@@ -2068,7 +2066,7 @@ unsigned find_get_entries(struct address_space *mapping, pgoff_t start, · 8 unmodified lines
2068 * Return: The number of entries which were found.2066 * Return: The number of entries which were found.
2069 */2067 */
2070unsigned find_lock_entries(struct address_space *mapping, pgoff_t start,2068unsigned find_lock_entries(struct address_space *mapping, pgoff_t start,
2071 pgoff_t end, struct pagevec *pvec, pgoff_t *indices)2069 pgoff_t end, struct folio_batch *fbatch, pgoff_t *indices)
2072{2070{
2073 XA_STATE(xas, &mapping->i_pages, start);2071 XA_STATE(xas, &mapping->i_pages, start);
2074 struct folio *folio;2072 struct folio *folio;
@@ -2088,8 +2086,8 @@ unsigned find_lock_entries(struct address_space *mapping, pgoff_t start, · 13 unmodified lines
2088 VM_BUG_ON_FOLIO(!folio_contains(folio, xas.xa_index),2086 VM_BUG_ON_FOLIO(!folio_contains(folio, xas.xa_index),
2089 folio);2087 folio);
2090 }2088 }
2091 indices[pvec->nr] = xas.xa_index;2089 indices[fbatch->nr] = xas.xa_index;
2092 if (!pagevec_add(pvec, &folio->page))2090 if (!folio_batch_add(fbatch, folio))
2093 break;2091 break;
2094 goto next;2092 goto next;
2095unlock:2093unlock:
@@ -2106,7 +2104,7 @@ next: · 10 unmodified lines
2106 }2104 }
2107 rcu_read_unlock();2105 rcu_read_unlock();
2108 2106
2109 return pagevec_count(pvec);2107 return folio_batch_count(fbatch);
2110}2108}
2111 2109
2112/**2110/**
mm/internal.h+1−1
@@ -93,7 +93,7 @@ static inline void force_page_cache_readahead(struct address_space *mapping, · 92 unmodified lines
93}93}
94 94
95unsigned find_lock_entries(struct address_space *mapping, pgoff_t start,95unsigned find_lock_entries(struct address_space *mapping, pgoff_t start,
96 pgoff_t end, struct pagevec *pvec, pgoff_t *indices);96 pgoff_t end, struct folio_batch *fbatch, pgoff_t *indices);
97unsigned find_get_entries(struct address_space *mapping, pgoff_t start,97unsigned find_get_entries(struct address_space *mapping, pgoff_t start,
98 pgoff_t end, struct folio_batch *fbatch, pgoff_t *indices);98 pgoff_t end, struct folio_batch *fbatch, pgoff_t *indices);
99void filemap_free_folio(struct address_space *mapping, struct folio *folio);99void filemap_free_folio(struct address_space *mapping, struct folio *folio);
mm/shmem.c+6−8
@@ -919,7 +919,6 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend, · 918 unmodified lines
919 pgoff_t end = (lend + 1) >> PAGE_SHIFT;919 pgoff_t end = (lend + 1) >> PAGE_SHIFT;
920 unsigned int partial_start = lstart & (PAGE_SIZE - 1);920 unsigned int partial_start = lstart & (PAGE_SIZE - 1);
921 unsigned int partial_end = (lend + 1) & (PAGE_SIZE - 1);921 unsigned int partial_end = (lend + 1) & (PAGE_SIZE - 1);
922 struct pagevec pvec;
923 struct folio_batch fbatch;922 struct folio_batch fbatch;
924 pgoff_t indices[PAGEVEC_SIZE];923 pgoff_t indices[PAGEVEC_SIZE];
925 long nr_swaps_freed = 0;924 long nr_swaps_freed = 0;
@@ -932,12 +931,12 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend, · 6 unmodified lines
932 if (info->fallocend > start && info->fallocend <= end && !unfalloc)931 if (info->fallocend > start && info->fallocend <= end && !unfalloc)
933 info->fallocend = start;932 info->fallocend = start;
934 933
935 pagevec_init(&pvec);934 folio_batch_init(&fbatch);
936 index = start;935 index = start;
937 while (index < end && find_lock_entries(mapping, index, end - 1,936 while (index < end && find_lock_entries(mapping, index, end - 1,
938 &pvec, indices)) {937 &fbatch, indices)) {
939 for (i = 0; i < pagevec_count(&pvec); i++) {938 for (i = 0; i < folio_batch_count(&fbatch); i++) {
940 struct folio *folio = (struct folio *)pvec.pages[i];939 struct folio *folio = fbatch.folios[i];
941 940
942 index = indices[i];941 index = indices[i];
943 942
@@ -954,8 +953,8 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend, · 10 unmodified lines
954 truncate_inode_folio(mapping, folio);953 truncate_inode_folio(mapping, folio);
955 folio_unlock(folio);954 folio_unlock(folio);
956 }955 }
957 pagevec_remove_exceptionals(&pvec);956 folio_batch_remove_exceptionals(&fbatch);
958 pagevec_release(&pvec);957 folio_batch_release(&fbatch);
959 cond_resched();958 cond_resched();
960 index++;959 index++;
961 }960 }
@@ -988,7 +987,6 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend, · 26 unmodified lines
988 if (start >= end)987 if (start >= end)
989 return;988 return;
990 989
991 folio_batch_init(&fbatch);
992 index = start;990 index = start;
993 while (index < end) {991 while (index < end) {
994 cond_resched();992 cond_resched();
mm/truncate.c+29−38
@@ -56,11 +56,11 @@ static void clear_shadow_entry(struct address_space *mapping, pgoff_t index, · 55 unmodified lines
56 56
57/*57/*
58 * Unconditionally remove exceptional entries. Usually called from truncate58 * Unconditionally remove exceptional entries. Usually called from truncate
59 * path. Note that the pagevec may be altered by this function by removing59 * path. Note that the folio_batch may be altered by this function by removing
60 * exceptional entries similar to what pagevec_remove_exceptionals does.60 * exceptional entries similar to what pagevec_remove_exceptionals does.
61 */61 */
62static void truncate_exceptional_pvec_entries(struct address_space *mapping,62static void truncate_folio_batch_exceptionals(struct address_space *mapping,
63 struct pagevec *pvec, pgoff_t *indices)63 struct folio_batch *fbatch, pgoff_t *indices)
64{64{
65 int i, j;65 int i, j;
66 bool dax;66 bool dax;
@@ -69,11 +69,11 @@ static void truncate_exceptional_pvec_entries(struct address_space *mapping, · 2 unmodified lines
69 if (shmem_mapping(mapping))69 if (shmem_mapping(mapping))
70 return;70 return;
71 71
72 for (j = 0; j < pagevec_count(pvec); j++)72 for (j = 0; j < folio_batch_count(fbatch); j++)
73 if (xa_is_value(pvec->pages[j]))73 if (xa_is_value(fbatch->folios[j]))
74 break;74 break;
75 75
76 if (j == pagevec_count(pvec))76 if (j == folio_batch_count(fbatch))
77 return;77 return;
78 78
79 dax = dax_mapping(mapping);79 dax = dax_mapping(mapping);
@@ -82,12 +82,12 @@ static void truncate_exceptional_pvec_entries(struct address_space *mapping, · 2 unmodified lines
82 xa_lock_irq(&mapping->i_pages);82 xa_lock_irq(&mapping->i_pages);
83 }83 }
84 84
85 for (i = j; i < pagevec_count(pvec); i++) {85 for (i = j; i < folio_batch_count(fbatch); i++) {
86 struct page *page = pvec->pages[i];86 struct folio *folio = fbatch->folios[i];
87 pgoff_t index = indices[i];87 pgoff_t index = indices[i];
88 88
89 if (!xa_is_value(page)) {89 if (!xa_is_value(folio)) {
90 pvec->pages[j++] = page;90 fbatch->folios[j++] = folio;
91 continue;91 continue;
92 }92 }
93 93
@@ -96,7 +96,7 @@ static void truncate_exceptional_pvec_entries(struct address_space *mapping, · 2 unmodified lines
96 continue;96 continue;
97 }97 }
98 98
99 __clear_shadow_entry(mapping, index, page);99 __clear_shadow_entry(mapping, index, folio);
100 }100 }
101 101
102 if (!dax) {102 if (!dax) {
@@ -105,14 +105,7 @@ static void truncate_exceptional_pvec_entries(struct address_space *mapping, · 2 unmodified lines
105 inode_add_lru(mapping->host);105 inode_add_lru(mapping->host);
106 spin_unlock(&mapping->host->i_lock);106 spin_unlock(&mapping->host->i_lock);
107 }107 }
108 pvec->nr = j;108 fbatch->nr = j;
109}
110
111static void truncate_folio_batch_exceptionals(struct address_space *mapping,
112 struct folio_batch *fbatch, pgoff_t *indices)
113{
114 truncate_exceptional_pvec_entries(mapping, (struct pagevec *)fbatch,
115 indices);
116}109}
117 110
118/*111/*
@@ -303,7 +296,6 @@ void truncate_inode_pages_range(struct address_space *mapping, · 184 unmodified lines
303 pgoff_t end; /* exclusive */296 pgoff_t end; /* exclusive */
304 unsigned int partial_start; /* inclusive */297 unsigned int partial_start; /* inclusive */
305 unsigned int partial_end; /* exclusive */298 unsigned int partial_end; /* exclusive */
306 struct pagevec pvec;
307 struct folio_batch fbatch;299 struct folio_batch fbatch;
308 pgoff_t indices[PAGEVEC_SIZE];300 pgoff_t indices[PAGEVEC_SIZE];
309 pgoff_t index;301 pgoff_t index;
@@ -333,18 +325,18 @@ void truncate_inode_pages_range(struct address_space *mapping, · 23 unmodified lines
333 else325 else
334 end = (lend + 1) >> PAGE_SHIFT;326 end = (lend + 1) >> PAGE_SHIFT;
335 327
336 pagevec_init(&pvec);328 folio_batch_init(&fbatch);
337 index = start;329 index = start;
338 while (index < end && find_lock_entries(mapping, index, end - 1,330 while (index < end && find_lock_entries(mapping, index, end - 1,
339 &pvec, indices)) {331 &fbatch, indices)) {
340 index = indices[pagevec_count(&pvec) - 1] + 1;332 index = indices[folio_batch_count(&fbatch) - 1] + 1;
341 truncate_exceptional_pvec_entries(mapping, &pvec, indices);333 truncate_folio_batch_exceptionals(mapping, &fbatch, indices);
342 for (i = 0; i < pagevec_count(&pvec); i++)334 for (i = 0; i < folio_batch_count(&fbatch); i++)
343 truncate_cleanup_folio(page_folio(pvec.pages[i]));335 truncate_cleanup_folio(fbatch.folios[i]);
344 delete_from_page_cache_batch(mapping, &pvec);336 delete_from_page_cache_batch(mapping, &fbatch);
345 for (i = 0; i < pagevec_count(&pvec); i++)337 for (i = 0; i < folio_batch_count(&fbatch); i++)
346 unlock_page(pvec.pages[i]);338 folio_unlock(fbatch.folios[i]);
347 pagevec_release(&pvec);339 folio_batch_release(&fbatch);
348 cond_resched();340 cond_resched();
349 }341 }
350 342
@@ -387,7 +379,6 @@ void truncate_inode_pages_range(struct address_space *mapping, · 36 unmodified lines
387 if (start >= end)379 if (start >= end)
388 goto out;380 goto out;
389 381
390 folio_batch_init(&fbatch);
391 index = start;382 index = start;
392 for ( ; ; ) {383 for ( ; ; ) {
393 cond_resched();384 cond_resched();
@@ -489,16 +480,16 @@ static unsigned long __invalidate_mapping_pages(struct address_space *mapping, · 95 unmodified lines
489 pgoff_t start, pgoff_t end, unsigned long *nr_pagevec)480 pgoff_t start, pgoff_t end, unsigned long *nr_pagevec)
490{481{
491 pgoff_t indices[PAGEVEC_SIZE];482 pgoff_t indices[PAGEVEC_SIZE];
492 struct pagevec pvec;483 struct folio_batch fbatch;
493 pgoff_t index = start;484 pgoff_t index = start;
494 unsigned long ret;485 unsigned long ret;
495 unsigned long count = 0;486 unsigned long count = 0;
496 int i;487 int i;
497 488
498 pagevec_init(&pvec);489 folio_batch_init(&fbatch);
499 while (find_lock_entries(mapping, index, end, &pvec, indices)) {490 while (find_lock_entries(mapping, index, end, &fbatch, indices)) {
500 for (i = 0; i < pagevec_count(&pvec); i++) {491 for (i = 0; i < folio_batch_count(&fbatch); i++) {
501 struct page *page = pvec.pages[i];492 struct page *page = &fbatch.folios[i]->page;
502 493
503 /* We rely upon deletion not changing page->index */494 /* We rely upon deletion not changing page->index */
504 index = indices[i];495 index = indices[i];
@@ -525,8 +516,8 @@ static unsigned long __invalidate_mapping_pages(struct address_space *mapping, · 20 unmodified lines
525 }516 }
526 count += ret;517 count += ret;
527 }518 }
528 pagevec_remove_exceptionals(&pvec);519 folio_batch_remove_exceptionals(&fbatch);
529 pagevec_release(&pvec);520 folio_batch_release(&fbatch);
530 cond_resched();521 cond_resched();
531 index++;522 index++;
532 }523 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t