@@ -95,33 +95,40 @@ static int get_session(struct cifs_mount_ctx *mnt_ctx, const char *full_path)
9595 ctx -> leaf_fullpath = (char * )full_path ;
9696 rc = cifs_mount_get_session (mnt_ctx );
9797 ctx -> leaf_fullpath = NULL ;
98- if (!rc ) {
99- struct cifs_ses * ses = mnt_ctx -> ses ;
10098
101- mutex_lock (& ses -> session_mutex );
102- ses -> dfs_root_ses = mnt_ctx -> root_ses ;
103- mutex_unlock (& ses -> session_mutex );
104- }
10599 return rc ;
106100}
107101
108- static void set_root_ses (struct cifs_mount_ctx * mnt_ctx )
102+ static int get_root_smb_session (struct cifs_mount_ctx * mnt_ctx )
109103{
110- if (mnt_ctx -> ses ) {
104+ struct smb3_fs_context * ctx = mnt_ctx -> fs_ctx ;
105+ struct dfs_root_ses * root_ses ;
106+ struct cifs_ses * ses = mnt_ctx -> ses ;
107+
108+ if (ses ) {
109+ root_ses = kmalloc (sizeof (* root_ses ), GFP_KERNEL );
110+ if (!root_ses )
111+ return - ENOMEM ;
112+
113+ INIT_LIST_HEAD (& root_ses -> list );
114+
111115 spin_lock (& cifs_tcp_ses_lock );
112- mnt_ctx -> ses -> ses_count ++ ;
116+ ses -> ses_count ++ ;
113117 spin_unlock (& cifs_tcp_ses_lock );
114- dfs_cache_add_refsrv_session (& mnt_ctx -> mount_id , mnt_ctx -> ses );
118+ root_ses -> ses = ses ;
119+ list_add_tail (& root_ses -> list , & mnt_ctx -> dfs_ses_list );
115120 }
116- mnt_ctx -> root_ses = mnt_ctx -> ses ;
121+ ctx -> dfs_root_ses = ses ;
122+ return 0 ;
117123}
118124
119125static int get_dfs_conn (struct cifs_mount_ctx * mnt_ctx , const char * ref_path , const char * full_path ,
120126 const struct dfs_cache_tgt_iterator * tit )
121127{
122128 struct smb3_fs_context * ctx = mnt_ctx -> fs_ctx ;
123129 struct dfs_info3_param ref = {};
124- int rc ;
130+ bool is_refsrv = false;
131+ int rc , rc2 ;
125132
126133 rc = dfs_cache_get_tgt_referral (ref_path + 1 , tit , & ref );
127134 if (rc )
@@ -136,8 +143,7 @@ static int get_dfs_conn(struct cifs_mount_ctx *mnt_ctx, const char *ref_path, co
136143 if (rc )
137144 goto out ;
138145
139- if (ref .flags & DFSREF_REFERRAL_SERVER )
140- set_root_ses (mnt_ctx );
146+ is_refsrv = !!(ref .flags & DFSREF_REFERRAL_SERVER );
141147
142148 rc = - EREMOTE ;
143149 if (ref .flags & DFSREF_STORAGE_SERVER ) {
@@ -146,13 +152,17 @@ static int get_dfs_conn(struct cifs_mount_ctx *mnt_ctx, const char *ref_path, co
146152 goto out ;
147153
148154 /* some servers may not advertise referral capability under ref.flags */
149- if (!(ref .flags & DFSREF_REFERRAL_SERVER ) &&
150- is_tcon_dfs (mnt_ctx -> tcon ))
151- set_root_ses (mnt_ctx );
155+ is_refsrv |= is_tcon_dfs (mnt_ctx -> tcon );
152156
153157 rc = cifs_is_path_remote (mnt_ctx );
154158 }
155159
160+ if (rc == - EREMOTE && is_refsrv ) {
161+ rc2 = get_root_smb_session (mnt_ctx );
162+ if (rc2 )
163+ rc = rc2 ;
164+ }
165+
156166out :
157167 free_dfs_info_param (& ref );
158168 return rc ;
@@ -165,6 +175,7 @@ static int __dfs_mount_share(struct cifs_mount_ctx *mnt_ctx)
165175 char * ref_path = NULL , * full_path = NULL ;
166176 struct dfs_cache_tgt_iterator * tit ;
167177 struct TCP_Server_Info * server ;
178+ struct cifs_tcon * tcon ;
168179 char * origin_fullpath = NULL ;
169180 int num_links = 0 ;
170181 int rc ;
@@ -234,12 +245,22 @@ static int __dfs_mount_share(struct cifs_mount_ctx *mnt_ctx)
234245
235246 if (!rc ) {
236247 server = mnt_ctx -> server ;
248+ tcon = mnt_ctx -> tcon ;
237249
238250 mutex_lock (& server -> refpath_lock );
239- server -> origin_fullpath = origin_fullpath ;
240- server -> current_fullpath = server -> leaf_fullpath ;
251+ if (!server -> origin_fullpath ) {
252+ server -> origin_fullpath = origin_fullpath ;
253+ server -> current_fullpath = server -> leaf_fullpath ;
254+ origin_fullpath = NULL ;
255+ }
241256 mutex_unlock (& server -> refpath_lock );
242- origin_fullpath = NULL ;
257+
258+ if (list_empty (& tcon -> dfs_ses_list )) {
259+ list_replace_init (& mnt_ctx -> dfs_ses_list ,
260+ & tcon -> dfs_ses_list );
261+ } else {
262+ dfs_put_root_smb_sessions (& mnt_ctx -> dfs_ses_list );
263+ }
243264 }
244265
245266out :
@@ -260,7 +281,7 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs)
260281 rc = get_session (mnt_ctx , NULL );
261282 if (rc )
262283 return rc ;
263- mnt_ctx -> root_ses = mnt_ctx -> ses ;
284+ ctx -> dfs_root_ses = mnt_ctx -> ses ;
264285 /*
265286 * If called with 'nodfs' mount option, then skip DFS resolving. Otherwise unconditionally
266287 * try to get an DFS referral (even cached) to determine whether it is an DFS mount.
@@ -280,7 +301,9 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs)
280301 }
281302
282303 * isdfs = true;
283- set_root_ses (mnt_ctx );
304+ rc = get_root_smb_session (mnt_ctx );
305+ if (rc )
306+ return rc ;
284307
285308 return __dfs_mount_share (mnt_ctx );
286309}
0 commit comments