Refator the fuse direct write code so that the fuse_perform_write
callig convention is simplified to match generic_perform_write and
it's updating ki_pos directly, and the generic direct_write_fallback
helper is used to consolidate buffered I/O fallback code.

Signed-off-by: Christoph Hellwig <h...@lst.de>
---
 fs/fuse/file.c | 44 +++++++++++---------------------------------
 1 file changed, 11 insertions(+), 33 deletions(-)

diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index de37a3a06a7169..55b64dac175d68 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1280,13 +1280,13 @@ static inline unsigned int fuse_wr_pages(loff_t pos, 
size_t len,
                     max_pages);
 }
 
-static ssize_t fuse_perform_write(struct kiocb *iocb,
-                                 struct address_space *mapping,
-                                 struct iov_iter *ii, loff_t pos)
+static ssize_t fuse_perform_write(struct kiocb *iocb, struct iov_iter *ii)
 {
+       struct address_space *mapping = iocb->ki_filp->f_mapping;
        struct inode *inode = mapping->host;
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_inode *fi = get_fuse_inode(inode);
+       loff_t pos = iocb->ki_pos;
        int err = 0;
        ssize_t res = 0;
 
@@ -1329,7 +1329,10 @@ static ssize_t fuse_perform_write(struct kiocb *iocb,
        fuse_write_update_attr(inode, pos, res);
        clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
 
-       return res > 0 ? res : err;
+       if (!res)
+               return err;
+       iocb->ki_pos += res;
+       return res;
 }
 
 static ssize_t fuse_cache_write_iter(struct kiocb *iocb, struct iov_iter *from)
@@ -1337,11 +1340,9 @@ static ssize_t fuse_cache_write_iter(struct kiocb *iocb, 
struct iov_iter *from)
        struct file *file = iocb->ki_filp;
        struct address_space *mapping = file->f_mapping;
        ssize_t written = 0;
-       ssize_t written_buffered = 0;
        struct inode *inode = mapping->host;
        ssize_t err;
        struct fuse_conn *fc = get_fuse_conn(inode);
-       loff_t endbyte = 0;
 
        if (fc->writeback_cache) {
                /* Update size (EOF optimization) and mode (SUID clearing) */
@@ -1378,35 +1379,12 @@ static ssize_t fuse_cache_write_iter(struct kiocb 
*iocb, struct iov_iter *from)
                goto out;
 
        if (iocb->ki_flags & IOCB_DIRECT) {
-               loff_t pos = iocb->ki_pos;
                written = generic_file_direct_write(iocb, from);
-               if (written < 0 || !iov_iter_count(from))
-                       goto out;
-
-               pos += written;
-
-               written_buffered = fuse_perform_write(iocb, mapping, from, pos);
-               if (written_buffered < 0) {
-                       err = written_buffered;
-                       goto out;
-               }
-               endbyte = pos + written_buffered - 1;
-
-               err = filemap_write_and_wait_range(file->f_mapping, pos,
-                                                  endbyte);
-               if (err)
-                       goto out;
-
-               invalidate_mapping_pages(file->f_mapping,
-                                        pos >> PAGE_SHIFT,
-                                        endbyte >> PAGE_SHIFT);
-
-               written += written_buffered;
-               iocb->ki_pos = pos + written_buffered;
+               if (written >= 0 && iov_iter_count(from))
+                       written = direct_write_fallback(iocb, from, written,
+                                       fuse_perform_write(iocb, from));
        } else {
-               written = fuse_perform_write(iocb, mapping, from, iocb->ki_pos);
-               if (written >= 0)
-                       iocb->ki_pos += written;
+               written = fuse_perform_write(iocb, from);
        }
 out:
        current->backing_dev_info = NULL;
-- 
2.39.2

Reply via email to