CIFS: Count SMB3 credits for malformed pending responses
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>
This commit is contained in:
parent
82e0457af5
commit
66265f134a
|
@ -385,8 +385,8 @@ struct smb_version_operations {
|
||||||
struct cifs_fid *);
|
struct cifs_fid *);
|
||||||
/* calculate a size of SMB message */
|
/* calculate a size of SMB message */
|
||||||
unsigned int (*calc_smb_size)(void *buf, struct TCP_Server_Info *ptcpi);
|
unsigned int (*calc_smb_size)(void *buf, struct TCP_Server_Info *ptcpi);
|
||||||
/* check for STATUS_PENDING and process it in a positive case */
|
/* check for STATUS_PENDING and process the response if yes */
|
||||||
bool (*is_status_pending)(char *, struct TCP_Server_Info *, int);
|
bool (*is_status_pending)(char *buf, struct TCP_Server_Info *server);
|
||||||
/* check for STATUS_NETWORK_SESSION_EXPIRED */
|
/* check for STATUS_NETWORK_SESSION_EXPIRED */
|
||||||
bool (*is_session_expired)(char *);
|
bool (*is_session_expired)(char *);
|
||||||
/* send oplock break response */
|
/* send oplock break response */
|
||||||
|
|
|
@ -1605,7 +1605,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (server->ops->is_status_pending &&
|
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);
|
cifs_discard_remaining_data(server);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1054,7 +1054,7 @@ cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (server->ops->is_status_pending &&
|
if (server->ops->is_status_pending &&
|
||||||
server->ops->is_status_pending(buf, server, length))
|
server->ops->is_status_pending(buf, server))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (!mid)
|
if (!mid)
|
||||||
|
|
|
@ -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.
|
* the number of credits and return true. Otherwise - return false.
|
||||||
*/
|
*/
|
||||||
static bool
|
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;
|
struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
|
||||||
|
|
||||||
if (shdr->Status != STATUS_PENDING)
|
if (shdr->Status != STATUS_PENDING)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!length) {
|
if (shdr->CreditRequest) {
|
||||||
spin_lock(&server->req_lock);
|
spin_lock(&server->req_lock);
|
||||||
server->credits += le16_to_cpu(shdr->CreditRequest);
|
server->credits += le16_to_cpu(shdr->CreditRequest);
|
||||||
spin_unlock(&server->req_lock);
|
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 &&
|
if (server->ops->is_status_pending &&
|
||||||
server->ops->is_status_pending(buf, server, 0))
|
server->ops->is_status_pending(buf, server))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* set up first two iov to get credits */
|
/* set up first two iov to get credits */
|
||||||
|
|
Loading…
Reference in New Issue