|
Enzo Matsumiya |
cba50e |
From: Shyam Prasad N <sprasad@microsoft.com>
|
|
Enzo Matsumiya |
cba50e |
Date: Mon, 19 Jul 2021 10:54:46 +0000
|
|
Enzo Matsumiya |
cba50e |
Subject: [PATCH] cifs: protect session channel fields with chan_lock
|
|
Enzo Matsumiya |
cba50e |
Git-commit: 724244cdb3828522109c88e56a0242537aefabe9
|
|
Enzo Matsumiya |
cba50e |
Patch-mainline: v5.16-rc1
|
|
Enzo Matsumiya |
cba50e |
References: bsc#1192606
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
Introducing a new spin lock to protect all the channel related
|
|
Enzo Matsumiya |
cba50e |
fields in a cifs_ses struct. This lock should be taken
|
|
Enzo Matsumiya |
cba50e |
whenever dealing with the channel fields, and should be held
|
|
Enzo Matsumiya |
cba50e |
only for very short intervals which will not sleep.
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
Currently, all channel related fields in cifs_ses structure
|
|
Enzo Matsumiya |
cba50e |
are protected by session_mutex. However, this mutex is held for
|
|
Enzo Matsumiya |
cba50e |
long periods (sometimes while waiting for a reply from server).
|
|
Enzo Matsumiya |
cba50e |
This makes the codepath quite tricky to change.
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
|
|
Enzo Matsumiya |
cba50e |
Reviewed-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
|
|
Enzo Matsumiya |
cba50e |
Signed-off-by: Steve French <stfrench@microsoft.com>
|
|
Enzo Matsumiya |
cba50e |
Acked-by: Enzo Matsumiya <ematsumiya@suse.de>
|
|
Enzo Matsumiya |
cba50e |
---
|
|
Enzo Matsumiya |
cba50e |
fs/cifs/cifs_debug.c | 2 ++
|
|
Enzo Matsumiya |
cba50e |
fs/cifs/cifsglob.h | 5 +++++
|
|
Enzo Matsumiya |
cba50e |
fs/cifs/connect.c | 25 +++++++++++++++++++---
|
|
Enzo Matsumiya |
cba50e |
fs/cifs/misc.c | 1 +
|
|
Enzo Matsumiya |
cba50e |
fs/cifs/sess.c | 50 +++++++++++++++++++++++++++++++++-----------
|
|
Enzo Matsumiya |
cba50e |
fs/cifs/transport.c | 3 +++
|
|
Enzo Matsumiya |
cba50e |
6 files changed, 71 insertions(+), 15 deletions(-)
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
|
|
Enzo Matsumiya |
cba50e |
index 905a901f7f80..248a8f973cf9 100644
|
|
Enzo Matsumiya |
cba50e |
--- a/fs/cifs/cifs_debug.c
|
|
Enzo Matsumiya |
cba50e |
+++ b/fs/cifs/cifs_debug.c
|
|
Enzo Matsumiya |
cba50e |
@@ -414,12 +414,14 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
|
|
Enzo Matsumiya |
cba50e |
from_kuid(&init_user_ns, ses->linux_uid),
|
|
Enzo Matsumiya |
cba50e |
from_kuid(&init_user_ns, ses->cred_uid));
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
+ spin_lock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
if (ses->chan_count > 1) {
|
|
Enzo Matsumiya |
cba50e |
seq_printf(m, "\n\n\tExtra Channels: %zu ",
|
|
Enzo Matsumiya |
cba50e |
ses->chan_count-1);
|
|
Enzo Matsumiya |
cba50e |
for (j = 1; j < ses->chan_count; j++)
|
|
Enzo Matsumiya |
cba50e |
cifs_dump_channel(m, j, &ses->chans[j]);
|
|
Enzo Matsumiya |
cba50e |
}
|
|
Enzo Matsumiya |
cba50e |
+ spin_unlock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
seq_puts(m, "\n\n\tShares: ");
|
|
Enzo Matsumiya |
cba50e |
j = 0;
|
|
Enzo Matsumiya |
cba50e |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
|
|
Enzo Matsumiya |
cba50e |
index 673ecbfe6d9a..3c18c56a119b 100644
|
|
Enzo Matsumiya |
cba50e |
--- a/fs/cifs/cifsglob.h
|
|
Enzo Matsumiya |
cba50e |
+++ b/fs/cifs/cifsglob.h
|
|
Enzo Matsumiya |
cba50e |
@@ -952,16 +952,21 @@ struct cifs_ses {
|
|
Enzo Matsumiya |
cba50e |
* iface_lock should be taken when accessing any of these fields
|
|
Enzo Matsumiya |
cba50e |
*/
|
|
Enzo Matsumiya |
cba50e |
spinlock_t iface_lock;
|
|
Enzo Matsumiya |
cba50e |
+ /* ========= begin: protected by iface_lock ======== */
|
|
Enzo Matsumiya |
cba50e |
struct cifs_server_iface *iface_list;
|
|
Enzo Matsumiya |
cba50e |
size_t iface_count;
|
|
Enzo Matsumiya |
cba50e |
unsigned long iface_last_update; /* jiffies */
|
|
Enzo Matsumiya |
cba50e |
+ /* ========= end: protected by iface_lock ======== */
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
+ spinlock_t chan_lock;
|
|
Enzo Matsumiya |
cba50e |
+ /* ========= begin: protected by chan_lock ======== */
|
|
Enzo Matsumiya |
cba50e |
#define CIFS_MAX_CHANNELS 16
|
|
Enzo Matsumiya |
cba50e |
struct cifs_chan chans[CIFS_MAX_CHANNELS];
|
|
Enzo Matsumiya |
cba50e |
struct cifs_chan *binding_chan;
|
|
Enzo Matsumiya |
cba50e |
size_t chan_count;
|
|
Enzo Matsumiya |
cba50e |
size_t chan_max;
|
|
Enzo Matsumiya |
cba50e |
atomic_t chan_seq; /* round robin state */
|
|
Enzo Matsumiya |
cba50e |
+ /* ========= end: protected by chan_lock ======== */
|
|
Enzo Matsumiya |
cba50e |
};
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
/*
|
|
Enzo Matsumiya |
cba50e |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
|
|
Enzo Matsumiya |
cba50e |
index 498ec05ca10d..09a532ed8fe4 100644
|
|
Enzo Matsumiya |
cba50e |
--- a/fs/cifs/connect.c
|
|
Enzo Matsumiya |
cba50e |
+++ b/fs/cifs/connect.c
|
|
Enzo Matsumiya |
cba50e |
@@ -1577,8 +1577,12 @@ static int match_session(struct cifs_ses *ses, struct smb3_fs_context *ctx)
|
|
Enzo Matsumiya |
cba50e |
* If an existing session is limited to less channels than
|
|
Enzo Matsumiya |
cba50e |
* requested, it should not be reused
|
|
Enzo Matsumiya |
cba50e |
*/
|
|
Enzo Matsumiya |
cba50e |
- if (ses->chan_max < ctx->max_channels)
|
|
Enzo Matsumiya |
cba50e |
+ spin_lock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
+ if (ses->chan_max < ctx->max_channels) {
|
|
Enzo Matsumiya |
cba50e |
+ spin_unlock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
return 0;
|
|
Enzo Matsumiya |
cba50e |
+ }
|
|
Enzo Matsumiya |
cba50e |
+ spin_unlock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
switch (ses->sectype) {
|
|
Enzo Matsumiya |
cba50e |
case Kerberos:
|
|
Enzo Matsumiya |
cba50e |
@@ -1713,6 +1717,7 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
|
|
Enzo Matsumiya |
cba50e |
void cifs_put_smb_ses(struct cifs_ses *ses)
|
|
Enzo Matsumiya |
cba50e |
{
|
|
Enzo Matsumiya |
cba50e |
unsigned int rc, xid;
|
|
Enzo Matsumiya |
cba50e |
+ unsigned int chan_count;
|
|
Enzo Matsumiya |
cba50e |
struct TCP_Server_Info *server = ses->server;
|
|
Enzo Matsumiya |
cba50e |
cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
@@ -1754,12 +1759,24 @@ void cifs_put_smb_ses(struct cifs_ses *ses)
|
|
Enzo Matsumiya |
cba50e |
list_del_init(&ses->smb_ses_list);
|
|
Enzo Matsumiya |
cba50e |
spin_unlock(&cifs_tcp_ses_lock);
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
+ spin_lock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
+ chan_count = ses->chan_count;
|
|
Enzo Matsumiya |
cba50e |
+ spin_unlock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
+
|
|
Enzo Matsumiya |
cba50e |
/* close any extra channels */
|
|
Enzo Matsumiya |
cba50e |
- if (ses->chan_count > 1) {
|
|
Enzo Matsumiya |
cba50e |
+ if (chan_count > 1) {
|
|
Enzo Matsumiya |
cba50e |
int i;
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
- for (i = 1; i < ses->chan_count; i++)
|
|
Enzo Matsumiya |
cba50e |
+ for (i = 1; i < chan_count; i++) {
|
|
Enzo Matsumiya |
cba50e |
+ /*
|
|
Enzo Matsumiya |
cba50e |
+ * note: for now, we're okay accessing ses->chans
|
|
Enzo Matsumiya |
cba50e |
+ * without chan_lock. But when chans can go away, we'll
|
|
Enzo Matsumiya |
cba50e |
+ * need to introduce ref counting to make sure that chan
|
|
Enzo Matsumiya |
cba50e |
+ * is not freed from under us.
|
|
Enzo Matsumiya |
cba50e |
+ */
|
|
Enzo Matsumiya |
cba50e |
cifs_put_tcp_session(ses->chans[i].server, 0);
|
|
Enzo Matsumiya |
cba50e |
+ ses->chans[i].server = NULL;
|
|
Enzo Matsumiya |
cba50e |
+ }
|
|
Enzo Matsumiya |
cba50e |
}
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
sesInfoFree(ses);
|
|
Enzo Matsumiya |
cba50e |
@@ -2018,9 +2035,11 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
|
|
Enzo Matsumiya |
cba50e |
mutex_lock(&ses->session_mutex);
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
/* add server as first channel */
|
|
Enzo Matsumiya |
cba50e |
+ spin_lock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
ses->chans[0].server = server;
|
|
Enzo Matsumiya |
cba50e |
ses->chan_count = 1;
|
|
Enzo Matsumiya |
cba50e |
ses->chan_max = ctx->multichannel ? ctx->max_channels:1;
|
|
Enzo Matsumiya |
cba50e |
+ spin_unlock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
rc = cifs_negotiate_protocol(xid, ses);
|
|
Enzo Matsumiya |
cba50e |
if (!rc)
|
|
Enzo Matsumiya |
cba50e |
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
|
|
Enzo Matsumiya |
cba50e |
index a6089ea53ad7..5148d48d6a35 100644
|
|
Enzo Matsumiya |
cba50e |
--- a/fs/cifs/misc.c
|
|
Enzo Matsumiya |
cba50e |
+++ b/fs/cifs/misc.c
|
|
Enzo Matsumiya |
cba50e |
@@ -75,6 +75,7 @@ sesInfoAlloc(void)
|
|
Enzo Matsumiya |
cba50e |
INIT_LIST_HEAD(&ret_buf->tcon_list);
|
|
Enzo Matsumiya |
cba50e |
mutex_init(&ret_buf->session_mutex);
|
|
Enzo Matsumiya |
cba50e |
spin_lock_init(&ret_buf->iface_lock);
|
|
Enzo Matsumiya |
cba50e |
+ spin_lock_init(&ret_buf->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
}
|
|
Enzo Matsumiya |
cba50e |
return ret_buf;
|
|
Enzo Matsumiya |
cba50e |
}
|
|
Enzo Matsumiya |
cba50e |
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
|
|
Enzo Matsumiya |
cba50e |
index 93a1619d60e6..27660bffb918 100644
|
|
Enzo Matsumiya |
cba50e |
--- a/fs/cifs/sess.c
|
|
Enzo Matsumiya |
cba50e |
+++ b/fs/cifs/sess.c
|
|
Enzo Matsumiya |
cba50e |
@@ -54,41 +54,53 @@ bool is_ses_using_iface(struct cifs_ses *ses, struct cifs_server_iface *iface)
|
|
Enzo Matsumiya |
cba50e |
{
|
|
Enzo Matsumiya |
cba50e |
int i;
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
+ spin_lock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
for (i = 0; i < ses->chan_count; i++) {
|
|
Enzo Matsumiya |
cba50e |
- if (is_server_using_iface(ses->chans[i].server, iface))
|
|
Enzo Matsumiya |
cba50e |
+ if (is_server_using_iface(ses->chans[i].server, iface)) {
|
|
Enzo Matsumiya |
cba50e |
+ spin_unlock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
return true;
|
|
Enzo Matsumiya |
cba50e |
+ }
|
|
Enzo Matsumiya |
cba50e |
}
|
|
Enzo Matsumiya |
cba50e |
+ spin_unlock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
return false;
|
|
Enzo Matsumiya |
cba50e |
}
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
/* returns number of channels added */
|
|
Enzo Matsumiya |
cba50e |
int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses)
|
|
Enzo Matsumiya |
cba50e |
{
|
|
Enzo Matsumiya |
cba50e |
- int old_chan_count = ses->chan_count;
|
|
Enzo Matsumiya |
cba50e |
- int left = ses->chan_max - ses->chan_count;
|
|
Enzo Matsumiya |
cba50e |
+ int old_chan_count, new_chan_count;
|
|
Enzo Matsumiya |
cba50e |
+ int left;
|
|
Enzo Matsumiya |
cba50e |
int i = 0;
|
|
Enzo Matsumiya |
cba50e |
int rc = 0;
|
|
Enzo Matsumiya |
cba50e |
int tries = 0;
|
|
Enzo Matsumiya |
cba50e |
struct cifs_server_iface *ifaces = NULL;
|
|
Enzo Matsumiya |
cba50e |
size_t iface_count;
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
+ if (ses->server->dialect < SMB30_PROT_ID) {
|
|
Enzo Matsumiya |
cba50e |
+ cifs_dbg(VFS, "multichannel is not supported on this protocol version, use 3.0 or above\n");
|
|
Enzo Matsumiya |
cba50e |
+ return 0;
|
|
Enzo Matsumiya |
cba50e |
+ }
|
|
Enzo Matsumiya |
cba50e |
+
|
|
Enzo Matsumiya |
cba50e |
+ spin_lock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
+
|
|
Enzo Matsumiya |
cba50e |
+ new_chan_count = old_chan_count = ses->chan_count;
|
|
Enzo Matsumiya |
cba50e |
+ left = ses->chan_max - ses->chan_count;
|
|
Enzo Matsumiya |
cba50e |
+
|
|
Enzo Matsumiya |
cba50e |
if (left <= 0) {
|
|
Enzo Matsumiya |
cba50e |
cifs_dbg(FYI,
|
|
Enzo Matsumiya |
cba50e |
"ses already at max_channels (%zu), nothing to open\n",
|
|
Enzo Matsumiya |
cba50e |
ses->chan_max);
|
|
Enzo Matsumiya |
cba50e |
- return 0;
|
|
Enzo Matsumiya |
cba50e |
- }
|
|
Enzo Matsumiya |
cba50e |
-
|
|
Enzo Matsumiya |
cba50e |
- if (ses->server->dialect < SMB30_PROT_ID) {
|
|
Enzo Matsumiya |
cba50e |
- cifs_dbg(VFS, "multichannel is not supported on this protocol version, use 3.0 or above\n");
|
|
Enzo Matsumiya |
cba50e |
+ spin_unlock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
return 0;
|
|
Enzo Matsumiya |
cba50e |
}
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
if (!(ses->server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) {
|
|
Enzo Matsumiya |
cba50e |
cifs_dbg(VFS, "server %s does not support multichannel\n", ses->server->hostname);
|
|
Enzo Matsumiya |
cba50e |
ses->chan_max = 1;
|
|
Enzo Matsumiya |
cba50e |
+ spin_unlock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
return 0;
|
|
Enzo Matsumiya |
cba50e |
}
|
|
Enzo Matsumiya |
cba50e |
+ spin_unlock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
/*
|
|
Enzo Matsumiya |
cba50e |
* Make a copy of the iface list at the time and use that
|
|
Enzo Matsumiya |
cba50e |
@@ -142,10 +154,11 @@ int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses)
|
|
Enzo Matsumiya |
cba50e |
cifs_dbg(FYI, "successfully opened new channel on iface#%d\n",
|
|
Enzo Matsumiya |
cba50e |
i);
|
|
Enzo Matsumiya |
cba50e |
left--;
|
|
Enzo Matsumiya |
cba50e |
+ new_chan_count++;
|
|
Enzo Matsumiya |
cba50e |
}
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
kfree(ifaces);
|
|
Enzo Matsumiya |
cba50e |
- return ses->chan_count - old_chan_count;
|
|
Enzo Matsumiya |
cba50e |
+ return new_chan_count - old_chan_count;
|
|
Enzo Matsumiya |
cba50e |
}
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
/*
|
|
Enzo Matsumiya |
cba50e |
@@ -157,10 +170,14 @@ cifs_ses_find_chan(struct cifs_ses *ses, struct TCP_Server_Info *server)
|
|
Enzo Matsumiya |
cba50e |
{
|
|
Enzo Matsumiya |
cba50e |
int i;
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
+ spin_lock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
for (i = 0; i < ses->chan_count; i++) {
|
|
Enzo Matsumiya |
cba50e |
- if (ses->chans[i].server == server)
|
|
Enzo Matsumiya |
cba50e |
+ if (ses->chans[i].server == server) {
|
|
Enzo Matsumiya |
cba50e |
+ spin_unlock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
return &ses->chans[i];
|
|
Enzo Matsumiya |
cba50e |
+ }
|
|
Enzo Matsumiya |
cba50e |
}
|
|
Enzo Matsumiya |
cba50e |
+ spin_unlock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
return NULL;
|
|
Enzo Matsumiya |
cba50e |
}
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
@@ -168,6 +185,7 @@ static int
|
|
Enzo Matsumiya |
cba50e |
cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
|
|
Enzo Matsumiya |
cba50e |
struct cifs_server_iface *iface)
|
|
Enzo Matsumiya |
cba50e |
{
|
|
Enzo Matsumiya |
cba50e |
+ struct TCP_Server_Info *chan_server;
|
|
Enzo Matsumiya |
cba50e |
struct cifs_chan *chan;
|
|
Enzo Matsumiya |
cba50e |
struct smb3_fs_context ctx = {NULL};
|
|
Enzo Matsumiya |
cba50e |
static const char unc_fmt[] = "\\%s\\foo";
|
|
Enzo Matsumiya |
cba50e |
@@ -240,15 +258,20 @@ cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
|
|
Enzo Matsumiya |
cba50e |
SMB2_CLIENT_GUID_SIZE);
|
|
Enzo Matsumiya |
cba50e |
ctx.use_client_guid = true;
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
- mutex_lock(&ses->session_mutex);
|
|
Enzo Matsumiya |
cba50e |
+ chan_server = cifs_get_tcp_session(&ctx;;
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
+ mutex_lock(&ses->session_mutex);
|
|
Enzo Matsumiya |
cba50e |
+ spin_lock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
chan = ses->binding_chan = &ses->chans[ses->chan_count];
|
|
Enzo Matsumiya |
cba50e |
- chan->server = cifs_get_tcp_session(&ctx;;
|
|
Enzo Matsumiya |
cba50e |
+ chan->server = chan_server;
|
|
Enzo Matsumiya |
cba50e |
if (IS_ERR(chan->server)) {
|
|
Enzo Matsumiya |
cba50e |
rc = PTR_ERR(chan->server);
|
|
Enzo Matsumiya |
cba50e |
chan->server = NULL;
|
|
Enzo Matsumiya |
cba50e |
+ spin_unlock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
goto out;
|
|
Enzo Matsumiya |
cba50e |
}
|
|
Enzo Matsumiya |
cba50e |
+ spin_unlock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
+
|
|
Enzo Matsumiya |
cba50e |
spin_lock(&cifs_tcp_ses_lock);
|
|
Enzo Matsumiya |
cba50e |
chan->server->is_channel = true;
|
|
Enzo Matsumiya |
cba50e |
spin_unlock(&cifs_tcp_ses_lock);
|
|
Enzo Matsumiya |
cba50e |
@@ -283,8 +306,11 @@ cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
|
|
Enzo Matsumiya |
cba50e |
* ses to the new server.
|
|
Enzo Matsumiya |
cba50e |
*/
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
+ spin_lock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
ses->chan_count++;
|
|
Enzo Matsumiya |
cba50e |
atomic_set(&ses->chan_seq, 0);
|
|
Enzo Matsumiya |
cba50e |
+ spin_unlock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
+
|
|
Enzo Matsumiya |
cba50e |
out:
|
|
Enzo Matsumiya |
cba50e |
ses->binding = false;
|
|
Enzo Matsumiya |
cba50e |
ses->binding_chan = NULL;
|
|
Enzo Matsumiya |
cba50e |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
|
|
Enzo Matsumiya |
cba50e |
index b7379329b741..61ea3d3f95b4 100644
|
|
Enzo Matsumiya |
cba50e |
--- a/fs/cifs/transport.c
|
|
Enzo Matsumiya |
cba50e |
+++ b/fs/cifs/transport.c
|
|
Enzo Matsumiya |
cba50e |
@@ -1044,14 +1044,17 @@ struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses)
|
|
Enzo Matsumiya |
cba50e |
if (!ses)
|
|
Enzo Matsumiya |
cba50e |
return NULL;
|
|
Enzo Matsumiya |
cba50e |
|
|
Enzo Matsumiya |
cba50e |
+ spin_lock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
if (!ses->binding) {
|
|
Enzo Matsumiya |
cba50e |
/* round robin */
|
|
Enzo Matsumiya |
cba50e |
if (ses->chan_count > 1) {
|
|
Enzo Matsumiya |
cba50e |
index = (uint)atomic_inc_return(&ses->chan_seq);
|
|
Enzo Matsumiya |
cba50e |
index %= ses->chan_count;
|
|
Enzo Matsumiya |
cba50e |
}
|
|
Enzo Matsumiya |
cba50e |
+ spin_unlock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
return ses->chans[index].server;
|
|
Enzo Matsumiya |
cba50e |
} else {
|
|
Enzo Matsumiya |
cba50e |
+ spin_unlock(&ses->chan_lock);
|
|
Enzo Matsumiya |
cba50e |
return cifs_ses_server(ses);
|
|
Enzo Matsumiya |
cba50e |
}
|
|
Enzo Matsumiya |
cba50e |
}
|
|
Enzo Matsumiya |
cba50e |
--
|
|
Enzo Matsumiya |
cba50e |
2.33.1
|
|
Enzo Matsumiya |
cba50e |
|