Add iomap_writeback_dirty_folio() for writing back a dirty folio. One use case of this is for folio laundering. Signed-off-by: Joanne Koong <joannelkoong@xxxxxxxxx> --- fs/iomap/buffered-io.c | 23 +++++++++++++++++++---- include/linux/iomap.h | 3 +++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c index 92f08b316d47..766a6673f79f 100644 --- a/fs/iomap/buffered-io.c +++ b/fs/iomap/buffered-io.c @@ -1592,7 +1592,8 @@ static bool iomap_writepage_handle_eof(struct folio *folio, struct inode *inode, } static int iomap_writepage_map(struct iomap_writepage_ctx *wpc, - struct writeback_control *wbc, struct folio *folio) + struct writeback_control *wbc, struct folio *folio, + bool unlock_folio) { struct iomap_folio_state *ifs = folio->private; struct inode *inode = folio->mapping->host; @@ -1610,7 +1611,8 @@ static int iomap_writepage_map(struct iomap_writepage_ctx *wpc, trace_iomap_writepage(inode, pos, folio_size(folio)); if (!iomap_writepage_handle_eof(folio, inode, &end_pos)) { - folio_unlock(folio); + if (unlock_folio) + folio_unlock(folio); return 0; } WARN_ON_ONCE(end_pos <= pos); @@ -1675,7 +1677,8 @@ static int iomap_writepage_map(struct iomap_writepage_ctx *wpc, * already at this point. In that case we need to clear the writeback * bit ourselves right after unlocking the page. */ - folio_unlock(folio); + if (unlock_folio) + folio_unlock(folio); if (ifs) { if (atomic_dec_and_test(&ifs->write_bytes_pending)) folio_end_writeback(folio); @@ -1709,11 +1712,23 @@ iomap_writepages(struct address_space *mapping, struct writeback_control *wbc, wpc->ops = ops; while ((folio = writeback_iter(mapping, wbc, folio, &error))) - error = iomap_writepage_map(wpc, wbc, folio); + error = iomap_writepage_map(wpc, wbc, folio, true); return iomap_submit_ioend(wpc, error); } EXPORT_SYMBOL_GPL(iomap_writepages); +int iomap_writeback_dirty_folio(struct folio *folio, struct writeback_control *wbc, + struct iomap_writepage_ctx *wpc, + const struct iomap_writeback_ops *ops) +{ + int error; + + wpc->ops = ops; + error = iomap_writepage_map(wpc, wbc, folio, false); + return iomap_submit_ioend(wpc, error); +} +EXPORT_SYMBOL_GPL(iomap_writeback_dirty_folio); + void iomap_start_folio_write(struct inode *inode, struct folio *folio, size_t len) { struct iomap_folio_state *ifs = folio->private; diff --git a/include/linux/iomap.h b/include/linux/iomap.h index 4b5e083fa802..a2b50b5489da 100644 --- a/include/linux/iomap.h +++ b/include/linux/iomap.h @@ -483,6 +483,9 @@ void iomap_sort_ioends(struct list_head *ioend_list); int iomap_writepages(struct address_space *mapping, struct writeback_control *wbc, struct iomap_writepage_ctx *wpc, const struct iomap_writeback_ops *ops); +int iomap_writeback_dirty_folio(struct folio *folio, struct writeback_control *wbc, + struct iomap_writepage_ctx *wpc, + const struct iomap_writeback_ops *ops); /* * Flags for direct I/O ->end_io: -- 2.47.1