fs/smb/client/cifssmb.c

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

File Facts

System
Linux kernel
Corpus path
fs/smb/client/cifssmb.c
Extension
.c
Size
191647 bytes
Lines
6442
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

if (smb_command != SMB_COM_TREE_DISCONNECT) {
			spin_unlock(&tcon->tc_lock);
			cifs_dbg(FYI, "can not send cmd %d while umounting\n",
				 smb_command);
			return -ENODEV;
		}
	}
	spin_unlock(&tcon->tc_lock);

again:
	rc = cifs_wait_for_server_reconnect(server, tcon->retry);
	if (rc)
		return rc;

	spin_lock(&ses->chan_lock);
	if (!cifs_chan_needs_reconnect(ses, server) && !tcon->need_reconnect) {
		spin_unlock(&ses->chan_lock);
		return 0;
	}
	spin_unlock(&ses->chan_lock);

	mutex_lock(&ses->session_mutex);
	/*
	 * Handle the case where a concurrent thread failed to negotiate or
	 * killed a channel.
	 */
	spin_lock(&server->srv_lock);
	switch (server->tcpStatus) {
	case CifsExiting:
		spin_unlock(&server->srv_lock);
		mutex_unlock(&ses->session_mutex);
		return -EHOSTDOWN;
	case CifsNeedReconnect:
		spin_unlock(&server->srv_lock);
		mutex_unlock(&ses->session_mutex);
		if (!tcon->retry)
			return -EHOSTDOWN;
		goto again;
	default:
		break;
	}
	spin_unlock(&server->srv_lock);

	/*
	 * need to prevent multiple threads trying to simultaneously
	 * reconnect the same SMB session
	 */
	spin_lock(&ses->ses_lock);
	spin_lock(&ses->chan_lock);
	if (!cifs_chan_needs_reconnect(ses, server) &&
	    ses->ses_status == SES_GOOD) {
		spin_unlock(&ses->chan_lock);
		spin_unlock(&ses->ses_lock);

		/* this means that we only need to tree connect */
		if (tcon->need_reconnect)
			goto skip_sess_setup;

		mutex_unlock(&ses->session_mutex);
		goto out;
	}
	spin_unlock(&ses->chan_lock);
	spin_unlock(&ses->ses_lock);

	rc = cifs_negotiate_protocol(0, ses, server);
	if (rc) {
		mutex_unlock(&ses->session_mutex);
		if (!tcon->retry)
			return -EHOSTDOWN;
		goto again;
	}
	rc = cifs_setup_session(0, ses, server, ses->local_nls);
	if ((rc == -EACCES) || (rc == -EHOSTDOWN) || (rc == -EKEYREVOKED)) {
		/*
		 * Try alternate password for next reconnect if an alternate
		 * password is available.
		 */
		if (ses->password2)
			swap(ses->password2, ses->password);
	}

	/* do we need to reconnect tcon? */
	if (rc || !tcon->need_reconnect) {
		mutex_unlock(&ses->session_mutex);
		goto out;
	}

skip_sess_setup:
	cifs_mark_open_files_invalid(tcon);
	rc = cifs_tree_connect(0, tcon);

Annotation

Implementation Notes