aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGermano Percossi <germano.percossi@citrix.com>2017-04-07 07:29:38 -0400
committerSteve French <smfrench@gmail.com>2017-04-11 00:36:39 -0400
commit1fa839b4986d648b907d117275869a0e46c324b9 (patch)
treefe4a98da41574596008a9fa7f85776fb09622ef3
parenta0918f1ce6a43ac980b42b300ec443c154970979 (diff)
CIFS: store results of cifs_reopen_file to avoid infinite wait
This fixes Continuous Availability when errors during file reopen are encountered. cifs_user_readv and cifs_user_writev would wait for ever if results of cifs_reopen_file are not stored and for later inspection. In fact, results are checked and, in case of errors, a chain of function calls leading to reads and writes to be scheduled in a separate thread is skipped. These threads will wake up the corresponding waiters once reads and writes are done. However, given the return value is not stored, when rc is checked for errors a previous one (always zero) is inspected instead. This leads to pending reads/writes added to the list, making cifs_user_readv and cifs_user_writev wait for ever. Signed-off-by: Germano Percossi <germano.percossi@citrix.com> Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com> CC: Stable <stable@vger.kernel.org> Signed-off-by: Steve French <smfrench@gmail.com>
-rw-r--r--fs/cifs/file.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index aa3debbba826..21d404535739 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2597,7 +2597,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
2597 wdata->credits = credits; 2597 wdata->credits = credits;
2598 2598
2599 if (!wdata->cfile->invalidHandle || 2599 if (!wdata->cfile->invalidHandle ||
2600 !cifs_reopen_file(wdata->cfile, false)) 2600 !(rc = cifs_reopen_file(wdata->cfile, false)))
2601 rc = server->ops->async_writev(wdata, 2601 rc = server->ops->async_writev(wdata,
2602 cifs_uncached_writedata_release); 2602 cifs_uncached_writedata_release);
2603 if (rc) { 2603 if (rc) {
@@ -3022,7 +3022,7 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
3022 rdata->credits = credits; 3022 rdata->credits = credits;
3023 3023
3024 if (!rdata->cfile->invalidHandle || 3024 if (!rdata->cfile->invalidHandle ||
3025 !cifs_reopen_file(rdata->cfile, true)) 3025 !(rc = cifs_reopen_file(rdata->cfile, true)))
3026 rc = server->ops->async_readv(rdata); 3026 rc = server->ops->async_readv(rdata);
3027error: 3027error:
3028 if (rc) { 3028 if (rc) {
@@ -3617,7 +3617,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
3617 } 3617 }
3618 3618
3619 if (!rdata->cfile->invalidHandle || 3619 if (!rdata->cfile->invalidHandle ||
3620 !cifs_reopen_file(rdata->cfile, true)) 3620 !(rc = cifs_reopen_file(rdata->cfile, true)))
3621 rc = server->ops->async_readv(rdata); 3621 rc = server->ops->async_readv(rdata);
3622 if (rc) { 3622 if (rc) {
3623 add_credits_and_wake_if(server, rdata->credits, 0); 3623 add_credits_and_wake_if(server, rdata->credits, 0);