From patchwork Thu Jan 10 22:24:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Shilovsky X-Patchwork-Id: 10757019 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id EE58E1399 for ; Thu, 10 Jan 2019 22:25:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DBC2E29BB3 for ; Thu, 10 Jan 2019 22:25:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D086A29BC9; Thu, 10 Jan 2019 22:25:18 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI 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 5239629BB3 for ; Thu, 10 Jan 2019 22:25:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728876AbfAJWZS (ORCPT ); Thu, 10 Jan 2019 17:25:18 -0500 Received: from mail-pf1-f195.google.com ([209.85.210.195]:42124 "EHLO mail-pf1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728614AbfAJWZR (ORCPT ); Thu, 10 Jan 2019 17:25:17 -0500 Received: by mail-pf1-f195.google.com with SMTP id 64so5938219pfr.9 for ; Thu, 10 Jan 2019 14:25:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=5/O7ogoXRZ2RlBpkxauJ+cYIG/dlHZ5camohReMTWag=; b=U77vZgk8P+c6UC1fvEQF4Sr2mUqe04Ke0XL+nmui6rYNp2Nx2rzAQe5VTiP43dKH/O feWGxhgSdc7rSnqMVcIA2DYKVpI0MBJFbcXXd6bfI0pCpKZ4IWXuBCg49gD8FQ9qUUOS r1RYcry0l99hX0YTBp6WHWmoIvA5x2vh9yS1MghpwT7h1+ItbkF6FAI0qamofkdXsk/J fMrdaxcv4Nrav678YqmykCkBzHEe8I6tvHOJBEhkA3RkuUax3uFHmDoGATJn14ELK4tA H8q8xnGktnzbx0JGpEWuq2ZvM+0oOzlVeSl6HPenHub7wFnHbhfWwPKqZFyD9uii/wmY ZO8w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=5/O7ogoXRZ2RlBpkxauJ+cYIG/dlHZ5camohReMTWag=; b=G3hQ3qDfIMnGH39xGJJ8o9bAdwUdfyF6X4x3PKmrPZx+YN6e7yRjKRgfEFIZGtpv/r eTysJbaQTVHkHaPg34dA8AonjowpK5zFqww5Phs9AtIn0SgR+G7fYCjKZwENKr6vVeHR jj9Z63zZgRwHih4ilW5BlMyK1h0pPNjWGJ/6xX5fW6tGvkzOKTSbjeImzk3uSfjNAL7y dL4ordf0mgoO3yMRgpO28s+Zw4rGW7LD+hRJ5hHNzrXtGyLVh9feNhtChKUPGDE9G22d qF44wOm1IjOYWeY3uu/DMnBSkobmRE8oRZOMuDWC9qZxHBLeO0XJedL4tdMvSzggV6SA cEsA== X-Gm-Message-State: AJcUukcS0VRuxndrjpn9cs6Zl0G+PDeeO7sLlNPaGwimiGFfsAo5CGbJ 48hG8mExreCQTvevA/kfGbD20Tw= X-Google-Smtp-Source: ALg8bN5z6tWUul2MLytw+Ky+32ZmqeFsTz68M2NwEc7Q3mBOP+wTA9zufqOI/tB2V0pgU2TOH9/jhA== X-Received: by 2002:a63:d747:: with SMTP id w7mr10785907pgi.360.1547159116171; Thu, 10 Jan 2019 14:25:16 -0800 (PST) Received: from ubuntu-vm.corp.microsoft.com ([2001:4898:80e8:3:a18b:4e9f:6b7c:507d]) by smtp.gmail.com with ESMTPSA id z127sm118006755pfb.80.2019.01.10.14.25.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 10 Jan 2019 14:25:15 -0800 (PST) From: Pavel Shilovsky X-Google-Original-From: Pavel Shilovsky To: linux-cifs@vger.kernel.org Cc: Steve French , Ronnie Sahlberg Subject: [PATCH 7/7] CIFS: Fix error paths in writeback code Date: Thu, 10 Jan 2019 14:24:58 -0800 Message-Id: <1547159098-19011-8-git-send-email-pshilov@microsoft.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1547159098-19011-1-git-send-email-pshilov@microsoft.com> References: <1547159098-19011-1-git-send-email-pshilov@microsoft.com> 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 aims to address writeback code problems related to error paths. In particular it respects EINTR and related error codes and stores the first error occured during writeback in order to return it to a caller. Signed-off-by: Pavel Shilovsky Acked-by: Jeff Layton --- fs/cifs/cifsglob.h | 19 +++++++++++++++++++ fs/cifs/cifssmb.c | 7 ++++--- fs/cifs/file.c | 29 +++++++++++++++++++++++------ fs/cifs/inode.c | 10 ++++++++++ 4 files changed, 56 insertions(+), 9 deletions(-) diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 7709268..94dbdbe 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -1575,6 +1575,25 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param, kfree(param); } +static inline bool is_interrupt_error(int error) +{ + switch (error) { + case -EINTR: + case -ERESTARTSYS: + case -ERESTARTNOHAND: + case -ERESTARTNOINTR: + return true; + } + return false; +} + +static inline bool is_retryable_error(int error) +{ + if (is_interrupt_error(error) || error == -EAGAIN) + return true; + return false; +} + #define MID_FREE 0 #define MID_REQUEST_ALLOCATED 1 #define MID_REQUEST_SUBMITTED 2 diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index b1f49c1..6930cdb 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -2114,7 +2114,7 @@ cifs_writev_requeue(struct cifs_writedata *wdata) for (j = 0; j < nr_pages; j++) { unlock_page(wdata2->pages[j]); - if (rc != 0 && rc != -EAGAIN) { + if (rc != 0 && !is_retryable_error(rc)) { SetPageError(wdata2->pages[j]); end_page_writeback(wdata2->pages[j]); put_page(wdata2->pages[j]); @@ -2123,7 +2123,7 @@ cifs_writev_requeue(struct cifs_writedata *wdata) if (rc) { kref_put(&wdata2->refcount, cifs_writedata_release); - if (rc == -EAGAIN) + if (is_retryable_error(rc)) continue; break; } @@ -2132,7 +2132,8 @@ cifs_writev_requeue(struct cifs_writedata *wdata) i += nr_pages; } while (i < wdata->nr_pages); - mapping_set_error(inode->i_mapping, rc); + if (rc != 0 && !is_retryable_error(rc)) + mapping_set_error(inode->i_mapping, rc); kref_put(&wdata->refcount, cifs_writedata_release); } diff --git a/fs/cifs/file.c b/fs/cifs/file.c index c23bf9d..109b1ef 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -732,7 +732,8 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) if (can_flush) { rc = filemap_write_and_wait(inode->i_mapping); - mapping_set_error(inode->i_mapping, rc); + if (!is_interrupt_error(rc)) + mapping_set_error(inode->i_mapping, rc); if (tcon->unix_ext) rc = cifs_get_inode_info_unix(&inode, full_path, @@ -2109,6 +2110,7 @@ static int cifs_writepages(struct address_space *mapping, pgoff_t end, index; struct cifs_writedata *wdata; int rc = 0; + int saved_rc = 0; unsigned int xid; /* @@ -2137,8 +2139,10 @@ static int cifs_writepages(struct address_space *mapping, rc = server->ops->wait_mtu_credits(server, cifs_sb->wsize, &wsize, &credits); - if (rc) + if (rc != 0) { + done = true; break; + } tofind = min((wsize / PAGE_SIZE) - 1, end - index) + 1; @@ -2146,6 +2150,7 @@ static int cifs_writepages(struct address_space *mapping, &found_pages); if (!wdata) { rc = -ENOMEM; + done = true; add_credits_and_wake_if(server, credits, 0); break; } @@ -2174,7 +2179,7 @@ static int cifs_writepages(struct address_space *mapping, if (rc != 0) { add_credits_and_wake_if(server, wdata->credits, 0); for (i = 0; i < nr_pages; ++i) { - if (rc == -EAGAIN) + if (is_retryable_error(rc)) redirty_page_for_writepage(wbc, wdata->pages[i]); else @@ -2182,7 +2187,7 @@ static int cifs_writepages(struct address_space *mapping, end_page_writeback(wdata->pages[i]); put_page(wdata->pages[i]); } - if (rc != -EAGAIN) + if (!is_retryable_error(rc)) mapping_set_error(mapping, rc); } kref_put(&wdata->refcount, cifs_writedata_release); @@ -2192,6 +2197,15 @@ static int cifs_writepages(struct address_space *mapping, continue; } + /* Return immediately if we received a signal during writing */ + if (is_interrupt_error(rc)) { + done = true; + break; + } + + if (rc != 0 && saved_rc == 0) + saved_rc = rc; + wbc->nr_to_write -= nr_pages; if (wbc->nr_to_write <= 0) done = true; @@ -2209,6 +2223,9 @@ static int cifs_writepages(struct address_space *mapping, goto retry; } + if (saved_rc != 0) + rc = saved_rc; + if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) mapping->writeback_index = index; @@ -2241,8 +2258,8 @@ cifs_writepage_locked(struct page *page, struct writeback_control *wbc) set_page_writeback(page); retry_write: rc = cifs_partialpagewrite(page, 0, PAGE_SIZE); - if (rc == -EAGAIN) { - if (wbc->sync_mode == WB_SYNC_ALL) + if (is_retryable_error(rc)) { + if (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN) goto retry_write; redirty_page_for_writepage(wbc, page); } else if (rc != 0) { diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 5b883a0..ba1152b 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -2260,6 +2260,11 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) * the flush returns error? */ rc = filemap_write_and_wait(inode->i_mapping); + if (is_interrupt_error(rc)) { + rc = -ERESTARTSYS; + goto out; + } + mapping_set_error(inode->i_mapping, rc); rc = 0; @@ -2403,6 +2408,11 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) * the flush returns error? */ rc = filemap_write_and_wait(inode->i_mapping); + if (is_interrupt_error(rc)) { + rc = -ERESTARTSYS; + goto cifs_setattr_exit; + } + mapping_set_error(inode->i_mapping, rc); rc = 0;