From: Bob Peterson <rpeterso@xxxxxxxxxx> Add function iomap_uninline_inode for converting an inline inode into a non-inline inode. This takes care of attaching a new iomap_page object to page->private if the block size is smaller than the page size. Signed-off-by: Andreas Gruenbacher <agruenba@xxxxxxxxxx> --- fs/iomap/buffered-io.c | 24 ++++++++++++++++++++++++ include/linux/iomap.h | 2 ++ 2 files changed, 26 insertions(+) diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c index 03537ecb2a94..44acb59191b2 100644 --- a/fs/iomap/buffered-io.c +++ b/fs/iomap/buffered-io.c @@ -226,6 +226,30 @@ iomap_read_inline_data(struct inode *inode, struct page *page, SetPageUptodate(page); } +int iomap_uninline_inode(struct inode *inode, + int (*uninline)(struct inode *, struct page *)) +{ + struct page *page = NULL; + int ret; + + if (i_size_read(inode)) { + page = find_or_create_page(inode->i_mapping, 0, GFP_NOFS); + if (!page) + return -ENOMEM; + } + ret = uninline(inode, page); + if (page) { + if (PageUptodate(page)) { + iomap_page_create(inode, page); + iomap_set_range_uptodate(page, 0, PAGE_SIZE); + } + unlock_page(page); + put_page(page); + } + return ret; +} +EXPORT_SYMBOL_GPL(iomap_uninline_inode); + static inline bool iomap_block_needs_zeroing(struct inode *inode, struct iomap *iomap, loff_t pos) { diff --git a/include/linux/iomap.h b/include/linux/iomap.h index c87d0cb0de6d..90c924eec09b 100644 --- a/include/linux/iomap.h +++ b/include/linux/iomap.h @@ -157,6 +157,8 @@ loff_t iomap_apply(struct inode *inode, loff_t pos, loff_t length, ssize_t iomap_file_buffered_write(struct kiocb *iocb, struct iov_iter *from, const struct iomap_ops *ops); +int iomap_uninline_inode(struct inode *inode, + int (*uninline)(struct inode *, struct page *)); int iomap_readpage(struct page *page, const struct iomap_ops *ops); void iomap_readahead(struct readahead_control *, const struct iomap_ops *ops); int iomap_set_page_dirty(struct page *page); -- 2.26.3