Wire the new iomap functionality into the inode operations. Entirely new functions for writeback and a minix_writeback_ops struct have been added, and the address space operation functions have been updated to use iomap. Since directory operations still work the old way, the old functions have been preserved with new names. Directories also get their own address operation struct. Also, bmap support is dropped entirely per Darrick Wong's suggestion. This patch also updates minix_symlink to use the new iomap_symlink_write function, removing the need to bypass iomap to read and write symlinks directly. This was also suggested by Darrick Wong. Suggested-by: Darrick J. Wong Signed-off-by: Jeremy Bingham --- fs/minix/inode.c | 85 +++++++++++++++++++++++++++++++++++++++++------- fs/minix/namei.c | 8 ++++- 2 files changed, 80 insertions(+), 13 deletions(-) diff --git a/fs/minix/inode.c b/fs/minix/inode.c index d5ba72f51049..f6747bacdb14 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -436,6 +436,31 @@ static int minix_statfs(struct dentry *dentry, struct kstatfs *buf) return 0; } +static ssize_t minix_writeback_range(struct iomap_writepage_ctx *wpc, + struct folio *folio, u64 pos, unsigned int len, u64 end_pos) +{ + int error; + + if (pos < wpc->iomap.offset || + pos >= wpc->iomap.offset + wpc->iomap.length) { + if (INODE_VERSION(wpc->inode) == MINIX_V1) + error = V1_minix_iomap_begin(wpc->inode, pos, len, IOMAP_WRITE, + &wpc->iomap, NULL); + else + error = V2_minix_iomap_begin(wpc->inode, pos, len, IOMAP_WRITE, + &wpc->iomap, NULL); + if (error) + return error; + } + + return iomap_add_to_ioend(wpc, folio, pos, end_pos, len); +} + +static const struct iomap_writeback_ops minix_writeback_ops = { + .writeback_range = minix_writeback_range, + .writeback_submit = iomap_ioend_writeback_submit, +}; + static int minix_get_block(struct inode *inode, sector_t block, struct buffer_head *bh_result, int create) { @@ -445,17 +470,45 @@ static int minix_get_block(struct inode *inode, sector_t block, return V2_minix_get_block(inode, block, bh_result, create); } -static int minix_writepages(struct address_space *mapping, +/* The old minix_writepages, preserved for directory operations. */ +static int minix_block_writepages(struct address_space *mapping, struct writeback_control *wbc) { return mpage_writepages(mapping, wbc, minix_get_block); } +static int minix_writepages(struct address_space *mapping, + struct writeback_control *wbc) +{ + struct iomap_writepage_ctx wpc = { + .inode = mapping->host, + .wbc = wbc, + .ops = &minix_writeback_ops, + }; + return iomap_writepages(&wpc); +} + static int minix_read_folio(struct file *file, struct folio *folio) +{ + const struct iomap_ops *ops = minix_iomap_ops_ver(folio->mapping->host); + + iomap_bio_read_folio(folio, ops); + return 0; +} + +/* The old minix_read_folio, preserved for directory operations. */ +static int minix_block_read_folio(struct file *file, struct folio *folio) { return block_read_full_folio(folio, minix_get_block); } +static void minix_readahead(struct readahead_control *rac) +{ + const struct iomap_ops *ops = minix_iomap_ops_ver(rac->mapping->host); + + iomap_bio_readahead(rac, ops); +} + int minix_prepare_chunk(struct folio *folio, loff_t pos, unsigned len) { return __block_write_begin(folio, pos, len, minix_get_block); @@ -485,26 +538,35 @@ static int minix_write_begin(const struct kiocb *iocb, return ret; } -static sector_t minix_bmap(struct address_space *mapping, sector_t block) -{ - return generic_block_bmap(mapping,block,minix_get_block); -} - const struct address_space_operations minix_aops = { - .dirty_folio = block_dirty_folio, - .invalidate_folio = block_invalidate_folio, + .dirty_folio = iomap_dirty_folio, + .invalidate_folio = iomap_invalidate_folio, .read_folio = minix_read_folio, + .readahead = minix_readahead, .writepages = minix_writepages, + .migrate_folio = filemap_migrate_folio, + .is_partially_uptodate = iomap_is_partially_uptodate, + .release_folio = iomap_release_folio, + .error_remove_folio = generic_error_remove_folio, +}; + +/* A special aops for directories that keeps using the buffer head chunks, at + * least for the time being. + */ +static const struct address_space_operations minix_dir_aops = { + .dirty_folio = block_dirty_folio, + .invalidate_folio = block_invalidate_folio, + .read_folio = minix_block_read_folio, .write_begin = minix_write_begin, .write_end = generic_write_end, .migrate_folio = buffer_migrate_folio, - .bmap = minix_bmap, - .direct_IO = noop_direct_IO + .writepages = minix_block_writepages, }; static const struct inode_operations minix_symlink_inode_operations = { .get_link = page_get_link, .getattr = minix_getattr, + .setattr = minix_setattr, }; void minix_set_inode(struct inode *inode, dev_t rdev) @@ -516,7 +578,7 @@ void minix_set_inode(struct inode *inode, dev_t rdev) } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &minix_dir_inode_operations; inode->i_fop = &minix_dir_operations; - inode->i_mapping->a_ops = &minix_aops; + inode->i_mapping->a_ops = &minix_dir_aops; } else if (S_ISLNK(inode->i_mode)) { inode->i_op = &minix_symlink_inode_operations; inode_nohighmem(inode); @@ -768,4 +830,3 @@ module_init(init_minix_fs) module_exit(exit_minix_fs) MODULE_DESCRIPTION("Minix file system"); MODULE_LICENSE("GPL"); - diff --git a/fs/minix/namei.c b/fs/minix/namei.c index 263e4ba8b1c8..bb5892f9fb2a 100644 --- a/fs/minix/namei.c +++ b/fs/minix/namei.c @@ -6,6 +6,7 @@ */ #include "minix.h" +#include static int add_nondir(struct dentry *dentry, struct inode *inode) { @@ -84,12 +85,17 @@ static int minix_symlink(struct mnt_idmap *idmap, struct inode *dir, return PTR_ERR(inode); minix_set_inode(inode, 0); - err = page_symlink(inode, symname, i); + err = iomap_symlink_write(inode, symname, i, minix_iomap_ops_ver(inode), NULL, NULL); + + if (!err) + i_size_write(inode, i - 1); + if (unlikely(err)) { inode_dec_link_count(inode); iput(inode); return err; } + return add_nondir(dentry, inode); } -- 2.47.3