Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 36988c76 authored by Jeff Layton's avatar Jeff Layton Committed by Steve French
Browse files

cifs: move SMB session creation code into separate function



...it's mostly part of cifs_mount. Break it out into a separate
function.

Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent a5fc4ce0
Loading
Loading
Loading
Loading
+93 −65
Original line number Diff line number Diff line
@@ -1616,6 +1616,7 @@ cifs_put_smb_ses(struct cifsSesInfo *ses)
	int xid;
	struct TCP_Server_Info *server = ses->server;

	cFYI(1, "%s: ses_count=%d\n", __func__, ses->ses_count);
	write_lock(&cifs_tcp_ses_lock);
	if (--ses->ses_count > 0) {
		write_unlock(&cifs_tcp_ses_lock);
@@ -1634,6 +1635,92 @@ cifs_put_smb_ses(struct cifsSesInfo *ses)
	cifs_put_tcp_session(server);
}

static struct cifsSesInfo *
cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
{
	int rc = -ENOMEM, xid;
	struct cifsSesInfo *ses;

	xid = GetXid();

	ses = cifs_find_smb_ses(server, volume_info->username);
	if (ses) {
		cFYI(1, "Existing smb sess found (status=%d)", ses->status);

		/* existing SMB ses has a server reference already */
		cifs_put_tcp_session(server);

		mutex_lock(&ses->session_mutex);
		if (ses->need_reconnect) {
			cFYI(1, "Session needs reconnect");
			rc = cifs_setup_session(xid, ses,
						volume_info->local_nls);
			if (rc) {
				mutex_unlock(&ses->session_mutex);
				/* problem -- put our reference */
				cifs_put_smb_ses(ses);
				FreeXid(xid);
				return ERR_PTR(rc);
			}
		}
		mutex_unlock(&ses->session_mutex);
		FreeXid(xid);
		return ses;
	}

	cFYI(1, "Existing smb sess not found");
	ses = sesInfoAlloc();
	if (ses == NULL)
		goto get_ses_fail;

	/* new SMB session uses our server ref */
	ses->server = server;
	if (server->addr.sockAddr6.sin6_family == AF_INET6)
		sprintf(ses->serverName, "%pI6",
			&server->addr.sockAddr6.sin6_addr);
	else
		sprintf(ses->serverName, "%pI4",
			&server->addr.sockAddr.sin_addr.s_addr);

	if (volume_info->username)
		strncpy(ses->userName, volume_info->username,
			MAX_USERNAME_SIZE);

	/* volume_info->password freed at unmount */
	if (volume_info->password) {
		ses->password = kstrdup(volume_info->password, GFP_KERNEL);
		if (!ses->password)
			goto get_ses_fail;
	}
	if (volume_info->domainname) {
		int len = strlen(volume_info->domainname);
		ses->domainName = kmalloc(len + 1, GFP_KERNEL);
		if (ses->domainName)
			strcpy(ses->domainName, volume_info->domainname);
	}
	ses->linux_uid = volume_info->linux_uid;
	ses->overrideSecFlg = volume_info->secFlg;

	mutex_lock(&ses->session_mutex);
	rc = cifs_setup_session(xid, ses, volume_info->local_nls);
	mutex_unlock(&ses->session_mutex);
	if (rc)
		goto get_ses_fail;

	/* success, put it on the list */
	write_lock(&cifs_tcp_ses_lock);
	list_add(&ses->smb_ses_list, &server->smb_ses_list);
	write_unlock(&cifs_tcp_ses_lock);

	FreeXid(xid);
	return ses;

get_ses_fail:
	sesInfoFree(ses);
	FreeXid(xid);
	return ERR_PTR(rc);
}

static struct cifsTconInfo *
cifs_find_tcon(struct cifsSesInfo *ses, const char *unc)
{
@@ -2376,72 +2463,13 @@ try_mount_again:
		goto out;
	}

	pSesInfo = cifs_find_smb_ses(srvTcp, volume_info->username);
	if (pSesInfo) {
		cFYI(1, "Existing smb sess found (status=%d)",
			pSesInfo->status);
		/*
		 * The existing SMB session already has a reference to srvTcp,
		 * so we can put back the extra one we got before
		 */
		cifs_put_tcp_session(srvTcp);

		mutex_lock(&pSesInfo->session_mutex);
		if (pSesInfo->need_reconnect) {
			cFYI(1, "Session needs reconnect");
			rc = cifs_setup_session(xid, pSesInfo,
						cifs_sb->local_nls);
		}
		mutex_unlock(&pSesInfo->session_mutex);
	} else if (!rc) {
		cFYI(1, "Existing smb sess not found");
		pSesInfo = sesInfoAlloc();
		if (pSesInfo == NULL) {
			rc = -ENOMEM;
			goto mount_fail_check;
		}

		/* new SMB session uses our srvTcp ref */
		pSesInfo->server = srvTcp;
		if (srvTcp->addr.sockAddr6.sin6_family == AF_INET6)
			sprintf(pSesInfo->serverName, "%pI6",
				&srvTcp->addr.sockAddr6.sin6_addr);
		else
			sprintf(pSesInfo->serverName, "%pI4",
				&srvTcp->addr.sockAddr.sin_addr.s_addr);

		write_lock(&cifs_tcp_ses_lock);
		list_add(&pSesInfo->smb_ses_list, &srvTcp->smb_ses_list);
		write_unlock(&cifs_tcp_ses_lock);

		/* volume_info->password freed at unmount */
		if (volume_info->password) {
			pSesInfo->password = kstrdup(volume_info->password,
						     GFP_KERNEL);
			if (!pSesInfo->password) {
				rc = -ENOMEM;
	/* get a reference to a SMB session */
	pSesInfo = cifs_get_smb_ses(srvTcp, volume_info);
	if (IS_ERR(pSesInfo)) {
		rc = PTR_ERR(pSesInfo);
		pSesInfo = NULL;
		goto mount_fail_check;
	}
		}
		if (volume_info->username)
			strncpy(pSesInfo->userName, volume_info->username,
				MAX_USERNAME_SIZE);
		if (volume_info->domainname) {
			int len = strlen(volume_info->domainname);
			pSesInfo->domainName = kmalloc(len + 1, GFP_KERNEL);
			if (pSesInfo->domainName)
				strcpy(pSesInfo->domainName,
					volume_info->domainname);
		}
		pSesInfo->linux_uid = volume_info->linux_uid;
		pSesInfo->overrideSecFlg = volume_info->secFlg;
		mutex_lock(&pSesInfo->session_mutex);

		/* BB FIXME need to pass vol->secFlgs BB */
		rc = cifs_setup_session(xid, pSesInfo,
					cifs_sb->local_nls);
		mutex_unlock(&pSesInfo->session_mutex);
	}

	/* search for existing tcon to this server share */
	if (!rc) {