Skip to content

Commit

Permalink
cifs: move tcon find/create into separate function
Browse files Browse the repository at this point in the history
...and out of cifs_mount.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
  • Loading branch information
Jeff Layton authored and Steve French committed Apr 26, 2010
1 parent 36988c7 commit d00c28d
Showing 1 changed file with 86 additions and 70 deletions.
156 changes: 86 additions & 70 deletions fs/cifs/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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,
Expand Down Expand Up @@ -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;

Expand Down

0 comments on commit d00c28d

Please sign in to comment.