|
@@ -2185,27 +2185,30 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
|
|
{
|
|
|
int rc = 0;
|
|
|
int xid;
|
|
|
- struct smb_vol volume_info;
|
|
|
+ struct smb_vol *volume_info;
|
|
|
struct cifsSesInfo *pSesInfo = NULL;
|
|
|
struct cifsTconInfo *tcon = NULL;
|
|
|
struct TCP_Server_Info *srvTcp = NULL;
|
|
|
|
|
|
xid = GetXid();
|
|
|
|
|
|
-/* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
|
|
|
+ volume_info = kzalloc(sizeof(struct smb_vol), GFP_KERNEL);
|
|
|
+ if (!volume_info) {
|
|
|
+ rc = -ENOMEM;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
|
|
|
- memset(&volume_info, 0, sizeof(struct smb_vol));
|
|
|
- if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
|
|
|
+ if (cifs_parse_mount_options(mount_data, devname, volume_info)) {
|
|
|
rc = -EINVAL;
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- if (volume_info.nullauth) {
|
|
|
+ if (volume_info->nullauth) {
|
|
|
cFYI(1, ("null user"));
|
|
|
- volume_info.username = "";
|
|
|
- } else if (volume_info.username) {
|
|
|
+ volume_info->username = "";
|
|
|
+ } else if (volume_info->username) {
|
|
|
/* BB fixme parse for domain name here */
|
|
|
- cFYI(1, ("Username: %s", volume_info.username));
|
|
|
+ cFYI(1, ("Username: %s", volume_info->username));
|
|
|
} else {
|
|
|
cifserror("No username specified");
|
|
|
/* In userspace mount helper we can get user name from alternate
|
|
@@ -2216,27 +2219,27 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
|
|
|
|
|
|
|
|
/* this is needed for ASCII cp to Unicode converts */
|
|
|
- if (volume_info.iocharset == NULL) {
|
|
|
+ if (volume_info->iocharset == NULL) {
|
|
|
cifs_sb->local_nls = load_nls_default();
|
|
|
/* load_nls_default can not return null */
|
|
|
} else {
|
|
|
- cifs_sb->local_nls = load_nls(volume_info.iocharset);
|
|
|
+ cifs_sb->local_nls = load_nls(volume_info->iocharset);
|
|
|
if (cifs_sb->local_nls == NULL) {
|
|
|
cERROR(1, ("CIFS mount error: iocharset %s not found",
|
|
|
- volume_info.iocharset));
|
|
|
+ volume_info->iocharset));
|
|
|
rc = -ELIBACC;
|
|
|
goto out;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* get a reference to a tcp session */
|
|
|
- srvTcp = cifs_get_tcp_session(&volume_info);
|
|
|
+ srvTcp = cifs_get_tcp_session(volume_info);
|
|
|
if (IS_ERR(srvTcp)) {
|
|
|
rc = PTR_ERR(srvTcp);
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- pSesInfo = cifs_find_smb_ses(srvTcp, volume_info.username);
|
|
|
+ pSesInfo = cifs_find_smb_ses(srvTcp, volume_info->username);
|
|
|
if (pSesInfo) {
|
|
|
cFYI(1, ("Existing smb sess found (status=%d)",
|
|
|
pSesInfo->status));
|
|
@@ -2274,24 +2277,24 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
|
|
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 = volume_info.password;
|
|
|
+ /* volume_info->password freed at unmount */
|
|
|
+ if (volume_info->password) {
|
|
|
+ pSesInfo->password = volume_info->password;
|
|
|
/* set to NULL to prevent freeing on exit */
|
|
|
- volume_info.password = NULL;
|
|
|
+ volume_info->password = NULL;
|
|
|
}
|
|
|
- if (volume_info.username)
|
|
|
- strncpy(pSesInfo->userName, volume_info.username,
|
|
|
+ if (volume_info->username)
|
|
|
+ strncpy(pSesInfo->userName, volume_info->username,
|
|
|
MAX_USERNAME_SIZE);
|
|
|
- if (volume_info.domainname) {
|
|
|
- int len = strlen(volume_info.domainname);
|
|
|
+ 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);
|
|
|
+ volume_info->domainname);
|
|
|
}
|
|
|
- pSesInfo->linux_uid = volume_info.linux_uid;
|
|
|
- pSesInfo->overrideSecFlg = volume_info.secFlg;
|
|
|
+ pSesInfo->linux_uid = volume_info->linux_uid;
|
|
|
+ pSesInfo->overrideSecFlg = volume_info->secFlg;
|
|
|
down(&pSesInfo->sesSem);
|
|
|
|
|
|
/* BB FIXME need to pass vol->secFlgs BB */
|
|
@@ -2302,14 +2305,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
|
|
|
|
|
/* search for existing tcon to this server share */
|
|
|
if (!rc) {
|
|
|
- setup_cifs_sb(&volume_info, cifs_sb);
|
|
|
+ setup_cifs_sb(volume_info, cifs_sb);
|
|
|
|
|
|
- tcon = cifs_find_tcon(pSesInfo, volume_info.UNC);
|
|
|
+ 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)
|
|
|
+ if (tcon->seal != volume_info->seal)
|
|
|
cERROR(1, ("transport encryption setting "
|
|
|
"conflicts with existing tid"));
|
|
|
} else {
|
|
@@ -2321,8 +2324,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
|
|
tcon->ses = pSesInfo;
|
|
|
|
|
|
/* check for null share name ie connect to dfs root */
|
|
|
- if ((strchr(volume_info.UNC + 3, '\\') == NULL)
|
|
|
- && (strchr(volume_info.UNC + 3, '/') == NULL)) {
|
|
|
+ if ((strchr(volume_info->UNC + 3, '\\') == NULL)
|
|
|
+ && (strchr(volume_info->UNC + 3, '/') == NULL)) {
|
|
|
/* rc = connect_to_dfs_path(...) */
|
|
|
cFYI(1, ("DFS root not supported"));
|
|
|
rc = -ENODEV;
|
|
@@ -2331,10 +2334,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
|
|
/* 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,
|
|
|
+ rc = CIFSTCon(xid, pSesInfo, volume_info->UNC,
|
|
|
tcon, cifs_sb->local_nls);
|
|
|
cFYI(1, ("CIFS Tcon rc = %d", rc));
|
|
|
- if (volume_info.nodfs) {
|
|
|
+ if (volume_info->nodfs) {
|
|
|
tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
|
|
|
cFYI(1, ("DFS disabled (%d)",
|
|
|
tcon->Flags));
|
|
@@ -2342,7 +2345,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
|
|
}
|
|
|
if (rc)
|
|
|
goto mount_fail_check;
|
|
|
- tcon->seal = volume_info.seal;
|
|
|
+ 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);
|
|
@@ -2352,9 +2355,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
|
|
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;
|
|
|
+ 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) {
|
|
@@ -2391,7 +2394,7 @@ mount_fail_check:
|
|
|
if (tcon->ses->capabilities & CAP_UNIX)
|
|
|
/* reset of caps checks mount to see if unix extensions
|
|
|
disabled for just this mount */
|
|
|
- reset_cifs_unix_caps(xid, tcon, sb, &volume_info);
|
|
|
+ reset_cifs_unix_caps(xid, tcon, sb, volume_info);
|
|
|
else
|
|
|
tcon->unix_ext = 0; /* server does not support them */
|
|
|
|
|
@@ -2410,18 +2413,22 @@ mount_fail_check:
|
|
|
cifs_sb->rsize = min(cifs_sb->rsize,
|
|
|
(tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
|
|
|
|
|
|
- /* volume_info.password is freed above when existing session found
|
|
|
+ /* volume_info->password is freed above when existing session found
|
|
|
(in which case it is not needed anymore) but when new sesion is created
|
|
|
the password ptr is put in the new session structure (in which case the
|
|
|
password will be freed at unmount time) */
|
|
|
out:
|
|
|
/* zero out password before freeing */
|
|
|
- if (volume_info.password != NULL) {
|
|
|
- memset(volume_info.password, 0, strlen(volume_info.password));
|
|
|
- kfree(volume_info.password);
|
|
|
+ if (volume_info) {
|
|
|
+ if (volume_info->password != NULL) {
|
|
|
+ memset(volume_info->password, 0,
|
|
|
+ strlen(volume_info->password));
|
|
|
+ kfree(volume_info->password);
|
|
|
+ }
|
|
|
+ kfree(volume_info->UNC);
|
|
|
+ kfree(volume_info->prepath);
|
|
|
+ kfree(volume_info);
|
|
|
}
|
|
|
- kfree(volume_info.UNC);
|
|
|
- kfree(volume_info.prepath);
|
|
|
FreeXid(xid);
|
|
|
return rc;
|
|
|
}
|