CIFS: Reopen file before get SMB2 MTU credits for async IO
authorPavel Shilovsky <pshilov@microsoft.com>
Fri, 25 Jan 2019 19:59:01 +0000 (11:59 -0800)
committerSteve French <stfrench@microsoft.com>
Wed, 6 Mar 2019 00:10:01 +0000 (18:10 -0600)
Currently we get MTU credits before we check an open file if
it needs to be reopened. Reopening the file in such conditions
leads to a possibility of being stuck waiting indefinitely
for credits in the transport layer. Fix this by reopening the
file first if needed and then getting MTU credits for async IO.

Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/cifs/file.c

index 67b361a..eaf5acb 100644 (file)
@@ -2650,6 +2650,14 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
                struct cifs_credits credits_on_stack;
                struct cifs_credits *credits = &credits_on_stack;
 
+               if (open_file->invalidHandle) {
+                       rc = cifs_reopen_file(open_file, false);
+                       if (rc == -EAGAIN)
+                               continue;
+                       else if (rc)
+                               break;
+               }
+
                rc = server->ops->wait_mtu_credits(server, cifs_sb->wsize,
                                                   &wsize, credits);
                if (rc)
@@ -2751,9 +2759,8 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
 
                if (!rc) {
                        if (wdata->cfile->invalidHandle)
-                               rc = cifs_reopen_file(wdata->cfile, false);
-
-                       if (!rc)
+                               rc = -EAGAIN;
+                       else
                                rc = server->ops->async_writev(wdata,
                                        cifs_uncached_writedata_release);
                }
@@ -3355,6 +3362,14 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
                iov_iter_advance(&direct_iov, offset - ctx->pos);
 
        do {
+               if (open_file->invalidHandle) {
+                       rc = cifs_reopen_file(open_file, true);
+                       if (rc == -EAGAIN)
+                               continue;
+                       else if (rc)
+                               break;
+               }
+
                rc = server->ops->wait_mtu_credits(server, cifs_sb->rsize,
                                                   &rsize, credits);
                if (rc)
@@ -3438,9 +3453,8 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
 
                if (!rc) {
                        if (rdata->cfile->invalidHandle)
-                               rc = cifs_reopen_file(rdata->cfile, true);
-
-                       if (!rc)
+                               rc = -EAGAIN;
+                       else
                                rc = server->ops->async_readv(rdata);
                }
 
@@ -4127,6 +4141,14 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
                struct cifs_credits credits_on_stack;
                struct cifs_credits *credits = &credits_on_stack;
 
+               if (open_file->invalidHandle) {
+                       rc = cifs_reopen_file(open_file, true);
+                       if (rc == -EAGAIN)
+                               continue;
+                       else if (rc)
+                               break;
+               }
+
                rc = server->ops->wait_mtu_credits(server, cifs_sb->rsize,
                                                   &rsize, credits);
                if (rc)
@@ -4185,9 +4207,8 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
 
                if (!rc) {
                        if (rdata->cfile->invalidHandle)
-                               rc = cifs_reopen_file(rdata->cfile, true);
-
-                       if (!rc)
+                               rc = -EAGAIN;
+                       else
                                rc = server->ops->async_readv(rdata);
                }