Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

filemap: add helper to look up dirty folios in a range

Add a new filemap_get_folios_dirty() helper to look up existing dirty
folios in a range and add them to a folio_batch. This is to support
optimization of certain iomap operations that only care about dirty
folios in a target range. For example, zero range only zeroes the subset
of dirty pages over unwritten mappings, seek hole/data may use similar
logic in the future, etc.

Note that the helper is intended for use under internal fs locks.
Therefore it trylocks folios in order to filter out clean folios.
This loosely follows the logic from filemap_range_has_writeback().

Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Christian Brauner <brauner@kernel.org>

authored by

Brian Foster and committed by
Christian Brauner
f8d98072 4966b466

+60
+2
include/linux/pagemap.h
··· 977 977 pgoff_t *start, pgoff_t end, struct folio_batch *fbatch); 978 978 unsigned filemap_get_folios_tag(struct address_space *mapping, pgoff_t *start, 979 979 pgoff_t end, xa_mark_t tag, struct folio_batch *fbatch); 980 + unsigned filemap_get_folios_dirty(struct address_space *mapping, 981 + pgoff_t *start, pgoff_t end, struct folio_batch *fbatch); 980 982 981 983 struct folio *read_cache_folio(struct address_space *, pgoff_t index, 982 984 filler_t *filler, struct file *file);
+58
mm/filemap.c
··· 2366 2366 } 2367 2367 EXPORT_SYMBOL(filemap_get_folios_tag); 2368 2368 2369 + /** 2370 + * filemap_get_folios_dirty - Get a batch of dirty folios 2371 + * @mapping: The address_space to search 2372 + * @start: The starting folio index 2373 + * @end: The final folio index (inclusive) 2374 + * @fbatch: The batch to fill 2375 + * 2376 + * filemap_get_folios_dirty() works exactly like filemap_get_folios(), except 2377 + * the returned folios are presumed to be dirty or undergoing writeback. Dirty 2378 + * state is presumed because we don't block on folio lock nor want to miss 2379 + * folios. Callers that need to can recheck state upon locking the folio. 2380 + * 2381 + * This may not return all dirty folios if the batch gets filled up. 2382 + * 2383 + * Return: The number of folios found. 2384 + * Also update @start to be positioned for traversal of the next folio. 2385 + */ 2386 + unsigned filemap_get_folios_dirty(struct address_space *mapping, pgoff_t *start, 2387 + pgoff_t end, struct folio_batch *fbatch) 2388 + { 2389 + XA_STATE(xas, &mapping->i_pages, *start); 2390 + struct folio *folio; 2391 + 2392 + rcu_read_lock(); 2393 + while ((folio = find_get_entry(&xas, end, XA_PRESENT)) != NULL) { 2394 + if (xa_is_value(folio)) 2395 + continue; 2396 + if (folio_trylock(folio)) { 2397 + bool clean = !folio_test_dirty(folio) && 2398 + !folio_test_writeback(folio); 2399 + folio_unlock(folio); 2400 + if (clean) { 2401 + folio_put(folio); 2402 + continue; 2403 + } 2404 + } 2405 + if (!folio_batch_add(fbatch, folio)) { 2406 + unsigned long nr = folio_nr_pages(folio); 2407 + *start = folio->index + nr; 2408 + goto out; 2409 + } 2410 + } 2411 + /* 2412 + * We come here when there is no folio beyond @end. We take care to not 2413 + * overflow the index @start as it confuses some of the callers. This 2414 + * breaks the iteration when there is a folio at index -1 but that is 2415 + * already broke anyway. 2416 + */ 2417 + if (end == (pgoff_t)-1) 2418 + *start = (pgoff_t)-1; 2419 + else 2420 + *start = end + 1; 2421 + out: 2422 + rcu_read_unlock(); 2423 + 2424 + return folio_batch_count(fbatch); 2425 + } 2426 + 2369 2427 /* 2370 2428 * CD/DVDs are error prone. When a medium error occurs, the driver may fail 2371 2429 * a _large_ part of the i/o request. Imagine the worst scenario: