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: 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:43 -04:00 committed by Steve French
parent a5fc4ce018
commit 36988c76f0
1 changed files with 93 additions and 65 deletions

View File

@ -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,71 +2463,12 @@ 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;
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);
/* 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;
}
/* search for existing tcon to this server share */