From patchwork Mon Jul 21 15:45:51 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Shilovsky X-Patchwork-Id: 4597071 Return-Path: X-Original-To: patchwork-cifs-client@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id A7F0E9F2B8 for ; Mon, 21 Jul 2014 15:46:35 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id ACE92200E3 for ; Mon, 21 Jul 2014 15:46:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id BCDB7200DE for ; Mon, 21 Jul 2014 15:46:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932548AbaGUPqd (ORCPT ); Mon, 21 Jul 2014 11:46:33 -0400 Received: from mail-lb0-f177.google.com ([209.85.217.177]:43122 "EHLO mail-lb0-f177.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933127AbaGUPqc (ORCPT ); Mon, 21 Jul 2014 11:46:32 -0400 Received: by mail-lb0-f177.google.com with SMTP id s7so4910940lbd.36 for ; Mon, 21 Jul 2014 08:46:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:subject:date:message-id:in-reply-to:references; bh=JmCEpCTgevxLks2iDGWjM6A4Led8oCfi2o6AGyWUyyM=; b=rdyY5Curpi933V4DjuyVmIlHJ633oUW7/OYMVMDFSa61j9KwkbJQib4P2SdWMKHuID u8P0U1QX9e2IcOSiTt4jT8+DdqHuYz5zCxWNTvmpA0tgEF9C4UrUVyPFHfuBQZ8WdMys X5GYg53ag4cqad2piqtbqdXrdEe7i+DD4KWl250B3oHkaHO7I7C67wkRpqXC+ryvkVzg LWktkt984TR2vVvcjB0OshE8Y1tYkxWqLqU8q+4LFoFsouXW6iUQgcrCvI2hASzCwgDT O8GbOMq99BbU75zS3tCX2B25Dyes7EsFVR8jvKsdMPvOmyQrhJ5A2OqhBAc3imX6aOXI qu1A== X-Received: by 10.152.36.169 with SMTP id r9mr28058419laj.14.1405957591202; Mon, 21 Jul 2014 08:46:31 -0700 (PDT) Received: from localhost.localdomain ([92.43.3.35]) by mx.google.com with ESMTPSA id ok1sm25762485lbc.18.2014.07.21.08.46.29 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 21 Jul 2014 08:46:30 -0700 (PDT) From: Pavel Shilovsky To: linux-cifs@vger.kernel.org Subject: [PATCH v3 09/16] CIFS: Fix wsize usage in iovec write Date: Mon, 21 Jul 2014 19:45:51 +0400 Message-Id: <1405957558-18476-10-git-send-email-pshilovsky@samba.org> X-Mailer: git-send-email 1.8.1.2 In-Reply-To: <1405957558-18476-1-git-send-email-pshilovsky@samba.org> References: <1405957558-18476-1-git-send-email-pshilovsky@samba.org> Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=ham 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 If a server change maximum buffer size for write (wsize) requests on reconnect we can fail on repeating with a big size buffer on -EAGAIN error in iovec write. Fix this by checking wsize all the time before repeating request in iovec write. Signed-off-by: Pavel Shilovsky Reviewed-by: Shirish Pargaonkar --- fs/cifs/cifssmb.c | 4 ---- fs/cifs/file.c | 63 ++++++++++++++++++++++++++++++++++--------------------- fs/cifs/smb2pdu.c | 4 ---- 3 files changed, 39 insertions(+), 32 deletions(-) diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index e273ded..784f105 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -196,10 +196,6 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) if (rc) goto out; - /* - * FIXME: check if wsize needs updated due to negotiated smb buffer - * size shrinking - */ atomic_inc(&tconInfoReconnectCount); /* tell server Unix caps we support */ diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 6660698..c9c4f5a 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -2401,28 +2401,6 @@ cifs_uncached_writev_complete(struct work_struct *work) kref_put(&wdata->refcount, cifs_uncached_writedata_release); } -/* attempt to send write to server, retry on any -EAGAIN errors */ -static int -cifs_uncached_retry_writev(struct cifs_writedata *wdata) -{ - int rc; - struct TCP_Server_Info *server; - - server = tlink_tcon(wdata->cfile->tlink)->ses->server; - - do { - if (wdata->cfile->invalidHandle) { - rc = cifs_reopen_file(wdata->cfile, false); - if (rc != 0) - continue; - } - rc = server->ops->async_writev(wdata, - cifs_uncached_writedata_release); - } while (rc == -EAGAIN); - - return rc; -} - static int wdata_fill_from_iovec(struct cifs_writedata *wdata, struct iov_iter *from, size_t *len, unsigned long *num_pages) @@ -2474,13 +2452,19 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, size_t cur_len; unsigned long nr_pages, num_pages, i; struct cifs_writedata *wdata; + struct iov_iter saved_from; + loff_t saved_offset = offset; pid_t pid; + struct TCP_Server_Info *server; if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) pid = open_file->pid; else pid = current->tgid; + server = tlink_tcon(open_file->tlink)->ses->server; + memcpy(&saved_from, from, sizeof(struct iov_iter)); + do { nr_pages = get_numpages(cifs_sb->wsize, len, &cur_len); wdata = cifs_writedata_alloc(nr_pages, @@ -2520,10 +2504,20 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, wdata->bytes = cur_len; wdata->pagesz = PAGE_SIZE; wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE); - rc = cifs_uncached_retry_writev(wdata); + + if (!wdata->cfile->invalidHandle || + !cifs_reopen_file(wdata->cfile, false)) + rc = server->ops->async_writev(wdata, + cifs_uncached_writedata_release); if (rc) { kref_put(&wdata->refcount, cifs_uncached_writedata_release); + if (rc == -EAGAIN) { + memcpy(from, &saved_from, + sizeof(struct iov_iter)); + iov_iter_advance(from, offset - saved_offset); + continue; + } break; } @@ -2545,6 +2539,7 @@ cifs_iovec_write(struct file *file, struct iov_iter *from, loff_t *poffset) struct cifs_sb_info *cifs_sb; struct cifs_writedata *wdata, *tmp; struct list_head wdata_list; + struct iov_iter saved_from; int rc; len = iov_iter_count(from); @@ -2565,6 +2560,8 @@ cifs_iovec_write(struct file *file, struct iov_iter *from, loff_t *poffset) if (!tcon->ses->server->ops->async_writev) return -ENOSYS; + memcpy(&saved_from, from, sizeof(struct iov_iter)); + rc = cifs_write_from_iter(*poffset, len, from, open_file, cifs_sb, &wdata_list); @@ -2596,7 +2593,25 @@ restart_loop: /* resend call if it's a retryable error */ if (rc == -EAGAIN) { - rc = cifs_uncached_retry_writev(wdata); + struct list_head tmp_list; + struct iov_iter tmp_from; + + INIT_LIST_HEAD(&tmp_list); + list_del_init(&wdata->list); + + memcpy(&tmp_from, &saved_from, + sizeof(struct iov_iter)); + iov_iter_advance(&tmp_from, + wdata->offset - *poffset); + + rc = cifs_write_from_iter(wdata->offset, + wdata->bytes, &tmp_from, + open_file, cifs_sb, &tmp_list); + + list_splice(&tmp_list, &wdata_list); + + kref_put(&wdata->refcount, + cifs_uncached_writedata_release); goto restart_loop; } } diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index b0b260d..8f5754a 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -245,10 +245,6 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) if (rc) goto out; atomic_inc(&tconInfoReconnectCount); - /* - * BB FIXME add code to check if wsize needs update due to negotiated - * smb buffer size shrinking. - */ out: /* * Check if handle based operation so we know whether we can continue