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

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

cifs: move tcon find/create into separate function



...and out of cifs_mount.

Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent 36988c76
Loading
Loading
Loading
Loading
+86 −70
Original line number Diff line number Diff line
@@ -1749,6 +1749,7 @@ cifs_put_tcon(struct cifsTconInfo *tcon)
	int xid;
	struct cifsSesInfo *ses = tcon->ses;

	cFYI(1, "%s: tc_count=%d\n", __func__, tcon->tc_count);
	write_lock(&cifs_tcp_ses_lock);
	if (--tcon->tc_count > 0) {
		write_unlock(&cifs_tcp_ses_lock);
@@ -1766,6 +1767,80 @@ cifs_put_tcon(struct cifsTconInfo *tcon)
	cifs_put_smb_ses(ses);
}

static struct cifsTconInfo *
cifs_get_tcon(struct cifsSesInfo *ses, struct smb_vol *volume_info)
{
	int rc, xid;
	struct cifsTconInfo *tcon;

	tcon = cifs_find_tcon(ses, volume_info->UNC);
	if (tcon) {
		cFYI(1, "Found match on UNC path");
		/* existing tcon already has a reference */
		cifs_put_smb_ses(ses);
		if (tcon->seal != volume_info->seal)
			cERROR(1, "transport encryption setting "
				   "conflicts with existing tid");
		return tcon;
	}

	tcon = tconInfoAlloc();
	if (tcon == NULL) {
		rc = -ENOMEM;
		goto out_fail;
	}

	tcon->ses = ses;
	if (volume_info->password) {
		tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
		if (!tcon->password) {
			rc = -ENOMEM;
			goto out_fail;
		}
	}

	if (strchr(volume_info->UNC + 3, '\\') == NULL
	    && strchr(volume_info->UNC + 3, '/') == NULL) {
		cERROR(1, "Missing share name");
		rc = -ENODEV;
		goto out_fail;
	}

	/* BB Do we need to wrap session_mutex around
	 * this TCon call and Unix SetFS as
	 * we do on SessSetup and reconnect? */
	xid = GetXid();
	rc = CIFSTCon(xid, ses, volume_info->UNC, tcon, volume_info->local_nls);
	FreeXid(xid);
	cFYI(1, "CIFS Tcon rc = %d", rc);
	if (rc)
		goto out_fail;

	if (volume_info->nodfs) {
		tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
		cFYI(1, "DFS disabled (%d)", tcon->Flags);
	}
	tcon->seal = volume_info->seal;
	/* we can have only one retry value for a connection
	   to a share so for resources mounted more than once
	   to the same server share the last value passed in
	   for the retry flag is used */
	tcon->retry = volume_info->retry;
	tcon->nocase = volume_info->nocase;
	tcon->local_lease = volume_info->local_lease;

	write_lock(&cifs_tcp_ses_lock);
	list_add(&tcon->tcon_list, &ses->tcon_list);
	write_unlock(&cifs_tcp_ses_lock);

	return tcon;

out_fail:
	tconInfoFree(tcon);
	return ERR_PTR(rc);
}


int
get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,
	     const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
@@ -2471,81 +2546,22 @@ try_mount_again:
		goto mount_fail_check;
	}

	/* search for existing tcon to this server share */
	if (!rc) {
	setup_cifs_sb(volume_info, cifs_sb);

		tcon = cifs_find_tcon(pSesInfo, volume_info->UNC);
		if (tcon) {
			cFYI(1, "Found match on UNC path");
			/* existing tcon already has a reference */
			cifs_put_smb_ses(pSesInfo);
			if (tcon->seal != volume_info->seal)
				cERROR(1, "transport encryption setting "
					   "conflicts with existing tid");
		} else {
			tcon = tconInfoAlloc();
			if (tcon == NULL) {
				rc = -ENOMEM;
				goto mount_fail_check;
			}

			tcon->ses = pSesInfo;
			if (volume_info->password) {
				tcon->password = kstrdup(volume_info->password,
							 GFP_KERNEL);
				if (!tcon->password) {
					rc = -ENOMEM;
					goto mount_fail_check;
				}
			}

			if ((strchr(volume_info->UNC + 3, '\\') == NULL)
			    && (strchr(volume_info->UNC + 3, '/') == NULL)) {
				cERROR(1, "Missing share name");
				rc = -ENODEV;
				goto mount_fail_check;
			} else {
				/* BB Do we need to wrap sesSem around
				 * this TCon call and Unix SetFS as
				 * we do on SessSetup and reconnect? */
				rc = CIFSTCon(xid, pSesInfo, volume_info->UNC,
					      tcon, cifs_sb->local_nls);
				cFYI(1, "CIFS Tcon rc = %d", rc);
				if (volume_info->nodfs) {
					tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
					cFYI(1, "DFS disabled (%d)",
						tcon->Flags);
				}
			}
			if (rc)
				goto remote_path_check;
			tcon->seal = volume_info->seal;
			write_lock(&cifs_tcp_ses_lock);
			list_add(&tcon->tcon_list, &pSesInfo->tcon_list);
			write_unlock(&cifs_tcp_ses_lock);
		}

		/* we can have only one retry value for a connection
		   to a share so for resources mounted more than once
		   to the same server share the last value passed in
		   for the retry flag is used */
		tcon->retry = volume_info->retry;
		tcon->nocase = volume_info->nocase;
		tcon->local_lease = volume_info->local_lease;
	}
	if (pSesInfo) {
	if (pSesInfo->capabilities & CAP_LARGE_FILES)
		sb->s_maxbytes = MAX_LFS_FILESIZE;
	else
		sb->s_maxbytes = MAX_NON_LFS;
	}

	/* BB FIXME fix time_gran to be larger for LANMAN sessions */
	sb->s_time_gran = 100;

	if (rc)
	/* search for existing tcon to this server share */
	tcon = cifs_get_tcon(pSesInfo, volume_info);
	if (IS_ERR(tcon)) {
		rc = PTR_ERR(tcon);
		tcon = NULL;
		goto remote_path_check;
	}

	cifs_sb->tcon = tcon;