fs/smb/client/connect.c

Source file repositories/reference/linux-study-clean/fs/smb/client/connect.c

File Facts

System
Linux kernel
Corpus path
fs/smb/client/connect.c
Extension
.c
Size
124896 bytes
Lines
4542
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

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->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);
		}
	}

	list_for_each_entry_safe(server, nserver, &reco, rlist) {
		list_del_init(&server->rlist);
		set_need_reco(server);
		cifs_put_tcp_session(server, 0);
	}
}

/*
 * Mark all sessions and tcons for reconnect.
 * IMPORTANT: make sure that this gets called only from
 * cifsd thread. For any other thread, use
 * cifs_signal_cifsd_for_reconnect
 *
 * @server: the tcp ses for which reconnect is needed
 * @server needs to be previously set to CifsNeedReconnect.
 * @mark_smb_session: whether even sessions need to be marked
 */
void
cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server,
				      bool mark_smb_session)
{
	struct TCP_Server_Info *pserver;
	struct cifs_ses *ses, *nses;
	struct cifs_tcon *tcon;

	/*
	 * before reconnecting the tcp session, mark the smb session (uid) and the tid bad so they
	 * are not used until reconnected.
	 */
	cifs_dbg(FYI, "%s: marking necessary sessions and tcons for reconnect\n", __func__);

	/* If server is a channel, select the primary channel */
	pserver = SERVER_IS_CHAN(server) ? server->primary_server : server;

	/*
	 * if the server has been marked for termination, there is a
	 * chance that the remaining channels all need reconnect. To be
	 * on the safer side, mark the session and trees for reconnect
	 * for this scenario. This might cause a few redundant session
	 * setup and tree connect requests, but it is better than not doing
	 * a tree connect when needed, and all following requests failing
	 */
	if (server->terminate) {
		mark_smb_session = true;
		server = pserver;
	}

	spin_lock(&cifs_tcp_ses_lock);
	list_for_each_entry_safe(ses, nses, &pserver->smb_ses_list, smb_ses_list) {
		spin_lock(&ses->ses_lock);
		if (ses->ses_status == SES_EXITING) {
			spin_unlock(&ses->ses_lock);
			continue;
		}
		spin_unlock(&ses->ses_lock);

		spin_lock(&ses->chan_lock);
		if (cifs_ses_get_chan_index(ses, server) ==
		    CIFS_INVAL_CHAN_INDEX) {
			spin_unlock(&ses->chan_lock);
			continue;
		}

		if (!cifs_chan_is_iface_active(ses, server)) {
			spin_unlock(&ses->chan_lock);
			cifs_chan_update_iface(ses, server);
			spin_lock(&ses->chan_lock);
		}

		if (!mark_smb_session && cifs_chan_needs_reconnect(ses, server)) {
			spin_unlock(&ses->chan_lock);

Annotation

Implementation Notes