This is the equivalent of page_symlink() but takes a buffered_write_operations structure. It also doesn't handle GFP_NOFS for you; if you need that, use memalloc_nofs_save() yourself. Signed-off-by: Matthew Wilcox (Oracle) <willy@xxxxxxxxxxxxx> --- fs/namei.c | 25 +++++++++++++++++++++++++ include/linux/pagemap.h | 2 ++ 2 files changed, 27 insertions(+) diff --git a/fs/namei.c b/fs/namei.c index 37fb0a8aa09a..4352206b0408 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -5255,6 +5255,31 @@ int page_symlink(struct inode *inode, const char *symname, int len) } EXPORT_SYMBOL(page_symlink); +int filemap_symlink(struct inode *inode, const char *symname, int len, + const struct buffered_write_operations *ops, void **fsdata) +{ + struct address_space *mapping = inode->i_mapping; + struct folio *folio; + int err; + +retry: + folio = ops->write_begin(NULL, mapping, 0, len-1, fsdata); + if (IS_ERR(folio)) + return PTR_ERR(folio); + + memcpy(folio_address(folio), symname, len-1); + + err = ops->write_end(NULL, mapping, 0, len-1, len-1, folio, fsdata); + if (err < 0) + return err; + if (err < len-1) + goto retry; + + mark_inode_dirty(inode); + return 0; +} +EXPORT_SYMBOL(filemap_symlink); + const struct inode_operations page_symlink_inode_operations = { .get_link = page_get_link, }; diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 2921c1cc6335..a7540f757368 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -39,6 +39,8 @@ ssize_t generic_file_write_iter(struct kiocb *, struct iov_iter *); #define __generic_file_write_iter(kiocb, iter) \ __filemap_write_iter(kiocb, iter, NULL, NULL) +int filemap_symlink(struct inode *inode, const char *symname, int len, + const struct buffered_write_operations *bw, void **fsdata); unsigned long invalidate_mapping_pages(struct address_space *mapping, pgoff_t start, pgoff_t end); -- 2.43.0