From patchwork Mon Jun 23 14:58:36 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Shilovsky X-Patchwork-Id: 4403651 Return-Path: X-Original-To: patchwork-cifs-client@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 61B88BEEAA for ; Mon, 23 Jun 2014 14:59:27 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 102EF2018B for ; Mon, 23 Jun 2014 14:59:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8180F20211 for ; Mon, 23 Jun 2014 14:59:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754980AbaFWO7H (ORCPT ); Mon, 23 Jun 2014 10:59:07 -0400 Received: from mail-lb0-f182.google.com ([209.85.217.182]:57133 "EHLO mail-lb0-f182.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755854AbaFWO7F (ORCPT ); Mon, 23 Jun 2014 10:59:05 -0400 Received: by mail-lb0-f182.google.com with SMTP id c11so4594159lbj.41 for ; Mon, 23 Jun 2014 07:59:03 -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=NPepQ0d874qqcW0Ya7xXiIGE+EAYR70cOphFvxeoxos=; b=ohiyyrCz7HnadVS3yGqM7JhG1w+6c69FDUfOFJ1hU4/wuCJzAUQDPzglXZPu2Njm40 YrWMA5sc+l2uEuQyvxkFkF2aInjY0NGkb8PzePf7CFji8MUWD/m2/6KanGc49C/lJGK1 r9evc/pXDyE9Byn8Hkdml3k1N0tFYOpdJXNdka05awBIrEojtGZjNr6uP04ISCdxLhgx e2q/fxqaLOGtKyu7WY5N4cEh3PU6Tfh9SF7f7/mpL7Wp5c4gcuDR4eKfw5Tr0xOtVY1K OIlKTeabuEUGZLaHEnkRv9MBzQyvHgzdg+YniRjnEY0OjSueerKMX2inCazgaLqBF7Fq NwEA== X-Received: by 10.152.36.38 with SMTP id n6mr17545810laj.0.1403535543183; Mon, 23 Jun 2014 07:59:03 -0700 (PDT) Received: from localhost.localdomain ([92.43.3.32]) by mx.google.com with ESMTPSA id fb6sm7964060lac.40.2014.06.23.07.59.01 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 23 Jun 2014 07:59:02 -0700 (PDT) From: Pavel Shilovsky To: linux-cifs@vger.kernel.org Subject: [PATCH 8/9] CIFS: Fix wsize usage in iovec write Date: Mon, 23 Jun 2014 18:58:36 +0400 Message-Id: <1403535517-8301-9-git-send-email-pshilovsky@samba.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1403535517-8301-1-git-send-email-pshilovsky@samba.org> References: <1403535517-8301-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,T_DKIM_INVALID,T_RP_MATCHES_RCVD,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 --- fs/cifs/file.c | 62 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 887c18c..4ba59cd 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 *it, size_t *len, unsigned long nr_pages) @@ -2472,23 +2450,28 @@ wdata_fill_from_iovec(struct cifs_writedata *wdata, struct iov_iter *it, static int cifs_write_from_iovec(loff_t offset, size_t len, const struct iovec *iov, - unsigned long nr_segs, struct cifsFileInfo *open_file, + unsigned long nr_segs, loff_t written, + struct cifsFileInfo *open_file, struct cifs_sb_info *cifs_sb, struct list_head *wdata_list) { int rc = 0; - size_t cur_len; + size_t cur_len, saved_len = len; unsigned long nr_pages, i; struct cifs_writedata *wdata; struct iov_iter it; + 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; - iov_iter_init(&it, iov, nr_segs, len, 0); + server = tlink_tcon(open_file->tlink)->ses->server; + + iov_iter_init(&it, iov, nr_segs, len, written); do { nr_pages = get_numpages(cifs_sb->wsize, len, &cur_len); wdata = cifs_writedata_alloc(nr_pages, @@ -2520,10 +2503,19 @@ cifs_write_from_iovec(loff_t offset, size_t len, const struct iovec *iov, 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) { + iov_iter_init(&it, iov, nr_segs, saved_len, + written + offset - saved_offset); + continue; + } break; } @@ -2564,7 +2556,7 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, if (!tcon->ses->server->ops->async_writev) return -ENOSYS; - rc = cifs_write_from_iovec(*poffset, len, iov, nr_segs, open_file, + rc = cifs_write_from_iovec(*poffset, len, iov, nr_segs, 0, open_file, cifs_sb, &wdata_list); /* @@ -2595,7 +2587,21 @@ restart_loop: /* resend call if it's a retryable error */ if (rc == -EAGAIN) { - rc = cifs_uncached_retry_writev(wdata); + struct list_head tmp_list; + + INIT_LIST_HEAD(&tmp_list); + list_del_init(&wdata->list); + + rc = cifs_write_from_iovec(wdata->offset, + wdata->bytes, iov, nr_segs, + wdata->offset - *poffset, open_file, + cifs_sb, &tmp_list); + + if (!list_empty(&tmp_list)) + list_splice(&tmp_list, &wdata_list); + + kref_put(&wdata->refcount, + cifs_uncached_writedata_release); goto restart_loop; } }