Skip to content

Commit

Permalink
CIFS: Fix credits calculations for reads with errors
Browse files Browse the repository at this point in the history
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: <[email protected]>
Signed-off-by: Pavel Shilovsky <[email protected]>
Reviewed-by: Ronnie Sahlberg <[email protected]>
Signed-off-by: Steve French <[email protected]>
  • Loading branch information
piastry authored and Steve French committed Jan 24, 2019
1 parent ef68e83 commit 8004c78
Showing 1 changed file with 23 additions and 12 deletions.
35 changes: 23 additions & 12 deletions fs/cifs/cifssmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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? */
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 8004c78

Please sign in to comment.