Skip to content

Commit fffca57

Browse files
committed
mpage: Provide variant of mpage_writepages() with own optional folio handler
Some filesystems need to treat some folios specially (for example for inodes with inline data). Doing the handling in their .writepages method in a race-free manner results in duplicating some of the writeback internals. So provide generalized version of mpage_writepages() that allows filesystem to provide a handler called for each folio which can handle the folio in a special way. Reviewed-by: Christoph Hellwig <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jan Kara <[email protected]>
1 parent c369299 commit fffca57

2 files changed

Lines changed: 33 additions & 8 deletions

File tree

fs/mpage.c

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -646,17 +646,24 @@ static int mpage_write_folio(struct writeback_control *wbc, struct folio *folio,
646646
}
647647

648648
/**
649-
* mpage_writepages - walk the list of dirty pages of the given address space & writepage() all of them
649+
* __mpage_writepages - walk the list of dirty pages of the given address space
650+
* & writepage() all of them
650651
* @mapping: address space structure to write
651652
* @wbc: subtract the number of written pages from *@wbc->nr_to_write
652653
* @get_block: the filesystem's block mapper function.
654+
* @write_folio: handler to call for each folio before calling
655+
* mpage_write_folio()
653656
*
654657
* This is a library function, which implements the writepages()
655-
* address_space_operation.
658+
* address_space_operation. It calls @write_folio handler for each folio. If
659+
* the handler returns value > 0, it calls mpage_write_folio() to do the
660+
* folio writeback.
656661
*/
657662
int
658-
mpage_writepages(struct address_space *mapping,
659-
struct writeback_control *wbc, get_block_t get_block)
663+
__mpage_writepages(struct address_space *mapping,
664+
struct writeback_control *wbc, get_block_t get_block,
665+
int (*write_folio)(struct folio *folio,
666+
struct writeback_control *wbc))
660667
{
661668
struct mpage_data mpd = {
662669
.get_block = get_block,
@@ -666,11 +673,22 @@ mpage_writepages(struct address_space *mapping,
666673
int error;
667674

668675
blk_start_plug(&plug);
669-
while ((folio = writeback_iter(mapping, wbc, folio, &error)))
676+
while ((folio = writeback_iter(mapping, wbc, folio, &error))) {
677+
if (write_folio) {
678+
error = write_folio(folio, wbc);
679+
/*
680+
* == 0 means folio is handled, < 0 means error. In
681+
* both cases hand back control to writeback_iter()
682+
*/
683+
if (error <= 0)
684+
continue;
685+
/* Let mpage_write_folio() handle the folio. */
686+
}
670687
error = mpage_write_folio(wbc, folio, &mpd);
688+
}
671689
if (mpd.bio)
672690
mpage_bio_submit_write(mpd.bio);
673691
blk_finish_plug(&plug);
674692
return error;
675693
}
676-
EXPORT_SYMBOL(mpage_writepages);
694+
EXPORT_SYMBOL(__mpage_writepages);

include/linux/mpage.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,14 @@ struct readahead_control;
1717

1818
void mpage_readahead(struct readahead_control *, get_block_t get_block);
1919
int mpage_read_folio(struct folio *folio, get_block_t get_block);
20-
int mpage_writepages(struct address_space *mapping,
21-
struct writeback_control *wbc, get_block_t get_block);
20+
int __mpage_writepages(struct address_space *mapping,
21+
struct writeback_control *wbc, get_block_t get_block,
22+
int (*write_folio)(struct folio *folio,
23+
struct writeback_control *wbc));
24+
static inline int mpage_writepages(struct address_space *mapping,
25+
struct writeback_control *wbc, get_block_t get_block)
26+
{
27+
return __mpage_writepages(mapping, wbc, get_block, NULL);
28+
}
2229

2330
#endif

0 commit comments

Comments
 (0)