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)
|
||||
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,
|
||||
iov_iter_count(&subreq->io_iter), subreq->transferred,
|
||||
subreq->len, rreq->i_size,
|
||||
|
@ -1261,16 +1261,32 @@ openRetry:
|
||||
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
|
||||
cifs_readv_callback(struct mid_q_entry *mid)
|
||||
{
|
||||
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 TCP_Server_Info *server = tcon->ses->server;
|
||||
struct smb_rqst rqst = { .rq_iov = rdata->iov,
|
||||
.rq_nvec = 2,
|
||||
.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",
|
||||
__func__, mid->mid, mid->mid_state, rdata->result,
|
||||
@ -1282,6 +1298,7 @@ cifs_readv_callback(struct mid_q_entry *mid)
|
||||
if (server->sign) {
|
||||
int rc = 0;
|
||||
|
||||
iov_iter_truncate(&rqst.rq_iter, rdata->got_bytes);
|
||||
rc = cifs_verify_signature(&rqst, server,
|
||||
mid->sequence_number);
|
||||
if (rc)
|
||||
@ -1306,13 +1323,21 @@ cifs_readv_callback(struct mid_q_entry *mid)
|
||||
rdata->result = -EIO;
|
||||
}
|
||||
|
||||
if (rdata->result == 0 || rdata->result == -EAGAIN)
|
||||
iov_iter_advance(&rdata->subreq.io_iter, rdata->got_bytes);
|
||||
if (rdata->result == -ENODATA) {
|
||||
__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;
|
||||
netfs_subreq_terminated(&rdata->subreq,
|
||||
(rdata->result == 0 || rdata->result == -EAGAIN) ?
|
||||
rdata->got_bytes : rdata->result,
|
||||
false);
|
||||
INIT_WORK(&rdata->subreq.work, cifs_readv_worker);
|
||||
queue_work(cifsiod_wq, &rdata->subreq.work);
|
||||
release_mid(mid);
|
||||
add_credits(server, &credits, 0);
|
||||
}
|
||||
@ -1619,9 +1644,15 @@ static void
|
||||
cifs_writev_callback(struct mid_q_entry *mid)
|
||||
{
|
||||
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);
|
||||
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;
|
||||
size_t written;
|
||||
|
||||
@ -1657,9 +1688,16 @@ cifs_writev_callback(struct mid_q_entry *mid)
|
||||
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;
|
||||
cifs_write_subrequest_terminated(wdata, result, true);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -656,6 +656,19 @@ allocate_buffers(struct TCP_Server_Info *server)
|
||||
static bool
|
||||
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
|
||||
* 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
|
||||
* a response in >60s.
|
||||
*/
|
||||
spin_lock(&server->srv_lock);
|
||||
if ((server->tcpStatus == CifsGood ||
|
||||
server->tcpStatus == CifsNeedNegotiate) &&
|
||||
(!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 */
|
||||
return -ESTALE;
|
||||
}
|
||||
if (inode->i_state & I_NEW)
|
||||
CIFS_I(inode)->netfs.zero_point = fattr->cf_eof;
|
||||
|
||||
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);
|
||||
if (rc == -EINVAL) {
|
||||
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,
|
||||
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);
|
||||
if (rc == -EINVAL) {
|
||||
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,
|
||||
full_path, &oparms, &in_iov,
|
||||
&(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);
|
||||
trace_smb3_too_many_credits(server->CurrentMid,
|
||||
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);
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
@ -338,8 +339,9 @@ smb2_adjust_credits(struct TCP_Server_Info *server,
|
||||
trace_smb3_reconnect_detected(server->CurrentMid,
|
||||
server->conn_id, server->hostname, scredits,
|
||||
credits->value - new_val, in_flight);
|
||||
cifs_server_dbg(VFS, "trying to return %d credits to old session\n",
|
||||
credits->value - new_val);
|
||||
cifs_server_dbg(VFS, "R=%x[%x] trying to return %d credits to old session\n",
|
||||
subreq->rreq->debug_id, subreq->subreq.debug_index,
|
||||
credits->value - new_val);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user