@@ -529,9 +529,7 @@ static int reconnect_dfs_server(struct TCP_Server_Info *server)
529529 mod_delayed_work (cifsiod_wq , & server -> reconnect , 0 );
530530 } while (server -> tcpStatus == CifsNeedReconnect );
531531
532- if (target_hint )
533- dfs_cache_noreq_update_tgthint (refpath , target_hint );
534-
532+ dfs_cache_noreq_update_tgthint (refpath , target_hint );
535533 dfs_cache_free_tgts (& tl );
536534
537535 /* Need to set up echo worker again once connection has been established */
@@ -4079,265 +4077,7 @@ cifs_prune_tlinks(struct work_struct *work)
40794077 TLINK_IDLE_EXPIRE );
40804078}
40814079
4082- #ifdef CONFIG_CIFS_DFS_UPCALL
4083- /* Update dfs referral path of superblock */
4084- static int update_server_fullpath (struct TCP_Server_Info * server , struct cifs_sb_info * cifs_sb ,
4085- const char * target )
4086- {
4087- int rc = 0 ;
4088- size_t len = strlen (target );
4089- char * refpath , * npath ;
4090-
4091- if (unlikely (len < 2 || * target != '\\' ))
4092- return - EINVAL ;
4093-
4094- if (target [1 ] == '\\' ) {
4095- len += 1 ;
4096- refpath = kmalloc (len , GFP_KERNEL );
4097- if (!refpath )
4098- return - ENOMEM ;
4099-
4100- scnprintf (refpath , len , "%s" , target );
4101- } else {
4102- len += sizeof ("\\" );
4103- refpath = kmalloc (len , GFP_KERNEL );
4104- if (!refpath )
4105- return - ENOMEM ;
4106-
4107- scnprintf (refpath , len , "\\%s" , target );
4108- }
4109-
4110- npath = dfs_cache_canonical_path (refpath , cifs_sb -> local_nls , cifs_remap (cifs_sb ));
4111- kfree (refpath );
4112-
4113- if (IS_ERR (npath )) {
4114- rc = PTR_ERR (npath );
4115- } else {
4116- mutex_lock (& server -> refpath_lock );
4117- kfree (server -> leaf_fullpath );
4118- server -> leaf_fullpath = npath ;
4119- mutex_unlock (& server -> refpath_lock );
4120- server -> current_fullpath = server -> leaf_fullpath ;
4121- }
4122- return rc ;
4123- }
4124-
4125- static int target_share_matches_server (struct TCP_Server_Info * server , const char * tcp_host ,
4126- size_t tcp_host_len , char * share , bool * target_match )
4127- {
4128- int rc = 0 ;
4129- const char * dfs_host ;
4130- size_t dfs_host_len ;
4131-
4132- * target_match = true;
4133- extract_unc_hostname (share , & dfs_host , & dfs_host_len );
4134-
4135- /* Check if hostnames or addresses match */
4136- if (dfs_host_len != tcp_host_len || strncasecmp (dfs_host , tcp_host , dfs_host_len ) != 0 ) {
4137- cifs_dbg (FYI , "%s: %.*s doesn't match %.*s\n" , __func__ , (int )dfs_host_len ,
4138- dfs_host , (int )tcp_host_len , tcp_host );
4139- rc = match_target_ip (server , dfs_host , dfs_host_len , target_match );
4140- if (rc )
4141- cifs_dbg (VFS , "%s: failed to match target ip: %d\n" , __func__ , rc );
4142- }
4143- return rc ;
4144- }
4145-
4146- static int __tree_connect_dfs_target (const unsigned int xid , struct cifs_tcon * tcon ,
4147- struct cifs_sb_info * cifs_sb , char * tree , bool islink ,
4148- struct dfs_cache_tgt_list * tl )
4149- {
4150- int rc ;
4151- struct TCP_Server_Info * server = tcon -> ses -> server ;
4152- const struct smb_version_operations * ops = server -> ops ;
4153- struct cifs_ses * root_ses = CIFS_DFS_ROOT_SES (tcon -> ses );
4154- struct cifs_tcon * ipc = root_ses -> tcon_ipc ;
4155- char * share = NULL , * prefix = NULL ;
4156- const char * tcp_host ;
4157- size_t tcp_host_len ;
4158- struct dfs_cache_tgt_iterator * tit ;
4159- bool target_match ;
4160-
4161- extract_unc_hostname (server -> hostname , & tcp_host , & tcp_host_len );
4162-
4163- tit = dfs_cache_get_tgt_iterator (tl );
4164- if (!tit ) {
4165- rc = - ENOENT ;
4166- goto out ;
4167- }
4168-
4169- /* Try to tree connect to all dfs targets */
4170- for (; tit ; tit = dfs_cache_get_next_tgt (tl , tit )) {
4171- const char * target = dfs_cache_get_tgt_name (tit );
4172- struct dfs_cache_tgt_list ntl = DFS_CACHE_TGT_LIST_INIT (ntl );
4173-
4174- kfree (share );
4175- kfree (prefix );
4176- share = prefix = NULL ;
4177-
4178- /* Check if share matches with tcp ses */
4179- rc = dfs_cache_get_tgt_share (server -> current_fullpath + 1 , tit , & share , & prefix );
4180- if (rc ) {
4181- cifs_dbg (VFS , "%s: failed to parse target share: %d\n" , __func__ , rc );
4182- break ;
4183- }
4184-
4185- rc = target_share_matches_server (server , tcp_host , tcp_host_len , share ,
4186- & target_match );
4187- if (rc )
4188- break ;
4189- if (!target_match ) {
4190- rc = - EHOSTUNREACH ;
4191- continue ;
4192- }
4193-
4194- if (ipc -> need_reconnect ) {
4195- scnprintf (tree , MAX_TREE_SIZE , "\\\\%s\\IPC$" , server -> hostname );
4196- rc = ops -> tree_connect (xid , ipc -> ses , tree , ipc , cifs_sb -> local_nls );
4197- if (rc )
4198- break ;
4199- }
4200-
4201- scnprintf (tree , MAX_TREE_SIZE , "\\%s" , share );
4202- if (!islink ) {
4203- rc = ops -> tree_connect (xid , tcon -> ses , tree , tcon , cifs_sb -> local_nls );
4204- break ;
4205- }
4206- /*
4207- * If no dfs referrals were returned from link target, then just do a TREE_CONNECT
4208- * to it. Otherwise, cache the dfs referral and then mark current tcp ses for
4209- * reconnect so either the demultiplex thread or the echo worker will reconnect to
4210- * newly resolved target.
4211- */
4212- if (dfs_cache_find (xid , root_ses , cifs_sb -> local_nls , cifs_remap (cifs_sb ), target ,
4213- NULL , & ntl )) {
4214- rc = ops -> tree_connect (xid , tcon -> ses , tree , tcon , cifs_sb -> local_nls );
4215- if (rc )
4216- continue ;
4217- rc = dfs_cache_noreq_update_tgthint (server -> current_fullpath + 1 , tit );
4218- if (!rc )
4219- rc = cifs_update_super_prepath (cifs_sb , prefix );
4220- } else {
4221- /* Target is another dfs share */
4222- rc = update_server_fullpath (server , cifs_sb , target );
4223- dfs_cache_free_tgts (tl );
4224-
4225- if (!rc ) {
4226- rc = - EREMOTE ;
4227- list_replace_init (& ntl .tl_list , & tl -> tl_list );
4228- } else
4229- dfs_cache_free_tgts (& ntl );
4230- }
4231- break ;
4232- }
4233-
4234- out :
4235- kfree (share );
4236- kfree (prefix );
4237-
4238- return rc ;
4239- }
4240-
4241- static int tree_connect_dfs_target (const unsigned int xid , struct cifs_tcon * tcon ,
4242- struct cifs_sb_info * cifs_sb , char * tree , bool islink ,
4243- struct dfs_cache_tgt_list * tl )
4244- {
4245- int rc ;
4246- int num_links = 0 ;
4247- struct TCP_Server_Info * server = tcon -> ses -> server ;
4248-
4249- do {
4250- rc = __tree_connect_dfs_target (xid , tcon , cifs_sb , tree , islink , tl );
4251- if (!rc || rc != - EREMOTE )
4252- break ;
4253- } while (rc = - ELOOP , ++ num_links < MAX_NESTED_LINKS );
4254- /*
4255- * If we couldn't tree connect to any targets from last referral path, then retry from
4256- * original referral path.
4257- */
4258- if (rc && server -> current_fullpath != server -> origin_fullpath ) {
4259- server -> current_fullpath = server -> origin_fullpath ;
4260- cifs_signal_cifsd_for_reconnect (server , true);
4261- }
4262-
4263- dfs_cache_free_tgts (tl );
4264- return rc ;
4265- }
4266-
4267- int cifs_tree_connect (const unsigned int xid , struct cifs_tcon * tcon , const struct nls_table * nlsc )
4268- {
4269- int rc ;
4270- struct TCP_Server_Info * server = tcon -> ses -> server ;
4271- const struct smb_version_operations * ops = server -> ops ;
4272- struct super_block * sb = NULL ;
4273- struct cifs_sb_info * cifs_sb ;
4274- struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT (tl );
4275- char * tree ;
4276- struct dfs_info3_param ref = {0 };
4277-
4278- /* only send once per connect */
4279- spin_lock (& tcon -> tc_lock );
4280- if (tcon -> ses -> ses_status != SES_GOOD ||
4281- (tcon -> status != TID_NEW &&
4282- tcon -> status != TID_NEED_TCON )) {
4283- spin_unlock (& tcon -> tc_lock );
4284- return 0 ;
4285- }
4286- tcon -> status = TID_IN_TCON ;
4287- spin_unlock (& tcon -> tc_lock );
4288-
4289- tree = kzalloc (MAX_TREE_SIZE , GFP_KERNEL );
4290- if (!tree ) {
4291- rc = - ENOMEM ;
4292- goto out ;
4293- }
4294-
4295- if (tcon -> ipc ) {
4296- scnprintf (tree , MAX_TREE_SIZE , "\\\\%s\\IPC$" , server -> hostname );
4297- rc = ops -> tree_connect (xid , tcon -> ses , tree , tcon , nlsc );
4298- goto out ;
4299- }
4300-
4301- sb = cifs_get_tcp_super (server );
4302- if (IS_ERR (sb )) {
4303- rc = PTR_ERR (sb );
4304- cifs_dbg (VFS , "%s: could not find superblock: %d\n" , __func__ , rc );
4305- goto out ;
4306- }
4307-
4308- cifs_sb = CIFS_SB (sb );
4309-
4310- /* If it is not dfs or there was no cached dfs referral, then reconnect to same share */
4311- if (!server -> current_fullpath ||
4312- dfs_cache_noreq_find (server -> current_fullpath + 1 , & ref , & tl )) {
4313- rc = ops -> tree_connect (xid , tcon -> ses , tcon -> tree_name , tcon , cifs_sb -> local_nls );
4314- goto out ;
4315- }
4316-
4317- rc = tree_connect_dfs_target (xid , tcon , cifs_sb , tree , ref .server_type == DFS_TYPE_LINK ,
4318- & tl );
4319- free_dfs_info_param (& ref );
4320-
4321- out :
4322- kfree (tree );
4323- cifs_put_tcp_super (sb );
4324-
4325- if (rc ) {
4326- spin_lock (& tcon -> tc_lock );
4327- if (tcon -> status == TID_IN_TCON )
4328- tcon -> status = TID_NEED_TCON ;
4329- spin_unlock (& tcon -> tc_lock );
4330- } else {
4331- spin_lock (& tcon -> tc_lock );
4332- if (tcon -> status == TID_IN_TCON )
4333- tcon -> status = TID_GOOD ;
4334- spin_unlock (& tcon -> tc_lock );
4335- tcon -> need_reconnect = false;
4336- }
4337-
4338- return rc ;
4339- }
4340- #else
4080+ #ifndef CONFIG_CIFS_DFS_UPCALL
43414081int cifs_tree_connect (const unsigned int xid , struct cifs_tcon * tcon , const struct nls_table * nlsc )
43424082{
43434083 int rc ;
0 commit comments