cifs: move tcon find/create into separate function

...and out of cifs_mount.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
Jeff Layton 2010-04-24 07:57:44 -04:00 committed by Steve French
parent 36988c76f0
commit d00c28de55

View File

@ -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 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
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;
}
setup_cifs_sb(volume_info, cifs_sb);
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;