Add a new iomap_symlink_write function as an iomap based equivalent to page_symlink found in fs/namei.c. This implementation was suggested by Darrick J. Wong, who also provided the initial implementation that I only needed to change slightly to get working. Suggested-by: Darrick J. Wong Signed-off-by: Jeremy Bingham --- fs/iomap/buffered-io.c | 31 +++++++++++++++++++++++++++++++ include/linux/iomap.h | 4 ++++ 2 files changed, 35 insertions(+) diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c index 276720bc18dc..6f3f79fdbd8b 100644 --- a/fs/iomap/buffered-io.c +++ b/fs/iomap/buffered-io.c @@ -2066,3 +2066,34 @@ iomap_writepages(struct iomap_writepage_ctx *wpc) return error; } EXPORT_SYMBOL_GPL(iomap_writepages); + +int iomap_symlink_write(struct inode *inode, const char *target, int len, + const struct iomap_ops *ops, + const struct iomap_write_ops *write_ops, void *private) +{ + struct kvec vec = { + .iov_base = (void *)target, + .iov_len = len, + }; + struct iomap_iter iter = { + .inode = inode, + .pos = 0, + .len = len, + .flags = IOMAP_WRITE, + .private = private, + }; + struct iov_iter iov; + int ret; + + iov_iter_kvec(&iov, ITER_SOURCE, &vec, 1, len); + + while ((ret = iomap_iter(&iter, ops)) > 0) + iter.status = iomap_write_iter(&iter, &iov, write_ops); + + if (unlikely(iter.pos == 0)) + return ret; + + mark_inode_dirty(inode); + return 0; +} +EXPORT_SYMBOL_GPL(iomap_symlink_write); diff --git a/include/linux/iomap.h b/include/linux/iomap.h index 56b43d594e6e..9274fa256bc9 100644 --- a/include/linux/iomap.h +++ b/include/linux/iomap.h @@ -393,6 +393,10 @@ loff_t iomap_seek_data(struct inode *inode, loff_t offset, sector_t iomap_bmap(struct address_space *mapping, sector_t bno, const struct iomap_ops *ops); +int iomap_symlink_write(struct inode *inode, const char *target, int len, + const struct iomap_ops *ops, + const struct iomap_write_ops *write_ops, void *private); + /* * Flags for iomap_ioend->io_flags. */ -- 2.47.3