Commit 5e90aa21 authored by Shyam Prasad N's avatar Shyam Prasad N Committed by Steve French

cifs: fix max_credits implementation

The current implementation of max_credits on the client does
not work because the CreditRequest logic for several commands
does not take max_credits into account.

Still, we can end up asking the server for more credits, depending
on the number of credits in flight. For this, we need to
limit the credits while parsing the responses too.
Signed-off-by: default avatarShyam Prasad N <sprasad@microsoft.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 2991b774
...@@ -34,6 +34,8 @@ static int ...@@ -34,6 +34,8 @@ static int
change_conf(struct TCP_Server_Info *server) change_conf(struct TCP_Server_Info *server)
{ {
server->credits += server->echo_credits + server->oplock_credits; server->credits += server->echo_credits + server->oplock_credits;
if (server->credits > server->max_credits)
server->credits = server->max_credits;
server->oplock_credits = server->echo_credits = 0; server->oplock_credits = server->echo_credits = 0;
switch (server->credits) { switch (server->credits) {
case 0: case 0:
......
...@@ -1305,7 +1305,12 @@ SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data) ...@@ -1305,7 +1305,12 @@ SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data)
} }
/* enough to enable echos and oplocks and one max size write */ /* enough to enable echos and oplocks and one max size write */
req->hdr.CreditRequest = cpu_to_le16(130); if (server->credits >= server->max_credits)
req->hdr.CreditRequest = cpu_to_le16(0);
else
req->hdr.CreditRequest = cpu_to_le16(
min_t(int, server->max_credits -
server->credits, 130));
/* only one of SMB2 signing flags may be set in SMB2 request */ /* only one of SMB2 signing flags may be set in SMB2 request */
if (server->sign) if (server->sign)
...@@ -1899,7 +1904,12 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, ...@@ -1899,7 +1904,12 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
rqst.rq_nvec = 2; rqst.rq_nvec = 2;
/* Need 64 for max size write so ask for more in case not there yet */ /* Need 64 for max size write so ask for more in case not there yet */
req->hdr.CreditRequest = cpu_to_le16(64); if (server->credits >= server->max_credits)
req->hdr.CreditRequest = cpu_to_le16(0);
else
req->hdr.CreditRequest = cpu_to_le16(
min_t(int, server->max_credits -
server->credits, 64));
rc = cifs_send_recv(xid, ses, server, rc = cifs_send_recv(xid, ses, server,
&rqst, &resp_buftype, flags, &rsp_iov); &rqst, &resp_buftype, flags, &rsp_iov);
...@@ -4227,6 +4237,7 @@ smb2_async_readv(struct cifs_readdata *rdata) ...@@ -4227,6 +4237,7 @@ smb2_async_readv(struct cifs_readdata *rdata)
struct TCP_Server_Info *server; struct TCP_Server_Info *server;
struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
unsigned int total_len; unsigned int total_len;
int credit_request;
cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n", cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
__func__, rdata->offset, rdata->bytes); __func__, rdata->offset, rdata->bytes);
...@@ -4258,7 +4269,13 @@ smb2_async_readv(struct cifs_readdata *rdata) ...@@ -4258,7 +4269,13 @@ smb2_async_readv(struct cifs_readdata *rdata)
if (rdata->credits.value > 0) { if (rdata->credits.value > 0) {
shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->bytes, shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->bytes,
SMB2_MAX_BUFFER_SIZE)); SMB2_MAX_BUFFER_SIZE));
shdr->CreditRequest = cpu_to_le16(le16_to_cpu(shdr->CreditCharge) + 8); credit_request = le16_to_cpu(shdr->CreditCharge) + 8;
if (server->credits >= server->max_credits)
shdr->CreditRequest = cpu_to_le16(0);
else
shdr->CreditRequest = cpu_to_le16(
min_t(int, server->max_credits -
server->credits, credit_request));
rc = adjust_credits(server, &rdata->credits, rdata->bytes); rc = adjust_credits(server, &rdata->credits, rdata->bytes);
if (rc) if (rc)
...@@ -4468,6 +4485,7 @@ smb2_async_writev(struct cifs_writedata *wdata, ...@@ -4468,6 +4485,7 @@ smb2_async_writev(struct cifs_writedata *wdata,
unsigned int total_len; unsigned int total_len;
struct cifs_io_parms _io_parms; struct cifs_io_parms _io_parms;
struct cifs_io_parms *io_parms = NULL; struct cifs_io_parms *io_parms = NULL;
int credit_request;
if (!wdata->server) if (!wdata->server)
server = wdata->server = cifs_pick_channel(tcon->ses); server = wdata->server = cifs_pick_channel(tcon->ses);
...@@ -4572,7 +4590,13 @@ smb2_async_writev(struct cifs_writedata *wdata, ...@@ -4572,7 +4590,13 @@ smb2_async_writev(struct cifs_writedata *wdata,
if (wdata->credits.value > 0) { if (wdata->credits.value > 0) {
shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->bytes, shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->bytes,
SMB2_MAX_BUFFER_SIZE)); SMB2_MAX_BUFFER_SIZE));
shdr->CreditRequest = cpu_to_le16(le16_to_cpu(shdr->CreditCharge) + 8); credit_request = le16_to_cpu(shdr->CreditCharge) + 8;
if (server->credits >= server->max_credits)
shdr->CreditRequest = cpu_to_le16(0);
else
shdr->CreditRequest = cpu_to_le16(
min_t(int, server->max_credits -
server->credits, credit_request));
rc = adjust_credits(server, &wdata->credits, io_parms->length); rc = adjust_credits(server, &wdata->credits, io_parms->length);
if (rc) if (rc)
......
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