Add iomap_writeback_dirty_folio() for writing back a dirty folio. One use case of this is for laundering a folio. Signed-off-by: Joanne Koong <joannelkoong@xxxxxxxxx> --- fs/iomap/buffered-io.c | 27 +++++++++++++++++++-------- include/linux/iomap.h | 3 +++ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c index 25ae1d53eccb..d47abeefe92b 100644 --- a/fs/iomap/buffered-io.c +++ b/fs/iomap/buffered-io.c @@ -1518,7 +1518,7 @@ static bool iomap_writepage_handle_eof(struct folio *folio, struct inode *inode, return true; } -static int iomap_writepage_map(struct iomap_writepage_ctx *wpc, +static int iomap_writeback(struct iomap_writepage_ctx *wpc, struct writeback_control *wbc, struct folio *folio) { struct iomap_folio_state *ifs = folio->private; @@ -1541,10 +1541,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 (!iomap_writepage_handle_eof(folio, inode, &end_pos)) return 0; - } WARN_ON_ONCE(end_pos <= pos); if (i_blocks_per_folio(inode, folio) > 1) { @@ -1602,9 +1600,8 @@ static int iomap_writepage_map(struct iomap_writepage_ctx *wpc, * But we may end up either not actually writing any blocks, or (when * there are multiple blocks in a folio) all I/O might have finished * already at this point. In that case we need to clear the writeback - * bit ourselves right after unlocking the page. + * bit ourselves. */ - folio_unlock(folio); if (ifs) { if (atomic_dec_and_test(&ifs->write_bytes_pending)) folio_end_writeback(folio); @@ -1633,12 +1630,26 @@ iomap_writepages(struct address_space *mapping, struct writeback_control *wbc, return -EIO; wpc->ops = ops; - while ((folio = writeback_iter(mapping, wbc, folio, &error))) - error = iomap_writepage_map(wpc, wbc, folio); + while ((folio = writeback_iter(mapping, wbc, folio, &error))) { + error = iomap_writeback(wpc, wbc, folio); + folio_unlock(folio); + } return iomap_writeback_complete(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_writeback(wpc, wbc, folio); + return iomap_writeback_complete(wpc, error); +} +EXPORT_SYMBOL_GPL(iomap_writeback_dirty_folio); + void iomap_start_folio_write(struct inode *inode, struct folio *folio, size_t len) { diff --git a/include/linux/iomap.h b/include/linux/iomap.h index 3115b00ff410..95646346dff5 100644 --- a/include/linux/iomap.h +++ b/include/linux/iomap.h @@ -478,6 +478,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