From patchwork Sat Jan 31 03:01:33 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxim Patlasov X-Patchwork-Id: 5753861 Return-Path: X-Original-To: patchwork-linux-fsdevel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id A8CA49F336 for ; Sat, 31 Jan 2015 03:01:47 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C3A8C2025B for ; Sat, 31 Jan 2015 03:01:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D00F9201EF for ; Sat, 31 Jan 2015 03:01:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754399AbbAaDBj (ORCPT ); Fri, 30 Jan 2015 22:01:39 -0500 Received: from relay.parallels.com ([195.214.232.42]:60898 "EHLO relay.parallels.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752531AbbAaDBj (ORCPT ); Fri, 30 Jan 2015 22:01:39 -0500 Received: from [10.10.39.160] by relay.parallels.com with esmtp (Exim 4.84) (envelope-from ) id 1YHOJV-0002Br-2M; Sat, 31 Jan 2015 06:01:37 +0300 Subject: Re: [PATCH 1/5] fs: don't allow to complete sync iocbs through aio_complete From: Maxim Patlasov To: hch@lst.de Cc: linux-fsdevel@vger.kernel.org, linux-aio@kvack.org, mszeredi@suse.cz, viro@zeniv.linux.org.uk Date: Fri, 30 Jan 2015 19:01:33 -0800 Message-ID: <20150131025520.12941.61643.stgit@R90AM809-1175L> In-Reply-To: <20150128165737.GB17313@lst.de> References: <20150128165737.GB17313@lst.de> User-Agent: StGit/0.17-dirty MIME-Version: 1.0 Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP On 01/28/2015 08:57 AM, Christoph Hellwig wrote: > On Wed, Jan 28, 2015 at 04:30:25PM +0100, Miklos Szeredi wrote: >> Adding Maxim Patlasov, who did the AIO mode in fuse. > > FYI, I don't think fuse should be too hard, it just needs a completion > in struct fuse_io_priv. I just didn't bother before getting some higher > level review for the concept. Yes, I agree. Here is an example implementation below. --- fs/fuse/file.c | 75 ++++++++++++++++++++++++++++++++++++++---------------- fs/fuse/fuse_i.h | 1 + 2 files changed, 54 insertions(+), 22 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/fs/fuse/file.c b/fs/fuse/file.c index d2be147..b82207a 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -528,6 +528,18 @@ 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 @@ -547,6 +559,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) { int left; + bool is_sync = is_sync_kiocb(io->iocb); spin_lock(&io->lock); if (err) @@ -555,27 +568,25 @@ static void fuse_aio_complete(struct fuse_io_priv *io, int err, ssize_t pos) io->bytes = pos; left = --io->reqs; - spin_unlock(&io->lock); - if (!left) { - long res; + if (!left && is_sync) { + if (io->waiter) + wake_up_process(io->waiter); + } - if (io->err) - res = io->err; - else if (io->bytes >= 0 && io->write) - res = -EIO; - else { - res = io->bytes < 0 ? io->size : io->bytes; + spin_unlock(&io->lock); - if (!is_sync_kiocb(io->iocb)) { - 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); + if (!left && !is_sync) { + ssize_t res = fuse_get_res_by_io(io); - spin_lock(&fc->lock); - fi->attr_version = ++fc->attr_version; - spin_unlock(&fc->lock); - } + 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); + + spin_lock(&fc->lock); + fi->attr_version = ++fc->attr_version; + spin_unlock(&fc->lock); } io->iocb->complete(io->iocb, res); @@ -2798,6 +2809,29 @@ static inline loff_t fuse_round_up(loff_t off) return round_up(off, FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT); } +static ssize_t fuse_dio_wait(struct fuse_io_priv *io) +{ + ssize_t res; + + spin_lock(&io->lock); + + while (io->reqs) { + __set_current_state(TASK_UNINTERRUPTIBLE); + io->waiter = current; + spin_unlock(&io->lock); + io_schedule(); + /* wake up sets us TASK_RUNNING */ + spin_lock(&io->lock); + io->waiter = NULL; + } + + spin_unlock(&io->lock); + + res = fuse_get_res_by_io(io); + kfree(io); + return res; +} + static ssize_t fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, loff_t offset) @@ -2841,10 +2875,8 @@ fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, /* * By default, we want to optimize all I/Os with async request * submission to the client filesystem if supported. - * - * XXX: need to add back support for this mode.. */ - io->async = async_dio && !is_sync_kiocb(iocb); + io->async = async_dio; io->iocb = iocb; /* @@ -2867,8 +2899,7 @@ fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, if (!is_sync_kiocb(iocb)) return -EIOCBQUEUED; - // XXX: need fuse specific replacement -// ret = wait_on_sync_kiocb(iocb); + ret = fuse_dio_wait(io); } else { kfree(io); } diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 1cdfb07..8d4872b 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -263,6 +263,7 @@ struct fuse_io_priv { int err; struct kiocb *iocb; struct file *file; + struct task_struct *waiter; }; /**