summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRonnie Sahlberg <lsahlber@redhat.com>2020-12-10 00:06:02 -0600
committerSteve French <stfrench@microsoft.com>2020-12-13 19:12:07 -0600
commit24e0a1eff9e2b9835a6e7c17039dfb6ecfd81f1f (patch)
tree56ba9dcbfc2c975fafc76582edfd18190b5737d6
parent66e7b09c731175064de5a3682c692ec166e02499 (diff)
cifs: switch to new mount api
See Documentation/filesystems/mount_api.rst for details on new mount API Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com> Signed-off-by: Steve French <stfrench@microsoft.com>
-rw-r--r--fs/cifs/cifs_dfs_ref.c4
-rw-r--r--fs/cifs/cifsencrypt.c5
-rw-r--r--fs/cifs/cifsfs.c54
-rw-r--r--fs/cifs/cifsfs.h4
-rw-r--r--fs/cifs/cifsproto.h5
-rw-r--r--fs/cifs/connect.c1158
-rw-r--r--fs/cifs/dfs_cache.c8
-rw-r--r--fs/cifs/fs_context.c1063
-rw-r--r--fs/cifs/fs_context.h74
-rw-r--r--fs/cifs/sess.c2
10 files changed, 1096 insertions, 1281 deletions
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index cc3ada12848d..4b0b9cfe2ab1 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -275,6 +275,10 @@ static struct vfsmount *cifs_dfs_do_mount(struct dentry *mntpt,
convert_delimiter(devname, '/');
+ /* TODO: change to call fs_context_for_mount(), fill in context directly, call fc_mount */
+
+ /* See afs_mntpt_do_automount in fs/afs/mntpt.c for an example */
+
/* strip first '\' from fullpath */
mountdata = cifs_compose_mount_options(cifs_sb->mountdata,
fullpath + 1, NULL, NULL);
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 9daa256f69d4..51d53e4bdf6b 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -661,6 +661,11 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
unsigned char *tiblob = NULL; /* target info blob */
__le64 rsp_timestamp;
+ if (nls_cp == NULL) {
+ cifs_dbg(VFS, "%s called with nls_cp==NULL\n", __func__);
+ return -EINVAL;
+ }
+
if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) {
if (!ses->domainName) {
if (ses->domainAuto) {
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 9fb85fcff6ae..907c82428c42 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -682,13 +682,6 @@ static int cifs_show_stats(struct seq_file *s, struct dentry *root)
}
#endif
-static int cifs_remount(struct super_block *sb, int *flags, char *data)
-{
- sync_filesystem(sb);
- *flags |= SB_NODIRATIME;
- return 0;
-}
-
static int cifs_drop_inode(struct inode *inode)
{
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
@@ -710,7 +703,6 @@ static const struct super_operations cifs_super_ops = {
as opens */
.show_options = cifs_show_options,
.umount_begin = cifs_umount_begin,
- .remount_fs = cifs_remount,
#ifdef CONFIG_CIFS_STATS2
.show_stats = cifs_show_stats,
#endif
@@ -778,9 +770,9 @@ static int cifs_set_super(struct super_block *sb, void *data)
return set_anon_super(sb, NULL);
}
-static struct dentry *
+struct dentry *
cifs_smb3_do_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data, bool is_smb3)
+ int flags, struct smb3_fs_context *old_ctx)
{
int rc;
struct super_block *sb;
@@ -794,13 +786,24 @@ cifs_smb3_do_mount(struct file_system_type *fs_type,
* If CIFS_DEBUG && cifs_FYI
*/
if (cifsFYI)
- cifs_dbg(FYI, "Devname: %s flags: %d\n", dev_name, flags);
+ cifs_dbg(FYI, "Devname: %s flags: %d\n", old_ctx->UNC, flags);
else
- cifs_info("Attempting to mount %s\n", dev_name);
+ cifs_info("Attempting to mount %s\n", old_ctx->UNC);
+
+ ctx = kzalloc(sizeof(struct smb3_fs_context), GFP_KERNEL);
+ if (!ctx)
+ return ERR_PTR(-ENOMEM);
+ rc = smb3_fs_context_dup(ctx, old_ctx);
+ if (rc) {
+ root = ERR_PTR(rc);
+ goto out;
+ }
- ctx = cifs_get_volume_info((char *)data, dev_name, is_smb3);
- if (IS_ERR(ctx))
- return ERR_CAST(ctx);
+ rc = cifs_setup_volume_info(ctx);
+ if (rc) {
+ root = ERR_PTR(rc);
+ goto out;
+ }
cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL);
if (cifs_sb == NULL) {
@@ -808,7 +811,7 @@ cifs_smb3_do_mount(struct file_system_type *fs_type,
goto out_nls;
}
- cifs_sb->mountdata = kstrndup(data, PAGE_SIZE, GFP_KERNEL);
+ cifs_sb->mountdata = kstrndup(ctx->mount_options, PAGE_SIZE, GFP_KERNEL);
if (cifs_sb->mountdata == NULL) {
root = ERR_PTR(-ENOMEM);
goto out_free;
@@ -878,19 +881,6 @@ out_nls:
goto out;
}
-static struct dentry *
-smb3_do_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
-{
- return cifs_smb3_do_mount(fs_type, flags, dev_name, data, true);
-}
-
-static struct dentry *
-cifs_do_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
-{
- return cifs_smb3_do_mount(fs_type, flags, dev_name, data, false);
-}
static ssize_t
cifs_loose_read_iter(struct kiocb *iocb, struct iov_iter *iter)
@@ -1027,7 +1017,8 @@ cifs_setlease(struct file *file, long arg, struct file_lock **lease, void **priv
struct file_system_type cifs_fs_type = {
.owner = THIS_MODULE,
.name = "cifs",
- .mount = cifs_do_mount,
+ .init_fs_context = smb3_init_fs_context,
+ .parameters = smb3_fs_parameters,
.kill_sb = cifs_kill_sb,
.fs_flags = FS_RENAME_DOES_D_MOVE,
};
@@ -1036,7 +1027,8 @@ MODULE_ALIAS_FS("cifs");
static struct file_system_type smb3_fs_type = {
.owner = THIS_MODULE,
.name = "smb3",
- .mount = smb3_do_mount,
+ .init_fs_context = smb3_init_fs_context,
+ .parameters = smb3_fs_parameters,
.kill_sb = cifs_kill_sb,
.fs_flags = FS_RENAME_DOES_D_MOVE,
};
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 905d03863721..d6976c28970d 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -152,6 +152,10 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
extern void cifs_setsize(struct inode *inode, loff_t offset);
extern int cifs_truncate_page(struct address_space *mapping, loff_t from);
+struct smb3_fs_context;
+extern struct dentry *cifs_smb3_do_mount(struct file_system_type *fs_type,
+ int flags, struct smb3_fs_context *ctx);
+
#ifdef CONFIG_CIFS_NFSD_EXPORT
extern const struct export_operations cifs_export_ops;
#endif /* CONFIG_CIFS_NFSD_EXPORT */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 0ef3deeb085f..8dde386d4893 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -239,8 +239,6 @@ extern int cifs_setup_cifs_sb(struct smb3_fs_context *ctx,
struct cifs_sb_info *cifs_sb);
extern int cifs_match_super(struct super_block *, void *);
extern void cifs_cleanup_volume_info(struct smb3_fs_context *ctx);
-extern struct smb3_fs_context *cifs_get_volume_info(char *mount_data,
- const char *devname, bool is_smb3);
extern int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx);
extern void cifs_umount(struct cifs_sb_info *);
extern void cifs_mark_open_files_invalid(struct cifs_tcon *tcon);
@@ -554,8 +552,7 @@ extern int SMBencrypt(unsigned char *passwd, const unsigned char *c8,
unsigned char *p24);
extern int
-cifs_setup_volume_info(struct smb3_fs_context *ctx, char *mount_data,
- const char *devname, bool is_smb3);
+cifs_setup_volume_info(struct smb3_fs_context *ctx);
extern void
cifs_cleanup_volume_info_contents(struct smb3_fs_context *ctx);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 8ae45367109c..1c463ca16226 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -73,156 +73,6 @@ extern bool disable_legacy_dialects;
/* Drop the connection to not overload the server */
#define NUM_STATUS_IO_TIMEOUT 5
-static const match_table_t cifs_mount_option_tokens = {
-
- { Opt_user_xattr, "user_xattr" },
- { Opt_nouser_xattr, "nouser_xattr" },
- { Opt_forceuid, "forceuid" },
- { Opt_noforceuid, "noforceuid" },
- { Opt_forcegid, "forcegid" },
- { Opt_noforcegid, "noforcegid" },
- { Opt_noblocksend, "noblocksend" },
- { Opt_noautotune, "noautotune" },
- { Opt_nolease, "nolease" },
- { Opt_hard, "hard" },
- { Opt_soft, "soft" },
- { Opt_perm, "perm" },
- { Opt_noperm, "noperm" },
- { Opt_nodelete, "nodelete" },
- { Opt_mapchars, "mapchars" }, /* SFU style */
- { Opt_nomapchars, "nomapchars" },
- { Opt_mapposix, "mapposix" }, /* SFM style */
- { Opt_nomapposix, "nomapposix" },
- { Opt_sfu, "sfu" },
- { Opt_nosfu, "nosfu" },
- { Opt_nodfs, "nodfs" },
- { Opt_posixpaths, "posixpaths" },
- { Opt_noposixpaths, "noposixpaths" },
- { Opt_nounix, "nounix" },
- { Opt_nounix, "nolinux" },
- { Opt_nounix, "noposix" },
- { Opt_unix, "unix" },
- { Opt_unix, "linux" },
- { Opt_unix, "posix" },
- { Opt_nocase, "nocase" },
- { Opt_nocase, "ignorecase" },
- { Opt_brl, "brl" },
- { Opt_nobrl, "nobrl" },
- { Opt_handlecache, "handlecache" },
- { Opt_nohandlecache, "nohandlecache" },
- { Opt_nobrl, "nolock" },
- { Opt_forcemandatorylock, "forcemandatorylock" },
- { Opt_forcemandatorylock, "forcemand" },
- { Opt_setuids, "setuids" },
- { Opt_nosetuids, "nosetuids" },
- { Opt_setuidfromacl, "idsfromsid" },
- { Opt_dynperm, "dynperm" },
- { Opt_nodynperm, "nodynperm" },
- { Opt_nohard, "nohard" },
- { Opt_nosoft, "nosoft" },
- { Opt_nointr, "nointr" },
- { Opt_intr, "intr" },
- { Opt_nostrictsync, "nostrictsync" },
- { Opt_strictsync, "strictsync" },
- { Opt_serverino, "serverino" },
- { Opt_noserverino, "noserverino" },
- { Opt_rwpidforward, "rwpidforward" },
- { Opt_modesid, "modefromsid" },
- { Opt_cifsacl, "cifsacl" },
- { Opt_nocifsacl, "nocifsacl" },
- { Opt_acl, "acl" },
- { Opt_noacl, "noacl" },
- { Opt_locallease, "locallease" },
- { Opt_sign, "sign" },
- { Opt_ignore_signature, "signloosely" },
- { Opt_seal, "seal" },
- { Opt_noac, "noac" },
- { Opt_fsc, "fsc" },
- { Opt_mfsymlinks, "mfsymlinks" },
- { Opt_multiuser, "multiuser" },
- { Opt_sloppy, "sloppy" },
- { Opt_nosharesock, "nosharesock" },
- { Opt_persistent, "persistenthandles"},
- { Opt_nopersistent, "nopersistenthandles"},
- { Opt_resilient, "resilienthandles"},
- { Opt_noresilient, "noresilienthandles"},
- { Opt_domainauto, "domainauto"},
- { Opt_rdma, "rdma"},
- { Opt_multichannel, "multichannel" },
- { Opt_nomultichannel, "nomultichannel" },
-
- { Opt_backupuid, "backupuid=%s" },
- { Opt_backupgid, "backupgid=%s" },
- { Opt_uid, "uid=%s" },
- { Opt_cruid, "cruid=%s" },
- { Opt_gid, "gid=%s" },
- { Opt_file_mode, "file_mode=%s" },
- { Opt_dirmode, "dirmode=%s" },
- { Opt_dirmode, "dir_mode=%s" },
- { Opt_port, "port=%s" },
- { Opt_min_enc_offload, "esize=%s" },
- { Opt_blocksize, "bsize=%s" },
- { Opt_rsize, "rsize=%s" },
- { Opt_wsize, "wsize=%s" },
- { Opt_actimeo, "actimeo=%s" },
- { Opt_handletimeout, "handletimeout=%s" },
- { Opt_echo_interval, "echo_interval=%s" },
- { Opt_max_credits, "max_credits=%s" },
- { Opt_snapshot, "snapshot=%s" },
- { Opt_max_channels, "max_channels=%s" },
- { Opt_compress, "compress=%s" },
-
- { Opt_blank_user, "user=" },
- { Opt_blank_user, "username=" },
- { Opt_user, "user=%s" },
- { Opt_user, "username=%s" },
- { Opt_blank_pass, "pass=" },
- { Opt_blank_pass, "password=" },
- { Opt_pass, "pass=%s" },
- { Opt_pass, "password=%s" },
- { Opt_blank_ip, "ip=" },
- { Opt_blank_ip, "addr=" },
- { Opt_ip, "ip=%s" },
- { Opt_ip, "addr=%s" },
- { Opt_ignore, "unc=%s" },
- { Opt_ignore, "target=%s" },
- { Opt_ignore, "path=%s" },
- { Opt_domain, "dom=%s" },
- { Opt_domain, "domain=%s" },
- { Opt_domain, "workgroup=%s" },
- { Opt_srcaddr, "srcaddr=%s" },
- { Opt_ignore, "prefixpath=%s" },
- { Opt_iocharset, "iocharset=%s" },
- { Opt_netbiosname, "netbiosname=%s" },
- { Opt_servern, "servern=%s" },
- { Opt_ver, "ver=%s" },
- { Opt_vers, "vers=%s" },
- { Opt_sec, "sec=%s" },
- { Opt_cache, "cache=%s" },
-
- { Opt_ignore, "cred" },
- { Opt_ignore, "credentials" },
- { Opt_ignore, "cred=%s" },
- { Opt_ignore, "credentials=%s" },
- { Opt_ignore, "guest" },
- { Opt_ignore, "rw" },
- { Opt_ignore, "ro" },
- { Opt_ignore, "suid" },
- { Opt_ignore, "nosuid" },
- { Opt_ignore, "exec" },
- { Opt_ignore, "noexec" },
- { Opt_ignore, "nodev" },
- { Opt_ignore, "noauto" },
- { Opt_ignore, "dev" },
- { Opt_ignore, "mand" },
- { Opt_ignore, "nomand" },
- { Opt_ignore, "relatime" },
- { Opt_ignore, "_netdev" },
- { Opt_rootfs, "rootfs" },
-
- { Opt_err, NULL }
-};
-
static int ip_connect(struct TCP_Server_Info *server);
static int generic_ip_connect(struct TCP_Server_Info *server);
static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
@@ -1208,960 +1058,6 @@ extract_hostname(const char *unc)
return dst;
}
-static int get_option_ul(substring_t args[], unsigned long *option)
-{
- int rc;
- char *string;
-
- string = match_strdup(args);
- if (string == NULL)
- return -ENOMEM;
- rc = kstrtoul(string, 0, option);
- kfree(string);
-
- return rc;
-}
-
-static int get_option_uid(substring_t args[], kuid_t *result)
-{
- unsigned long value;
- kuid_t uid;
- int rc;
-
- rc = get_option_ul(args, &value);
- if (rc)
- return rc;
-
- uid = make_kuid(current_user_ns(), value);
- if (!uid_valid(uid))
- return -EINVAL;
-
- *result = uid;
- return 0;
-}
-
-static int get_option_gid(substring_t args[], kgid_t *result)
-{
- unsigned long value;
- kgid_t gid;
- int rc;
-
- rc = get_option_ul(args, &value);
- if (rc)
- return rc;
-
- gid = make_kgid(current_user_ns(), value);
- if (!gid_valid(gid))
- return -EINVAL;
-
- *result = gid;
- return 0;
-}
-
-static int
-cifs_parse_mount_options(const char *mountdata, const char *devname,
- struct smb3_fs_context *ctx, bool is_smb3)
-{
- char *data, *end;
- char *mountdata_copy = NULL, *options;
- unsigned int temp_len, i, j;
- char separator[2];
- short int override_uid = -1;
- short int override_gid = -1;
- bool uid_specified = false;
- bool gid_specified = false;
- bool sloppy = false;
- char *invalid = NULL;
- char *nodename = utsname()->nodename;
- char *string = NULL;
- char *tmp_end, *value;
- char delim;
- bool got_ip = false;
- bool got_version = false;
- unsigned short port = 0;
- struct sockaddr *dstaddr = (struct sockaddr *)&ctx->dstaddr;
-
- separator[0] = ',';
- separator[1] = 0;
- delim = separator[0];
-
- /* ensure we always start with zeroed-out ctx */
- memset(ctx, 0, sizeof(*ctx));
-
- /*
- * does not have to be perfect mapping since field is
- * informational, only used for servers that do not support
- * port 445 and it can be overridden at mount time
- */
- memset(ctx->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
- for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
- ctx->source_rfc1001_name[i] = toupper(nodename[i]);
-
- ctx->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
- /* null target name indicates to use *SMBSERVR default called name
- if we end up sending RFC1001 session initialize */
- ctx->target_rfc1001_name[0] = 0;
- ctx->cred_uid = current_uid();
- ctx->linux_uid = current_uid();
- ctx->linux_gid = current_gid();
- ctx->bsize = 1024 * 1024; /* can improve cp performance significantly */
- /*
- * default to SFM style remapping of seven reserved characters
- * unless user overrides it or we negotiate CIFS POSIX where
- * it is unnecessary. Can not simultaneously use more than one mapping
- * since then readdir could list files that open could not open
- */
- ctx->remap = true;
-
- /* default to only allowing write access to owner of the mount */
- ctx->dir_mode = ctx->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
-
- /* ctx->retry default is 0 (i.e. "soft" limited retry not hard retry) */
- /* default is always to request posix paths. */
- ctx->posix_paths = 1;
- /* default to using server inode numbers where available */
- ctx->server_ino = 1;
-
- /* default is to use strict cifs caching semantics */
- ctx->strict_io = true;
-
- ctx->actimeo = CIFS_DEF_ACTIMEO;
-
- /* Most clients set timeout to 0, allows server to use its default */
- ctx->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */
-
- /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
- ctx->ops = &smb30_operations;
- ctx->vals = &smbdefault_values;
-
- ctx->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
-
- /* default to no multichannel (single server connection) */
- ctx->multichannel = false;
- ctx->max_channels = 1;
-
- if (!mountdata)
- goto cifs_parse_mount_err;
-
- mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
- if (!mountdata_copy)
- goto cifs_parse_mount_err;
-
- options = mountdata_copy;
- end = options + strlen(options);
-
- if (strncmp(options, "sep=", 4) == 0) {
- if (options[4] != 0) {
- separator[0] = options[4];
- options += 5;
- } else {
- cifs_dbg(FYI, "Null separator not allowed\n");
- }
- }
- ctx->backupuid_specified = false; /* no backup intent for a user */
- ctx->backupgid_specified = false; /* no backup intent for a group */
-
- switch (smb3_parse_devname(devname, ctx)) {
- case 0:
- break;
- case -ENOMEM:
- cifs_dbg(VFS, "Unable to allocate memory for devname\n");
- goto cifs_parse_mount_err;
- case -EINVAL:
- cifs_dbg(VFS, "Malformed UNC in devname\n");
- goto cifs_parse_mount_err;
- default:
- cifs_dbg(VFS, "Unknown error parsing devname\n");
- goto cifs_parse_mount_err;
- }
-
- while ((data = strsep(&options, separator)) != NULL) {
- substring_t args[MAX_OPT_ARGS];
- unsigned long option;
- int token;
-
- if (!*data)
- continue;
-
- token = match_token(data, cifs_mount_option_tokens, args);
-
- switch (token) {
-
- /* Ingnore the following */
- case Opt_ignore:
- break;
-
- /* Boolean values */
- case Opt_user_xattr:
- ctx->no_xattr = 0;
- break;
- case Opt_nouser_xattr:
- ctx->no_xattr = 1;
- break;
- case Opt_forceuid:
- override_uid = 1;
- break;
- case Opt_noforceuid:
- override_uid = 0;
- break;
- case Opt_forcegid:
- override_gid = 1;
- break;
- case Opt_noforcegid:
- override_gid = 0;
- break;
- case Opt_noblocksend:
- ctx->noblocksnd = 1;
- break;
- case Opt_noautotune:
- ctx->noautotune = 1;
- break;
- case Opt_nolease:
- ctx->no_lease = 1;
- break;
- case Opt_hard:
- ctx->retry = 1;
- break;
- case Opt_soft:
- ctx->retry = 0;
- break;
- case Opt_perm:
- ctx->noperm = 0;
- break;
- case Opt_noperm:
- ctx->noperm = 1;
- break;
- case Opt_nodelete:
- ctx->nodelete = 1;
- break;
- case Opt_mapchars:
- ctx->sfu_remap = true;
- ctx->remap = false; /* disable SFM mapping */
- break;
- case Opt_nomapchars:
- ctx->sfu_remap = false;
- break;
- case Opt_mapposix:
- ctx->remap = true;
- ctx->sfu_remap = false; /* disable SFU mapping */
- break;
- case Opt_nomapposix:
- ctx->remap = false;
- break;
- case Opt_sfu:
- ctx->sfu_emul = 1;
- break;
- case Opt_nosfu:
- ctx->sfu_emul = 0;
- break;
- case Opt_nodfs:
- ctx->nodfs = 1;
- break;
- case Opt_rootfs:
-#ifdef CONFIG_CIFS_ROOT
- ctx->rootfs = true;
-#endif
- break;
- case Opt_posixpaths:
- ctx->posix_paths = 1;
- break;
- case Opt_noposixpaths:
- ctx->posix_paths = 0;
- break;
- case Opt_nounix:
- if (ctx->linux_ext)
- cifs_dbg(VFS,
- "conflicting unix mount options\n");
- ctx->no_linux_ext = 1;
- break;
- case Opt_unix:
- if (ctx->no_linux_ext)
- cifs_dbg(VFS,
- "conflicting unix mount options\n");
- ctx->linux_ext = 1;
- break;
- case Opt_nocase:
- ctx->nocase = 1;
- break;
- case Opt_brl:
- ctx->nobrl = 0;
- break;
- case Opt_nobrl:
- ctx->nobrl = 1;
- /*
- * turn off mandatory locking in mode
- * if remote locking is turned off since the
- * local vfs will do advisory
- */
- if (ctx->file_mode ==
- (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
- ctx->file_mode = S_IALLUGO;
- break;
- case Opt_nohandlecache:
- ctx->nohandlecache = 1;
- break;
- case Opt_handlecache:
- ctx->nohandlecache = 0;
- break;
- case Opt_forcemandatorylock:
- ctx->mand_lock = 1;
- break;
- case Opt_setuids:
- ctx->setuids = 1;
- break;
- case Opt_nosetuids:
- ctx->setuids = 0;
- break;
- case Opt_setuidfromacl:
- ctx->setuidfromacl = 1;
- break;
- case Opt_dynperm:
- ctx->dynperm = true;
- break;
- case Opt_nodynperm:
- ctx->dynperm = false;
- break;
- case Opt_nohard:
- ctx->retry = 0;
- break;
- case Opt_nosoft:
- ctx->retry = 1;
- break;
- case Opt_nointr:
- ctx->intr = 0;
- break;
- case Opt_intr:
- ctx->intr = 1;
- break;
- case Opt_nostrictsync:
- ctx->nostrictsync = 1;
- break;
- case Opt_strictsync:
- ctx->nostrictsync = 0;
- break;
- case Opt_serverino:
- ctx->server_ino = 1;
- break;
- case Opt_noserverino:
- ctx->server_ino = 0;
- break;
- case Opt_rwpidforward:
- ctx->rwpidforward = 1;
- break;
- case Opt_modesid:
- ctx->mode_ace = 1;
- break;
- case Opt_cifsacl:
- ctx->cifs_acl = 1;
- break;
- case Opt_nocifsacl:
- ctx->cifs_acl = 0;
- break;
- case Opt_acl:
- ctx->no_psx_acl = 0;
- break;
- case Opt_noacl:
- ctx->no_psx_acl = 1;
- break;
- case Opt_locallease:
- ctx->local_lease = 1;
- break;
- case Opt_sign:
- ctx->sign = true;
- break;
- case Opt_ignore_signature:
- ctx->sign = true;
- ctx->ignore_signature = true;
- break;
- case Opt_seal:
- /* we do not do the following in secFlags because seal
- * is a per tree connection (mount) not a per socket
- * or per-smb connection option in the protocol
- * ctx->secFlg |= CIFSSEC_MUST_SEAL;
- */
- ctx->seal = 1;
- break;
- case Opt_noac:
- pr_warn("Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
- break;
- case Opt_fsc:
-#ifndef CONFIG_CIFS_FSCACHE
- cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
- goto cifs_parse_mount_err;
-#endif
- ctx->fsc = true;
- break;
- case Opt_mfsymlinks:
- ctx->mfsymlinks = true;
- break;
- case Opt_multiuser:
- ctx->multiuser = true;
- break;
- case Opt_sloppy:
- sloppy = true;
- break;
- case Opt_nosharesock:
- ctx->nosharesock = true;
- break;
- case Opt_nopersistent:
- ctx->nopersistent = true;
- if (ctx->persistent) {
- cifs_dbg(VFS,
- "persistenthandles mount options conflict\n");
- goto cifs_parse_mount_err;
- }
- break;
- case Opt_persistent:
- ctx->persistent = true;
- if ((ctx->nopersistent) || (ctx->resilient)) {
- cifs_dbg(VFS,
- "persistenthandles mount options conflict\n");
- goto cifs_parse_mount_err;
- }
- break;
- case Opt_resilient:
- ctx->resilient = true;
- if (ctx->persistent) {
- cifs_dbg(VFS,
- "persistenthandles mount options conflict\n");
- goto cifs_parse_mount_err;
- }
- break;
- case Opt_noresilient:
- ctx->resilient = false; /* already the default */
- break;
- case Opt_domainauto:
- ctx->domainauto = true;
- break;
- case Opt_rdma:
- ctx->rdma = true;
- break;
- case Opt_multichannel:
- ctx->multichannel = true;
- /* if number of channels not specified, default to 2 */
- if (ctx->max_channels < 2)
- ctx->max_channels = 2;
- break;
- case Opt_nomultichannel:
- ctx->multichannel = false;
- ctx->max_channels = 1;
- break;
- case Opt_compress:
- ctx->compression = UNKNOWN_TYPE;
- cifs_dbg(VFS,
- "SMB3 compression support is experimental\n");
- break;
-
- /* Numeric Values */
- case Opt_backupuid:
- if (get_option_uid(args, &ctx->backupuid)) {
- cifs_dbg(VFS, "%s: Invalid backupuid value\n",
- __func__);
- goto cifs_parse_mount_err;
- }
- ctx->backupuid_specified = true;
- break;
- case Opt_backupgid:
- if (get_option_gid(args, &ctx->backupgid)) {
- cifs_dbg(VFS, "%s: Invalid backupgid value\n",
- __func__);
- goto cifs_parse_mount_err;
- }
- ctx->backupgid_specified = true;
- break;
- case Opt_uid:
- if (get_option_uid(args, &ctx->linux_uid)) {
- cifs_dbg(VFS, "%s: Invalid uid value\n",
- __func__);
- goto cifs_parse_mount_err;
- }
- uid_specified = true;
- break;
- case Opt_cruid:
- if (get_option_uid(args, &ctx->cred_uid)) {
- cifs_dbg(VFS, "%s: Invalid cruid value\n",
- __func__);
- goto cifs_parse_mount_err;
- }
- break;
- case Opt_gid:
- if (get_option_gid(args, &ctx->linux_gid)) {
- cifs_dbg(VFS, "%s: Invalid gid value\n",
- __func__);
- goto cifs_parse_mount_err;
- }
- gid_specified = true;
- break;
- case Opt_file_mode:
- if (get_option_ul(args, &option)) {
- cifs_dbg(VFS, "%s: Invalid file_mode value\n",
- __func__);
- goto cifs_parse_mount_err;
- }
- ctx->file_mode = option;
- break;
- case Opt_dirmode:
- if (get_option_ul(args, &option)) {
- cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
- __func__);
- goto cifs_parse_mount_err;
- }
- ctx->dir_mode = option;
- break;
- case Opt_port:
- if (get_option_ul(args, &option) ||
- option > USHRT_MAX) {
- cifs_dbg(VFS, "%s: Invalid port value\n",
- __func__);
- goto cifs_parse_mount_err;
- }
- port = (unsigned short)option;
- break;
- case Opt_min_enc_offload:
- if (get_option_ul(args, &option)) {
- cifs_dbg(VFS, "Invalid minimum encrypted read offload size (esize)\n");
- goto cifs_parse_mount_err;
- }
- ctx->min_offload = option;
- break;
- case Opt_blocksize:
- if (get_option_ul(args, &option)) {
- cifs_dbg(VFS, "%s: Invalid blocksize value\n",
- __func__);
- goto cifs_parse_mount_err;
- }
- /*
- * inode blocksize realistically should never need to be
- * less than 16K or greater than 16M and default is 1MB.
- * Note that small inode block sizes (e.g. 64K) can lead
- * to very poor performance of common tools like cp and scp
- */
- if ((option < CIFS_MAX_MSGSIZE) ||
- (option > (4 * SMB3_DEFAULT_IOSIZE))) {
- cifs_dbg(VFS, "%s: Invalid blocksize\n",
- __func__);
- goto cifs_parse_mount_err;
- }
- ctx->bsize = option;
- break;
- case Opt_rsize:
- if (get_option_ul(args, &option)) {
- cifs_dbg(VFS, "%s: Invalid rsize value\n",
- __func__);
- goto cifs_parse_mount_err;
- }
- ctx->rsize = option;
- break;
- case Opt_wsize:
- if (get_option_ul(args, &option)) {
- cifs_dbg(VFS, "%s: Invalid wsize value\n",
- __func__);
- goto cifs_parse_mount_err;
- }
- ctx->wsize = option;
- break;
- case Opt_actimeo:
- if (get_option_ul(args, &option)) {
- cifs_dbg(VFS, "%s: Invalid actimeo value\n",
- __func__);
- goto cifs_parse_mount_err;
- }
- ctx->actimeo = HZ * option;
- if (ctx->actimeo > CIFS_MAX_ACTIMEO) {
- cifs_dbg(VFS, "attribute cache timeout too large\n");
- goto cifs_parse_mount_err;
- }
- break;
- case Opt_handletimeout:
- if (get_option_ul(args, &option)) {
- cifs_dbg(VFS, "%s: Invalid handletimeout value\n",
- __func__);
- goto cifs_parse_mount_err;
- }
- ctx->handle_timeout = option;
- if (ctx->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) {
- cifs_dbg(VFS, "Invalid handle cache timeout, longer than 16 minutes\n");
- goto cifs_parse_mount_err;
- }
- break;
- case Opt_echo_interval:
- if (get_option_ul(args, &option)) {
- cifs_dbg(VFS, "%s: Invalid echo interval value\n",
- __func__);
- goto cifs_parse_mount_err;
- }
- ctx->echo_interval = option;
- break;
- case Opt_snapshot:
- if (get_option_ul(args, &option)) {
- cifs_dbg(VFS, "%s: Invalid snapshot time\n",
- __func__);
- goto cifs_parse_mount_err;
- }
- ctx->snapshot_time = option;
- break;
- case Opt_max_credits:
- if (get_option_ul(args, &option) || (option < 20) ||
- (option > 60000)) {
- cifs_dbg(VFS, "%s: Invalid max_credits value\n",
- __func__);
- goto cifs_parse_mount_err;
- }
- ctx->max_credits = option;
- break;
- case Opt_max_channels:
- if (get_option_ul(args, &option) || option < 1 ||
- option > CIFS_MAX_CHANNELS) {
- cifs_dbg(VFS, "%s: Invalid max_channels value, needs to be 1-%d\n",
- __func__, CIFS_MAX_CHANNELS);
- goto cifs_parse_mount_err;
- }
- ctx->max_channels = option;
- break;
-
- /* String Arguments */
-
- case Opt_blank_user:
- /* null user, ie. anonymous authentication */
- ctx->nullauth = 1;
- ctx->username = NULL;
- break;
- case Opt_user:
- string = match_strdup(args);
- if (string == NULL)
- goto out_nomem;
-
- if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
- CIFS_MAX_USERNAME_LEN) {
- pr_warn("username too long\n");
- goto cifs_parse_mount_err;
- }
-
- kfree(ctx->username);
- ctx->username = kstrdup(string, GFP_KERNEL);
- if (!ctx->username)
- goto cifs_parse_mount_err;
- break;
- case Opt_blank_pass:
- /* passwords have to be handled differently
- * to allow the character used for deliminator
- * to be passed within them
- */
-
- /*
- * Check if this is a case where the password
- * starts with a delimiter
- */
- tmp_end = strchr(data, '=');
- tmp_end++;
- if (!(tmp_end < end && tmp_end[1] == delim)) {
- /* No it is not. Set the password to NULL */
- kfree_sensitive(ctx->password);
- ctx->password = NULL;
- break;
- }
- fallthrough; /* to Opt_pass below */
- case Opt_pass:
- /* Obtain the value string */
- value = strchr(data, '=');
- value++;
-
- /* Set tmp_end to end of the string */
- tmp_end = (char *) value + strlen(value);
-
- /* Check if following character is the deliminator
- * If yes, we have encountered a double deliminator
- * reset the NULL character to the deliminator
- */
- if (tmp_end < end && tmp_end[1] == delim) {
- tmp_end[0] = delim;
-
- /* Keep iterating until we get to a single
- * deliminator OR the end
- */
- while ((tmp_end = strchr(tmp_end, delim))
- != NULL && (tmp_end[1] == delim)) {
- tmp_end = (char *) &tmp_end[2];
- }
-
- /* Reset var options to point to next element */
- if (tmp_end) {
- tmp_end[0] = '\0';
- options = (char *) &tmp_end[1];
- } else
- /* Reached the end of the mount option
- * string */
- options = end;
- }
-
- kfree_sensitive(ctx->password);
- /* Now build new password string */
- temp_len = strlen(value);
- ctx->password = kzalloc(temp_len+1, GFP_KERNEL);
- if (ctx->password == NULL) {
- pr_warn("no memory for password\n");
- goto cifs_parse_mount_err;
- }
-
- for (i = 0, j = 0; i < temp_len; i++, j++) {
- ctx->password[j] = value[i];
- if ((value[i] == delim) &&
- value[i+1] == delim)
- /* skip the second deliminator */
- i++;
- }
- ctx->password[j] = '\0';
- break;
- case Opt_blank_ip:
- /* FIXME: should this be an error instead? */
- got_ip = false;
- break;
- case Opt_ip:
- string = match_strdup(args);
- if (string == NULL)
- goto out_nomem;
-
- if (!cifs_convert_address(dstaddr, string,
- strlen(string))) {
- pr_err("bad ip= option (%s)\n", string);
- goto cifs_parse_mount_err;
- }
- got_ip = true;
- break;
- case Opt_domain:
- string = match_strdup(args);
- if (string == NULL)
- goto out_nomem;
-
- if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
- == CIFS_MAX_DOMAINNAME_LEN) {
- pr_warn("domain name too long\n");
- goto cifs_parse_mount_err;
- }
-
- kfree(ctx->domainname);
- ctx->domainname = kstrdup(string, GFP_KERNEL);
- if (!ctx->domainname) {
- pr_warn("no memory for domainname\n");
- goto cifs_parse_mount_err;
- }
- cifs_dbg(FYI, "Domain name set\n");
- break;
- case Opt_srcaddr:
- string = match_strdup(args);
- if (string == NULL)
- goto out_nomem;
-
- if (!cifs_convert_address(
- (struct