CIFS: Fix leaking locked VFS cache pages in writeback retry

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>
This commit is contained in:
Pavel Shilovsky 2019-01-29 16:40:28 -08:00 committed by Steve French
parent 1c163f4c7b
commit 165df9a080
1 changed files with 13 additions and 4 deletions

View File

@ -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);