]>
Commit | Line | Data |
---|---|---|
98979065 GKH |
1 | From 4a5ba0e0bfe552ac7451f57e304f6343c3d87f89 Mon Sep 17 00:00:00 2001 |
2 | From: Paulo Alcantara <pc@manguebit.com> | |
3 | Date: Mon, 1 Apr 2024 22:44:08 -0300 | |
4 | Subject: smb: client: handle DFS tcons in cifs_construct_tcon() | |
5 | ||
6 | From: Paulo Alcantara <pc@manguebit.com> | |
7 | ||
8 | commit 4a5ba0e0bfe552ac7451f57e304f6343c3d87f89 upstream. | |
9 | ||
10 | The tcons created by cifs_construct_tcon() on multiuser mounts must | |
11 | also be able to failover and refresh DFS referrals, so set the | |
12 | appropriate fields in order to get a full DFS tcon. They could be | |
13 | shared among different superblocks later, too. | |
14 | ||
15 | Cc: stable@vger.kernel.org # 6.4+ | |
16 | Reported-by: kernel test robot <lkp@intel.com> | |
17 | Closes: https://lore.kernel.org/oe-kbuild-all/202404021518.3Xu2VU4s-lkp@intel.com/ | |
18 | Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.com> | |
19 | Signed-off-by: Steve French <stfrench@microsoft.com> | |
20 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
21 | --- | |
22 | fs/smb/client/connect.c | 30 ++++++++++++++++++++++++++++++ | |
23 | 1 file changed, 30 insertions(+) | |
24 | ||
25 | --- a/fs/smb/client/connect.c | |
26 | +++ b/fs/smb/client/connect.c | |
27 | @@ -3988,6 +3988,7 @@ cifs_construct_tcon(struct cifs_sb_info | |
28 | struct cifs_ses *ses; | |
29 | struct cifs_tcon *tcon = NULL; | |
30 | struct smb3_fs_context *ctx; | |
31 | + char *origin_fullpath = NULL; | |
32 | ||
33 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); | |
34 | if (ctx == NULL) | |
35 | @@ -4011,6 +4012,7 @@ cifs_construct_tcon(struct cifs_sb_info | |
36 | ctx->sign = master_tcon->ses->sign; | |
37 | ctx->seal = master_tcon->seal; | |
38 | ctx->witness = master_tcon->use_witness; | |
39 | + ctx->dfs_root_ses = master_tcon->ses->dfs_root_ses; | |
40 | ||
41 | rc = cifs_set_vol_auth(ctx, master_tcon->ses); | |
42 | if (rc) { | |
43 | @@ -4030,12 +4032,39 @@ cifs_construct_tcon(struct cifs_sb_info | |
44 | goto out; | |
45 | } | |
46 | ||
47 | +#ifdef CONFIG_CIFS_DFS_UPCALL | |
48 | + spin_lock(&master_tcon->tc_lock); | |
49 | + if (master_tcon->origin_fullpath) { | |
50 | + spin_unlock(&master_tcon->tc_lock); | |
51 | + origin_fullpath = dfs_get_path(cifs_sb, cifs_sb->ctx->source); | |
52 | + if (IS_ERR(origin_fullpath)) { | |
53 | + tcon = ERR_CAST(origin_fullpath); | |
54 | + origin_fullpath = NULL; | |
55 | + cifs_put_smb_ses(ses); | |
56 | + goto out; | |
57 | + } | |
58 | + } else { | |
59 | + spin_unlock(&master_tcon->tc_lock); | |
60 | + } | |
61 | +#endif | |
62 | + | |
63 | tcon = cifs_get_tcon(ses, ctx); | |
64 | if (IS_ERR(tcon)) { | |
65 | cifs_put_smb_ses(ses); | |
66 | goto out; | |
67 | } | |
68 | ||
69 | +#ifdef CONFIG_CIFS_DFS_UPCALL | |
70 | + if (origin_fullpath) { | |
71 | + spin_lock(&tcon->tc_lock); | |
72 | + tcon->origin_fullpath = origin_fullpath; | |
73 | + spin_unlock(&tcon->tc_lock); | |
74 | + origin_fullpath = NULL; | |
75 | + queue_delayed_work(dfscache_wq, &tcon->dfs_cache_work, | |
76 | + dfs_cache_get_ttl() * HZ); | |
77 | + } | |
78 | +#endif | |
79 | + | |
80 | #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
81 | if (cap_unix(ses)) | |
82 | reset_cifs_unix_caps(0, tcon, NULL, ctx); | |
83 | @@ -4044,6 +4073,7 @@ cifs_construct_tcon(struct cifs_sb_info | |
84 | out: | |
85 | kfree(ctx->username); | |
86 | kfree_sensitive(ctx->password); | |
87 | + kfree(origin_fullpath); | |
88 | kfree(ctx); | |
89 | ||
90 | return tcon; |