summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2026-03-26 15:06:31 +0100
committerJan Kara <jack@suse.cz>2026-03-27 17:01:36 +0100
commitfffca572f9ca51607f180a37d0c898404c8f9112 (patch)
tree0b91de63e160267c7b47a5b420ea880cd1fc2ece /fs
parentc369299895a591d96745d6492d4888259b004a9e (diff)
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/mpage.c30
1 files changed, 24 insertions, 6 deletions
diff --git a/fs/mpage.c b/fs/mpage.c
index 7dae5afc2b9e..b3d9f231a04a 100644
--- a/fs/mpage.c
+++ b/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
* @wbc: subtract the number of written pages from *@wbc->nr_to_write
* @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()
- * 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
-mpage_writepages(struct address_space *mapping,
- struct writeback_control *wbc, get_block_t get_block)
+__mpage_writepages(struct address_space *mapping,
+ struct writeback_control *wbc, get_block_t get_block,
+ int (*write_folio)(struct folio *folio,
+ struct writeback_control *wbc))
{
struct mpage_data mpd = {
.get_block = get_block,
@@ -666,11 +673,22 @@ mpage_writepages(struct address_space *mapping,
int error;
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);
+ }
if (mpd.bio)
mpage_bio_submit_write(mpd.bio);
blk_finish_plug(&plug);
return error;
}
-EXPORT_SYMBOL(mpage_writepages);
+EXPORT_SYMBOL(__mpage_writepages);