Loading fs/fuse/file.c +31 −20 Original line number Diff line number Diff line Loading @@ -528,6 +528,17 @@ static void fuse_release_user_pages(struct fuse_req *req, int write) } } static ssize_t fuse_get_res_by_io(struct fuse_io_priv *io) { if (io->err) return io->err; if (io->bytes >= 0 && io->write) return -EIO; return io->bytes < 0 ? io->size : io->bytes; } /** * In case of short read, the caller sets 'pos' to the position of * actual end of fuse request in IO request. Otherwise, if bytes_requested Loading @@ -546,6 +557,7 @@ static void fuse_release_user_pages(struct fuse_req *req, int write) */ static void fuse_aio_complete(struct fuse_io_priv *io, int err, ssize_t pos) { bool is_sync = is_sync_kiocb(io->iocb); int left; spin_lock(&io->lock); Loading @@ -555,19 +567,14 @@ static void fuse_aio_complete(struct fuse_io_priv *io, int err, ssize_t pos) io->bytes = pos; left = --io->reqs; if (!left && is_sync) complete(io->done); spin_unlock(&io->lock); if (!left) { long res; if (io->err) res = io->err; else if (io->bytes >= 0 && io->write) res = -EIO; else { res = io->bytes < 0 ? io->size : io->bytes; if (!left && !is_sync) { ssize_t res = fuse_get_res_by_io(io); if (!is_sync_kiocb(io->iocb)) { if (res >= 0) { struct inode *inode = file_inode(io->iocb->ki_filp); struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_inode *fi = get_fuse_inode(inode); Loading @@ -576,7 +583,6 @@ static void fuse_aio_complete(struct fuse_io_priv *io, int err, ssize_t pos) fi->attr_version = ++fc->attr_version; spin_unlock(&fc->lock); } } aio_complete(io->iocb, res, 0); kfree(io); Loading Loading @@ -2801,6 +2807,7 @@ static ssize_t fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, loff_t offset) { DECLARE_COMPLETION_ONSTACK(wait); ssize_t ret = 0; struct file *file = iocb->ki_filp; struct fuse_file *ff = file->private_data; Loading Loading @@ -2852,6 +2859,9 @@ fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, if (!is_sync_kiocb(iocb) && (offset + count > i_size) && rw == WRITE) io->async = false; if (io->async && is_sync_kiocb(iocb)) io->done = &wait; if (rw == WRITE) ret = __fuse_direct_write(io, iter, &pos); else Loading @@ -2864,11 +2874,12 @@ fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, if (!is_sync_kiocb(iocb)) return -EIOCBQUEUED; ret = wait_on_sync_kiocb(iocb); } else { kfree(io); wait_for_completion(&wait); ret = fuse_get_res_by_io(io); } kfree(io); if (rw == WRITE) { if (ret > 0) fuse_write_update_size(inode, pos); Loading fs/fuse/fuse_i.h +1 −0 Original line number Diff line number Diff line Loading @@ -263,6 +263,7 @@ struct fuse_io_priv { int err; struct kiocb *iocb; struct file *file; struct completion *done; }; /** Loading Loading
fs/fuse/file.c +31 −20 Original line number Diff line number Diff line Loading @@ -528,6 +528,17 @@ static void fuse_release_user_pages(struct fuse_req *req, int write) } } static ssize_t fuse_get_res_by_io(struct fuse_io_priv *io) { if (io->err) return io->err; if (io->bytes >= 0 && io->write) return -EIO; return io->bytes < 0 ? io->size : io->bytes; } /** * In case of short read, the caller sets 'pos' to the position of * actual end of fuse request in IO request. Otherwise, if bytes_requested Loading @@ -546,6 +557,7 @@ static void fuse_release_user_pages(struct fuse_req *req, int write) */ static void fuse_aio_complete(struct fuse_io_priv *io, int err, ssize_t pos) { bool is_sync = is_sync_kiocb(io->iocb); int left; spin_lock(&io->lock); Loading @@ -555,19 +567,14 @@ static void fuse_aio_complete(struct fuse_io_priv *io, int err, ssize_t pos) io->bytes = pos; left = --io->reqs; if (!left && is_sync) complete(io->done); spin_unlock(&io->lock); if (!left) { long res; if (io->err) res = io->err; else if (io->bytes >= 0 && io->write) res = -EIO; else { res = io->bytes < 0 ? io->size : io->bytes; if (!left && !is_sync) { ssize_t res = fuse_get_res_by_io(io); if (!is_sync_kiocb(io->iocb)) { if (res >= 0) { struct inode *inode = file_inode(io->iocb->ki_filp); struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_inode *fi = get_fuse_inode(inode); Loading @@ -576,7 +583,6 @@ static void fuse_aio_complete(struct fuse_io_priv *io, int err, ssize_t pos) fi->attr_version = ++fc->attr_version; spin_unlock(&fc->lock); } } aio_complete(io->iocb, res, 0); kfree(io); Loading Loading @@ -2801,6 +2807,7 @@ static ssize_t fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, loff_t offset) { DECLARE_COMPLETION_ONSTACK(wait); ssize_t ret = 0; struct file *file = iocb->ki_filp; struct fuse_file *ff = file->private_data; Loading Loading @@ -2852,6 +2859,9 @@ fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, if (!is_sync_kiocb(iocb) && (offset + count > i_size) && rw == WRITE) io->async = false; if (io->async && is_sync_kiocb(iocb)) io->done = &wait; if (rw == WRITE) ret = __fuse_direct_write(io, iter, &pos); else Loading @@ -2864,11 +2874,12 @@ fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, if (!is_sync_kiocb(iocb)) return -EIOCBQUEUED; ret = wait_on_sync_kiocb(iocb); } else { kfree(io); wait_for_completion(&wait); ret = fuse_get_res_by_io(io); } kfree(io); if (rw == WRITE) { if (ret > 0) fuse_write_update_size(inode, pos); Loading
fs/fuse/fuse_i.h +1 −0 Original line number Diff line number Diff line Loading @@ -263,6 +263,7 @@ struct fuse_io_priv { int err; struct kiocb *iocb; struct file *file; struct completion *done; }; /** Loading