five smb3 client fixes
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmbbVKkACgkQiiy9cAdy T1FTUgv8C/Qek0abESCC9AEvKUiAGwabOcdvKQnpCjI3eLQVmwGIHXXPdnkgxJmL gUQm4CBj6jWw5OfhBw2BTvnVz9YahQC8Xbg0XfLomaggD8NxVFnQyiWyyjPJtIiQ JRhOqV82Ko2NFMpouwfNTLPLMBpjNp6IrvkAY2bH5vUzPmoC/aU+eQMVXMqTFalD Q+vV2cFBcMsTTsRFCMG0er8114A1XvyG4IKr/95bTDjn/wnOVX9sUGrMbNXuoCsj yzMAkBoc60k2PjGoYMIQJsVDFryz7TpF7wyS2Oo5EkqzR/GKcIYGxTn0AznVhs83 5mAPXgyqpxg3wAsIVAs+vj0Jo2/cfpWuLb9pR5kt3lNA5EH7D1DNzXcHSe8GPvC6 iwrFI0RnR59HbDh1UGOSoVZv/W9cwmam6WG5HpS7YcRYocZqZyv+XjxUTlj2r+nV 12v9nnAWkH2Ub6kf3WHPzeXS3L6mvucody8b01UUL+j8hqWKN67sbXzH0Y2Nv0tv KFgbJCSk =CntT -----END PGP SIGNATURE----- Merge tag 'v6.11-rc6-cifs-client-fixes' of git://git.samba.org/sfrench/cifs-2.6 Pull smb client fixes from Steve French: - fix potential mount hang - fix retry problem in two types of compound operations - important netfs integration fix in SMB1 read paths - fix potential uninitialized zero point of inode - minor patch to improve debugging for potential crediting problems * tag 'v6.11-rc6-cifs-client-fixes' of git://git.samba.org/sfrench/cifs-2.6: netfs, cifs: Improve some debugging bits cifs: Fix SMB1 readv/writev callback in the same way as SMB2/3 cifs: Fix zero_point init on inode initialisation smb: client: fix double put of @cfile in smb2_set_path_size() smb: client: fix double put of @cfile in smb2_rename_path() smb: client: fix hang in wait_for_response() for negproto
This commit is contained in:
commit
a86b83f777
@ -270,7 +270,7 @@ static void netfs_reset_subreq_iter(struct netfs_io_request *rreq,
|
|||||||
if (count == remaining)
|
if (count == remaining)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_debug("R=%08x[%u] ITER RESUB-MISMATCH %zx != %zx-%zx-%llx %x\n",
|
_debug("R=%08x[%u] ITER RESUB-MISMATCH %zx != %zx-%zx-%llx %x",
|
||||||
rreq->debug_id, subreq->debug_index,
|
rreq->debug_id, subreq->debug_index,
|
||||||
iov_iter_count(&subreq->io_iter), subreq->transferred,
|
iov_iter_count(&subreq->io_iter), subreq->transferred,
|
||||||
subreq->len, rreq->i_size,
|
subreq->len, rreq->i_size,
|
||||||
|
@ -1261,16 +1261,32 @@ openRetry:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cifs_readv_worker(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct cifs_io_subrequest *rdata =
|
||||||
|
container_of(work, struct cifs_io_subrequest, subreq.work);
|
||||||
|
|
||||||
|
netfs_subreq_terminated(&rdata->subreq,
|
||||||
|
(rdata->result == 0 || rdata->result == -EAGAIN) ?
|
||||||
|
rdata->got_bytes : rdata->result, true);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cifs_readv_callback(struct mid_q_entry *mid)
|
cifs_readv_callback(struct mid_q_entry *mid)
|
||||||
{
|
{
|
||||||
struct cifs_io_subrequest *rdata = mid->callback_data;
|
struct cifs_io_subrequest *rdata = mid->callback_data;
|
||||||
|
struct netfs_inode *ictx = netfs_inode(rdata->rreq->inode);
|
||||||
struct cifs_tcon *tcon = tlink_tcon(rdata->req->cfile->tlink);
|
struct cifs_tcon *tcon = tlink_tcon(rdata->req->cfile->tlink);
|
||||||
struct TCP_Server_Info *server = tcon->ses->server;
|
struct TCP_Server_Info *server = tcon->ses->server;
|
||||||
struct smb_rqst rqst = { .rq_iov = rdata->iov,
|
struct smb_rqst rqst = { .rq_iov = rdata->iov,
|
||||||
.rq_nvec = 2,
|
.rq_nvec = 2,
|
||||||
.rq_iter = rdata->subreq.io_iter };
|
.rq_iter = rdata->subreq.io_iter };
|
||||||
struct cifs_credits credits = { .value = 1, .instance = 0 };
|
struct cifs_credits credits = {
|
||||||
|
.value = 1,
|
||||||
|
.instance = 0,
|
||||||
|
.rreq_debug_id = rdata->rreq->debug_id,
|
||||||
|
.rreq_debug_index = rdata->subreq.debug_index,
|
||||||
|
};
|
||||||
|
|
||||||
cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%zu\n",
|
cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%zu\n",
|
||||||
__func__, mid->mid, mid->mid_state, rdata->result,
|
__func__, mid->mid, mid->mid_state, rdata->result,
|
||||||
@ -1282,6 +1298,7 @@ cifs_readv_callback(struct mid_q_entry *mid)
|
|||||||
if (server->sign) {
|
if (server->sign) {
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
|
iov_iter_truncate(&rqst.rq_iter, rdata->got_bytes);
|
||||||
rc = cifs_verify_signature(&rqst, server,
|
rc = cifs_verify_signature(&rqst, server,
|
||||||
mid->sequence_number);
|
mid->sequence_number);
|
||||||
if (rc)
|
if (rc)
|
||||||
@ -1306,13 +1323,21 @@ cifs_readv_callback(struct mid_q_entry *mid)
|
|||||||
rdata->result = -EIO;
|
rdata->result = -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rdata->result == 0 || rdata->result == -EAGAIN)
|
if (rdata->result == -ENODATA) {
|
||||||
iov_iter_advance(&rdata->subreq.io_iter, rdata->got_bytes);
|
__set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags);
|
||||||
|
rdata->result = 0;
|
||||||
|
} else {
|
||||||
|
if (rdata->got_bytes < rdata->actual_len &&
|
||||||
|
rdata->subreq.start + rdata->subreq.transferred + rdata->got_bytes ==
|
||||||
|
ictx->remote_i_size) {
|
||||||
|
__set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags);
|
||||||
|
rdata->result = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rdata->credits.value = 0;
|
rdata->credits.value = 0;
|
||||||
netfs_subreq_terminated(&rdata->subreq,
|
INIT_WORK(&rdata->subreq.work, cifs_readv_worker);
|
||||||
(rdata->result == 0 || rdata->result == -EAGAIN) ?
|
queue_work(cifsiod_wq, &rdata->subreq.work);
|
||||||
rdata->got_bytes : rdata->result,
|
|
||||||
false);
|
|
||||||
release_mid(mid);
|
release_mid(mid);
|
||||||
add_credits(server, &credits, 0);
|
add_credits(server, &credits, 0);
|
||||||
}
|
}
|
||||||
@ -1619,9 +1644,15 @@ static void
|
|||||||
cifs_writev_callback(struct mid_q_entry *mid)
|
cifs_writev_callback(struct mid_q_entry *mid)
|
||||||
{
|
{
|
||||||
struct cifs_io_subrequest *wdata = mid->callback_data;
|
struct cifs_io_subrequest *wdata = mid->callback_data;
|
||||||
|
struct TCP_Server_Info *server = wdata->server;
|
||||||
struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink);
|
struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink);
|
||||||
WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
|
WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
|
||||||
struct cifs_credits credits = { .value = 1, .instance = 0 };
|
struct cifs_credits credits = {
|
||||||
|
.value = 1,
|
||||||
|
.instance = 0,
|
||||||
|
.rreq_debug_id = wdata->rreq->debug_id,
|
||||||
|
.rreq_debug_index = wdata->subreq.debug_index,
|
||||||
|
};
|
||||||
ssize_t result;
|
ssize_t result;
|
||||||
size_t written;
|
size_t written;
|
||||||
|
|
||||||
@ -1657,9 +1688,16 @@ cifs_writev_callback(struct mid_q_entry *mid)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trace_smb3_rw_credits(credits.rreq_debug_id, credits.rreq_debug_index,
|
||||||
|
wdata->credits.value,
|
||||||
|
server->credits, server->in_flight,
|
||||||
|
0, cifs_trace_rw_credits_write_response_clear);
|
||||||
wdata->credits.value = 0;
|
wdata->credits.value = 0;
|
||||||
cifs_write_subrequest_terminated(wdata, result, true);
|
cifs_write_subrequest_terminated(wdata, result, true);
|
||||||
release_mid(mid);
|
release_mid(mid);
|
||||||
|
trace_smb3_rw_credits(credits.rreq_debug_id, credits.rreq_debug_index, 0,
|
||||||
|
server->credits, server->in_flight,
|
||||||
|
credits.value, cifs_trace_rw_credits_write_response_add);
|
||||||
add_credits(tcon->ses->server, &credits, 0);
|
add_credits(tcon->ses->server, &credits, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -656,6 +656,19 @@ allocate_buffers(struct TCP_Server_Info *server)
|
|||||||
static bool
|
static bool
|
||||||
server_unresponsive(struct TCP_Server_Info *server)
|
server_unresponsive(struct TCP_Server_Info *server)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* If we're in the process of mounting a share or reconnecting a session
|
||||||
|
* and the server abruptly shut down (e.g. socket wasn't closed, packet
|
||||||
|
* had been ACK'ed but no SMB response), don't wait longer than 20s to
|
||||||
|
* negotiate protocol.
|
||||||
|
*/
|
||||||
|
spin_lock(&server->srv_lock);
|
||||||
|
if (server->tcpStatus == CifsInNegotiate &&
|
||||||
|
time_after(jiffies, server->lstrp + 20 * HZ)) {
|
||||||
|
spin_unlock(&server->srv_lock);
|
||||||
|
cifs_reconnect(server, false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* We need to wait 3 echo intervals to make sure we handle such
|
* We need to wait 3 echo intervals to make sure we handle such
|
||||||
* situations right:
|
* situations right:
|
||||||
@ -667,7 +680,6 @@ server_unresponsive(struct TCP_Server_Info *server)
|
|||||||
* 65s kernel_recvmsg times out, and we see that we haven't gotten
|
* 65s kernel_recvmsg times out, and we see that we haven't gotten
|
||||||
* a response in >60s.
|
* a response in >60s.
|
||||||
*/
|
*/
|
||||||
spin_lock(&server->srv_lock);
|
|
||||||
if ((server->tcpStatus == CifsGood ||
|
if ((server->tcpStatus == CifsGood ||
|
||||||
server->tcpStatus == CifsNeedNegotiate) &&
|
server->tcpStatus == CifsNeedNegotiate) &&
|
||||||
(!server->ops->can_echo || server->ops->can_echo(server)) &&
|
(!server->ops->can_echo || server->ops->can_echo(server)) &&
|
||||||
|
@ -172,6 +172,8 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr,
|
|||||||
CIFS_I(inode)->time = 0; /* force reval */
|
CIFS_I(inode)->time = 0; /* force reval */
|
||||||
return -ESTALE;
|
return -ESTALE;
|
||||||
}
|
}
|
||||||
|
if (inode->i_state & I_NEW)
|
||||||
|
CIFS_I(inode)->netfs.zero_point = fattr->cf_eof;
|
||||||
|
|
||||||
cifs_revalidate_cache(inode, fattr);
|
cifs_revalidate_cache(inode, fattr);
|
||||||
|
|
||||||
|
@ -1106,6 +1106,8 @@ int smb2_rename_path(const unsigned int xid,
|
|||||||
co, DELETE, SMB2_OP_RENAME, cfile, source_dentry);
|
co, DELETE, SMB2_OP_RENAME, cfile, source_dentry);
|
||||||
if (rc == -EINVAL) {
|
if (rc == -EINVAL) {
|
||||||
cifs_dbg(FYI, "invalid lease key, resending request without lease");
|
cifs_dbg(FYI, "invalid lease key, resending request without lease");
|
||||||
|
cifs_get_writable_path(tcon, from_name,
|
||||||
|
FIND_WR_WITH_DELETE, &cfile);
|
||||||
rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
|
rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
|
||||||
co, DELETE, SMB2_OP_RENAME, cfile, NULL);
|
co, DELETE, SMB2_OP_RENAME, cfile, NULL);
|
||||||
}
|
}
|
||||||
@ -1149,6 +1151,7 @@ smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
|
|||||||
cfile, NULL, NULL, dentry);
|
cfile, NULL, NULL, dentry);
|
||||||
if (rc == -EINVAL) {
|
if (rc == -EINVAL) {
|
||||||
cifs_dbg(FYI, "invalid lease key, resending request without lease");
|
cifs_dbg(FYI, "invalid lease key, resending request without lease");
|
||||||
|
cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
|
||||||
rc = smb2_compound_op(xid, tcon, cifs_sb,
|
rc = smb2_compound_op(xid, tcon, cifs_sb,
|
||||||
full_path, &oparms, &in_iov,
|
full_path, &oparms, &in_iov,
|
||||||
&(int){SMB2_OP_SET_EOF}, 1,
|
&(int){SMB2_OP_SET_EOF}, 1,
|
||||||
|
@ -316,7 +316,8 @@ smb2_adjust_credits(struct TCP_Server_Info *server,
|
|||||||
cifs_trace_rw_credits_no_adjust_up);
|
cifs_trace_rw_credits_no_adjust_up);
|
||||||
trace_smb3_too_many_credits(server->CurrentMid,
|
trace_smb3_too_many_credits(server->CurrentMid,
|
||||||
server->conn_id, server->hostname, 0, credits->value - new_val, 0);
|
server->conn_id, server->hostname, 0, credits->value - new_val, 0);
|
||||||
cifs_server_dbg(VFS, "request has less credits (%d) than required (%d)",
|
cifs_server_dbg(VFS, "R=%x[%x] request has less credits (%d) than required (%d)",
|
||||||
|
subreq->rreq->debug_id, subreq->subreq.debug_index,
|
||||||
credits->value, new_val);
|
credits->value, new_val);
|
||||||
|
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
@ -338,8 +339,9 @@ smb2_adjust_credits(struct TCP_Server_Info *server,
|
|||||||
trace_smb3_reconnect_detected(server->CurrentMid,
|
trace_smb3_reconnect_detected(server->CurrentMid,
|
||||||
server->conn_id, server->hostname, scredits,
|
server->conn_id, server->hostname, scredits,
|
||||||
credits->value - new_val, in_flight);
|
credits->value - new_val, in_flight);
|
||||||
cifs_server_dbg(VFS, "trying to return %d credits to old session\n",
|
cifs_server_dbg(VFS, "R=%x[%x] trying to return %d credits to old session\n",
|
||||||
credits->value - new_val);
|
subreq->rreq->debug_id, subreq->subreq.debug_index,
|
||||||
|
credits->value - new_val);
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user