diff options
author | Pavel Shilovsky <pshilovsky@samba.org> | 2014-07-10 11:31:48 +0400 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2014-08-02 01:23:04 -0500 |
commit | d913ed17f0a7d74e2847695bc920d77a33f2490b (patch) | |
tree | 2c511ecc0304b341b370834fc989d4b9d3c42d60 | |
parent | fb8a3e52559ad52829c6838d304f5b75c140b97a (diff) | |
download | linux-stable-d913ed17f0a7d74e2847695bc920d77a33f2490b.tar.gz linux-stable-d913ed17f0a7d74e2847695bc920d77a33f2490b.tar.bz2 linux-stable-d913ed17f0a7d74e2847695bc920d77a33f2490b.zip |
CIFS: Optimize cifs_user_read() in a short read case on reconnects
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>
-rw-r--r-- | fs/cifs/cifssmb.c | 6 | ||||
-rw-r--r-- | fs/cifs/file.c | 23 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.c | 6 |
3 files changed, 32 insertions, 3 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 57d447c56d83..66f65001a6d8 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -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; diff --git a/fs/cifs/file.c b/fs/cifs/file.c index e17012817d9d..5d2501df8f6b 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -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); diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index c66ae4183bd3..cde943d61fb6 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -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) |