mirror of
https://github.com/torvalds/linux.git
synced 2024-11-27 06:31:52 +00:00
cifs: take cifs_tcp_ses_lock for status checks
While checking/updating status for tcp ses, smb ses or tcon, we take GlobalMid_Lock. This doesn't make any sense. Replaced it with cifs_tcp_ses_lock. Ideally, we should take a spin lock per struct. But since tcp ses, smb ses and tcon objects won't add up to a lot, I think there should not be too much contention. Also, in few other places, these are checked without locking. Added locking for these. Signed-off-by: Shyam Prasad N <sprasad@microsoft.com> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
183eea2ee5
commit
080dc5e565
@ -498,10 +498,10 @@ static int cifs_swn_reconnect(struct cifs_tcon *tcon, struct sockaddr_storage *a
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (tcon->ses->server->tcpStatus != CifsExiting)
|
||||
tcon->ses->server->tcpStatus = CifsNeedReconnect;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&tcon->ses->server->srv_mutex);
|
||||
|
@ -141,9 +141,13 @@ int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
|
||||
if ((cifs_pdu == NULL) || (server == NULL))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (!(cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) ||
|
||||
server->tcpStatus == CifsNeedNegotiate)
|
||||
server->tcpStatus == CifsNeedNegotiate) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return rc;
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
if (!server->session_estab) {
|
||||
memcpy(cifs_pdu->Signature.SecuritySignature, "BSRSPYL", 8);
|
||||
|
@ -586,7 +586,7 @@ struct TCP_Server_Info {
|
||||
char server_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
|
||||
struct smb_version_operations *ops;
|
||||
struct smb_version_values *vals;
|
||||
/* updates to tcpStatus protected by GlobalMid_Lock */
|
||||
/* updates to tcpStatus protected by cifs_tcp_ses_lock */
|
||||
enum statusEnum tcpStatus; /* what we think the status is */
|
||||
char *hostname; /* hostname portion of UNC string */
|
||||
struct socket *ssocket;
|
||||
@ -924,7 +924,7 @@ struct cifs_ses {
|
||||
struct mutex session_mutex;
|
||||
struct TCP_Server_Info *server; /* pointer to server info */
|
||||
int ses_count; /* reference counter */
|
||||
enum statusEnum status; /* updates protected by GlobalMid_Lock */
|
||||
enum statusEnum status; /* updates protected by cifs_tcp_ses_lock */
|
||||
unsigned overrideSecFlg; /* if non-zero override global sec flags */
|
||||
char *serverOS; /* name of operating system underlying server */
|
||||
char *serverNOS; /* name of network operating system of server */
|
||||
|
@ -120,15 +120,18 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
|
||||
* only tree disconnect, open, and write, (and ulogoff which does not
|
||||
* have tcon) are allowed as we start force umount
|
||||
*/
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (tcon->tidStatus == CifsExiting) {
|
||||
if (smb_command != SMB_COM_WRITE_ANDX &&
|
||||
smb_command != SMB_COM_OPEN_ANDX &&
|
||||
smb_command != SMB_COM_TREE_DISCONNECT) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
cifs_dbg(FYI, "can not send cmd %d while umounting\n",
|
||||
smb_command);
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
retries = server->nr_targets;
|
||||
|
||||
@ -148,8 +151,12 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
|
||||
}
|
||||
|
||||
/* are we still trying to reconnect? */
|
||||
if (server->tcpStatus != CifsNeedReconnect)
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (server->tcpStatus != CifsNeedReconnect) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
break;
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
if (retries && --retries)
|
||||
continue;
|
||||
@ -186,11 +193,14 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
|
||||
* and the server never sends an answer the socket will be closed
|
||||
* and tcpStatus set to reconnect.
|
||||
*/
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (server->tcpStatus == CifsNeedReconnect) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
rc = -EHOSTDOWN;
|
||||
mutex_unlock(&ses->session_mutex);
|
||||
goto out;
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
/*
|
||||
* need to prevent multiple threads trying to simultaneously
|
||||
|
@ -467,9 +467,12 @@ reconnect_dfs_server(struct TCP_Server_Info *server,
|
||||
dfs_cache_free_tgts(&tl);
|
||||
|
||||
/* Need to set up echo worker again once connection has been established */
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (server->tcpStatus == CifsNeedNegotiate)
|
||||
mod_delayed_work(cifsiod_wq, &server->echo, 0);
|
||||
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
wake_up(&server->response_q);
|
||||
return rc;
|
||||
}
|
||||
@ -571,15 +574,18 @@ 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(&cifs_tcp_ses_lock);
|
||||
if ((server->tcpStatus == CifsGood ||
|
||||
server->tcpStatus == CifsNeedNegotiate) &&
|
||||
(!server->ops->can_echo || server->ops->can_echo(server)) &&
|
||||
time_after(jiffies, server->lstrp + 3 * server->echo_interval)) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
cifs_server_dbg(VFS, "has not responded in %lu seconds. Reconnecting...\n",
|
||||
(3 * server->echo_interval) / HZ);
|
||||
cifs_reconnect(server, false);
|
||||
return true;
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -624,13 +630,18 @@ cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
|
||||
else
|
||||
length = sock_recvmsg(server->ssocket, smb_msg, 0);
|
||||
|
||||
if (server->tcpStatus == CifsExiting)
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (server->tcpStatus == CifsExiting) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return -ESHUTDOWN;
|
||||
}
|
||||
|
||||
if (server->tcpStatus == CifsNeedReconnect) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
cifs_reconnect(server, false);
|
||||
return -ECONNABORTED;
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
if (length == -ERESTARTSYS ||
|
||||
length == -EAGAIN ||
|
||||
@ -808,9 +819,9 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server)
|
||||
cancel_delayed_work_sync(&server->echo);
|
||||
cancel_delayed_work_sync(&server->resolve);
|
||||
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
server->tcpStatus = CifsExiting;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
wake_up_all(&server->response_q);
|
||||
|
||||
/* check if we have blocked requests that need to free */
|
||||
@ -1427,9 +1438,9 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
|
||||
else
|
||||
cancel_delayed_work_sync(&server->reconnect);
|
||||
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
server->tcpStatus = CifsExiting;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
cifs_crypto_secmech_release(server);
|
||||
|
||||
@ -1582,7 +1593,9 @@ smbd_connected:
|
||||
* to the struct since the kernel thread not created yet
|
||||
* no need to spinlock this update of tcpStatus
|
||||
*/
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
tcp_ses->tcpStatus = CifsNeedNegotiate;
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
if ((ctx->max_credits < 20) || (ctx->max_credits > 60000))
|
||||
tcp_ses->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
|
||||
@ -1799,15 +1812,13 @@ void cifs_put_smb_ses(struct cifs_ses *ses)
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return;
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
/* ses_count can never go negative */
|
||||
WARN_ON(ses->ses_count < 0);
|
||||
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
if (ses->status == CifsGood)
|
||||
ses->status = CifsExiting;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
cifs_free_ipc(ses);
|
||||
|
||||
@ -3075,12 +3086,15 @@ static int mount_get_conns(struct mount_ctx *mnt_ctx)
|
||||
* for just this mount.
|
||||
*/
|
||||
reset_cifs_unix_caps(xid, tcon, cifs_sb, ctx);
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
|
||||
(le64_to_cpu(tcon->fsUnixInfo.Capability) &
|
||||
CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
rc = -EACCES;
|
||||
goto out;
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
} else
|
||||
tcon->unix_ext = 0; /* server does not support them */
|
||||
|
||||
@ -3755,7 +3769,9 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
|
||||
if (rc == 0) {
|
||||
bool is_unicode;
|
||||
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
tcon->tidStatus = CifsGood;
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
tcon->need_reconnect = false;
|
||||
tcon->tid = smb_buffer_response->Tid;
|
||||
bcc_ptr = pByteArea(smb_buffer_response);
|
||||
@ -3859,12 +3875,12 @@ cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses,
|
||||
|
||||
rc = server->ops->negotiate(xid, ses, server);
|
||||
if (rc == 0) {
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (server->tcpStatus == CifsNeedNegotiate)
|
||||
server->tcpStatus = CifsGood;
|
||||
else
|
||||
rc = -EHOSTDOWN;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
@ -896,10 +896,10 @@ map_and_check_smb_error(struct mid_q_entry *mid, bool logErr)
|
||||
if (class == ERRSRV && code == ERRbaduid) {
|
||||
cifs_dbg(FYI, "Server returned 0x%x, reconnecting session...\n",
|
||||
code);
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (mid->server->tcpStatus != CifsExiting)
|
||||
mid->server->tcpStatus = CifsNeedReconnect;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -369,10 +369,10 @@ void cifs_ses_mark_for_reconnect(struct cifs_ses *ses)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ses->chan_count; i++) {
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (ses->chans[i].server->tcpStatus != CifsExiting)
|
||||
ses->chans[i].server->tcpStatus = CifsNeedReconnect;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1052,9 +1052,9 @@ sess_establish_session(struct sess_data *sess_data)
|
||||
spin_unlock(&ses->chan_lock);
|
||||
|
||||
/* Even if one channel is active, session is in good state */
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
ses->status = CifsGood;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ cifs_get_next_mid(struct TCP_Server_Info *server)
|
||||
{
|
||||
__u64 mid = 0;
|
||||
__u16 last_mid, cur_mid;
|
||||
bool collision;
|
||||
bool collision, reconnect;
|
||||
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
|
||||
@ -215,7 +215,7 @@ cifs_get_next_mid(struct TCP_Server_Info *server)
|
||||
* an eventual reconnect to clean out the pending_mid_q.
|
||||
*/
|
||||
if (num_mids > 32768)
|
||||
server->tcpStatus = CifsNeedReconnect;
|
||||
reconnect = true;
|
||||
|
||||
if (!collision) {
|
||||
mid = (__u64)cur_mid;
|
||||
@ -225,6 +225,13 @@ cifs_get_next_mid(struct TCP_Server_Info *server)
|
||||
cur_mid++;
|
||||
}
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
|
||||
if (reconnect) {
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
server->tcpStatus = CifsNeedReconnect;
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
}
|
||||
|
||||
return mid;
|
||||
}
|
||||
|
||||
|
@ -121,9 +121,13 @@ smb2_add_credits(struct TCP_Server_Info *server,
|
||||
optype, scredits, add);
|
||||
}
|
||||
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (server->tcpStatus == CifsNeedReconnect
|
||||
|| server->tcpStatus == CifsExiting)
|
||||
|| server->tcpStatus == CifsExiting) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return;
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
switch (rc) {
|
||||
case -1:
|
||||
@ -208,11 +212,15 @@ smb2_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size,
|
||||
return rc;
|
||||
spin_lock(&server->req_lock);
|
||||
} else {
|
||||
spin_unlock(&server->req_lock);
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (server->tcpStatus == CifsExiting) {
|
||||
spin_unlock(&server->req_lock);
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return -ENOENT;
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
spin_lock(&server->req_lock);
|
||||
scredits = server->credits;
|
||||
/* can deadlock with reopen */
|
||||
if (scredits <= 8) {
|
||||
@ -4983,10 +4991,12 @@ static void smb2_decrypt_offload(struct work_struct *work)
|
||||
|
||||
mid->callback(mid);
|
||||
} else {
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
if (dw->server->tcpStatus == CifsNeedReconnect) {
|
||||
mid->mid_state = MID_RETRY_NEEDED;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
mid->callback(mid);
|
||||
} else {
|
||||
mid->mid_state = MID_REQUEST_SUBMITTED;
|
||||
@ -4994,6 +5004,7 @@ static void smb2_decrypt_offload(struct work_struct *work)
|
||||
list_add_tail(&mid->qhead,
|
||||
&dw->server->pending_mid_q);
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
}
|
||||
}
|
||||
cifs_mid_q_entry_release(mid);
|
||||
|
@ -162,6 +162,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
|
||||
if (smb2_command == SMB2_TREE_CONNECT || smb2_command == SMB2_IOCTL)
|
||||
return 0;
|
||||
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (tcon->tidStatus == CifsExiting) {
|
||||
/*
|
||||
* only tree disconnect, open, and write,
|
||||
@ -171,11 +172,13 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
|
||||
if ((smb2_command != SMB2_WRITE) &&
|
||||
(smb2_command != SMB2_CREATE) &&
|
||||
(smb2_command != SMB2_TREE_DISCONNECT)) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
cifs_dbg(FYI, "can not send cmd %d while umounting\n",
|
||||
smb2_command);
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
if ((!tcon->ses) || (tcon->ses->status == CifsExiting) ||
|
||||
(!tcon->ses->server) || !server)
|
||||
return -EIO;
|
||||
@ -214,8 +217,12 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
|
||||
}
|
||||
|
||||
/* are we still trying to reconnect? */
|
||||
if (server->tcpStatus != CifsNeedReconnect)
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (server->tcpStatus != CifsNeedReconnect) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
break;
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
if (retries && --retries)
|
||||
continue;
|
||||
@ -255,11 +262,14 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
|
||||
* and the server never sends an answer the socket will be closed
|
||||
* and tcpStatus set to reconnect.
|
||||
*/
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (server->tcpStatus == CifsNeedReconnect) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
rc = -EHOSTDOWN;
|
||||
mutex_unlock(&ses->session_mutex);
|
||||
goto out;
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
/*
|
||||
* need to prevent multiple threads trying to simultaneously
|
||||
@ -1386,9 +1396,9 @@ SMB2_sess_establish_session(struct SMB2_sess_data *sess_data)
|
||||
spin_unlock(&ses->chan_lock);
|
||||
|
||||
/* Even if one channel is active, session is in good state */
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
ses->status = CifsGood;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -1917,7 +1927,9 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
|
||||
tcon->share_flags = le32_to_cpu(rsp->ShareFlags);
|
||||
tcon->capabilities = rsp->Capabilities; /* we keep caps little endian */
|
||||
tcon->maximal_access = le32_to_cpu(rsp->MaximalAccess);
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
tcon->tidStatus = CifsGood;
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
tcon->need_reconnect = false;
|
||||
tcon->tid = le32_to_cpu(rsp->hdr.Id.SyncId.TreeId);
|
||||
strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
|
||||
@ -3854,11 +3866,14 @@ SMB2_echo(struct TCP_Server_Info *server)
|
||||
|
||||
cifs_dbg(FYI, "In echo request\n");
|
||||
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (server->tcpStatus == CifsNeedNegotiate) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
/* No need to send echo on newly established connections */
|
||||
mod_delayed_work(cifsiod_wq, &server->reconnect, 0);
|
||||
return rc;
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
rc = smb2_plain_req_init(SMB2_ECHO, NULL, server,
|
||||
(void **)&req, &total_len);
|
||||
|
@ -634,8 +634,12 @@ smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server)
|
||||
|
||||
if (!is_signed)
|
||||
return 0;
|
||||
if (server->tcpStatus == CifsNeedNegotiate)
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (server->tcpStatus == CifsNeedNegotiate) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return 0;
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
if (!is_binding && !server->session_estab) {
|
||||
strncpy(shdr->Signature, "BSRSPYL", 8);
|
||||
return 0;
|
||||
@ -751,30 +755,41 @@ static int
|
||||
smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_Server_Info *server,
|
||||
struct smb2_hdr *shdr, struct mid_q_entry **mid)
|
||||
{
|
||||
if (server->tcpStatus == CifsExiting)
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (server->tcpStatus == CifsExiting) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (server->tcpStatus == CifsNeedReconnect) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
cifs_dbg(FYI, "tcp session dead - return to caller to retry\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (server->tcpStatus == CifsNeedNegotiate &&
|
||||
shdr->Command != SMB2_NEGOTIATE)
|
||||
shdr->Command != SMB2_NEGOTIATE) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (ses->status == CifsNew) {
|
||||
if ((shdr->Command != SMB2_SESSION_SETUP) &&
|
||||
(shdr->Command != SMB2_NEGOTIATE))
|
||||
(shdr->Command != SMB2_NEGOTIATE)) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return -EAGAIN;
|
||||
}
|
||||
/* else ok - we are setting up session */
|
||||
}
|
||||
|
||||
if (ses->status == CifsExiting) {
|
||||
if (shdr->Command != SMB2_LOGOFF)
|
||||
if (shdr->Command != SMB2_LOGOFF) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return -EAGAIN;
|
||||
}
|
||||
/* else ok - we are shutting down the session */
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
*mid = smb2_mid_entry_alloc(shdr, server);
|
||||
if (*mid == NULL)
|
||||
@ -847,9 +862,13 @@ smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
|
||||
(struct smb2_hdr *)rqst->rq_iov[0].iov_base;
|
||||
struct mid_q_entry *mid;
|
||||
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (server->tcpStatus == CifsNeedNegotiate &&
|
||||
shdr->Command != SMB2_NEGOTIATE)
|
||||
shdr->Command != SMB2_NEGOTIATE) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return ERR_PTR(-EAGAIN);
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
smb2_seq_num_into_buf(server, shdr);
|
||||
|
||||
|
@ -430,9 +430,9 @@ unmask:
|
||||
* be taken as the remainder of this one. We need to kill the
|
||||
* socket so the server throws away the partial SMB
|
||||
*/
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
server->tcpStatus = CifsNeedReconnect;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
trace_smb3_partial_send_reconnect(server->CurrentMid,
|
||||
server->conn_id, server->hostname);
|
||||
}
|
||||
@ -578,10 +578,14 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits,
|
||||
return -ERESTARTSYS;
|
||||
spin_lock(&server->req_lock);
|
||||
} else {
|
||||
spin_unlock(&server->req_lock);
|
||||
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (server->tcpStatus == CifsExiting) {
|
||||
spin_unlock(&server->req_lock);
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return -ENOENT;
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
/*
|
||||
* For normal commands, reserve the last MAX_COMPOUND
|
||||
@ -596,6 +600,7 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits,
|
||||
* for servers that are slow to hand out credits on
|
||||
* new sessions.
|
||||
*/
|
||||
spin_lock(&server->req_lock);
|
||||
if (!optype && num_credits == 1 &&
|
||||
server->in_flight > 2 * MAX_COMPOUND &&
|
||||
*credits <= MAX_COMPOUND) {
|
||||
@ -723,28 +728,36 @@ cifs_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size,
|
||||
static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
|
||||
struct mid_q_entry **ppmidQ)
|
||||
{
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (ses->server->tcpStatus == CifsExiting) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (ses->server->tcpStatus == CifsNeedReconnect) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
cifs_dbg(FYI, "tcp session dead - return to caller to retry\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (ses->status == CifsNew) {
|
||||
if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
|
||||
(in_buf->Command != SMB_COM_NEGOTIATE))
|
||||
(in_buf->Command != SMB_COM_NEGOTIATE)) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return -EAGAIN;
|
||||
}
|
||||
/* else ok - we are setting up session */
|
||||
}
|
||||
|
||||
if (ses->status == CifsExiting) {
|
||||
/* check if SMB session is bad because we are setting it up */
|
||||
if (in_buf->Command != SMB_COM_LOGOFF_ANDX)
|
||||
if (in_buf->Command != SMB_COM_LOGOFF_ANDX) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return -EAGAIN;
|
||||
}
|
||||
/* else ok - we are shutting down session */
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
*ppmidQ = AllocMidQEntry(in_buf, ses->server);
|
||||
if (*ppmidQ == NULL)
|
||||
@ -1085,8 +1098,12 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (server->tcpStatus == CifsExiting)
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (server->tcpStatus == CifsExiting) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return -ENOENT;
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
/*
|
||||
* Wait for all the requests to become available.
|
||||
@ -1189,11 +1206,17 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
|
||||
/*
|
||||
* Compounding is never used during session establish.
|
||||
*/
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP) || (optype & CIFS_SESS_OP)) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
mutex_lock(&server->srv_mutex);
|
||||
smb311_update_preauth_hash(ses, server, rqst[0].rq_iov, rqst[0].rq_nvec);
|
||||
mutex_unlock(&server->srv_mutex);
|
||||
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
for (i = 0; i < num_rqst; i++) {
|
||||
rc = wait_for_response(server, midQ[i]);
|
||||
@ -1256,15 +1279,19 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
|
||||
/*
|
||||
* Compounding is never used during session establish.
|
||||
*/
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP) || (optype & CIFS_SESS_OP)) {
|
||||
struct kvec iov = {
|
||||
.iov_base = resp_iov[0].iov_base,
|
||||
.iov_len = resp_iov[0].iov_len
|
||||
};
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
mutex_lock(&server->srv_mutex);
|
||||
smb311_update_preauth_hash(ses, server, &iov, 1);
|
||||
mutex_unlock(&server->srv_mutex);
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
out:
|
||||
/*
|
||||
@ -1353,8 +1380,12 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (server->tcpStatus == CifsExiting)
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (server->tcpStatus == CifsExiting) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return -ENOENT;
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
/* Ensure that we do not send more than 50 overlapping requests
|
||||
to the same server. We may make this configurable later or
|
||||
@ -1494,8 +1525,12 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (server->tcpStatus == CifsExiting)
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (server->tcpStatus == CifsExiting) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return -ENOENT;
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
/* Ensure that we do not send more than 50 overlapping requests
|
||||
to the same server. We may make this configurable later or
|
||||
@ -1553,10 +1588,12 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
(server->tcpStatus != CifsNew)));
|
||||
|
||||
/* Were we interrupted by a signal ? */
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if ((rc == -ERESTARTSYS) &&
|
||||
(midQ->mid_state == MID_REQUEST_SUBMITTED) &&
|
||||
((server->tcpStatus == CifsGood) ||
|
||||
(server->tcpStatus == CifsNew))) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
if (in_buf->Command == SMB_COM_TRANSACTION2) {
|
||||
/* POSIX lock. We send a NT_CANCEL SMB to cause the
|
||||
@ -1595,7 +1632,9 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
|
||||
/* We got the response - restart system call. */
|
||||
rstart = 1;
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
rc = cifs_sync_mid_result(midQ, server);
|
||||
if (rc != 0)
|
||||
|
Loading…
Reference in New Issue
Block a user