CIFS: Count SMB3 credits for malformed pending responses
authorPavel Shilovsky <pshilov@microsoft.com>
Thu, 24 Jan 2019 01:11:16 +0000 (17:11 -0800)
committerSteve French <stfrench@microsoft.com>
Tue, 5 Mar 2019 02:06:39 +0000 (20:06 -0600)
Even if a response is malformed, we should count credits
granted by the server to avoid miscalculations and unnecessary
reconnects due to client or server bugs. If the response has
been received partially, the session will be reconnected anyway
on the next iteration of the demultiplex thread, so counting
credits for such cases shouldn't break things.

Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/cifs/cifsglob.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/smb2ops.c

index 1b25e6e95d45f8fe9ec2f39420de960c5fe0202b..0c796a27d1ebd826731301ce83c93521d14a141a 100644 (file)
@@ -385,8 +385,8 @@ struct smb_version_operations {
                         struct cifs_fid *);
        /* calculate a size of SMB message */
        unsigned int (*calc_smb_size)(void *buf, struct TCP_Server_Info *ptcpi);
-       /* check for STATUS_PENDING and process it in a positive case */
-       bool (*is_status_pending)(char *, struct TCP_Server_Info *, int);
+       /* check for STATUS_PENDING and process the response if yes */
+       bool (*is_status_pending)(char *buf, struct TCP_Server_Info *server);
        /* check for STATUS_NETWORK_SESSION_EXPIRED */
        bool (*is_session_expired)(char *);
        /* send oplock break response */
index 6bd3605b9b65686d62eed5316e73687abe06a89d..683c7c9d5a026a86317e8f499d3f9636776fca71 100644 (file)
@@ -1605,7 +1605,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
        }
 
        if (server->ops->is_status_pending &&
-           server->ops->is_status_pending(buf, server, 0)) {
+           server->ops->is_status_pending(buf, server)) {
                cifs_discard_remaining_data(server);
                return -1;
        }
index 106b6508f138833727596c5a0316856df8a32860..306a2a6f4e474f2fbd267f715786019778d6038f 100644 (file)
@@ -1054,7 +1054,7 @@ cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
        }
 
        if (server->ops->is_status_pending &&
-           server->ops->is_status_pending(buf, server, length))
+           server->ops->is_status_pending(buf, server))
                return -1;
 
        if (!mid)
index 90b1a8e218c9786d05c34a53f8dee80736d7380c..5adfe68f475449b64386cd3df798008842c9273e 100644 (file)
@@ -1773,14 +1773,14 @@ smb2_close_dir(const unsigned int xid, struct cifs_tcon *tcon,
 * the number of credits and return true. Otherwise - return false.
 */
 static bool
-smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length)
+smb2_is_status_pending(char *buf, struct TCP_Server_Info *server)
 {
        struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
 
        if (shdr->Status != STATUS_PENDING)
                return false;
 
-       if (!length) {
+       if (shdr->CreditRequest) {
                spin_lock(&server->req_lock);
                server->credits += le16_to_cpu(shdr->CreditRequest);
                spin_unlock(&server->req_lock);
@@ -3239,7 +3239,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
        }
 
        if (server->ops->is_status_pending &&
-                       server->ops->is_status_pending(buf, server, 0))
+                       server->ops->is_status_pending(buf, server))
                return -1;
 
        /* set up first two iov to get credits */