mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-25 13:14:07 +08:00
CIFS: Fix credits calculations for reads with errors
Currently we mark MID as malformed if we get an error from server in a read response. This leads to not properly processing credits in the readv callback. Fix this by marking such a response as normal received response and process it appropriately. Cc: <stable@vger.kernel.org> Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com> Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
ef68e83184
commit
8004c78c68
@ -1549,18 +1549,26 @@ cifs_discard_remaining_data(struct TCP_Server_Info *server)
|
||||
}
|
||||
|
||||
static int
|
||||
cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
||||
__cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid,
|
||||
bool malformed)
|
||||
{
|
||||
int length;
|
||||
struct cifs_readdata *rdata = mid->callback_data;
|
||||
|
||||
length = cifs_discard_remaining_data(server);
|
||||
dequeue_mid(mid, rdata->result);
|
||||
dequeue_mid(mid, malformed);
|
||||
mid->resp_buf = server->smallbuf;
|
||||
server->smallbuf = NULL;
|
||||
return length;
|
||||
}
|
||||
|
||||
static int
|
||||
cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
||||
{
|
||||
struct cifs_readdata *rdata = mid->callback_data;
|
||||
|
||||
return __cifs_readv_discard(server, mid, rdata->result);
|
||||
}
|
||||
|
||||
int
|
||||
cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
||||
{
|
||||
@ -1602,12 +1610,23 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* set up first two iov for signature check and to get credits */
|
||||
rdata->iov[0].iov_base = buf;
|
||||
rdata->iov[0].iov_len = 4;
|
||||
rdata->iov[1].iov_base = buf + 4;
|
||||
rdata->iov[1].iov_len = server->total_read - 4;
|
||||
cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
|
||||
rdata->iov[0].iov_base, rdata->iov[0].iov_len);
|
||||
cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n",
|
||||
rdata->iov[1].iov_base, rdata->iov[1].iov_len);
|
||||
|
||||
/* Was the SMB read successful? */
|
||||
rdata->result = server->ops->map_error(buf, false);
|
||||
if (rdata->result != 0) {
|
||||
cifs_dbg(FYI, "%s: server returned error %d\n",
|
||||
__func__, rdata->result);
|
||||
return cifs_readv_discard(server, mid);
|
||||
/* normal error on read response */
|
||||
return __cifs_readv_discard(server, mid, false);
|
||||
}
|
||||
|
||||
/* Is there enough to get to the rest of the READ_RSP header? */
|
||||
@ -1651,14 +1670,6 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
||||
server->total_read += length;
|
||||
}
|
||||
|
||||
/* set up first iov for signature check */
|
||||
rdata->iov[0].iov_base = buf;
|
||||
rdata->iov[0].iov_len = 4;
|
||||
rdata->iov[1].iov_base = buf + 4;
|
||||
rdata->iov[1].iov_len = server->total_read - 4;
|
||||
cifs_dbg(FYI, "0: iov_base=%p iov_len=%u\n",
|
||||
rdata->iov[0].iov_base, server->total_read);
|
||||
|
||||
/* how much data is in the response? */
|
||||
#ifdef CONFIG_CIFS_SMB_DIRECT
|
||||
use_rdma_mr = rdata->mr;
|
||||
|
Loading…
Reference in New Issue
Block a user