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 <hch@lst.de> Link: https://patch.msgid.link/20260326140635.15895-3-jack@suse.cz Signed-off-by: Jan Kara <jack@suse.cz>
This commit is contained in:
parent
c369299895
commit
fffca572f9
30
fs/mpage.c
30
fs/mpage.c
|
|
@ -646,17 +646,24 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mpage_writepages - walk the list of dirty pages of the given address space & writepage() all of them
|
* __mpage_writepages - walk the list of dirty pages of the given address space
|
||||||
|
* & writepage() all of them
|
||||||
* @mapping: address space structure to write
|
* @mapping: address space structure to write
|
||||||
* @wbc: subtract the number of written pages from *@wbc->nr_to_write
|
* @wbc: subtract the number of written pages from *@wbc->nr_to_write
|
||||||
* @get_block: the filesystem's block mapper function.
|
* @get_block: the filesystem's block mapper function.
|
||||||
|
* @write_folio: handler to call for each folio before calling
|
||||||
|
* mpage_write_folio()
|
||||||
*
|
*
|
||||||
* This is a library function, which implements the writepages()
|
* This is a library function, which implements the writepages()
|
||||||
* address_space_operation.
|
* address_space_operation. It calls @write_folio handler for each folio. If
|
||||||
|
* the handler returns value > 0, it calls mpage_write_folio() to do the
|
||||||
|
* folio writeback.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
mpage_writepages(struct address_space *mapping,
|
__mpage_writepages(struct address_space *mapping,
|
||||||
struct writeback_control *wbc, get_block_t get_block)
|
struct writeback_control *wbc, get_block_t get_block,
|
||||||
|
int (*write_folio)(struct folio *folio,
|
||||||
|
struct writeback_control *wbc))
|
||||||
{
|
{
|
||||||
struct mpage_data mpd = {
|
struct mpage_data mpd = {
|
||||||
.get_block = get_block,
|
.get_block = get_block,
|
||||||
|
|
@ -666,11 +673,22 @@ mpage_writepages(struct address_space *mapping,
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
blk_start_plug(&plug);
|
blk_start_plug(&plug);
|
||||||
while ((folio = writeback_iter(mapping, wbc, folio, &error)))
|
while ((folio = writeback_iter(mapping, wbc, folio, &error))) {
|
||||||
|
if (write_folio) {
|
||||||
|
error = write_folio(folio, wbc);
|
||||||
|
/*
|
||||||
|
* == 0 means folio is handled, < 0 means error. In
|
||||||
|
* both cases hand back control to writeback_iter()
|
||||||
|
*/
|
||||||
|
if (error <= 0)
|
||||||
|
continue;
|
||||||
|
/* Let mpage_write_folio() handle the folio. */
|
||||||
|
}
|
||||||
error = mpage_write_folio(wbc, folio, &mpd);
|
error = mpage_write_folio(wbc, folio, &mpd);
|
||||||
|
}
|
||||||
if (mpd.bio)
|
if (mpd.bio)
|
||||||
mpage_bio_submit_write(mpd.bio);
|
mpage_bio_submit_write(mpd.bio);
|
||||||
blk_finish_plug(&plug);
|
blk_finish_plug(&plug);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(mpage_writepages);
|
EXPORT_SYMBOL(__mpage_writepages);
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,14 @@ struct readahead_control;
|
||||||
|
|
||||||
void mpage_readahead(struct readahead_control *, get_block_t get_block);
|
void mpage_readahead(struct readahead_control *, get_block_t get_block);
|
||||||
int mpage_read_folio(struct folio *folio, get_block_t get_block);
|
int mpage_read_folio(struct folio *folio, get_block_t get_block);
|
||||||
int mpage_writepages(struct address_space *mapping,
|
int __mpage_writepages(struct address_space *mapping,
|
||||||
struct writeback_control *wbc, get_block_t get_block);
|
struct writeback_control *wbc, get_block_t get_block,
|
||||||
|
int (*write_folio)(struct folio *folio,
|
||||||
|
struct writeback_control *wbc));
|
||||||
|
static inline int mpage_writepages(struct address_space *mapping,
|
||||||
|
struct writeback_control *wbc, get_block_t get_block)
|
||||||
|
{
|
||||||
|
return __mpage_writepages(mapping, wbc, get_block, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue