From patchwork Tue Apr 25 18:52:31 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Shilovskiy X-Patchwork-Id: 9699455 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 4F531601D3 for ; Tue, 25 Apr 2017 18:54:12 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3E1E12864B for ; Tue, 25 Apr 2017 18:54:12 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 32D4D28650; Tue, 25 Apr 2017 18:54:12 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 72E892864B for ; Tue, 25 Apr 2017 18:54:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1953531AbdDYSyK (ORCPT ); Tue, 25 Apr 2017 14:54:10 -0400 Received: from mail-cys01nam02on0135.outbound.protection.outlook.com ([104.47.37.135]:14992 "EHLO NAM02-CY1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1951843AbdDYSyI (ORCPT ); Tue, 25 Apr 2017 14:54:08 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=B74+5IyIjOt7xjDUGA7kYhM9o9s4rCqUzgMKvs6D84w=; b=IBzf3ethaF4GgAG8yGIXUUV+GqCspIrDklT+kjvVBrcQRhbHxdJzw/CojZqaNTUQOzeop1jThR82tTwAh+ndRaTnR8f1d7RZNdjMxCdeFa8d1VVYMKiSZxwUl9pLn5sWwsWVXQPQHsCjq6Q0EtyatnMUAVQ8LdhSpmZgy271NK0= Authentication-Results: vger.kernel.org; dkim=none (message not signed) header.d=none;vger.kernel.org; dmarc=none action=none header.from=microsoft.com; Received: from ubuntu-vm.corp.microsoft.com (2001:4898:80e8:5::63b) by CY4PR03MB2551.namprd03.prod.outlook.com (10.173.41.150) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1019.17; Tue, 25 Apr 2017 18:52:46 +0000 From: Pavel Shilovsky To: linux-cifs@vger.kernel.org Cc: piastryyy@gmail.com, Steve French , Jeff Layton Subject: [PATCH v2 3/3] CIFS: Add asynchronous write support through kernel AIO Date: Tue, 25 Apr 2017 11:52:31 -0700 Message-Id: <1493146351-124933-4-git-send-email-pshilov@microsoft.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1493146351-124933-1-git-send-email-pshilov@microsoft.com> References: <1493146351-124933-1-git-send-email-pshilov@microsoft.com> MIME-Version: 1.0 X-Originating-IP: [2001:4898:80e8:5::63b] X-ClientProxiedBy: BN6PR1601CA0008.namprd16.prod.outlook.com (10.172.104.146) To CY4PR03MB2551.namprd03.prod.outlook.com (10.173.41.150) X-MS-Office365-Filtering-Correlation-Id: bbcef2e8-2830-4ecb-cf72-08d48c0c43b5 X-MS-Office365-Filtering-HT: Tenant X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001)(48565401081)(201703131423075)(201703031133081); SRVR:CY4PR03MB2551; X-Microsoft-Exchange-Diagnostics: 1; CY4PR03MB2551; 3:iVpHQOITj980Zd7Vb3imlO7J4/jwFGk064mq3rOdJf2xWD42SXb85EpvdaaR0daxWGkVidM3WqkwzaeYnXpqiRoCbxkSZ8axtRG7LSAJiUbkfd4CXLbA6nje4NoC+BpPCUndKwc+TcfXhJRPvQWkLhNOrhYwOLLOICx5yd9PTwC3Cq7+vrNgpdJ/3LSEZxWAshrj96B41CLhaxUnE3ttzOvn9pVMEXMFIU2Wwh20roBZm7FklKFb9BOMtrxpSa51e2769ANHsp/RO22MmHK3EhYrrb2lv+lmx7jZopfdIHxl0ETuzejXGltzslG/iEKdIvFaZXoOxxflAC4HR6m6ctiAbhzzfDGHhfORWNtkLKI=; 25:pi4qtnisGanD3S488802YFJ2AI3y8BplzcH2M3ktC2skcQh/cbuCg6ym3Y6vaDKjBaEpthEHoT5YRV59f1bpZzCgTcp5/yHNWK5YvBuqr/6B6CaxYWSrCQY4cKIhS/Y7aMsshzNJz093TgsODJIGTh7NCHr1OPzQ2N9xK2D+k7tT+NyqtDdFl7jyYRpBDXqbj/OEDVTrDy5EcnlhpoJxiqwut4MQWe0ugbnrhnnX2MysP39NFwXO32JVGM8vezDLVtWAXSEdNbdE2nYWM63Ir/g930PxwpyDnKPbsuoVu3x6lqciSZxgWadGXQ0ursJsCtj0r0E4a5gNrYRYBc40GzkmgwiF19y9byB2DNzdtyRQL/FcoVDTgUMdiINYLFCE2q436usD4RABX7/sD+Qudph1pkbp+oBiUXDCTv6osSfLdyy625UozOZsKrAhrCzQxC0OeuFDXAh7L5bOTPWlkg== X-Microsoft-Exchange-Diagnostics: 1; CY4PR03MB2551; 31:ur/+sC9RFb1qbP7K3O2UCzbXlpNXRznup+tkY4lGIwiBa4unhvSDoGhWU7hB7f7ie/fwJMl5OVLpVWbclignsKcHnLYEu7PuAzgetePd2x7sb/IV+4fbOJ1Pvo0N5f2cLmJVeaG640FNrbAYB0E8uwIo1HYMYVudJIxQuljDTQZw+yzQH6N5LP5B66miKuSnDxCaCd8zAWFo+MmkaNhgaCyJznKCrFR//nKo464Slm9eb8lkKuDqqLhpr0vGyg/Yg/VGsn+cyEDLVn6K2c/7Jw==; 20:pDYYPYHyjrTI42LG8NGFe77itSXPPzpVkUp8c0ElTQZkYTJnQVMoEfM31E1Jnq5nmCaciMMjeTQFETmn0lElyY+gaj7bJkN0DNJAwP0aQulqjdnT4dYbEaEy1FzSdmMfoR/Bi3YftX0bpyeb2GsTtfYZcdRwkAdNzxI+PEmdSfup1HK7bVxlhQSm6txMsEhg/byHgvP0qLVg8o1c14UrXXaZItoGxQ4I2aPjbgijN+30rp65vlQtlg03kh/U0/HdXahyFHjPKkvjy/Rt3edlB3qpWaI14w0J9jFdZujowv9sk2GtFRCoxImb1t4QIvYjnu2RSLCd5T/uxqcPRmSIvC+6MGiYOf2A7fOmBdKqcelH4Ebh/jbey6a5CKjEJsfJsltgen98RwIxnn42CuH3Nvq9b+RfrYPcl6RggZDwXxUKCfirj+lXNKuZP0v+T0YmcK6rMLg3qm5OJNCQdIzpMxNTckc9R1YYkW+v1OxQ8KOkP0Bj1lxcmD3KB6G0a+wc X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(278428928389397); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040450)(601004)(2401047)(8121501046)(5005006)(3002001)(10201501046)(93006095)(93001095)(6055026)(6041248)(20161123564025)(20161123562025)(20161123555025)(20161123560025)(201703131423075)(201702281528075)(201703061421075)(6072148); SRVR:CY4PR03MB2551; BCL:0; PCL:0; RULEID:; SRVR:CY4PR03MB2551; X-Microsoft-Exchange-Diagnostics: 1; CY4PR03MB2551; 4:1oS0g4/Z4iyidtGgJLtSKYhjPYYD1hp+4ceaIpCvNiNIfWOwOR6wH9tbWQ7w09OBU7TlhGwc0OqZjlGs8M2M37DjzGke9KLq11SpR6XDym55a9RC6peGNCBjOOr0FS4U/zHYtSobdUKIf1Ht6kT/XnP7iPXDNfErgENkxLaNGtX+t1mcVcX9Osw1uFzbjLXJ0lQiE5wIEzSygf0QV63dNECCjTXtHk6/taG+tFZbceZ0Bl/+I8Co6taeyt8anD6QlnBd7W5s/vDpoVVJimpw213Usha/YF6TTlF41fmwHDOeI02Y5fCWrXUydTcDS1TYyzC1OsgEq6M3rYtTHhtrHuYsqLsi0zRTZpmuic42s28+ptfaxvHoOOjNCbNocNqu3h/U9KVNeSak2jGMx0lI5lWD8nXV0FlzQ9tgj6lCK5Avh13bji+yJqFkRogHR3T96REdmcePrng2WAshv0GJbcjjB4OJW7iJIzFGF4IPsRTqUiP7AqT2Aa01kXRhMgad/siY6wEA0mUpunI4gnULjfgLkk5/vzJKTBoy/g7x6jgszxvlfst9Rd63WxQyBENjAqon17MXuMo+HQ1idwQK92qkJy0dRhATAY2KxawU2cDwuifsYEIEsISE9fM7EHD2Li7+YYgRJIFgDS17nu8gBK8atJtXhNPLkUJS+aDeTABlx5vo/ZVVc+P39/Y0zBpxF5oOgTr49Uppn9cxno1eE8Svaeokan/udb+DOzMzezosbjCNcaZ3qQDkNuwDgOzL/aLeHwXdnDYgR90YKP7j9g== X-Forefront-PRVS: 0288CD37D9 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10019020)(4630300001)(979002)(6009001)(39410400002)(39450400003)(39860400002)(39840400002)(39850400002)(39400400002)(76176999)(6486002)(25786009)(38730400002)(48376002)(6916009)(5003940100001)(50466002)(42186005)(6116002)(4326008)(2351001)(10090500001)(7736002)(33646002)(6666003)(189998001)(50986999)(106356001)(2361001)(8676002)(86362001)(110136004)(36756003)(86612001)(2950100002)(81166006)(53936002)(50226002)(575784001)(2906002)(5660300001)(54906002)(5005710100001)(305945005)(47776003)(10290500003)(969003)(989001)(999001)(1009001)(1019001); DIR:OUT; SFP:1102; SCL:1; SRVR:CY4PR03MB2551; H:ubuntu-vm.corp.microsoft.com; FPR:; SPF:None; MLV:ovrnspm; PTR:InfoNoRecords; LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; CY4PR03MB2551; 23:tZiBNT1q0oe32CO0lxJDg0MBN8/LrHEOHTDaScJ6F?= =?us-ascii?Q?O3OCI1E1hU/y3xbFONrH/saLVCA2c+xi7+rX+kY4wdmQiKWI+dlbXmgtO/LV?= =?us-ascii?Q?ounYLtShgUwlCMu6+R7myq0+XlEQLxFcxVFDqCsFaabHN3me9RthH57beynU?= =?us-ascii?Q?ToIVSxwdJr9Fdfaq0vuKkScNH2LpSX8fuzTTZ/n+ROzZI0Qrt4tJV64OirHi?= =?us-ascii?Q?H/4O53dMmEme1ISFX0/8b8MezjDMb/FywOU18O3DICd6FPdKSme9Fa9QVv8d?= =?us-ascii?Q?1W5Sw7WfcD9FCPqTlU85t6CrtBUKr0f5SXSK8neYVpiE4/N19XwsJuS3oZbA?= =?us-ascii?Q?2jmD4gN+MJr/IrPGevaEulkVOG3hZ3CT3NxUUuaEM/sS0+2of1i/ILSYbZGD?= =?us-ascii?Q?T1zu9tGjsZXdlBuUbzM6hdKCtHsHK3eH1vYFUZtr6gI84ZVcGpJl8LFjmuBo?= =?us-ascii?Q?/zuNW5VtfR8Qt+9F+Kl2pU1SgbpKDumwmYZu6t/ptj/e+2iJQsiwUWmcPTEh?= =?us-ascii?Q?yZaekyFGe26AORJg4l0EJThpY1TKUgWiUQKt+omNMSwtZZCCZYaC7Ju1KtK6?= =?us-ascii?Q?KumAKl+VX+f0Yg/TWvsoCNE3x4rcvDI3r2GUyltFoFpR7GL5GsZPQHCp8pnr?= =?us-ascii?Q?OXFFgcm2jD2dvwTR6hNukTp0NdHXgeYfxHEyyPYS46F5p/+VMmqh0eb0wZUR?= =?us-ascii?Q?mZ0pBuNFLKy9fE7SXR2d7kEZV1XockJnTYShYKe2XYJKVZN2AR9Sy46YBGLk?= =?us-ascii?Q?WGcXo9lYoDvMRq34hLXYIVmI8zctnw8azlMm4YecZWSXK1WdT3mMy41h8Gtf?= =?us-ascii?Q?/lHBOdBxzN6PEJKR9c6dVFRy0Ikgk3OeR3ExbnfzGnmnqkv2M7doq7h/E7Q/?= =?us-ascii?Q?672JoGgGJGnRXF620PWu9T2lY4ovQi0E/hCbq7tTBZ2Dvc3dScJeBAQp3Jdx?= =?us-ascii?Q?MV5luGsVOEeSSkmGANSlyRQ/neYlcCkcrTgDJjg+0dmuEiDTPb5VS+Atp+7d?= =?us-ascii?Q?tUuwiIzfpU63d1NSVa6rXbTJ70m9w4JhOgS+ztcjQi20pPlUw90L5+T3jOm1?= =?us-ascii?Q?pBx/CDXaUhO3AL9oFRrZip0iPYXRtshK0/TUA3hwpbHJkpY04kOk6YkUeF0u?= =?us-ascii?Q?kuqyJquftLYPE7pdSqtqn7BoUylsxzdHLDXB52drsOwqdZVVrRRKCRSSaccp?= =?us-ascii?Q?q57bVskThwL57v4f6ewPEGW0LY5rQ4GCiqosvZSQ3M0L8ce1mKrfPX2JEz0N?= =?us-ascii?Q?4v4Gs//sB/w/8EGOy5p9oRO9RD3o8jQAIAUZ6bt?= X-Microsoft-Exchange-Diagnostics: 1; CY4PR03MB2551; 6:0E2suJdEkF1UXu8RMy8W8ZIVvIuw0GVpV867Dp+CTdDNzp5mKqT+Q12JWm2jP8fhPsM0M5nfE6oWDA3W0HkrZ1XZzBrlL13r0UfOS/RfmfFg11D9qOfm9YGuWrnImf6ikB64EmvuScyAJpksjnd/Q8guJztVgmajzdRWqQwxndci+OS4NbsmwpgEzQn+LQKjdD9ivqtaqOC++417q9ARgKNGKk6RC59h90PBtuVJJAfcwpczcqzS5cYDJd2WcYGG+ZLwr8hAiz48EOuu7OrDzQrNXbklAGXc3uRF5wR0Le8KqtGVlHg3LpRfll2NADVMr31l3vLe3AehqtDlfGcdVcKc5v0jlStesad06zvZKUZJXbXkxgGrEs3KyFzh3MNq6JkbGQsoUNjPZOxBbPaawbkoTj3gcs2Ix+S0eRWnbemjzbnTJEP71INZrc8T+tMDAi1uyMNwEUA3wtrg2oJzZ16GFQwa13gS9d2NHwZKImNwtIECKwd1BhGFFrUDUYaoWItZUTf0EgYoiQTxLx4/YWvJjKJpNrPKlbiEbET6Ce4=; 5:SORF8RY1H4j0YitFODcfEIQrSu8PtIW6lH0f8WmNeYXyvPe/rzcrIkTo9GpVqiotzdUjEhQpVvv8l5eGMEypEcbSQrc6q+vrUtpz/ndPmR3Hc19sRnt38j0F4YG56ztqCSsuxZirO7wziicratabhA==; 24:n0X46c3DP8iZ77ZteEXJNLBzaaqieQEIxCe96CsMWEs4IoQDg6zZFszR+xzB+TkBlvarxugm/oH7ywT05VR/6+wcxCafTm8GQKRoc3IHiCo= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; CY4PR03MB2551; 7:bVEiwfQD0loyCScRi0moiaKqLq9nbj97WkDpW1tWzW48LJixI1dDcGk3/eXpI1d5a5bMUggfIIoxmJhvoR94tWSYO2NYgybxblPF2kEqWOMyHwd/eAe60GF2hckBEzXU5Z5cL9aBXdF1LjjlwGwGkyoob1hMn02f0FgtdKGDzziovnxtxgooDI9gAcfqLE0dDeAnQ7eAN6BJN7m+AEHH22CqdCqAw26Lza41ENqxNYISs7XIvkSlI2VRucBAff/ja4t04xO5VeEG1uvamNXkMqZ8LsndJQSMa0UmdMbYcCPXvk0ZoOciJq0gfCXyiKsYw/0l+9J2cQRExYPihSRRZw== X-OriginatorOrg: microsoft.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 25 Apr 2017 18:52:46.1770 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY4PR03MB2551 Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds support to process write calls passed by io_submit() asynchronously. It based on the previously introduced async context that allows to process i/o responses in a separate thread and return the caller immediately for asynchronous calls. This improves writing performance of single threaded applications with increasing of i/o queue depth size. Signed-off-by: Pavel Shilovsky --- fs/cifs/cifsglob.h | 2 + fs/cifs/file.c | 188 ++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 139 insertions(+), 51 deletions(-) diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 9438c7c..5c0e11a 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -1124,6 +1124,7 @@ struct cifs_aio_ctx { struct kiocb *iocb; struct cifsFileInfo *cfile; struct bio_vec *bv; + loff_t pos; unsigned int npages; ssize_t rc; unsigned int len; @@ -1171,6 +1172,7 @@ struct cifs_writedata { enum writeback_sync_modes sync_mode; struct work_struct work; struct cifsFileInfo *cfile; + struct cifs_aio_ctx *ctx; __u64 offset; pid_t pid; unsigned int bytes; diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 9564e2c..6ef78ad 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -2458,11 +2458,14 @@ cifs_uncached_writedata_release(struct kref *refcount) struct cifs_writedata *wdata = container_of(refcount, struct cifs_writedata, refcount); + kref_put(&wdata->ctx->refcount, cifs_aio_ctx_release); for (i = 0; i < wdata->nr_pages; i++) put_page(wdata->pages[i]); cifs_writedata_release(refcount); } +static void collect_uncached_write_data(struct cifs_aio_ctx *ctx); + static void cifs_uncached_writev_complete(struct work_struct *work) { @@ -2478,7 +2481,8 @@ cifs_uncached_writev_complete(struct work_struct *work) spin_unlock(&inode->i_lock); complete(&wdata->done); - + collect_uncached_write_data(wdata->ctx); + /* the below call can possibly free the last ref to aio ctx */ kref_put(&wdata->refcount, cifs_uncached_writedata_release); } @@ -2527,7 +2531,8 @@ wdata_fill_from_iovec(struct cifs_writedata *wdata, struct iov_iter *from, static int cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, struct cifsFileInfo *open_file, - struct cifs_sb_info *cifs_sb, struct list_head *wdata_list) + struct cifs_sb_info *cifs_sb, struct list_head *wdata_list, + struct cifs_aio_ctx *ctx) { int rc = 0; size_t cur_len; @@ -2595,6 +2600,8 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, wdata->pagesz = PAGE_SIZE; wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE); wdata->credits = credits; + wdata->ctx = ctx; + kref_get(&ctx->refcount); if (!wdata->cfile->invalidHandle || !(rc = cifs_reopen_file(wdata->cfile, false))) @@ -2620,81 +2627,61 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, return rc; } -ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from) +static void collect_uncached_write_data(struct cifs_aio_ctx *ctx) { - struct file *file = iocb->ki_filp; - ssize_t total_written = 0; - struct cifsFileInfo *open_file; + struct cifs_writedata *wdata, *tmp; struct cifs_tcon *tcon; struct cifs_sb_info *cifs_sb; - struct cifs_writedata *wdata, *tmp; - struct list_head wdata_list; - struct iov_iter saved_from = *from; + struct dentry *dentry = ctx->cfile->dentry; + unsigned int i; int rc; - /* - * BB - optimize the way when signing is disabled. We can drop this - * extra memory-to-memory copying and use iovec buffers for constructing - * write request. - */ - - rc = generic_write_checks(iocb, from); - if (rc <= 0) - return rc; - - INIT_LIST_HEAD(&wdata_list); - cifs_sb = CIFS_FILE_SB(file); - open_file = file->private_data; - tcon = tlink_tcon(open_file->tlink); - - if (!tcon->ses->server->ops->async_writev) - return -ENOSYS; + tcon = tlink_tcon(ctx->cfile->tlink); + cifs_sb = CIFS_SB(dentry->d_sb); - rc = cifs_write_from_iter(iocb->ki_pos, iov_iter_count(from), from, - open_file, cifs_sb, &wdata_list); + mutex_lock(&ctx->aio_mutex); - /* - * If at least one write was successfully sent, then discard any rc - * value from the later writes. If the other write succeeds, then - * we'll end up returning whatever was written. If it fails, then - * we'll get a new rc value from that. - */ - if (!list_empty(&wdata_list)) - rc = 0; + if (list_empty(&ctx->list)) { + mutex_unlock(&ctx->aio_mutex); + return; + } + rc = ctx->rc; /* * Wait for and collect replies for any successful sends in order of - * increasing offset. Once an error is hit or we get a fatal signal - * while waiting, then return without waiting for any more replies. + * increasing offset. Once an error is hit, then return without waiting + * for any more replies. */ restart_loop: - list_for_each_entry_safe(wdata, tmp, &wdata_list, list) { + list_for_each_entry_safe(wdata, tmp, &ctx->list, list) { if (!rc) { - /* FIXME: freezable too? */ - rc = wait_for_completion_killable(&wdata->done); - if (rc) - rc = -EINTR; - else if (wdata->result) + if (!try_wait_for_completion(&wdata->done)) { + mutex_unlock(&ctx->aio_mutex); + return; + } + + if (wdata->result) rc = wdata->result; else - total_written += wdata->bytes; + ctx->total_len += wdata->bytes; /* resend call if it's a retryable error */ if (rc == -EAGAIN) { struct list_head tmp_list; - struct iov_iter tmp_from = saved_from; + struct iov_iter tmp_from = ctx->iter; INIT_LIST_HEAD(&tmp_list); list_del_init(&wdata->list); iov_iter_advance(&tmp_from, - wdata->offset - iocb->ki_pos); + wdata->offset - ctx->pos); rc = cifs_write_from_iter(wdata->offset, wdata->bytes, &tmp_from, - open_file, cifs_sb, &tmp_list); + ctx->cfile, cifs_sb, &tmp_list, + ctx); - list_splice(&tmp_list, &wdata_list); + list_splice(&tmp_list, &ctx->list); kref_put(&wdata->refcount, cifs_uncached_writedata_release); @@ -2705,12 +2692,111 @@ ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from) kref_put(&wdata->refcount, cifs_uncached_writedata_release); } + for (i = 0; i < ctx->npages; i++) + put_page(ctx->bv[i].bv_page); + + cifs_stats_bytes_written(tcon, ctx->total_len); + set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(dentry->d_inode)->flags); + + ctx->rc = (rc == 0) ? ctx->total_len : rc; + + mutex_unlock(&ctx->aio_mutex); + + if (ctx->iocb && ctx->iocb->ki_complete) + ctx->iocb->ki_complete(ctx->iocb, ctx->rc, 0); + else + complete(&ctx->done); +} + +ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from) +{ + struct file *file = iocb->ki_filp; + ssize_t total_written = 0; + struct cifsFileInfo *cfile; + struct cifs_tcon *tcon; + struct cifs_sb_info *cifs_sb; + struct cifs_aio_ctx *ctx; + struct iov_iter saved_from = *from; + int rc; + + /* + * BB - optimize the way when signing is disabled. We can drop this + * extra memory-to-memory copying and use iovec buffers for constructing + * write request. + */ + + rc = generic_write_checks(iocb, from); + if (rc <= 0) + return rc; + + cifs_sb = CIFS_FILE_SB(file); + cfile = file->private_data; + tcon = tlink_tcon(cfile->tlink); + + if (!tcon->ses->server->ops->async_writev) + return -ENOSYS; + + ctx = cifs_aio_ctx_alloc(); + if (!ctx) + return -ENOMEM; + + ctx->cfile = cifsFileInfo_get(cfile); + + if (!is_sync_kiocb(iocb)) + ctx->iocb = iocb; + + ctx->pos = iocb->ki_pos; + + rc = setup_aio_ctx_iter(ctx, from, WRITE); + if (rc) { + kref_put(&ctx->refcount, cifs_aio_ctx_release); + return rc; + } + + /* grab a lock here due to read response handlers can access ctx */ + mutex_lock(&ctx->aio_mutex); + + rc = cifs_write_from_iter(iocb->ki_pos, ctx->len, &saved_from, + cfile, cifs_sb, &ctx->list, ctx); + + /* + * If at least one write was successfully sent, then discard any rc + * value from the later writes. If the other write succeeds, then + * we'll end up returning whatever was written. If it fails, then + * we'll get a new rc value from that. + */ + if (!list_empty(&ctx->list)) + rc = 0; + + mutex_unlock(&ctx->aio_mutex); + + if (rc) { + kref_put(&ctx->refcount, cifs_aio_ctx_release); + return rc; + } + + if (!is_sync_kiocb(iocb)) { + kref_put(&ctx->refcount, cifs_aio_ctx_release); + return -EIOCBQUEUED; + } + + rc = wait_for_completion_killable(&ctx->done); + if (rc) { + mutex_lock(&ctx->aio_mutex); + ctx->rc = rc = -EINTR; + total_written = ctx->total_len; + mutex_unlock(&ctx->aio_mutex); + } else { + rc = ctx->rc; + total_written = ctx->total_len; + } + + kref_put(&ctx->refcount, cifs_aio_ctx_release); + if (unlikely(!total_written)) return rc; iocb->ki_pos += total_written; - set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(file_inode(file))->flags); - cifs_stats_bytes_written(tcon, total_written); return total_written; }