summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Shilovsky <pshilov@microsoft.com>2019-01-29 16:40:28 -0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-03-23 20:11:16 +0100
commit75bbb83e80c764ddfb4a70270c5b269c92cebd66 (patch)
treecd293e54e23caa8ba062978dff2573787b6a1a8e
parentafaf9d664b0f2e94110947db89123be1fcc1f5e9 (diff)
downloadtalos-obmc-linux-75bbb83e80c764ddfb4a70270c5b269c92cebd66.tar.gz
talos-obmc-linux-75bbb83e80c764ddfb4a70270c5b269c92cebd66.zip
CIFS: Fix leaking locked VFS cache pages in writeback retry
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@vger.kernel.org> Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com> Signed-off-by: Steve French <stfrench@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/cifs/cifssmb.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index bb54ccf8481c..551924beb86f 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -2125,12 +2125,13 @@ cifs_writev_requeue(struct cifs_writedata *wdata)
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_writedata *wdata)
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_writedata *wdata)
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);
OpenPOWER on IntegriCloud