[PATCH 2/7] fuse: Use filemap_invalidate_pages()
"Matthew Wilcox (Oracle)" <[email protected]>
| Newsgroups | org.kernel.vger.linux-nfs,dev.linux.lists.fuse-devel,org.kernel.vger.linux-block,org.kernel.vger.linux-btrfs,org.kernel.vger.linux-fsdevel,org.kvack.linux-mm |
|---|---|
| Message-ID | <[email protected]> |
FUSE relies on invalidate_inode_pages2() / invalidate_inode_pages2_range() doing writeback by calling fuse_launder_folio(). While this works, it is inefficient as each page is written back and waited for individually. Far better to call filemap_invalidate_pages() which will do a bulk write first, then remove the page cache. With this done, fuse_launder_folio() no longer needs to exist so delete it. Signed-off-by: Matthew Wilcox (Oracle) <[email protected]> --- fs/fuse/dax.c | 15 +++------------ fs/fuse/dir.c | 12 +++++++----- fs/fuse/file.c | 46 ++++++---------------------------------------- fs/fuse/inode.c | 17 +++++------------ 4 files changed, 21 insertions(+), 69 deletions(-) diff --git a/fs/fuse/dax.c b/fs/fuse/dax.c index 8b53625ac7ab..45843975e28b 100644 --- a/fs/fuse/dax.c +++ b/fs/fuse/dax.c @@ -835,19 +835,10 @@ static int dmap_writeback_invalidate(struct inode *inode, loff_t start_pos = dmap->itn.start << FUSE_DAX_SHIFT; loff_t end_pos = (start_pos + FUSE_DAX_SZ - 1); - ret = filemap_fdatawrite_range(inode->i_mapping, start_pos, end_pos); - if (ret) { - pr_debug("fuse: filemap_fdatawrite_range() failed. err=%d start_pos=0x%llx, end_pos=0x%llx\n", - ret, start_pos, end_pos); - return ret; - } - - ret = invalidate_inode_pages2_range(inode->i_mapping, - start_pos >> PAGE_SHIFT, - end_pos >> PAGE_SHIFT); + ret = filemap_invalidate_pages(inode->i_mapping, start_pos, end_pos); if (ret) - pr_debug("fuse: invalidate_inode_pages2_range() failed err=%d\n", - ret); + pr_debug("fuse: filemap_invalidate_pages() failed. err=%d start_pos=0x%llx, end_pos=0x%llx\n", + ret, start_pos, end_pos); return ret; } diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 0e2a1039fa43..c6c72c0ee669 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -913,7 +913,8 @@ static int fuse_create_open(struct mnt_idmap *idmap, struct inode *dir, if (fm->fc->atomic_o_trunc && trunc) truncate_pagecache(inode, 0); else if (!(ff->open_flags & FOPEN_KEEP_CACHE)) - invalidate_inode_pages2(inode->i_mapping); + filemap_invalidate_pages(inode->i_mapping, 0, + OFFSET_MAX); } return err; @@ -1904,7 +1905,8 @@ static int fuse_dir_open(struct inode *inode, struct file *file) if (ff->open_flags & (FOPEN_STREAM | FOPEN_NONSEEKABLE)) nonseekable_open(inode, file); if (!(ff->open_flags & FOPEN_KEEP_CACHE)) - invalidate_inode_pages2(inode->i_mapping); + filemap_invalidate_pages(inode->i_mapping, 0, + OFFSET_MAX); } return err; @@ -2277,13 +2279,13 @@ int fuse_do_setattr(struct mnt_idmap *idmap, struct dentry *dentry, spin_unlock(&fi->lock); /* - * Only call invalidate_inode_pages2() after removing - * FUSE_NOWRITE, otherwise fuse_launder_folio() would deadlock. + * Only call filemap_invalidate_pages() after removing + * FUSE_NOWRITE, otherwise it would deadlock. */ if ((is_truncate || !is_wb) && S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) { truncate_pagecache(inode, outarg.attr.size); - invalidate_inode_pages2(mapping); + filemap_invalidate_pages(mapping, 0, OFFSET_MAX); } clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); diff --git a/fs/fuse/file.c b/fs/fuse/file.c index ceada75310b8..2496161f9298 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -294,7 +294,8 @@ static int fuse_open(struct inode *inode, struct file *file) if (is_truncate) truncate_pagecache(inode, 0); else if (!(ff->open_flags & FOPEN_KEEP_CACHE)) - invalidate_inode_pages2(inode->i_mapping); + filemap_invalidate_pages(inode->i_mapping, 0, + OFFSET_MAX); } if (dax_truncate) filemap_invalidate_unlock(inode->i_mapping); @@ -644,10 +645,8 @@ static void fuse_aio_invalidate_worker(struct work_struct *work) struct fuse_io_priv *io = container_of(work, struct fuse_io_priv, work); struct address_space *mapping = io->iocb->ki_filp->f_mapping; ssize_t res = fuse_get_res_by_io(io); - pgoff_t start = io->offset >> PAGE_SHIFT; - pgoff_t end = (io->offset + res - 1) >> PAGE_SHIFT; - invalidate_inode_pages2_range(mapping, start, end); + filemap_invalidate_pages(mapping, io->offset, io->offset + res - 1); io->iocb->ki_complete(io->iocb, res); kref_put(&io->refcnt, fuse_io_release); } @@ -1675,8 +1674,6 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, size_t nmax = write ? fc->max_write : fc->max_read; loff_t pos = *ppos; size_t count = iov_iter_count(iter); - pgoff_t idx_from = pos >> PAGE_SHIFT; - pgoff_t idx_to = (pos + count - 1) >> PAGE_SHIFT; ssize_t res = 0; int err = 0; struct fuse_io_args *ia; @@ -1689,7 +1686,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, return -ENOMEM; if (fopen_direct_io) { - res = filemap_write_and_wait_range(mapping, pos, pos + count - 1); + res = filemap_invalidate_pages(mapping, pos, pos + count - 1); if (res) { fuse_io_free(ia); return res; @@ -1703,14 +1700,6 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, inode_unlock(inode); } - if (fopen_direct_io && write) { - res = invalidate_inode_pages2_range(mapping, idx_from, idx_to); - if (res) { - fuse_io_free(ia); - return res; - } - } - io->should_dirty = !write && user_backed_iter(iter); while (count) { ssize_t nres; @@ -1824,9 +1813,7 @@ static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from) * write, to invalidate read-ahead cache that may have * with the write. */ - invalidate_inode_pages2_range(mapping, - pos >> PAGE_SHIFT, - (pos + res - 1) >> PAGE_SHIFT); + filemap_invalidate_pages(mapping, pos, pos + res - 1); } } fuse_dio_unlock(iocb, exclusive); @@ -2324,26 +2311,6 @@ static int fuse_writepages(struct address_space *mapping, return iomap_writepages(&wpc); } -static int fuse_launder_folio(struct folio *folio) -{ - int err = 0; - struct fuse_fill_wb_data data = {}; - struct iomap_writepage_ctx wpc = { - .inode = folio->mapping->host, - .iomap.type = IOMAP_MAPPED, - .ops = &fuse_writeback_ops, - .wb_ctx = &data, - }; - - if (folio_clear_dirty_for_io(folio)) { - err = iomap_writeback_folio(&wpc, folio); - err = fuse_iomap_writeback_submit(&wpc, err); - if (!err) - folio_wait_writeback(folio); - } - return err; -} - /* * Write back dirty data/metadata now (there may not be any suitable * open files later for data) @@ -2427,7 +2394,7 @@ static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma) if ((vma->vm_flags & VM_MAYSHARE) && !fc->direct_io_allow_mmap) return -ENODEV; - invalidate_inode_pages2(file->f_mapping); + filemap_invalidate_pages(file->f_mapping, 0, OFFSET_MAX); if (!(vma->vm_flags & VM_MAYSHARE)) { /* MAP_PRIVATE */ @@ -3102,7 +3069,6 @@ static const struct address_space_operations fuse_file_aops = { .read_folio = fuse_read_folio, .readahead = fuse_readahead, .writepages = fuse_writepages, - .launder_folio = fuse_launder_folio, .dirty_folio = iomap_dirty_folio, .release_folio = iomap_release_folio, .invalidate_folio = iomap_invalidate_folio, diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index d975073c6029..2c9a93a2173a 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -382,7 +382,8 @@ static void fuse_change_attributes_i(struct inode *inode, struct fuse_attr *attr } if (inval) - invalidate_inode_pages2(inode->i_mapping); + filemap_invalidate_pages(inode->i_mapping, 0, + OFFSET_MAX); } if (IS_ENABLED(CONFIG_FUSE_DAX)) @@ -547,8 +548,6 @@ int fuse_reverse_inval_inode(struct fuse_conn *fc, u64 nodeid, { struct fuse_inode *fi; struct inode *inode; - pgoff_t pg_start; - pgoff_t pg_end; inode = fuse_ilookup(fc, nodeid, NULL); if (!inode) @@ -561,15 +560,9 @@ int fuse_reverse_inval_inode(struct fuse_conn *fc, u64 nodeid, fuse_invalidate_attr(inode); forget_all_cached_acls(inode); - if (offset >= 0) { - pg_start = offset >> PAGE_SHIFT; - if (len <= 0) - pg_end = -1; - else - pg_end = (offset + len - 1) >> PAGE_SHIFT; - invalidate_inode_pages2_range(inode->i_mapping, - pg_start, pg_end); - } + if (offset >= 0) + filemap_invalidate_pages(inode->i_mapping, offset, + offset + len - 1); iput(inode); return 0; } -- 2.47.3