Commit 6642d600 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag '5.11-rc5-smb3' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs fixes from Steve French:
 "Four cifs patches found in additional testing of the conversion to the
  new mount API: three small option processing ones, and one fixing domain
  based DFS referrals"

* tag '5.11-rc5-smb3' of git://git.samba.org/sfrench/cifs-2.6:
  cifs: fix dfs domain referrals
  cifs: returning mount parm processing errors correctly
  cifs: fix mounts to subdirectories of target
  cifs: ignore auto and noauto options if given
parents ad8b3c1e 0d4873f9
...@@ -133,8 +133,9 @@ cifs_build_devname(char *nodename, const char *prepath) ...@@ -133,8 +133,9 @@ cifs_build_devname(char *nodename, const char *prepath)
* Caller is responsible for freeing returned value if it is not error. * Caller is responsible for freeing returned value if it is not error.
*/ */
char *cifs_compose_mount_options(const char *sb_mountdata, char *cifs_compose_mount_options(const char *sb_mountdata,
const char *fullpath, const char *fullpath,
const struct dfs_info3_param *ref) const struct dfs_info3_param *ref,
char **devname)
{ {
int rc; int rc;
char *name; char *name;
...@@ -231,7 +232,10 @@ char *cifs_compose_mount_options(const char *sb_mountdata, ...@@ -231,7 +232,10 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
strcat(mountdata, "ip="); strcat(mountdata, "ip=");
strcat(mountdata, srvIP); strcat(mountdata, srvIP);
kfree(name); if (devname)
*devname = name;
else
kfree(name);
/*cifs_dbg(FYI, "%s: parent mountdata: %s\n", __func__, sb_mountdata);*/ /*cifs_dbg(FYI, "%s: parent mountdata: %s\n", __func__, sb_mountdata);*/
/*cifs_dbg(FYI, "%s: submount mountdata: %s\n", __func__, mountdata );*/ /*cifs_dbg(FYI, "%s: submount mountdata: %s\n", __func__, mountdata );*/
...@@ -278,7 +282,7 @@ static struct vfsmount *cifs_dfs_do_mount(struct dentry *mntpt, ...@@ -278,7 +282,7 @@ static struct vfsmount *cifs_dfs_do_mount(struct dentry *mntpt,
/* strip first '\' from fullpath */ /* strip first '\' from fullpath */
mountdata = cifs_compose_mount_options(cifs_sb->ctx->mount_options, mountdata = cifs_compose_mount_options(cifs_sb->ctx->mount_options,
fullpath + 1, NULL); fullpath + 1, NULL, NULL);
if (IS_ERR(mountdata)) { if (IS_ERR(mountdata)) {
kfree(devname); kfree(devname);
return (struct vfsmount *)mountdata; return (struct vfsmount *)mountdata;
......
...@@ -822,7 +822,7 @@ cifs_smb3_do_mount(struct file_system_type *fs_type, ...@@ -822,7 +822,7 @@ cifs_smb3_do_mount(struct file_system_type *fs_type,
goto out; goto out;
} }
rc = cifs_setup_volume_info(cifs_sb->ctx); rc = cifs_setup_volume_info(cifs_sb->ctx, NULL, old_ctx->UNC);
if (rc) { if (rc) {
root = ERR_PTR(rc); root = ERR_PTR(rc);
goto out; goto out;
......
...@@ -78,7 +78,8 @@ extern char *cifs_build_path_to_root(struct smb3_fs_context *ctx, ...@@ -78,7 +78,8 @@ extern char *cifs_build_path_to_root(struct smb3_fs_context *ctx,
int add_treename); int add_treename);
extern char *build_wildcard_path_from_dentry(struct dentry *direntry); extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
extern char *cifs_compose_mount_options(const char *sb_mountdata, extern char *cifs_compose_mount_options(const char *sb_mountdata,
const char *fullpath, const struct dfs_info3_param *ref); const char *fullpath, const struct dfs_info3_param *ref,
char **devname);
/* extern void renew_parental_timestamps(struct dentry *direntry);*/ /* extern void renew_parental_timestamps(struct dentry *direntry);*/
extern struct mid_q_entry *AllocMidQEntry(const struct smb_hdr *smb_buffer, extern struct mid_q_entry *AllocMidQEntry(const struct smb_hdr *smb_buffer,
struct TCP_Server_Info *server); struct TCP_Server_Info *server);
...@@ -89,6 +90,7 @@ extern void cifs_wake_up_task(struct mid_q_entry *mid); ...@@ -89,6 +90,7 @@ extern void cifs_wake_up_task(struct mid_q_entry *mid);
extern int cifs_handle_standard(struct TCP_Server_Info *server, extern int cifs_handle_standard(struct TCP_Server_Info *server,
struct mid_q_entry *mid); struct mid_q_entry *mid);
extern int smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx); extern int smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx);
extern int smb3_parse_opt(const char *options, const char *key, char **val);
extern bool cifs_match_ipaddr(struct sockaddr *srcaddr, struct sockaddr *rhs); extern bool cifs_match_ipaddr(struct sockaddr *srcaddr, struct sockaddr *rhs);
extern int cifs_discard_remaining_data(struct TCP_Server_Info *server); extern int cifs_discard_remaining_data(struct TCP_Server_Info *server);
extern int cifs_call_async(struct TCP_Server_Info *server, extern int cifs_call_async(struct TCP_Server_Info *server,
...@@ -549,7 +551,7 @@ extern int SMBencrypt(unsigned char *passwd, const unsigned char *c8, ...@@ -549,7 +551,7 @@ extern int SMBencrypt(unsigned char *passwd, const unsigned char *c8,
unsigned char *p24); unsigned char *p24);
extern int extern int
cifs_setup_volume_info(struct smb3_fs_context *ctx); cifs_setup_volume_info(struct smb3_fs_context *ctx, const char *mntopts, const char *devname);
extern struct TCP_Server_Info * extern struct TCP_Server_Info *
cifs_find_tcp_session(struct smb3_fs_context *ctx); cifs_find_tcp_session(struct smb3_fs_context *ctx);
......
...@@ -2972,17 +2972,20 @@ expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses, ...@@ -2972,17 +2972,20 @@ expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb), rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
ref_path, &referral, NULL); ref_path, &referral, NULL);
if (!rc) { if (!rc) {
char *fake_devname = NULL;
mdata = cifs_compose_mount_options(cifs_sb->ctx->mount_options, mdata = cifs_compose_mount_options(cifs_sb->ctx->mount_options,
full_path + 1, &referral); full_path + 1, &referral,
&fake_devname);
free_dfs_info_param(&referral); free_dfs_info_param(&referral);
if (IS_ERR(mdata)) { if (IS_ERR(mdata)) {
rc = PTR_ERR(mdata); rc = PTR_ERR(mdata);
mdata = NULL; mdata = NULL;
} else { } else {
smb3_cleanup_fs_context_contents(ctx); rc = cifs_setup_volume_info(ctx, mdata, fake_devname);
rc = cifs_setup_volume_info(ctx);
} }
kfree(fake_devname);
kfree(cifs_sb->ctx->mount_options); kfree(cifs_sb->ctx->mount_options);
cifs_sb->ctx->mount_options = mdata; cifs_sb->ctx->mount_options = mdata;
} }
...@@ -3036,6 +3039,7 @@ static int setup_dfs_tgt_conn(const char *path, const char *full_path, ...@@ -3036,6 +3039,7 @@ static int setup_dfs_tgt_conn(const char *path, const char *full_path,
struct dfs_info3_param ref = {0}; struct dfs_info3_param ref = {0};
char *mdata = NULL; char *mdata = NULL;
struct smb3_fs_context fake_ctx = {NULL}; struct smb3_fs_context fake_ctx = {NULL};
char *fake_devname = NULL;
cifs_dbg(FYI, "%s: dfs path: %s\n", __func__, path); cifs_dbg(FYI, "%s: dfs path: %s\n", __func__, path);
...@@ -3044,16 +3048,18 @@ static int setup_dfs_tgt_conn(const char *path, const char *full_path, ...@@ -3044,16 +3048,18 @@ static int setup_dfs_tgt_conn(const char *path, const char *full_path,
return rc; return rc;
mdata = cifs_compose_mount_options(cifs_sb->ctx->mount_options, mdata = cifs_compose_mount_options(cifs_sb->ctx->mount_options,
full_path + 1, &ref); full_path + 1, &ref,
&fake_devname);
free_dfs_info_param(&ref); free_dfs_info_param(&ref);
if (IS_ERR(mdata)) { if (IS_ERR(mdata)) {
rc = PTR_ERR(mdata); rc = PTR_ERR(mdata);
mdata = NULL; mdata = NULL;
} else } else
rc = cifs_setup_volume_info(&fake_ctx); rc = cifs_setup_volume_info(&fake_ctx, mdata, fake_devname);
kfree(mdata); kfree(mdata);
kfree(fake_devname);
if (!rc) { if (!rc) {
/* /*
...@@ -3122,10 +3128,24 @@ static int do_dfs_failover(const char *path, const char *full_path, struct cifs_ ...@@ -3122,10 +3128,24 @@ static int do_dfs_failover(const char *path, const char *full_path, struct cifs_
* we should pass a clone of the original context? * we should pass a clone of the original context?
*/ */
int int
cifs_setup_volume_info(struct smb3_fs_context *ctx) cifs_setup_volume_info(struct smb3_fs_context *ctx, const char *mntopts, const char *devname)
{ {
int rc = 0; int rc = 0;
smb3_parse_devname(devname, ctx);
if (mntopts) {
char *ip;
cifs_dbg(FYI, "%s: mntopts=%s\n", __func__, mntopts);
rc = smb3_parse_opt(mntopts, "ip", &ip);
if (!rc && !cifs_convert_address((struct sockaddr *)&ctx->dstaddr, ip,
strlen(ip))) {
cifs_dbg(VFS, "%s: failed to convert ip address\n", __func__);
return -EINVAL;
}
}
if (ctx->nullauth) { if (ctx->nullauth) {
cifs_dbg(FYI, "Anonymous login\n"); cifs_dbg(FYI, "Anonymous login\n");
kfree(ctx->username); kfree(ctx->username);
......
...@@ -1417,7 +1417,7 @@ static struct cifs_ses *find_root_ses(struct vol_info *vi, ...@@ -1417,7 +1417,7 @@ static struct cifs_ses *find_root_ses(struct vol_info *vi,
int rc; int rc;
struct cache_entry *ce; struct cache_entry *ce;
struct dfs_info3_param ref = {0}; struct dfs_info3_param ref = {0};
char *mdata = NULL; char *mdata = NULL, *devname = NULL;
struct TCP_Server_Info *server; struct TCP_Server_Info *server;
struct cifs_ses *ses; struct cifs_ses *ses;
struct smb3_fs_context ctx = {NULL}; struct smb3_fs_context ctx = {NULL};
...@@ -1444,7 +1444,8 @@ static struct cifs_ses *find_root_ses(struct vol_info *vi, ...@@ -1444,7 +1444,8 @@ static struct cifs_ses *find_root_ses(struct vol_info *vi,
up_read(&htable_rw_lock); up_read(&htable_rw_lock);
mdata = cifs_compose_mount_options(vi->mntdata, rpath, &ref); mdata = cifs_compose_mount_options(vi->mntdata, rpath, &ref,
&devname);
free_dfs_info_param(&ref); free_dfs_info_param(&ref);
if (IS_ERR(mdata)) { if (IS_ERR(mdata)) {
...@@ -1453,7 +1454,7 @@ static struct cifs_ses *find_root_ses(struct vol_info *vi, ...@@ -1453,7 +1454,7 @@ static struct cifs_ses *find_root_ses(struct vol_info *vi,
goto out; goto out;
} }
rc = cifs_setup_volume_info(&ctx); rc = cifs_setup_volume_info(&ctx, NULL, devname);
if (rc) { if (rc) {
ses = ERR_PTR(rc); ses = ERR_PTR(rc);
...@@ -1472,6 +1473,7 @@ static struct cifs_ses *find_root_ses(struct vol_info *vi, ...@@ -1472,6 +1473,7 @@ static struct cifs_ses *find_root_ses(struct vol_info *vi,
smb3_cleanup_fs_context_contents(&ctx); smb3_cleanup_fs_context_contents(&ctx);
kfree(mdata); kfree(mdata);
kfree(rpath); kfree(rpath);
kfree(devname);
return ses; return ses;
} }
......
...@@ -175,8 +175,10 @@ const struct fs_parameter_spec smb3_fs_parameters[] = { ...@@ -175,8 +175,10 @@ const struct fs_parameter_spec smb3_fs_parameters[] = {
fsparam_flag_no("exec", Opt_ignore), fsparam_flag_no("exec", Opt_ignore),
fsparam_flag_no("dev", Opt_ignore), fsparam_flag_no("dev", Opt_ignore),
fsparam_flag_no("mand", Opt_ignore), fsparam_flag_no("mand", Opt_ignore),
fsparam_flag_no("auto", Opt_ignore),
fsparam_string("cred", Opt_ignore), fsparam_string("cred", Opt_ignore),
fsparam_string("credentials", Opt_ignore), fsparam_string("credentials", Opt_ignore),
fsparam_string("prefixpath", Opt_ignore),
{} {}
}; };
...@@ -399,6 +401,37 @@ cifs_parse_smb_version(char *value, struct smb3_fs_context *ctx, bool is_smb3) ...@@ -399,6 +401,37 @@ cifs_parse_smb_version(char *value, struct smb3_fs_context *ctx, bool is_smb3)
return 0; return 0;
} }
int smb3_parse_opt(const char *options, const char *key, char **val)
{
int rc = -ENOENT;
char *opts, *orig, *p;
orig = opts = kstrdup(options, GFP_KERNEL);
if (!opts)
return -ENOMEM;
while ((p = strsep(&opts, ","))) {
char *nval;
if (!*p)
continue;
if (strncasecmp(p, key, strlen(key)))
continue;
nval = strchr(p, '=');
if (nval) {
if (nval == p)
continue;
*nval++ = 0;
*val = kstrndup(nval, strlen(nval), GFP_KERNEL);
rc = !*val ? -ENOMEM : 0;
goto out;
}
}
out:
kfree(orig);
return rc;
}
/* /*
* Parse a devname into substrings and populate the ctx->UNC and ctx->prepath * Parse a devname into substrings and populate the ctx->UNC and ctx->prepath
* fields with the result. Returns 0 on success and an error otherwise * fields with the result. Returns 0 on success and an error otherwise
...@@ -531,7 +564,7 @@ static int smb3_fs_context_validate(struct fs_context *fc) ...@@ -531,7 +564,7 @@ static int smb3_fs_context_validate(struct fs_context *fc)
if (ctx->rdma && ctx->vals->protocol_id < SMB30_PROT_ID) { if (ctx->rdma && ctx->vals->protocol_id < SMB30_PROT_ID) {
cifs_dbg(VFS, "SMB Direct requires Version >=3.0\n"); cifs_dbg(VFS, "SMB Direct requires Version >=3.0\n");
return -1; return -EOPNOTSUPP;
} }
#ifndef CONFIG_KEYS #ifndef CONFIG_KEYS
...@@ -554,7 +587,7 @@ static int smb3_fs_context_validate(struct fs_context *fc) ...@@ -554,7 +587,7 @@ static int smb3_fs_context_validate(struct fs_context *fc)
/* make sure UNC has a share name */ /* make sure UNC has a share name */
if (strlen(ctx->UNC) < 3 || !strchr(ctx->UNC + 3, '\\')) { if (strlen(ctx->UNC) < 3 || !strchr(ctx->UNC + 3, '\\')) {
cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n"); cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
return -1; return -ENOENT;
} }
if (!ctx->got_ip) { if (!ctx->got_ip) {
...@@ -568,7 +601,7 @@ static int smb3_fs_context_validate(struct fs_context *fc) ...@@ -568,7 +601,7 @@ static int smb3_fs_context_validate(struct fs_context *fc)
if (!cifs_convert_address((struct sockaddr *)&ctx->dstaddr, if (!cifs_convert_address((struct sockaddr *)&ctx->dstaddr,
&ctx->UNC[2], len)) { &ctx->UNC[2], len)) {
pr_err("Unable to determine destination address\n"); pr_err("Unable to determine destination address\n");
return -1; return -EHOSTUNREACH;
} }
} }
...@@ -1263,7 +1296,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, ...@@ -1263,7 +1296,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
return 0; return 0;
cifs_parse_mount_err: cifs_parse_mount_err:
return 1; return -EINVAL;
} }
int smb3_init_fs_context(struct fs_context *fc) int smb3_init_fs_context(struct fs_context *fc)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment