CIFS: Optimize cifs_user_read() in a short read case on reconnects
authorPavel Shilovsky <pshilovsky@samba.org>
Thu, 10 Jul 2014 07:31:48 +0000 (11:31 +0400)
committerSteve French <smfrench@gmail.com>
Sat, 2 Aug 2014 06:23:04 +0000 (01:23 -0500)
by filling the output buffer with a data got from a partially received
response and requesting the remaining data from the server. This is
suitable for non-signed connections.

Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org>
Signed-off-by: Steve French <smfrench@gmail.com>
fs/cifs/cifssmb.c
fs/cifs/file.c
fs/cifs/smb2pdu.c

index 57d447c56d8367247cc9dc148e525fb1b7b8a2f2..66f65001a6d836513b5872ba24b273b82464a67e 100644 (file)
@@ -1561,6 +1561,12 @@ cifs_readv_callback(struct mid_q_entry *mid)
        case MID_REQUEST_SUBMITTED:
        case MID_RETRY_NEEDED:
                rdata->result = -EAGAIN;
+               if (server->sign && rdata->got_bytes)
+                       /* reset bytes number since we can not check a sign */
+                       rdata->got_bytes = 0;
+               /* FIXME: should this be counted toward the initiating task? */
+               task_io_account_read(rdata->got_bytes);
+               cifs_stats_bytes_read(tcon, rdata->got_bytes);
                break;
        default:
                rdata->result = -EIO;
index e17012817d9dd6dc131cdbddae76850aabbe6e68..5d2501df8f6b9f0284bf5d287fd305e82b1bbd32 100644 (file)
@@ -3030,13 +3030,30 @@ again:
                        else if (rdata->result == -EAGAIN) {
                                /* resend call if it's a retryable error */
                                struct list_head tmp_list;
+                               unsigned int got_bytes = rdata->got_bytes;
 
                                list_del_init(&rdata->list);
                                INIT_LIST_HEAD(&tmp_list);
 
-                               rc = cifs_send_async_read(rdata->offset,
-                                               rdata->bytes, rdata->cfile,
-                                               cifs_sb, &tmp_list);
+                               /*
+                                * Got a part of data and then reconnect has
+                                * happened -- fill the buffer and continue
+                                * reading.
+                                */
+                               if (got_bytes && got_bytes < rdata->bytes) {
+                                       rc = cifs_readdata_to_iov(rdata, to);
+                                       if (rc) {
+                                               kref_put(&rdata->refcount,
+                                               cifs_uncached_readdata_release);
+                                               continue;
+                                       }
+                               }
+
+                               rc = cifs_send_async_read(
+                                               rdata->offset + got_bytes,
+                                               rdata->bytes - got_bytes,
+                                               rdata->cfile, cifs_sb,
+                                               &tmp_list);
 
                                list_splice(&tmp_list, &rdata_list);
 
index c66ae4183bd31f07a9af323afd53f6dd48f5ce55..cde943d61fb673b9c55a79a2bce5a35f23bf75c6 100644 (file)
@@ -1729,6 +1729,12 @@ smb2_readv_callback(struct mid_q_entry *mid)
        case MID_REQUEST_SUBMITTED:
        case MID_RETRY_NEEDED:
                rdata->result = -EAGAIN;
+               if (server->sign && rdata->got_bytes)
+                       /* reset bytes number since we can not check a sign */
+                       rdata->got_bytes = 0;
+               /* FIXME: should this be counted toward the initiating task? */
+               task_io_account_read(rdata->got_bytes);
+               cifs_stats_bytes_read(tcon, rdata->got_bytes);
                break;
        default:
                if (rdata->result != -ENODATA)