Message ID | 20191204142506.12545-1-pc@cjr.nz (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | cifs: Fix lookup of SMB connections on multichannel | expand |
tentatively merged to cifs-2.6.git for-next and buildbot github tree pending more testing On Wed, Dec 4, 2019 at 8:25 AM Paulo Alcantara (SUSE) <pc@cjr.nz> wrote: > > With the addition of SMB session channels, we introduced new TCP > server pointers that have no sessions or tcons associated with them. > > In this case, when we started looking for TCP connections, we might > end up picking session channel rather than the master connection, > hence failing to get either a session or a tcon. > > In order to fix that, this patch introduces a new "is_channel" field > to TCP_Server_Info structure so we can skip session channels during > lookup of connections. > > Signed-off-by: Paulo Alcantara (SUSE) <pc@cjr.nz> > Reviewed-by: Aurelien Aptel <aaptel@suse.com> > --- > fs/cifs/cifsglob.h | 1 + > fs/cifs/connect.c | 6 +++++- > fs/cifs/sess.c | 3 +++ > 3 files changed, 9 insertions(+), 1 deletion(-) > > diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h > index 5b976e01dd6b..fd0262ce5ad5 100644 > --- a/fs/cifs/cifsglob.h > +++ b/fs/cifs/cifsglob.h > @@ -777,6 +777,7 @@ struct TCP_Server_Info { > */ > int nr_targets; > bool noblockcnt; /* use non-blocking connect() */ > + bool is_channel; /* if a session channel */ > }; > > struct cifs_credits { > diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c > index 86d1baedf21c..05ea0e2b7e0e 100644 > --- a/fs/cifs/connect.c > +++ b/fs/cifs/connect.c > @@ -2712,7 +2712,11 @@ cifs_find_tcp_session(struct smb_vol *vol) > > spin_lock(&cifs_tcp_ses_lock); > list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { > - if (!match_server(server, vol)) > + /* > + * Skip ses channels since they're only handled in lower layers > + * (e.g. cifs_send_recv). > + */ > + if (server->is_channel || !match_server(server, vol)) > continue; > > ++server->srv_count; > diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c > index fb3bdc44775c..d95137304224 100644 > --- a/fs/cifs/sess.c > +++ b/fs/cifs/sess.c > @@ -213,6 +213,9 @@ cifs_ses_add_channel(struct cifs_ses *ses, struct cifs_server_iface *iface) > chan->server = NULL; > goto out; > } > + spin_lock(&cifs_tcp_ses_lock); > + chan->server->is_channel = true; > + spin_unlock(&cifs_tcp_ses_lock); > > /* > * We need to allocate the server crypto now as we will need > -- > 2.24.0 >
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 5b976e01dd6b..fd0262ce5ad5 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -777,6 +777,7 @@ struct TCP_Server_Info { */ int nr_targets; bool noblockcnt; /* use non-blocking connect() */ + bool is_channel; /* if a session channel */ }; struct cifs_credits { diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 86d1baedf21c..05ea0e2b7e0e 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2712,7 +2712,11 @@ cifs_find_tcp_session(struct smb_vol *vol) spin_lock(&cifs_tcp_ses_lock); list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { - if (!match_server(server, vol)) + /* + * Skip ses channels since they're only handled in lower layers + * (e.g. cifs_send_recv). + */ + if (server->is_channel || !match_server(server, vol)) continue; ++server->srv_count; diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index fb3bdc44775c..d95137304224 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -213,6 +213,9 @@ cifs_ses_add_channel(struct cifs_ses *ses, struct cifs_server_iface *iface) chan->server = NULL; goto out; } + spin_lock(&cifs_tcp_ses_lock); + chan->server->is_channel = true; + spin_unlock(&cifs_tcp_ses_lock); /* * We need to allocate the server crypto now as we will need