Commit 482592b7 authored by Pavel Shilovsky's avatar Pavel Shilovsky Committed by Greg Kroah-Hartman

CIFS: Fix credits calculations for reads with errors

commit 8004c78c upstream.

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: default avatarPavel Shilovsky <pshilov@microsoft.com>
Reviewed-by: default avatarRonnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 8a9c970f
...@@ -1445,18 +1445,26 @@ cifs_discard_remaining_data(struct TCP_Server_Info *server) ...@@ -1445,18 +1445,26 @@ cifs_discard_remaining_data(struct TCP_Server_Info *server)
} }
static int 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; int length;
struct cifs_readdata *rdata = mid->callback_data;
length = cifs_discard_remaining_data(server); length = cifs_discard_remaining_data(server);
dequeue_mid(mid, rdata->result); dequeue_mid(mid, malformed);
mid->resp_buf = server->smallbuf; mid->resp_buf = server->smallbuf;
server->smallbuf = NULL; server->smallbuf = NULL;
return length; 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 int
cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
{ {
...@@ -1496,12 +1504,23 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) ...@@ -1496,12 +1504,23 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
return -1; 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? */ /* Was the SMB read successful? */
rdata->result = server->ops->map_error(buf, false); rdata->result = server->ops->map_error(buf, false);
if (rdata->result != 0) { if (rdata->result != 0) {
cifs_dbg(FYI, "%s: server returned error %d\n", cifs_dbg(FYI, "%s: server returned error %d\n",
__func__, rdata->result); __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? */ /* Is there enough to get to the rest of the READ_RSP header? */
...@@ -1544,14 +1563,6 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) ...@@ -1544,14 +1563,6 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
server->total_read += length; 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? */ /* how much data is in the response? */
data_len = server->ops->read_data_length(buf); data_len = server->ops->read_data_length(buf);
if (data_offset + data_len > buflen) { if (data_offset + data_len > buflen) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment