Commit fffca572 authored by Jan Kara's avatar Jan Kara
Browse files

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: default avatarChristoph Hellwig <hch@lst.de>
Link: https://patch.msgid.link/20260326140635.15895-3-jack@suse.cz


Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent c3692998
Loading
Loading
Loading
Loading
+24 −6
Original line number Diff line number Diff line
@@ -646,17 +646,24 @@ static int mpage_write_folio(struct writeback_control *wbc, struct folio *folio,
}

/**
 * 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);
+9 −2
Original line number Diff line number Diff line
@@ -17,7 +17,14 @@ struct readahead_control;

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_writepages(struct address_space *mapping,
		struct writeback_control *wbc, get_block_t get_block);
int __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));
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