aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorGermano Percossi <germano.percossi@citrix.com>2017-04-07 07:29:38 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-04-21 03:31:19 -0400
commit730fecb3401f8a7cc84e8d7b454976efdfdc65c9 (patch)
treeb9445e8fd2449e3e746aaff0019430df4a5c83a2 /fs
parent3d8d2f2344767cbab597027e2cde21d1a8b32cca (diff)
CIFS: store results of cifs_reopen_file to avoid infinite wait
commit 1fa839b4986d648b907d117275869a0e46c324b9 upstream. 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> Signed-off-by: Steve French <smfrench@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-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 1cd0e2eefc66..3925758f6dde 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) {
@@ -3002,7 +3002,7 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
3002 rdata->credits = credits; 3002 rdata->credits = credits;
3003 3003
3004 if (!rdata->cfile->invalidHandle || 3004 if (!rdata->cfile->invalidHandle ||
3005 !cifs_reopen_file(rdata->cfile, true)) 3005 !(rc = cifs_reopen_file(rdata->cfile, true)))
3006 rc = server->ops->async_readv(rdata); 3006 rc = server->ops->async_readv(rdata);
3007error: 3007error:
3008 if (rc) { 3008 if (rc) {
@@ -3577,7 +3577,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
3577 } 3577 }
3578 3578
3579 if (!rdata->cfile->invalidHandle || 3579 if (!rdata->cfile->invalidHandle ||
3580 !cifs_reopen_file(rdata->cfile, true)) 3580 !(rc = cifs_reopen_file(rdata->cfile, true)))
3581 rc = server->ops->async_readv(rdata); 3581 rc = server->ops->async_readv(rdata);
3582 if (rc) { 3582 if (rc) {
3583 add_credits_and_wake_if(server, rdata->credits, 0); 3583 add_credits_and_wake_if(server, rdata->credits, 0);