[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20190322111301.438582621@linuxfoundation.org>
Date: Fri, 22 Mar 2019 12:14:30 +0100
From: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
To: linux-kernel@...r.kernel.org
Cc: Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
stable@...r.kernel.org, Pavel Shilovsky <pshilov@...rosoft.com>,
Steve French <stfrench@...rosoft.com>
Subject: [PATCH 5.0 051/238] CIFS: Fix leaking locked VFS cache pages in writeback retry
5.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pavel Shilovsky <pshilov@...rosoft.com>
commit 165df9a080b6863ae286fa01780c13d87cd81076 upstream.
If we don't find a writable file handle when retrying writepages
we break of the loop and do not unlock and put pages neither from
wdata2 nor from the original wdata. Fix this by walking through
all the remaining pages and cleanup them properly.
Cc: <stable@...r.kernel.org>
Signed-off-by: Pavel Shilovsky <pshilov@...rosoft.com>
Signed-off-by: Steve French <stfrench@...rosoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
---
fs/cifs/cifssmb.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -2125,12 +2125,13 @@ cifs_writev_requeue(struct cifs_writedat
wdata2->cfile = find_writable_file(CIFS_I(inode), false);
if (!wdata2->cfile) {
- cifs_dbg(VFS, "No writable handles for inode\n");
+ cifs_dbg(VFS, "No writable handle to retry writepages\n");
rc = -EBADF;
- break;
+ } else {
+ wdata2->pid = wdata2->cfile->pid;
+ rc = server->ops->async_writev(wdata2,
+ cifs_writedata_release);
}
- wdata2->pid = wdata2->cfile->pid;
- rc = server->ops->async_writev(wdata2, cifs_writedata_release);
for (j = 0; j < nr_pages; j++) {
unlock_page(wdata2->pages[j]);
@@ -2145,6 +2146,7 @@ cifs_writev_requeue(struct cifs_writedat
kref_put(&wdata2->refcount, cifs_writedata_release);
if (is_retryable_error(rc))
continue;
+ i += nr_pages;
break;
}
@@ -2152,6 +2154,13 @@ cifs_writev_requeue(struct cifs_writedat
i += nr_pages;
} while (i < wdata->nr_pages);
+ /* cleanup remaining pages from the original wdata */
+ for (; i < wdata->nr_pages; i++) {
+ SetPageError(wdata->pages[i]);
+ end_page_writeback(wdata->pages[i]);
+ put_page(wdata->pages[i]);
+ }
+
if (rc != 0 && !is_retryable_error(rc))
mapping_set_error(inode->i_mapping, rc);
kref_put(&wdata->refcount, cifs_writedata_release);
Powered by blists - more mailing lists