Skip to content

Commit abf5a4d

Browse files
author
CKI KWF Bot
committed
Merge: smb: client: handle lack of IPC in dfs_cache_refresh() [rhel-10.2]
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/1717 - handle lack of IPC in dfs_cache_refresh() JIRA: https://issues.redhat.com/browse/RHEL-126228 Signed-off-by: Paulo Alcantara <paalcant@redhat.com> Approved-by: Jay Shin <jaeshin@redhat.com> Approved-by: David Howells <dhowells@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: CKI GitLab Kmaint Pipeline Bot <26919896-cki-kmaint-pipeline-bot@users.noreply.gitlab.com>
2 parents 09e7a88 + 2e9c74d commit abf5a4d

File tree

3 files changed

+66
-29
lines changed

3 files changed

+66
-29
lines changed

fs/smb/client/cifsproto.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,8 @@ extern int E_md4hash(const unsigned char *passwd, unsigned char *p16,
615615
extern struct TCP_Server_Info *
616616
cifs_find_tcp_session(struct smb3_fs_context *ctx);
617617

618+
struct cifs_tcon *cifs_setup_ipc(struct cifs_ses *ses, bool seal);
619+
618620
void __cifs_put_smb_ses(struct cifs_ses *ses);
619621

620622
extern struct cifs_ses *

fs/smb/client/connect.c

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2015,39 +2015,31 @@ static int match_session(struct cifs_ses *ses,
20152015
/**
20162016
* cifs_setup_ipc - helper to setup the IPC tcon for the session
20172017
* @ses: smb session to issue the request on
2018-
* @ctx: the superblock configuration context to use for building the
2019-
* new tree connection for the IPC (interprocess communication RPC)
2018+
* @seal: if encryption is requested
20202019
*
20212020
* A new IPC connection is made and stored in the session
20222021
* tcon_ipc. The IPC tcon has the same lifetime as the session.
20232022
*/
2024-
static int
2025-
cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx)
2023+
struct cifs_tcon *cifs_setup_ipc(struct cifs_ses *ses, bool seal)
20262024
{
20272025
int rc = 0, xid;
20282026
struct cifs_tcon *tcon;
20292027
char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0};
2030-
bool seal = false;
20312028
struct TCP_Server_Info *server = ses->server;
20322029

20332030
/*
20342031
* If the mount request that resulted in the creation of the
20352032
* session requires encryption, force IPC to be encrypted too.
20362033
*/
2037-
if (ctx->seal) {
2038-
if (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
2039-
seal = true;
2040-
else {
2041-
cifs_server_dbg(VFS,
2042-
"IPC: server doesn't support encryption\n");
2043-
return -EOPNOTSUPP;
2044-
}
2034+
if (seal && !(server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)) {
2035+
cifs_server_dbg(VFS, "IPC: server doesn't support encryption\n");
2036+
return ERR_PTR(-EOPNOTSUPP);
20452037
}
20462038

20472039
/* no need to setup directory caching on IPC share, so pass in false */
20482040
tcon = tcon_info_alloc(false, netfs_trace_tcon_ref_new_ipc);
20492041
if (tcon == NULL)
2050-
return -ENOMEM;
2042+
return ERR_PTR(-ENOMEM);
20512043

20522044
spin_lock(&server->srv_lock);
20532045
scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", server->hostname);
@@ -2057,23 +2049,21 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx)
20572049
tcon->ses = ses;
20582050
tcon->ipc = true;
20592051
tcon->seal = seal;
2060-
rc = server->ops->tree_connect(xid, ses, unc, tcon, ctx->local_nls);
2052+
rc = server->ops->tree_connect(xid, ses, unc, tcon, ses->local_nls);
20612053
free_xid(xid);
20622054

20632055
if (rc) {
2064-
cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
2056+
cifs_server_dbg(VFS | ONCE, "failed to connect to IPC (rc=%d)\n", rc);
20652057
tconInfoFree(tcon, netfs_trace_tcon_ref_free_ipc_fail);
2066-
goto out;
2058+
return ERR_PTR(rc);
20672059
}
20682060

20692061
cifs_dbg(FYI, "IPC tcon rc=%d ipc tid=0x%x\n", rc, tcon->tid);
20702062

20712063
spin_lock(&tcon->tc_lock);
20722064
tcon->status = TID_GOOD;
20732065
spin_unlock(&tcon->tc_lock);
2074-
ses->tcon_ipc = tcon;
2075-
out:
2076-
return rc;
2066+
return tcon;
20772067
}
20782068

20792069
static struct cifs_ses *
@@ -2347,6 +2337,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
23472337
{
23482338
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
23492339
struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
2340+
struct cifs_tcon *ipc;
23502341
struct cifs_ses *ses;
23512342
unsigned int xid;
23522343
int retries = 0;
@@ -2525,7 +2516,12 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
25252516
list_add(&ses->smb_ses_list, &server->smb_ses_list);
25262517
spin_unlock(&cifs_tcp_ses_lock);
25272518

2528-
cifs_setup_ipc(ses, ctx);
2519+
ipc = cifs_setup_ipc(ses, ctx->seal);
2520+
spin_lock(&cifs_tcp_ses_lock);
2521+
spin_lock(&ses->ses_lock);
2522+
ses->tcon_ipc = !IS_ERR(ipc) ? ipc : NULL;
2523+
spin_unlock(&ses->ses_lock);
2524+
spin_unlock(&cifs_tcp_ses_lock);
25292525

25302526
free_xid(xid);
25312527

fs/smb/client/dfs_cache.c

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,24 +1120,63 @@ static bool target_share_equal(struct cifs_tcon *tcon, const char *s1)
11201120
return match;
11211121
}
11221122

1123-
static bool is_ses_good(struct cifs_ses *ses)
1123+
static bool is_ses_good(struct cifs_tcon *tcon, struct cifs_ses *ses)
11241124
{
11251125
struct TCP_Server_Info *server = ses->server;
1126-
struct cifs_tcon *tcon = ses->tcon_ipc;
1126+
struct cifs_tcon *ipc = NULL;
11271127
bool ret;
11281128

1129+
spin_lock(&cifs_tcp_ses_lock);
11291130
spin_lock(&ses->ses_lock);
11301131
spin_lock(&ses->chan_lock);
1132+
11311133
ret = !cifs_chan_needs_reconnect(ses, server) &&
1132-
ses->ses_status == SES_GOOD &&
1133-
!tcon->need_reconnect;
1134+
ses->ses_status == SES_GOOD;
1135+
11341136
spin_unlock(&ses->chan_lock);
1137+
1138+
if (!ret)
1139+
goto out;
1140+
1141+
if (likely(ses->tcon_ipc)) {
1142+
if (ses->tcon_ipc->need_reconnect) {
1143+
ret = false;
1144+
goto out;
1145+
}
1146+
} else {
1147+
spin_unlock(&ses->ses_lock);
1148+
spin_unlock(&cifs_tcp_ses_lock);
1149+
1150+
ipc = cifs_setup_ipc(ses, tcon->seal);
1151+
1152+
spin_lock(&cifs_tcp_ses_lock);
1153+
spin_lock(&ses->ses_lock);
1154+
if (!IS_ERR(ipc)) {
1155+
if (!ses->tcon_ipc) {
1156+
ses->tcon_ipc = ipc;
1157+
ipc = NULL;
1158+
}
1159+
} else {
1160+
ret = false;
1161+
ipc = NULL;
1162+
}
1163+
}
1164+
1165+
out:
11351166
spin_unlock(&ses->ses_lock);
1167+
spin_unlock(&cifs_tcp_ses_lock);
1168+
if (ipc && server->ops->tree_disconnect) {
1169+
unsigned int xid = get_xid();
1170+
1171+
(void)server->ops->tree_disconnect(xid, ipc);
1172+
_free_xid(xid);
1173+
}
1174+
tconInfoFree(ipc, netfs_trace_tcon_ref_free_ipc);
11361175
return ret;
11371176
}
11381177

11391178
/* Refresh dfs referral of @ses */
1140-
static void refresh_ses_referral(struct cifs_ses *ses)
1179+
static void refresh_ses_referral(struct cifs_tcon *tcon, struct cifs_ses *ses)
11411180
{
11421181
struct cache_entry *ce;
11431182
unsigned int xid;
@@ -1153,7 +1192,7 @@ static void refresh_ses_referral(struct cifs_ses *ses)
11531192
}
11541193

11551194
ses = CIFS_DFS_ROOT_SES(ses);
1156-
if (!is_ses_good(ses)) {
1195+
if (!is_ses_good(tcon, ses)) {
11571196
cifs_dbg(FYI, "%s: skip cache refresh due to disconnected ipc\n",
11581197
__func__);
11591198
goto out;
@@ -1241,7 +1280,7 @@ static void refresh_tcon_referral(struct cifs_tcon *tcon, bool force_refresh)
12411280
up_read(&htable_rw_lock);
12421281

12431282
ses = CIFS_DFS_ROOT_SES(ses);
1244-
if (!is_ses_good(ses)) {
1283+
if (!is_ses_good(tcon, ses)) {
12451284
cifs_dbg(FYI, "%s: skip cache refresh due to disconnected ipc\n",
12461285
__func__);
12471286
goto out;
@@ -1309,7 +1348,7 @@ void dfs_cache_refresh(struct work_struct *work)
13091348
tcon = container_of(work, struct cifs_tcon, dfs_cache_work.work);
13101349

13111350
list_for_each_entry(ses, &tcon->dfs_ses_list, dlist)
1312-
refresh_ses_referral(ses);
1351+
refresh_ses_referral(tcon, ses);
13131352
refresh_tcon_referral(tcon, false);
13141353

13151354
queue_delayed_work(dfscache_wq, &tcon->dfs_cache_work,

0 commit comments

Comments
 (0)