diff options
Diffstat (limited to 'fs/smb/client/connect.c')
| -rw-r--r-- | fs/smb/client/connect.c | 58 | 
1 files changed, 36 insertions, 22 deletions
| diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index c48869c29e15..685c65dcb8c4 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -124,6 +124,14 @@ static void smb2_query_server_interfaces(struct work_struct *work)  			   (SMB_INTERFACE_POLL_INTERVAL * HZ));  } +#define set_need_reco(server) \ +do { \ +	spin_lock(&server->srv_lock); \ +	if (server->tcpStatus != CifsExiting) \ +		server->tcpStatus = CifsNeedReconnect; \ +	spin_unlock(&server->srv_lock); \ +} while (0) +  /*   * Update the tcpStatus for the server.   * This is used to signal the cifsd thread to call cifs_reconnect @@ -137,39 +145,45 @@ void  cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server,  				bool all_channels)  { -	struct TCP_Server_Info *pserver; +	struct TCP_Server_Info *nserver;  	struct cifs_ses *ses; +	LIST_HEAD(reco);  	int i; -	/* If server is a channel, select the primary channel */ -	pserver = SERVER_IS_CHAN(server) ? server->primary_server : server; -  	/* if we need to signal just this channel */  	if (!all_channels) { -		spin_lock(&server->srv_lock); -		if (server->tcpStatus != CifsExiting) -			server->tcpStatus = CifsNeedReconnect; -		spin_unlock(&server->srv_lock); +		set_need_reco(server);  		return;  	} -	spin_lock(&cifs_tcp_ses_lock); -	list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) { -		if (cifs_ses_exiting(ses)) -			continue; -		spin_lock(&ses->chan_lock); -		for (i = 0; i < ses->chan_count; i++) { -			if (!ses->chans[i].server) +	if (SERVER_IS_CHAN(server)) +		server = server->primary_server; +	scoped_guard(spinlock, &cifs_tcp_ses_lock) { +		set_need_reco(server); +		list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { +			spin_lock(&ses->ses_lock); +			if (ses->ses_status == SES_EXITING) { +				spin_unlock(&ses->ses_lock);  				continue; - -			spin_lock(&ses->chans[i].server->srv_lock); -			if (ses->chans[i].server->tcpStatus != CifsExiting) -				ses->chans[i].server->tcpStatus = CifsNeedReconnect; -			spin_unlock(&ses->chans[i].server->srv_lock); +			} +			spin_lock(&ses->chan_lock); +			for (i = 1; i < ses->chan_count; i++) { +				nserver = ses->chans[i].server; +				if (!nserver) +					continue; +				nserver->srv_count++; +				list_add(&nserver->rlist, &reco); +			} +			spin_unlock(&ses->chan_lock); +			spin_unlock(&ses->ses_lock);  		} -		spin_unlock(&ses->chan_lock);  	} -	spin_unlock(&cifs_tcp_ses_lock); + +	list_for_each_entry_safe(server, nserver, &reco, rlist) { +		list_del_init(&server->rlist); +		set_need_reco(server); +		cifs_put_tcp_session(server, 0); +	}  }  /* | 
