From patchwork Tue Apr 25 18:52:30 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Shilovskiy X-Patchwork-Id: 9699453 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 5EF16601D3 for ; Tue, 25 Apr 2017 18:54:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4DD3D2864D for ; Tue, 25 Apr 2017 18:54:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 42B8C28651; Tue, 25 Apr 2017 18:54:10 +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 9125F2864D for ; Tue, 25 Apr 2017 18:54:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1953530AbdDYSyJ (ORCPT ); Tue, 25 Apr 2017 14:54:09 -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 S1953528AbdDYSyH (ORCPT ); Tue, 25 Apr 2017 14:54:07 -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=5wG1TZIvGAMiqkMzTtNZN5pEh/bALes7C6W5PyjMJ0A=; b=jN4K5lr0ZypzcX4W9DyLGJm3LkpX6JpiCeHXdCnVLg46U9BzDIiaD5drFfQVZnxn5Pcc/YyRlxzhi+2ADZ/jY0UXNT3XmmLL8/k4MDaGbejpDT7MGtINcvQ7ew7KIfijeTB+w9ok/OZjESXIBmR+ZkiB7ydtJAnCZ5NU1rnOeag= 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:44 +0000 From: Pavel Shilovsky To: linux-cifs@vger.kernel.org Cc: piastryyy@gmail.com, Steve French , Jeff Layton Subject: [PATCH v2 2/3] CIFS: Add asynchronous read support through kernel AIO Date: Tue, 25 Apr 2017 11:52:30 -0700 Message-Id: <1493146351-124933-3-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: bb10b0ed-7676-48ab-2bd7-08d48c0c42e9 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:tGqztB3esNSCjPJy/hAWO4rC1+LcbJoxsfXKrDmZe6Yk9EoFxnbUZhrbktIA8OFvSehTH9iEBVgP10lGRPatWaPyDpsIL+WVkIOwE9Tw2crc3bOAfVE7ZWq4B7ur7isOOgYv16Q0bEUIZIyfMCiH/pm3BaHs3JxE7OQ50QYJH2owXuPc8uUI+L0bxhlOnSXfON59+Eq9dc2wvf1T7RfUbCb286xoJ3QnWGt7rHonjUHHeCFHq/9F+briHdG44IB2pv05EPiD4obVZEvzxqkM8lNHTo8DNzPjq1jP1ydvCToNUFG7Wd1/m9+FRhBI3+vMQ+uB3XKD5HCv1ji2bBYI9ED21bHfSJlTHKlmJK35xLA=; 25:xCSqJ9iPSMKM5fZ76Y+8X9f0TL9XG/l+MteiU1X6uV0h8Qy/scNfK3gtqdPTUTbQdLf2BmKkIU6MnYmum5zoHFztB/2k0HrMxIkN3ZTcJ6NzbzcDLmupYdmT338E22+1Nu4CaJlW0KMDgHEOLk91JvTxM/ni6Hxla9irMQFoBq9YL65ZmR4Tmw08drAa1+dKMAOfGdqasxrI45RgxuWuTx9ZuK/JVDsSKQ0VsEkVr4D62NplOcNSEmqxgukbrb6sZXmKBeqo2TXXVlNmXklNS5HlyOUT9KOQyUFYyKL9y6th0lMqzCNo1TiQSEJVeQh4vkCMA5Fh3882ZObVsukLzXMcyb/P0OHe0fpBSxZonQwTZXFPbOTC1koGRQeEoF6IMnKyYGbdOn/gGpCGfp7SQ7Qixutay8LQFIO7anhtfACax66IER4IjpHcrBSDaU5Wb1AJvUYR8hSwIEJEhGnorA== X-Microsoft-Exchange-Diagnostics: 1; CY4PR03MB2551; 31:9h8XMNej1UMoUf46cKGShaSzcKnEVFxfwQ/tT1o7JL2rAesc5CxBbJSu7Ybn6nSgy17/eXEie5GnMjm3KdJ6L/eh6ezXGDj+KrrHHIcxmWlujWVAzGNAZbrMOYCqg3lB5fSC2IOJyUiubyOgnrsa74d3dJ2Fy96ZQCZqu6L03JZqinIEzJaxh/01cXjPOxBJJi8czE0OPDxHHrV5roGRERh3uyNmUeEHUULRHgDyqW787BEBhrJ6mOX2e8AKTpvaM+q+s0gbJGhSa8SaJyZr/8R6FWecBMyxccqCjn2tf4I=; 20:doTK1lFfYqGFj84X3C8ZbGQ/ZddnRIPmaubiHHvkWD8PQFIguci2i8fxX16QWnE9hirErZidWEVftvZcwWCI882tUBc8KYn35o01AVSfDFuLoSHcZ72HVUp9ISQJ1WnIHqDMs+QEH7RTTcLkHH72OJbdfnixuUsHaXUOiDuH29KNW9hicuKmzuhi3t522QaJoVYRq+0xaov+DkAyblgXxiOIDrihHFOEGrYCLxiuJE/IKAkiVsyO4n6rTLJob+2WOixHCQnfz8DXZxG4bCRw9PyOBHE2o02YxFsCcAycPVRMV7mVuFf3RjJJGTE1kHdis1WGEKbaxOTgLFbjQTN4MWdykGbX4hjr7NQejnollmFNs8wxLUthN1PGemGatOhvxs4helfx3CKlvGqxqlr3pLREC4rKW4lLkjvakpwK7DIBdnAgWKyy8JtOKk8e8m+0R1A2g/Hjxe0HoBTAHmHnZZwX97Apwmmli8ANp9kVMN4IJXBYQ+g+khLLYtOqjHJ4 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:43dgEFo6wZCKyulndDry25MZaMG882pQoB1V6jmB4As/2X9sKUyp8Y/KXxnfoVNaruxmTe5iMZhzBgaRjYaN+EsKznQdRPCb4mUf+z2nBn5cIpcwAqt3jt57eh3DkMlORuhhiBlm9gRaH37fioGqzJRYxNbo1HrrMZfcnxh9hRJAayzJYtYuduYsRNSItIC+GlYdBF9mGYwxxEOxiWbfAw6umzCLD6THLkY03H5wqC9FYt3sylTQyUoUUwfAV1TYFGop5BAzZkRsuc7DVkkkIYx9riJxZC+u5gTYy1OgteuasDPccBbj5B+N36O8+t6fwfZxb8fBLJ60CM5BKZCOqXnWCQO5Q/9H0QwiNZOL/nMX/cUtJYdq01M+JzDBnkOoZV7e40YSnjlzvULwzoAAg4Ok6wBvi7IN4quKcxpANQFqILVDQytPiJRu9bqSiEN0yLsKku7sR7NDOPx8EvwxkfJEH0mdSjw+La9hiAnimYmUT22hj1lU/JAxPF9e2tnbZy4fq7Zu+llY6TeoC8nOABacODJTV9E2Enwx2YHp4uAAduAOe1VODx6/kL6Z4mcJ3970cO+2ND+VrBiO/i43Vic0j5TWCmViB+b69cftF2C2dIuyDGiKdH461OxN9DFHN9HFoaViUvVdDwiSSqJt0QpWlpJ7Y1ecW7AJPY2R9e5wbNgTcRMuui8gdSMygd4MxBSi0liDBkmbTgIO47vHJ6kN45K2ximuLHUV1lGAK6WlkkkJW05C3pZ2a4paxJ+OQCeAGCAbOvgIFyKxcxCH6g== X-Forefront-PRVS: 0288CD37D9 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10019020)(4630300001)(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)(2361001)(8676002)(86362001)(110136004)(36756003)(86612001)(2950100002)(81166006)(53936002)(50226002)(2906002)(5660300001)(54906002)(5005710100001)(305945005)(47776003)(10290500003); DIR:OUT; SFP:1102; SCL:1; SRVR:CY4PR03MB2551; H:ubuntu-vm.corp.microsoft.com; FPR:; SPF:None; MLV:sfv; LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; CY4PR03MB2551; 23:4qTufYh2NBuw7Sg3TiblLh59asTlTP17mOzhgchRm?= =?us-ascii?Q?wjlPT6woM0T+2tUGiGyYyx39fjke64qBF9zRpfcR5r8UaUEMt3MFRPioDby7?= =?us-ascii?Q?A4MjMBWZtYP5j9qoi0F+ASMkqeycGB/iHZBwByYf3RtkArDvjoKWFw6/WCdm?= =?us-ascii?Q?+ipD1fcqVqqAPzvWKF7EXkz8eHxP2YS2XwEuuiT4njghbbiwCH1vOJMtvlkA?= =?us-ascii?Q?brXVCnMQQeBVD57BedgFe3T020qQM9jKcl07yAqoToaBkMPAkkJbUDuPv7GM?= =?us-ascii?Q?QTm0PGB8YFRIXe9XHxZvYDQJrSOg6fuh+3Y8ODUoFCmGAXZAXaPvJVPtT79W?= =?us-ascii?Q?LR1mceTj+F/uLDJjykfXyjUD7UqcLXCEihHKI5qWXvT7dpuuEfaYxN5L/QUW?= =?us-ascii?Q?uf/pg8KS6RIel72BeRVCRSBEUFInqY5PlCyvhPa/NcxOpY36XNAdO25Ue/pB?= =?us-ascii?Q?Vfa3EFfaaHjokSwTzZN0T+BKxHXDfVQTHJH5QEB+6NnPiRbbPM1hpqgGD5iJ?= =?us-ascii?Q?x8TZ0XZlZI1sOFyp29AdYGx+UslUC4AbZog9hi2o0YIiqgi+rW7lmrXT7b1J?= =?us-ascii?Q?y38ovlIEj+CVfVh388p0P4RVMZJ2I8NtyNE5/J7nBI3XtQ89qZ8aBWFyH4co?= =?us-ascii?Q?rebwSJNmyPrTvskmzQp8JyzhzQxWcDGrIBz5TUsToEN+2/AnIoYrUJN3PxXk?= =?us-ascii?Q?mj1u2gwfrWKVK25ppj5oSGgqu7MHeL7y5LX5ctYUyzi/TH/Z+hbJK62JDH9N?= =?us-ascii?Q?+tCcA3Pqxgv7wUZAU1LHXq+3uZfJyiWiifY6X7a6y5K6mbxjRHtt+fXx3Zp5?= =?us-ascii?Q?pH5dwvAh3+ppno3TI9epuZPnBPPQhbBOLJHgNu2lsFVTbY/UB0tyugWGFtH8?= =?us-ascii?Q?67BZ9nv21Zd5Br+mMKbD1udtXTcdECpeHFSdDo4MGvT4YxlCqxwiicaNIXHN?= =?us-ascii?Q?0zIftAHMhoQuVUrEQLCk+gGcAzCyhWCaeEGBjM+7tS/OYEog+rSEvLUxXFsD?= =?us-ascii?Q?fibmvAp+hXIBI5NKteZsQVbMLv8Yj7+EDztspOqwPxsAB+kmnhuZgOTtU5wY?= =?us-ascii?Q?UUbBUn27XV9QpySf4GIjgByi0GV8lXyG9M3CsSLADSUeP3G74fYAg4lf/iz/?= =?us-ascii?Q?ezBvOEeYZY=3D?= X-Microsoft-Exchange-Diagnostics: 1; CY4PR03MB2551; 6:HYgzVzkkKoV8QXqszNdslN6xu0wts6nOkNnjSMrJjyE2RHgmDtnFXhwXXQAqUwmykeB+7jHkAIMmY0SZaMi9Zv1bvQkT7vpDmTOgM4MMMdcVZdWaqlm0GeCJzF0vSeyec9CcqEIFO0RtE0RrJ8aK+hmMEudcwxnhU4E0jmC2BjMhpsknBzM84NWcDzutyeW9SkNOYnN/ETxbpwhgGy9+SOQOYbAVWq2mCCbdDXmap+ReRHNIJfUnOV9pRSgpmpaj7cu/MO78V4okavYncDizXJ+joEPkZA3ZDnlU+U3/sF6qNgR+/fJ5vkdTAYtvDERlmJdew48d86pxtGt14PKaCTxtYKm3f+3p21QgDZtGfUl06w4MFiN7+M8gyNU2yXZZbK2RiwE9G6t7GZ632aj6y/kHxJQ10jhjfndEuCYNCEfYx3Pje6P8qnnThjwviS1pAx/NcElB2kcufsie0i8TgiOfV4tGCQZcOwfc07lsakQ8Xn2oI06pNWIMmwV+v/1LSRU27fAypIumFrOup9R82ufmbhp+39pf1tfG6vJzT5s=; 5:EPWwNIQ4hBrvDCO+r7COz4XCwiOFGqFYfeXaSU48k3IvZSqFVktuHDC607VhKCXv+ofAwMCYVl99EuTmfMUIwir4YOU9o9TIiYV8BaE3BaEcJ/ZG/dS42x8Xvwp6hV1lsv/RmkC+EgRacU8WgFgMCw==; 24:P6vzv4EQWnOZsP+ObyyrlfH5xdUMm4eqgAo6fFBvBnwvv52+SvwRGrFrBsOYR69NzZKIagHTqj1b0xVLPmAV3q7UCUVLeAFJhL0jTcodnhk= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; CY4PR03MB2551; 7:yRQOtZJ5N/owckfvIT1nlPaV+2QLTbrAwSw/G3RfcY3bLJvJ4SSQChfNWTTovQY6dfuVdhhQE8xxipHPdTeg+JpJFJQlCYMrigzELYGAvz3K+BtwgfcN8zPV1V8Gw7qhRwisgmiQp80EbOxrxJ3st1m3efHhStDCyC8C5M1/MJRtyj6rNLFJEFNmkEQTZXpYtj1VrUz4VUsz+TGkvCxmuVStNoO/w8loH++B0G1qpCaoPUPGvF4lWP8AuVjoG/9Y6K7eyht8PJzh4yVmIupTIJRhfaL5oT9PrTHggCJ5no+lX9YO4QlcaHMHhtQcn3DJRQcLGAX51mYZUgCain8XkQ== X-OriginatorOrg: microsoft.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 25 Apr 2017 18:52:44.8409 (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 read 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 reading performance of single threaded applications with increasing of i/o queue depth size. Signed-off-by: Pavel Shilovsky --- fs/cifs/cifsglob.h | 1 + fs/cifs/file.c | 169 ++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 131 insertions(+), 39 deletions(-) diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index bb41226..9438c7c 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -1140,6 +1140,7 @@ struct cifs_readdata { struct completion done; struct cifsFileInfo *cfile; struct address_space *mapping; + struct cifs_aio_ctx *ctx; __u64 offset; unsigned int bytes; unsigned int got_bytes; diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 21d4045..9564e2c 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -2859,6 +2859,7 @@ cifs_uncached_readdata_release(struct kref *refcount) struct cifs_readdata, refcount); unsigned int i; + kref_put(&rdata->ctx->refcount, cifs_aio_ctx_release); for (i = 0; i < rdata->nr_pages; i++) { put_page(rdata->pages[i]); rdata->pages[i] = NULL; @@ -2900,6 +2901,8 @@ cifs_readdata_to_iov(struct cifs_readdata *rdata, struct iov_iter *iter) return remaining ? -EFAULT : 0; } +static void collect_uncached_read_data(struct cifs_aio_ctx *ctx); + static void cifs_uncached_readv_complete(struct work_struct *work) { @@ -2907,6 +2910,8 @@ cifs_uncached_readv_complete(struct work_struct *work) struct cifs_readdata, work); complete(&rdata->done); + collect_uncached_read_data(rdata->ctx); + /* the below call can possibly free the last ref to aio ctx */ kref_put(&rdata->refcount, cifs_uncached_readdata_release); } @@ -2973,7 +2978,8 @@ cifs_uncached_copy_into_pages(struct TCP_Server_Info *server, static int cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, - struct cifs_sb_info *cifs_sb, struct list_head *rdata_list) + struct cifs_sb_info *cifs_sb, struct list_head *rdata_list, + struct cifs_aio_ctx *ctx) { struct cifs_readdata *rdata; unsigned int npages, rsize, credits; @@ -3020,6 +3026,8 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, rdata->read_into_pages = cifs_uncached_read_into_pages; rdata->copy_into_pages = cifs_uncached_copy_into_pages; rdata->credits = credits; + rdata->ctx = ctx; + kref_get(&ctx->refcount); if (!rdata->cfile->invalidHandle || !(rc = cifs_reopen_file(rdata->cfile, true))) @@ -3042,50 +3050,37 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, return rc; } -ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to) +static void +collect_uncached_read_data(struct cifs_aio_ctx *ctx) { - struct file *file = iocb->ki_filp; - ssize_t rc; - size_t len; - ssize_t total_read = 0; - loff_t offset = iocb->ki_pos; + struct cifs_readdata *rdata, *tmp; + struct iov_iter *to = &ctx->iter; struct cifs_sb_info *cifs_sb; struct cifs_tcon *tcon; - struct cifsFileInfo *open_file; - struct cifs_readdata *rdata, *tmp; - struct list_head rdata_list; - - len = iov_iter_count(to); - if (!len) - return 0; + unsigned int i; + int rc; - INIT_LIST_HEAD(&rdata_list); - cifs_sb = CIFS_FILE_SB(file); - open_file = file->private_data; - tcon = tlink_tcon(open_file->tlink); + tcon = tlink_tcon(ctx->cfile->tlink); + cifs_sb = CIFS_SB(ctx->cfile->dentry->d_sb); - if (!tcon->ses->server->ops->async_readv) - return -ENOSYS; + mutex_lock(&ctx->aio_mutex); - if ((file->f_flags & O_ACCMODE) == O_WRONLY) - cifs_dbg(FYI, "attempting read on write only file instance\n"); - - rc = cifs_send_async_read(offset, len, open_file, cifs_sb, &rdata_list); - - /* if at least one read request send succeeded, then reset rc */ - if (!list_empty(&rdata_list)) - rc = 0; + if (list_empty(&ctx->list)) { + mutex_unlock(&ctx->aio_mutex); + return; + } - len = iov_iter_count(to); + rc = ctx->rc; /* the loop below should proceed in the order of increasing offsets */ again: - list_for_each_entry_safe(rdata, tmp, &rdata_list, list) { + list_for_each_entry_safe(rdata, tmp, &ctx->list, list) { if (!rc) { - /* FIXME: freezable sleep too? */ - rc = wait_for_completion_killable(&rdata->done); - if (rc) - rc = -EINTR; - else if (rdata->result == -EAGAIN) { + if (!try_wait_for_completion(&rdata->done)) { + mutex_unlock(&ctx->aio_mutex); + return; + } + + if (rdata->result == -EAGAIN) { /* resend call if it's a retryable error */ struct list_head tmp_list; unsigned int got_bytes = rdata->got_bytes; @@ -3111,9 +3106,9 @@ ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to) rdata->offset + got_bytes, rdata->bytes - got_bytes, rdata->cfile, cifs_sb, - &tmp_list); + &tmp_list, ctx); - list_splice(&tmp_list, &rdata_list); + list_splice(&tmp_list, &ctx->list); kref_put(&rdata->refcount, cifs_uncached_readdata_release); @@ -3131,14 +3126,110 @@ ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to) kref_put(&rdata->refcount, cifs_uncached_readdata_release); } - total_read = len - iov_iter_count(to); + for (i = 0; i < ctx->npages; i++) { + if (ctx->should_dirty) + set_page_dirty(ctx->bv[i].bv_page); + put_page(ctx->bv[i].bv_page); + } - cifs_stats_bytes_read(tcon, total_read); + ctx->total_len = ctx->len - iov_iter_count(to); + + cifs_stats_bytes_read(tcon, ctx->total_len); /* mask nodata case */ if (rc == -ENODATA) rc = 0; + 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_readv(struct kiocb *iocb, struct iov_iter *to) +{ + struct file *file = iocb->ki_filp; + ssize_t rc; + size_t len; + ssize_t total_read = 0; + loff_t offset = iocb->ki_pos; + struct cifs_sb_info *cifs_sb; + struct cifs_tcon *tcon; + struct cifsFileInfo *cfile; + struct cifs_aio_ctx *ctx; + + len = iov_iter_count(to); + if (!len) + return 0; + + cifs_sb = CIFS_FILE_SB(file); + cfile = file->private_data; + tcon = tlink_tcon(cfile->tlink); + + if (!tcon->ses->server->ops->async_readv) + return -ENOSYS; + + if ((file->f_flags & O_ACCMODE) == O_WRONLY) + cifs_dbg(FYI, "attempting read on write only file instance\n"); + + ctx = cifs_aio_ctx_alloc(); + if (!ctx) + return -ENOMEM; + + ctx->cfile = cifsFileInfo_get(cfile); + + if (!is_sync_kiocb(iocb)) + ctx->iocb = iocb; + + if (to->type & ITER_IOVEC) + ctx->should_dirty = true; + + rc = setup_aio_ctx_iter(ctx, to, READ); + if (rc) { + kref_put(&ctx->refcount, cifs_aio_ctx_release); + return rc; + } + + len = ctx->len; + + /* grab a lock here due to read response handlers can access ctx */ + mutex_lock(&ctx->aio_mutex); + + rc = cifs_send_async_read(offset, len, cfile, cifs_sb, &ctx->list, ctx); + + /* if at least one read request send succeeded, then reset rc */ + 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_read = ctx->total_len; + mutex_unlock(&ctx->aio_mutex); + } else { + rc = ctx->rc; + total_read = ctx->total_len; + } + + kref_put(&ctx->refcount, cifs_aio_ctx_release); + if (total_read) { iocb->ki_pos += total_read; return total_read;