* [PATCH v6 24/27] NFS: Convert mount option parsing to use functionality from fs_parser.h
From: Scott Mayhew @ 2019-12-10 12:31 UTC (permalink / raw)
To: anna.schumaker, trond.myklebust
Cc: dhowells, viro, linux-nfs, linux-fsdevel, linux-kernel,
linux-security-module
In-Reply-To: <20191210123115.1655-1-smayhew@redhat.com>
Split out from commit "NFS: Add fs_context support."
Convert existing mount option definitions to fs_parameter_enum's and
fs_parameter_spec's. Parse mount options using fs_parse() and
lookup_constant().
Notes:
1) Fixed a typo in the udp6 definition in nfs_xprt_protocol_tokens
from the original commit.
2) fs_parse() expects an fs_context as the first arg so that any
errors can be logged to the fs_context. We're passing NULL for the
fs_context (this will change in commit "NFS: Add fs_context support.")
which is okay as it will cause logfc() to do a printk() instead.
3) fs_parse() expects an fs_paramter as the third arg. We're
building an fs_parameter manually in nfs_fs_context_parse_option(),
which will go away in commit "NFS: Add fs_context support.".
Signed-off-by: Scott Mayhew <smayhew@redhat.com>
---
fs/nfs/fs_context.c | 787 ++++++++++++++++++++------------------------
1 file changed, 364 insertions(+), 423 deletions(-)
diff --git a/fs/nfs/fs_context.c b/fs/nfs/fs_context.c
index 44531443a92b..9a3162055d5d 100644
--- a/fs/nfs/fs_context.c
+++ b/fs/nfs/fs_context.c
@@ -11,7 +11,8 @@
#include <linux/module.h>
#include <linux/fs.h>
-#include <linux/parser.h>
+#include <linux/fs_context.h>
+#include <linux/fs_parser.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_mount.h>
#include <linux/nfs4_mount.h>
@@ -28,218 +29,215 @@
#define NFS_MAX_CONNECTIONS 16
-enum {
- /* Mount options that take no arguments */
- Opt_soft, Opt_softerr, Opt_hard,
- Opt_posix, Opt_noposix,
- Opt_cto, Opt_nocto,
- Opt_ac, Opt_noac,
- Opt_lock, Opt_nolock,
- Opt_udp, Opt_tcp, Opt_rdma,
- Opt_acl, Opt_noacl,
- Opt_rdirplus, Opt_nordirplus,
- Opt_sharecache, Opt_nosharecache,
- Opt_resvport, Opt_noresvport,
- Opt_fscache, Opt_nofscache,
- Opt_migration, Opt_nomigration,
-
- /* Mount options that take integer arguments */
- Opt_port,
- Opt_rsize, Opt_wsize, Opt_bsize,
- Opt_timeo, Opt_retrans,
- Opt_acregmin, Opt_acregmax,
- Opt_acdirmin, Opt_acdirmax,
+enum nfs_param {
+ Opt_ac,
+ Opt_acdirmax,
+ Opt_acdirmin,
+ Opt_acl,
+ Opt_acregmax,
+ Opt_acregmin,
Opt_actimeo,
- Opt_namelen,
+ Opt_addr,
+ Opt_bg,
+ Opt_bsize,
+ Opt_clientaddr,
+ Opt_cto,
+ Opt_fg,
+ Opt_fscache,
+ Opt_hard,
+ Opt_intr,
+ Opt_local_lock,
+ Opt_lock,
+ Opt_lookupcache,
+ Opt_migration,
+ Opt_minorversion,
+ Opt_mountaddr,
+ Opt_mounthost,
Opt_mountport,
+ Opt_mountproto,
Opt_mountvers,
- Opt_minorversion,
-
- /* Mount options that take string arguments */
- Opt_nfsvers,
- Opt_sec, Opt_proto, Opt_mountproto, Opt_mounthost,
- Opt_addr, Opt_mountaddr, Opt_clientaddr,
+ Opt_namelen,
Opt_nconnect,
- Opt_lookupcache,
- Opt_fscache_uniq,
- Opt_local_lock,
-
- /* Special mount options */
- Opt_userspace, Opt_deprecated, Opt_sloppy,
-
- Opt_err
+ Opt_port,
+ Opt_posix,
+ Opt_proto,
+ Opt_rdirplus,
+ Opt_rdma,
+ Opt_resvport,
+ Opt_retrans,
+ Opt_retry,
+ Opt_rsize,
+ Opt_sec,
+ Opt_sharecache,
+ Opt_sloppy,
+ Opt_soft,
+ Opt_softerr,
+ Opt_source,
+ Opt_tcp,
+ Opt_timeo,
+ Opt_udp,
+ Opt_v,
+ Opt_vers,
+ Opt_wsize,
};
-static const match_table_t nfs_mount_option_tokens = {
- { Opt_userspace, "bg" },
- { Opt_userspace, "fg" },
- { Opt_userspace, "retry=%s" },
-
- { Opt_sloppy, "sloppy" },
-
- { Opt_soft, "soft" },
- { Opt_softerr, "softerr" },
- { Opt_hard, "hard" },
- { Opt_deprecated, "intr" },
- { Opt_deprecated, "nointr" },
- { Opt_posix, "posix" },
- { Opt_noposix, "noposix" },
- { Opt_cto, "cto" },
- { Opt_nocto, "nocto" },
- { Opt_ac, "ac" },
- { Opt_noac, "noac" },
- { Opt_lock, "lock" },
- { Opt_nolock, "nolock" },
- { Opt_udp, "udp" },
- { Opt_tcp, "tcp" },
- { Opt_rdma, "rdma" },
- { Opt_acl, "acl" },
- { Opt_noacl, "noacl" },
- { Opt_rdirplus, "rdirplus" },
- { Opt_nordirplus, "nordirplus" },
- { Opt_sharecache, "sharecache" },
- { Opt_nosharecache, "nosharecache" },
- { Opt_resvport, "resvport" },
- { Opt_noresvport, "noresvport" },
- { Opt_fscache, "fsc" },
- { Opt_nofscache, "nofsc" },
- { Opt_migration, "migration" },
- { Opt_nomigration, "nomigration" },
-
- { Opt_port, "port=%s" },
- { Opt_rsize, "rsize=%s" },
- { Opt_wsize, "wsize=%s" },
- { Opt_bsize, "bsize=%s" },
- { Opt_timeo, "timeo=%s" },
- { Opt_retrans, "retrans=%s" },
- { Opt_acregmin, "acregmin=%s" },
- { Opt_acregmax, "acregmax=%s" },
- { Opt_acdirmin, "acdirmin=%s" },
- { Opt_acdirmax, "acdirmax=%s" },
- { Opt_actimeo, "actimeo=%s" },
- { Opt_namelen, "namlen=%s" },
- { Opt_mountport, "mountport=%s" },
- { Opt_mountvers, "mountvers=%s" },
- { Opt_minorversion, "minorversion=%s" },
-
- { Opt_nfsvers, "nfsvers=%s" },
- { Opt_nfsvers, "vers=%s" },
-
- { Opt_sec, "sec=%s" },
- { Opt_proto, "proto=%s" },
- { Opt_mountproto, "mountproto=%s" },
- { Opt_addr, "addr=%s" },
- { Opt_clientaddr, "clientaddr=%s" },
- { Opt_mounthost, "mounthost=%s" },
- { Opt_mountaddr, "mountaddr=%s" },
-
- { Opt_nconnect, "nconnect=%s" },
-
- { Opt_lookupcache, "lookupcache=%s" },
- { Opt_fscache_uniq, "fsc=%s" },
- { Opt_local_lock, "local_lock=%s" },
-
- /* The following needs to be listed after all other options */
- { Opt_nfsvers, "v%s" },
-
- { Opt_err, NULL }
+static const struct fs_parameter_spec nfs_param_specs[] = {
+ fsparam_flag_no("ac", Opt_ac),
+ fsparam_u32 ("acdirmax", Opt_acdirmax),
+ fsparam_u32 ("acdirmin", Opt_acdirmin),
+ fsparam_flag_no("acl", Opt_acl),
+ fsparam_u32 ("acregmax", Opt_acregmax),
+ fsparam_u32 ("acregmin", Opt_acregmin),
+ fsparam_u32 ("actimeo", Opt_actimeo),
+ fsparam_string("addr", Opt_addr),
+ fsparam_flag ("bg", Opt_bg),
+ fsparam_u32 ("bsize", Opt_bsize),
+ fsparam_string("clientaddr", Opt_clientaddr),
+ fsparam_flag_no("cto", Opt_cto),
+ fsparam_flag ("fg", Opt_fg),
+ __fsparam(fs_param_is_string, "fsc", Opt_fscache,
+ fs_param_neg_with_no|fs_param_v_optional),
+ fsparam_flag ("hard", Opt_hard),
+ __fsparam(fs_param_is_flag, "intr", Opt_intr,
+ fs_param_neg_with_no|fs_param_deprecated),
+ fsparam_enum ("local_lock", Opt_local_lock),
+ fsparam_flag_no("lock", Opt_lock),
+ fsparam_enum ("lookupcache", Opt_lookupcache),
+ fsparam_flag_no("migration", Opt_migration),
+ fsparam_u32 ("minorversion", Opt_minorversion),
+ fsparam_string("mountaddr", Opt_mountaddr),
+ fsparam_string("mounthost", Opt_mounthost),
+ fsparam_u32 ("mountport", Opt_mountport),
+ fsparam_string("mountproto", Opt_mountproto),
+ fsparam_u32 ("mountvers", Opt_mountvers),
+ fsparam_u32 ("namlen", Opt_namelen),
+ fsparam_u32 ("nconnect", Opt_nconnect),
+ fsparam_string("nfsvers", Opt_vers),
+ fsparam_u32 ("port", Opt_port),
+ fsparam_flag_no("posix", Opt_posix),
+ fsparam_string("proto", Opt_proto),
+ fsparam_flag_no("rdirplus", Opt_rdirplus),
+ fsparam_flag ("rdma", Opt_rdma),
+ fsparam_flag_no("resvport", Opt_resvport),
+ fsparam_u32 ("retrans", Opt_retrans),
+ fsparam_string("retry", Opt_retry),
+ fsparam_u32 ("rsize", Opt_rsize),
+ fsparam_string("sec", Opt_sec),
+ fsparam_flag_no("sharecache", Opt_sharecache),
+ fsparam_flag ("sloppy", Opt_sloppy),
+ fsparam_flag ("soft", Opt_soft),
+ fsparam_flag ("softerr", Opt_softerr),
+ fsparam_string("source", Opt_source),
+ fsparam_flag ("tcp", Opt_tcp),
+ fsparam_u32 ("timeo", Opt_timeo),
+ fsparam_flag ("udp", Opt_udp),
+ fsparam_flag ("v2", Opt_v),
+ fsparam_flag ("v3", Opt_v),
+ fsparam_flag ("v4", Opt_v),
+ fsparam_flag ("v4.0", Opt_v),
+ fsparam_flag ("v4.1", Opt_v),
+ fsparam_flag ("v4.2", Opt_v),
+ fsparam_string("vers", Opt_vers),
+ fsparam_u32 ("wsize", Opt_wsize),
+ {}
};
enum {
- Opt_xprt_udp, Opt_xprt_udp6, Opt_xprt_tcp, Opt_xprt_tcp6, Opt_xprt_rdma,
- Opt_xprt_rdma6,
-
- Opt_xprt_err
-};
-
-static const match_table_t nfs_xprt_protocol_tokens = {
- { Opt_xprt_udp, "udp" },
- { Opt_xprt_udp6, "udp6" },
- { Opt_xprt_tcp, "tcp" },
- { Opt_xprt_tcp6, "tcp6" },
- { Opt_xprt_rdma, "rdma" },
- { Opt_xprt_rdma6, "rdma6" },
-
- { Opt_xprt_err, NULL }
+ Opt_local_lock_all,
+ Opt_local_lock_flock,
+ Opt_local_lock_none,
+ Opt_local_lock_posix,
};
enum {
- Opt_sec_none, Opt_sec_sys,
- Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
- Opt_sec_lkey, Opt_sec_lkeyi, Opt_sec_lkeyp,
- Opt_sec_spkm, Opt_sec_spkmi, Opt_sec_spkmp,
-
- Opt_sec_err
+ Opt_lookupcache_all,
+ Opt_lookupcache_none,
+ Opt_lookupcache_positive,
};
-static const match_table_t nfs_secflavor_tokens = {
- { Opt_sec_none, "none" },
- { Opt_sec_none, "null" },
- { Opt_sec_sys, "sys" },
-
- { Opt_sec_krb5, "krb5" },
- { Opt_sec_krb5i, "krb5i" },
- { Opt_sec_krb5p, "krb5p" },
-
- { Opt_sec_lkey, "lkey" },
- { Opt_sec_lkeyi, "lkeyi" },
- { Opt_sec_lkeyp, "lkeyp" },
-
- { Opt_sec_spkm, "spkm3" },
- { Opt_sec_spkmi, "spkm3i" },
- { Opt_sec_spkmp, "spkm3p" },
+static const struct fs_parameter_enum nfs_param_enums[] = {
+ { Opt_local_lock, "all", Opt_local_lock_all },
+ { Opt_local_lock, "flock", Opt_local_lock_flock },
+ { Opt_local_lock, "none", Opt_local_lock_none },
+ { Opt_local_lock, "posix", Opt_local_lock_posix },
+ { Opt_lookupcache, "all", Opt_lookupcache_all },
+ { Opt_lookupcache, "none", Opt_lookupcache_none },
+ { Opt_lookupcache, "pos", Opt_lookupcache_positive },
+ { Opt_lookupcache, "positive", Opt_lookupcache_positive },
+ {}
+};
- { Opt_sec_err, NULL }
+static const struct fs_parameter_description nfs_fs_parameters = {
+ .name = "nfs",
+ .specs = nfs_param_specs,
+ .enums = nfs_param_enums,
};
enum {
- Opt_lookupcache_all, Opt_lookupcache_positive,
- Opt_lookupcache_none,
-
- Opt_lookupcache_err
+ Opt_vers_2,
+ Opt_vers_3,
+ Opt_vers_4,
+ Opt_vers_4_0,
+ Opt_vers_4_1,
+ Opt_vers_4_2,
};
-static const match_table_t nfs_lookupcache_tokens = {
- { Opt_lookupcache_all, "all" },
- { Opt_lookupcache_positive, "pos" },
- { Opt_lookupcache_positive, "positive" },
- { Opt_lookupcache_none, "none" },
-
- { Opt_lookupcache_err, NULL }
+static const struct constant_table nfs_vers_tokens[] = {
+ { "2", Opt_vers_2 },
+ { "3", Opt_vers_3 },
+ { "4", Opt_vers_4 },
+ { "4.0", Opt_vers_4_0 },
+ { "4.1", Opt_vers_4_1 },
+ { "4.2", Opt_vers_4_2 },
};
enum {
- Opt_local_lock_all, Opt_local_lock_flock, Opt_local_lock_posix,
- Opt_local_lock_none,
-
- Opt_local_lock_err
+ Opt_xprt_rdma,
+ Opt_xprt_rdma6,
+ Opt_xprt_tcp,
+ Opt_xprt_tcp6,
+ Opt_xprt_udp,
+ Opt_xprt_udp6,
+ nr__Opt_xprt
};
-static const match_table_t nfs_local_lock_tokens = {
- { Opt_local_lock_all, "all" },
- { Opt_local_lock_flock, "flock" },
- { Opt_local_lock_posix, "posix" },
- { Opt_local_lock_none, "none" },
-
- { Opt_local_lock_err, NULL }
+static const struct constant_table nfs_xprt_protocol_tokens[nr__Opt_xprt] = {
+ { "rdma", Opt_xprt_rdma },
+ { "rdma6", Opt_xprt_rdma6 },
+ { "tcp", Opt_xprt_tcp },
+ { "tcp6", Opt_xprt_tcp6 },
+ { "udp", Opt_xprt_udp },
+ { "udp6", Opt_xprt_udp6 },
};
enum {
- Opt_vers_2, Opt_vers_3, Opt_vers_4, Opt_vers_4_0,
- Opt_vers_4_1, Opt_vers_4_2,
-
- Opt_vers_err
+ Opt_sec_krb5,
+ Opt_sec_krb5i,
+ Opt_sec_krb5p,
+ Opt_sec_lkey,
+ Opt_sec_lkeyi,
+ Opt_sec_lkeyp,
+ Opt_sec_none,
+ Opt_sec_spkm,
+ Opt_sec_spkmi,
+ Opt_sec_spkmp,
+ Opt_sec_sys,
+ nr__Opt_sec
};
-static const match_table_t nfs_vers_tokens = {
- { Opt_vers_2, "2" },
- { Opt_vers_3, "3" },
- { Opt_vers_4, "4" },
- { Opt_vers_4_0, "4.0" },
- { Opt_vers_4_1, "4.1" },
- { Opt_vers_4_2, "4.2" },
-
- { Opt_vers_err, NULL }
+static const struct constant_table nfs_secflavor_tokens[] = {
+ { "krb5", Opt_sec_krb5 },
+ { "krb5i", Opt_sec_krb5i },
+ { "krb5p", Opt_sec_krb5p },
+ { "lkey", Opt_sec_lkey },
+ { "lkeyi", Opt_sec_lkeyi },
+ { "lkeyp", Opt_sec_lkeyp },
+ { "none", Opt_sec_none },
+ { "null", Opt_sec_none },
+ { "spkm3", Opt_sec_spkm },
+ { "spkm3i", Opt_sec_spkmi },
+ { "spkm3p", Opt_sec_spkmp },
+ { "sys", Opt_sec_sys },
};
struct nfs_fs_context *nfs_alloc_parsed_mount_data(void)
@@ -368,17 +366,19 @@ static int nfs_auth_info_add(struct nfs_fs_context *ctx,
/*
* Parse the value of the 'sec=' option.
*/
-static int nfs_parse_security_flavors(struct nfs_fs_context *ctx, char *value)
+static int nfs_parse_security_flavors(struct nfs_fs_context *ctx,
+ struct fs_parameter *param)
{
- substring_t args[MAX_OPT_ARGS];
rpc_authflavor_t pseudoflavor;
- char *p;
+ char *string = param->string, *p;
int ret;
- dfprintk(MOUNT, "NFS: parsing sec=%s option\n", value);
+ dfprintk(MOUNT, "NFS: parsing %s=%s option\n", param->key, param->string);
- while ((p = strsep(&value, ":")) != NULL) {
- switch (match_token(p, nfs_secflavor_tokens, args)) {
+ while ((p = strsep(&string, ":")) != NULL) {
+ if (!*p)
+ continue;
+ switch (lookup_constant(nfs_secflavor_tokens, p, -1)) {
case Opt_sec_none:
pseudoflavor = RPC_AUTH_NULL;
break;
@@ -427,11 +427,10 @@ static int nfs_parse_security_flavors(struct nfs_fs_context *ctx, char *value)
}
static int nfs_parse_version_string(struct nfs_fs_context *ctx,
- char *string,
- substring_t *args)
+ const char *string)
{
ctx->flags &= ~NFS_MOUNT_VER3;
- switch (match_token(string, nfs_vers_tokens, args)) {
+ switch (lookup_constant(nfs_vers_tokens, string, -1)) {
case Opt_vers_2:
ctx->version = 2;
break;
@@ -465,64 +464,24 @@ static int nfs_parse_version_string(struct nfs_fs_context *ctx,
return 0;
}
-static int nfs_get_option_str(substring_t args[], char **option)
-{
- kfree(*option);
- *option = match_strdup(args);
- return !*option;
-}
-
-static int nfs_get_option_ui(struct nfs_fs_context *ctx,
- substring_t args[], unsigned int *option)
-{
- match_strlcpy(ctx->buf, args, sizeof(ctx->buf));
- return kstrtouint(ctx->buf, 10, option);
-}
-
-static int nfs_get_option_ui_bound(struct nfs_fs_context *ctx,
- substring_t args[], unsigned int *option,
- unsigned int l_bound, unsigned u_bound)
-{
- int ret;
-
- match_strlcpy(ctx->buf, args, sizeof(ctx->buf));
- ret = kstrtouint(ctx->buf, 10, option);
- if (ret < 0)
- return ret;
- if (*option < l_bound || *option > u_bound)
- return -ERANGE;
- return 0;
-}
-
-static int nfs_get_option_us_bound(struct nfs_fs_context *ctx,
- substring_t args[], unsigned short *option,
- unsigned short l_bound,
- unsigned short u_bound)
-{
- int ret;
-
- match_strlcpy(ctx->buf, args, sizeof(ctx->buf));
- ret = kstrtou16(ctx->buf, 10, option);
- if (ret < 0)
- return ret;
- if (*option < l_bound || *option > u_bound)
- return -ERANGE;
- return 0;
-}
-
/*
- * Parse a single mount option in "key[=val]" form.
+ * Parse a single mount parameter.
*/
-static int nfs_fs_context_parse_option(struct nfs_fs_context *ctx, char *p)
+static int nfs_fs_context_parse_param(struct nfs_fs_context *ctx,
+ struct fs_parameter *param)
{
- substring_t args[MAX_OPT_ARGS];
- char *string;
- int token, ret;
+ struct fs_parse_result result;
+ unsigned short protofamily, mountfamily;
+ unsigned int len;
+ int ret, opt;
+
+ dfprintk(MOUNT, "NFS: parsing nfs mount option '%s'\n", param->key);
- dfprintk(MOUNT, "NFS: parsing nfs mount option '%s'\n", p);
+ opt = fs_parse(NULL, &nfs_fs_parameters, param, &result);
+ if (opt < 0)
+ return ctx->sloppy ? 1 : opt;
- token = match_token(p, nfs_mount_option_tokens, args);
- switch (token) {
+ switch (opt) {
/*
* boolean options: foo/nofoo
*/
@@ -538,30 +497,31 @@ static int nfs_fs_context_parse_option(struct nfs_fs_context *ctx, char *p)
ctx->flags &= ~(NFS_MOUNT_SOFT|NFS_MOUNT_SOFTERR);
break;
case Opt_posix:
- ctx->flags |= NFS_MOUNT_POSIX;
- break;
- case Opt_noposix:
- ctx->flags &= ~NFS_MOUNT_POSIX;
+ if (result.negated)
+ ctx->flags &= ~NFS_MOUNT_POSIX;
+ else
+ ctx->flags |= NFS_MOUNT_POSIX;
break;
case Opt_cto:
- ctx->flags &= ~NFS_MOUNT_NOCTO;
- break;
- case Opt_nocto:
- ctx->flags |= NFS_MOUNT_NOCTO;
+ if (result.negated)
+ ctx->flags |= NFS_MOUNT_NOCTO;
+ else
+ ctx->flags &= ~NFS_MOUNT_NOCTO;
break;
case Opt_ac:
- ctx->flags &= ~NFS_MOUNT_NOAC;
- break;
- case Opt_noac:
- ctx->flags |= NFS_MOUNT_NOAC;
+ if (result.negated)
+ ctx->flags |= NFS_MOUNT_NOAC;
+ else
+ ctx->flags &= ~NFS_MOUNT_NOAC;
break;
case Opt_lock:
- ctx->flags &= ~NFS_MOUNT_NONLM;
- ctx->flags &= ~(NFS_MOUNT_LOCAL_FLOCK | NFS_MOUNT_LOCAL_FCNTL);
- break;
- case Opt_nolock:
- ctx->flags |= NFS_MOUNT_NONLM;
- ctx->flags |= (NFS_MOUNT_LOCAL_FLOCK | NFS_MOUNT_LOCAL_FCNTL);
+ if (result.negated) {
+ ctx->flags |= NFS_MOUNT_NONLM;
+ ctx->flags |= (NFS_MOUNT_LOCAL_FLOCK | NFS_MOUNT_LOCAL_FCNTL);
+ } else {
+ ctx->flags &= ~NFS_MOUNT_NONLM;
+ ctx->flags &= ~(NFS_MOUNT_LOCAL_FLOCK | NFS_MOUNT_LOCAL_FCNTL);
+ }
break;
case Opt_udp:
ctx->flags &= ~NFS_MOUNT_TCP;
@@ -574,195 +534,177 @@ static int nfs_fs_context_parse_option(struct nfs_fs_context *ctx, char *p)
case Opt_rdma:
ctx->flags |= NFS_MOUNT_TCP; /* for side protocols */
ctx->nfs_server.protocol = XPRT_TRANSPORT_RDMA;
- xprt_load_transport(p);
+ xprt_load_transport(param->key);
break;
case Opt_acl:
- ctx->flags &= ~NFS_MOUNT_NOACL;
- break;
- case Opt_noacl:
- ctx->flags |= NFS_MOUNT_NOACL;
+ if (result.negated)
+ ctx->flags |= NFS_MOUNT_NOACL;
+ else
+ ctx->flags &= ~NFS_MOUNT_NOACL;
break;
case Opt_rdirplus:
- ctx->flags &= ~NFS_MOUNT_NORDIRPLUS;
- break;
- case Opt_nordirplus:
- ctx->flags |= NFS_MOUNT_NORDIRPLUS;
+ if (result.negated)
+ ctx->flags |= NFS_MOUNT_NORDIRPLUS;
+ else
+ ctx->flags &= ~NFS_MOUNT_NORDIRPLUS;
break;
case Opt_sharecache:
- ctx->flags &= ~NFS_MOUNT_UNSHARED;
- break;
- case Opt_nosharecache:
- ctx->flags |= NFS_MOUNT_UNSHARED;
+ if (result.negated)
+ ctx->flags |= NFS_MOUNT_UNSHARED;
+ else
+ ctx->flags &= ~NFS_MOUNT_UNSHARED;
break;
case Opt_resvport:
- ctx->flags &= ~NFS_MOUNT_NORESVPORT;
- break;
- case Opt_noresvport:
- ctx->flags |= NFS_MOUNT_NORESVPORT;
+ if (result.negated)
+ ctx->flags |= NFS_MOUNT_NORESVPORT;
+ else
+ ctx->flags &= ~NFS_MOUNT_NORESVPORT;
break;
case Opt_fscache:
- ctx->options |= NFS_OPTION_FSCACHE;
kfree(ctx->fscache_uniq);
- ctx->fscache_uniq = NULL;
- break;
- case Opt_nofscache:
- ctx->options &= ~NFS_OPTION_FSCACHE;
- kfree(ctx->fscache_uniq);
- ctx->fscache_uniq = NULL;
+ ctx->fscache_uniq = param->string;
+ param->string = NULL;
+ if (result.negated)
+ ctx->options &= ~NFS_OPTION_FSCACHE;
+ else
+ ctx->options |= NFS_OPTION_FSCACHE;
break;
case Opt_migration:
- ctx->options |= NFS_OPTION_MIGRATION;
- break;
- case Opt_nomigration:
- ctx->options &= ~NFS_OPTION_MIGRATION;
+ if (result.negated)
+ ctx->options &= ~NFS_OPTION_MIGRATION;
+ else
+ ctx->options |= NFS_OPTION_MIGRATION;
break;
/*
* options that take numeric values
*/
case Opt_port:
- if (nfs_get_option_ui_bound(ctx, args, &ctx->nfs_server.port,
- 0, USHRT_MAX))
- goto out_invalid_value;
+ if (result.uint_32 > USHRT_MAX)
+ goto out_of_bounds;
+ ctx->nfs_server.port = result.uint_32;
break;
case Opt_rsize:
- if (nfs_get_option_ui(ctx, args, &ctx->rsize))
- goto out_invalid_value;
+ ctx->rsize = result.uint_32;
break;
case Opt_wsize:
- if (nfs_get_option_ui(ctx, args, &ctx->wsize))
- goto out_invalid_value;
+ ctx->wsize = result.uint_32;
break;
case Opt_bsize:
- if (nfs_get_option_ui(ctx, args, &ctx->bsize))
- goto out_invalid_value;
+ ctx->bsize = result.uint_32;
break;
case Opt_timeo:
- if (nfs_get_option_ui_bound(ctx, args, &ctx->timeo, 1, INT_MAX))
- goto out_invalid_value;
+ if (result.uint_32 < 1 || result.uint_32 > INT_MAX)
+ goto out_of_bounds;
+ ctx->timeo = result.uint_32;
break;
case Opt_retrans:
- if (nfs_get_option_ui_bound(ctx, args, &ctx->retrans, 0, INT_MAX))
- goto out_invalid_value;
+ if (result.uint_32 > INT_MAX)
+ goto out_of_bounds;
+ ctx->retrans = result.uint_32;
break;
case Opt_acregmin:
- if (nfs_get_option_ui(ctx, args, &ctx->acregmin))
- goto out_invalid_value;
+ ctx->acregmin = result.uint_32;
break;
case Opt_acregmax:
- if (nfs_get_option_ui(ctx, args, &ctx->acregmax))
- goto out_invalid_value;
+ ctx->acregmax = result.uint_32;
break;
case Opt_acdirmin:
- if (nfs_get_option_ui(ctx, args, &ctx->acdirmin))
- goto out_invalid_value;
+ ctx->acdirmin = result.uint_32;
break;
case Opt_acdirmax:
- if (nfs_get_option_ui(ctx, args, &ctx->acdirmax))
- goto out_invalid_value;
+ ctx->acdirmax = result.uint_32;
break;
case Opt_actimeo:
- if (nfs_get_option_ui(ctx, args, &ctx->acdirmax))
- goto out_invalid_value;
- ctx->acregmin = ctx->acregmax =
- ctx->acdirmin = ctx->acdirmax;
+ ctx->acregmin = result.uint_32;
+ ctx->acregmax = result.uint_32;
+ ctx->acdirmin = result.uint_32;
+ ctx->acdirmax = result.uint_32;
break;
case Opt_namelen:
- if (nfs_get_option_ui(ctx, args, &ctx->namlen))
- goto out_invalid_value;
+ ctx->namlen = result.uint_32;
break;
case Opt_mountport:
- if (nfs_get_option_ui_bound(ctx, args, &ctx->mount_server.port,
- 0, USHRT_MAX))
- goto out_invalid_value;
+ if (result.uint_32 > USHRT_MAX)
+ goto out_of_bounds;
+ ctx->mount_server.port = result.uint_32;
break;
case Opt_mountvers:
- if (nfs_get_option_ui_bound(ctx, args, &ctx->mount_server.version,
- NFS_MNT_VERSION, NFS_MNT3_VERSION))
- goto out_invalid_value;
+ if (result.uint_32 < NFS_MNT_VERSION ||
+ result.uint_32 > NFS_MNT3_VERSION)
+ goto out_of_bounds;
+ ctx->mount_server.version = result.uint_32;
break;
case Opt_minorversion:
- if (nfs_get_option_ui_bound(ctx, args, &ctx->minorversion,
- 0, NFS4_MAX_MINOR_VERSION))
- goto out_invalid_value;
+ if (result.uint_32 > NFS4_MAX_MINOR_VERSION)
+ goto out_of_bounds;
+ ctx->minorversion = result.uint_32;
break;
/*
* options that take text values
*/
- case Opt_nfsvers:
- string = match_strdup(args);
- if (string == NULL)
- goto out_nomem;
- ret = nfs_parse_version_string(ctx, string, args);
- kfree(string);
+ case Opt_v:
+ ret = nfs_parse_version_string(ctx, param->key + 1);
+ if (ret < 0)
+ return ret;
+ break;
+ case Opt_vers:
+ ret = nfs_parse_version_string(ctx, param->string);
if (ret < 0)
return ret;
break;
case Opt_sec:
- string = match_strdup(args);
- if (string == NULL)
- goto out_nomem;
- ret = nfs_parse_security_flavors(ctx, string);
- kfree(string);
+ ret = nfs_parse_security_flavors(ctx, param);
if (ret < 0)
return ret;
break;
- case Opt_proto:
- string = match_strdup(args);
- if (string == NULL)
- goto out_nomem;
- token = match_token(string, nfs_xprt_protocol_tokens, args);
- ctx->protofamily = AF_INET;
- switch (token) {
+ case Opt_proto:
+ protofamily = AF_INET;
+ switch (lookup_constant(nfs_xprt_protocol_tokens, param->string, -1)) {
case Opt_xprt_udp6:
- ctx->protofamily = AF_INET6;
+ protofamily = AF_INET6;
/* fall through */
case Opt_xprt_udp:
ctx->flags &= ~NFS_MOUNT_TCP;
ctx->nfs_server.protocol = XPRT_TRANSPORT_UDP;
break;
case Opt_xprt_tcp6:
- ctx->protofamily = AF_INET6;
+ protofamily = AF_INET6;
/* fall through */
case Opt_xprt_tcp:
ctx->flags |= NFS_MOUNT_TCP;
ctx->nfs_server.protocol = XPRT_TRANSPORT_TCP;
break;
case Opt_xprt_rdma6:
- ctx->protofamily = AF_INET6;
+ protofamily = AF_INET6;
/* fall through */
case Opt_xprt_rdma:
/* vector side protocols to TCP */
ctx->flags |= NFS_MOUNT_TCP;
ctx->nfs_server.protocol = XPRT_TRANSPORT_RDMA;
- xprt_load_transport(string);
+ xprt_load_transport(param->string);
break;
default:
- kfree(string);
dfprintk(MOUNT, "NFS: unrecognized transport protocol\n");
return -EINVAL;
}
- kfree(string);
+
+ ctx->protofamily = protofamily;
break;
- case Opt_mountproto:
- string = match_strdup(args);
- if (string == NULL)
- goto out_nomem;
- token = match_token(string, nfs_xprt_protocol_tokens, args);
- kfree(string);
- ctx->mountfamily = AF_INET;
- switch (token) {
+ case Opt_mountproto:
+ mountfamily = AF_INET;
+ switch (lookup_constant(nfs_xprt_protocol_tokens, param->string, -1)) {
case Opt_xprt_udp6:
- ctx->mountfamily = AF_INET6;
+ mountfamily = AF_INET6;
/* fall through */
case Opt_xprt_udp:
ctx->mount_server.protocol = XPRT_TRANSPORT_UDP;
break;
case Opt_xprt_tcp6:
- ctx->mountfamily = AF_INET6;
+ mountfamily = AF_INET6;
/* fall through */
case Opt_xprt_tcp:
ctx->mount_server.protocol = XPRT_TRANSPORT_TCP;
@@ -772,51 +714,42 @@ static int nfs_fs_context_parse_option(struct nfs_fs_context *ctx, char *p)
dfprintk(MOUNT, "NFS: unrecognized transport protocol\n");
return -EINVAL;
}
+ ctx->mountfamily = mountfamily;
break;
+
case Opt_addr:
- string = match_strdup(args);
- if (string == NULL)
- goto out_nomem;
- ctx->nfs_server.addrlen =
- rpc_pton(ctx->net, string, strlen(string),
- &ctx->nfs_server.address,
- sizeof(ctx->nfs_server._address));
- kfree(string);
- if (ctx->nfs_server.addrlen == 0)
+ len = rpc_pton(ctx->net, param->string, param->size,
+ &ctx->nfs_server.address,
+ sizeof(ctx->nfs_server._address));
+ if (len == 0)
goto out_invalid_address;
+ ctx->nfs_server.addrlen = len;
break;
case Opt_clientaddr:
- if (nfs_get_option_str(args, &ctx->client_address))
- goto out_nomem;
+ kfree(ctx->client_address);
+ ctx->client_address = param->string;
+ param->string = NULL;
break;
case Opt_mounthost:
- if (nfs_get_option_str(args, &ctx->mount_server.hostname))
- goto out_nomem;
+ kfree(ctx->mount_server.hostname);
+ ctx->mount_server.hostname = param->string;
+ param->string = NULL;
break;
case Opt_mountaddr:
- string = match_strdup(args);
- if (string == NULL)
- goto out_nomem;
- ctx->mount_server.addrlen =
- rpc_pton(ctx->net, string, strlen(string),
- &ctx->mount_server.address,
- sizeof(ctx->mount_server._address));
- kfree(string);
- if (ctx->mount_server.addrlen == 0)
+ len = rpc_pton(ctx->net, param->string, param->size,
+ &ctx->mount_server.address,
+ sizeof(ctx->mount_server._address));
+ if (len == 0)
goto out_invalid_address;
+ ctx->mount_server.addrlen = len;
break;
case Opt_nconnect:
- if (nfs_get_option_us_bound(ctx, args, &ctx->nfs_server.nconnect,
- 1, NFS_MAX_CONNECTIONS))
- goto out_invalid_value;
+ if (result.uint_32 < 1 || result.uint_32 > NFS_MAX_CONNECTIONS)
+ goto out_of_bounds;
+ ctx->nfs_server.nconnect = result.uint_32;
break;
case Opt_lookupcache:
- string = match_strdup(args);
- if (string == NULL)
- goto out_nomem;
- token = match_token(string, nfs_lookupcache_tokens, args);
- kfree(string);
- switch (token) {
+ switch (result.uint_32) {
case Opt_lookupcache_all:
ctx->flags &= ~(NFS_MOUNT_LOOKUP_CACHE_NONEG|NFS_MOUNT_LOOKUP_CACHE_NONE);
break;
@@ -828,22 +761,11 @@ static int nfs_fs_context_parse_option(struct nfs_fs_context *ctx, char *p)
ctx->flags |= NFS_MOUNT_LOOKUP_CACHE_NONEG|NFS_MOUNT_LOOKUP_CACHE_NONE;
break;
default:
- dfprintk(MOUNT, "NFS: invalid lookupcache argument\n");
- return -EINVAL;
+ goto out_invalid_value;
}
break;
- case Opt_fscache_uniq:
- if (nfs_get_option_str(args, &ctx->fscache_uniq))
- goto out_nomem;
- ctx->options |= NFS_OPTION_FSCACHE;
- break;
case Opt_local_lock:
- string = match_strdup(args);
- if (string == NULL)
- goto out_nomem;
- token = match_token(string, nfs_local_lock_tokens, args);
- kfree(string);
- switch (token) {
+ switch (result.uint_32) {
case Opt_local_lock_all:
ctx->flags |= (NFS_MOUNT_LOCAL_FLOCK |
NFS_MOUNT_LOCAL_FCNTL);
@@ -859,8 +781,7 @@ static int nfs_fs_context_parse_option(struct nfs_fs_context *ctx, char *p)
NFS_MOUNT_LOCAL_FCNTL);
break;
default:
- dfprintk(MOUNT, "NFS: invalid local_lock argument\n");
- return -EINVAL;
+ goto out_invalid_value;
}
break;
@@ -868,30 +789,50 @@ static int nfs_fs_context_parse_option(struct nfs_fs_context *ctx, char *p)
* Special options
*/
case Opt_sloppy:
- ctx->sloppy = 1;
+ ctx->sloppy = true;
dfprintk(MOUNT, "NFS: relaxing parsing rules\n");
break;
- case Opt_userspace:
- case Opt_deprecated:
- dfprintk(MOUNT, "NFS: ignoring mount option '%s'\n", p);
- break;
-
- default:
- dfprintk(MOUNT, "NFS: unrecognized mount option '%s'\n", p);
- return -EINVAL;
}
return 0;
-out_invalid_address:
- printk(KERN_INFO "NFS: bad IP address specified: %s\n", p);
- return -EINVAL;
out_invalid_value:
- printk(KERN_INFO "NFS: bad mount option value specified: %s\n", p);
+ printk(KERN_INFO "NFS: Bad mount option value specified\n");
return -EINVAL;
-out_nomem:
- printk(KERN_INFO "NFS: not enough memory to parse option\n");
- return -ENOMEM;
+out_invalid_address:
+ printk(KERN_INFO "NFS: Bad IP address specified\n");
+ return -EINVAL;
+out_of_bounds:
+ printk(KERN_INFO "NFS: Value for '%s' out of range\n", param->key);
+ return -ERANGE;
+}
+
+/* cribbed from generic_parse_monolithic and vfs_parse_fs_string */
+static int nfs_fs_context_parse_option(struct nfs_fs_context *ctx, char *p)
+{
+ int ret;
+ char *key = p, *value;
+ size_t v_size = 0;
+ struct fs_parameter param;
+
+ memset(¶m, 0, sizeof(param));
+ value = strchr(key, '=');
+ if (value && value != key) {
+ *value++ = 0;
+ v_size = strlen(value);
+ }
+ param.key = key;
+ param.type = fs_value_is_flag;
+ param.size = v_size;
+ if (v_size > 0) {
+ param.type = fs_value_is_string;
+ param.string = kmemdup_nul(value, v_size, GFP_KERNEL);
+ if (!param.string)
+ return -ENOMEM;
+ }
+ ret = nfs_fs_context_parse_param(ctx, ¶m);
+ kfree(param.string);
+ return ret;
}
/*
--
2.17.2
^ permalink raw reply related
* [PATCH v6 20/27] NFS: Deindent nfs_fs_context_parse_option()
From: Scott Mayhew @ 2019-12-10 12:31 UTC (permalink / raw)
To: anna.schumaker, trond.myklebust
Cc: dhowells, viro, linux-nfs, linux-fsdevel, linux-kernel,
linux-security-module
In-Reply-To: <20191210123115.1655-1-smayhew@redhat.com>
From: David Howells <dhowells@redhat.com>
Deindent nfs_fs_context_parse_option().
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/nfs/fs_context.c | 739 ++++++++++++++++++++++----------------------
1 file changed, 367 insertions(+), 372 deletions(-)
diff --git a/fs/nfs/fs_context.c b/fs/nfs/fs_context.c
index a386825c3b0f..92a1e4bd9133 100644
--- a/fs/nfs/fs_context.c
+++ b/fs/nfs/fs_context.c
@@ -500,410 +500,405 @@ static int nfs_get_option_ul_bound(substring_t args[], unsigned long *option,
*/
static int nfs_fs_context_parse_option(struct nfs_fs_context *ctx, char *p)
{
+ substring_t args[MAX_OPT_ARGS];
+ unsigned long option;
char *string;
- int rc;
-
- {
- substring_t args[MAX_OPT_ARGS];
- unsigned long option;
- int token;
+ int token, rc;
- dfprintk(MOUNT, "NFS: parsing nfs mount option '%s'\n", p);
-
- token = match_token(p, nfs_mount_option_tokens, args);
- switch (token) {
+ dfprintk(MOUNT, "NFS: parsing nfs mount option '%s'\n", p);
+ token = match_token(p, nfs_mount_option_tokens, args);
+ switch (token) {
/*
* boolean options: foo/nofoo
*/
- case Opt_soft:
- ctx->flags |= NFS_MOUNT_SOFT;
- ctx->flags &= ~NFS_MOUNT_SOFTERR;
- break;
- case Opt_softerr:
- ctx->flags |= NFS_MOUNT_SOFTERR;
- ctx->flags &= ~NFS_MOUNT_SOFT;
- break;
- case Opt_hard:
- ctx->flags &= ~(NFS_MOUNT_SOFT|NFS_MOUNT_SOFTERR);
- break;
- case Opt_posix:
- ctx->flags |= NFS_MOUNT_POSIX;
- break;
- case Opt_noposix:
- ctx->flags &= ~NFS_MOUNT_POSIX;
- break;
- case Opt_cto:
- ctx->flags &= ~NFS_MOUNT_NOCTO;
- break;
- case Opt_nocto:
- ctx->flags |= NFS_MOUNT_NOCTO;
- break;
- case Opt_ac:
- ctx->flags &= ~NFS_MOUNT_NOAC;
- break;
- case Opt_noac:
- ctx->flags |= NFS_MOUNT_NOAC;
- break;
- case Opt_lock:
- ctx->flags &= ~NFS_MOUNT_NONLM;
- ctx->flags &= ~(NFS_MOUNT_LOCAL_FLOCK |
- NFS_MOUNT_LOCAL_FCNTL);
- break;
- case Opt_nolock:
- ctx->flags |= NFS_MOUNT_NONLM;
- ctx->flags |= (NFS_MOUNT_LOCAL_FLOCK |
- NFS_MOUNT_LOCAL_FCNTL);
- break;
- case Opt_udp:
- ctx->flags &= ~NFS_MOUNT_TCP;
- ctx->nfs_server.protocol = XPRT_TRANSPORT_UDP;
- break;
- case Opt_tcp:
- ctx->flags |= NFS_MOUNT_TCP;
- ctx->nfs_server.protocol = XPRT_TRANSPORT_TCP;
- break;
- case Opt_rdma:
- ctx->flags |= NFS_MOUNT_TCP; /* for side protocols */
- ctx->nfs_server.protocol = XPRT_TRANSPORT_RDMA;
- xprt_load_transport(p);
- break;
- case Opt_acl:
- ctx->flags &= ~NFS_MOUNT_NOACL;
- break;
- case Opt_noacl:
- ctx->flags |= NFS_MOUNT_NOACL;
- break;
- case Opt_rdirplus:
- ctx->flags &= ~NFS_MOUNT_NORDIRPLUS;
- break;
- case Opt_nordirplus:
- ctx->flags |= NFS_MOUNT_NORDIRPLUS;
- break;
- case Opt_sharecache:
- ctx->flags &= ~NFS_MOUNT_UNSHARED;
- break;
- case Opt_nosharecache:
- ctx->flags |= NFS_MOUNT_UNSHARED;
- break;
- case Opt_resvport:
- ctx->flags &= ~NFS_MOUNT_NORESVPORT;
- break;
- case Opt_noresvport:
- ctx->flags |= NFS_MOUNT_NORESVPORT;
- break;
- case Opt_fscache:
- ctx->options |= NFS_OPTION_FSCACHE;
- kfree(ctx->fscache_uniq);
- ctx->fscache_uniq = NULL;
- break;
- case Opt_nofscache:
- ctx->options &= ~NFS_OPTION_FSCACHE;
- kfree(ctx->fscache_uniq);
- ctx->fscache_uniq = NULL;
- break;
- case Opt_migration:
- ctx->options |= NFS_OPTION_MIGRATION;
- break;
- case Opt_nomigration:
- ctx->options &= ~NFS_OPTION_MIGRATION;
- break;
+ case Opt_soft:
+ ctx->flags |= NFS_MOUNT_SOFT;
+ ctx->flags &= ~NFS_MOUNT_SOFTERR;
+ break;
+ case Opt_softerr:
+ ctx->flags |= NFS_MOUNT_SOFTERR;
+ ctx->flags &= ~NFS_MOUNT_SOFT;
+ break;
+ case Opt_hard:
+ ctx->flags &= ~(NFS_MOUNT_SOFT|NFS_MOUNT_SOFTERR);
+ break;
+ case Opt_posix:
+ ctx->flags |= NFS_MOUNT_POSIX;
+ break;
+ case Opt_noposix:
+ ctx->flags &= ~NFS_MOUNT_POSIX;
+ break;
+ case Opt_cto:
+ ctx->flags &= ~NFS_MOUNT_NOCTO;
+ break;
+ case Opt_nocto:
+ ctx->flags |= NFS_MOUNT_NOCTO;
+ break;
+ case Opt_ac:
+ ctx->flags &= ~NFS_MOUNT_NOAC;
+ break;
+ case Opt_noac:
+ ctx->flags |= NFS_MOUNT_NOAC;
+ break;
+ case Opt_lock:
+ ctx->flags &= ~NFS_MOUNT_NONLM;
+ ctx->flags &= ~(NFS_MOUNT_LOCAL_FLOCK |
+ NFS_MOUNT_LOCAL_FCNTL);
+ break;
+ case Opt_nolock:
+ ctx->flags |= NFS_MOUNT_NONLM;
+ ctx->flags |= (NFS_MOUNT_LOCAL_FLOCK |
+ NFS_MOUNT_LOCAL_FCNTL);
+ break;
+ case Opt_udp:
+ ctx->flags &= ~NFS_MOUNT_TCP;
+ ctx->nfs_server.protocol = XPRT_TRANSPORT_UDP;
+ break;
+ case Opt_tcp:
+ ctx->flags |= NFS_MOUNT_TCP;
+ ctx->nfs_server.protocol = XPRT_TRANSPORT_TCP;
+ break;
+ case Opt_rdma:
+ ctx->flags |= NFS_MOUNT_TCP; /* for side protocols */
+ ctx->nfs_server.protocol = XPRT_TRANSPORT_RDMA;
+ xprt_load_transport(p);
+ break;
+ case Opt_acl:
+ ctx->flags &= ~NFS_MOUNT_NOACL;
+ break;
+ case Opt_noacl:
+ ctx->flags |= NFS_MOUNT_NOACL;
+ break;
+ case Opt_rdirplus:
+ ctx->flags &= ~NFS_MOUNT_NORDIRPLUS;
+ break;
+ case Opt_nordirplus:
+ ctx->flags |= NFS_MOUNT_NORDIRPLUS;
+ break;
+ case Opt_sharecache:
+ ctx->flags &= ~NFS_MOUNT_UNSHARED;
+ break;
+ case Opt_nosharecache:
+ ctx->flags |= NFS_MOUNT_UNSHARED;
+ break;
+ case Opt_resvport:
+ ctx->flags &= ~NFS_MOUNT_NORESVPORT;
+ break;
+ case Opt_noresvport:
+ ctx->flags |= NFS_MOUNT_NORESVPORT;
+ break;
+ case Opt_fscache:
+ ctx->options |= NFS_OPTION_FSCACHE;
+ kfree(ctx->fscache_uniq);
+ ctx->fscache_uniq = NULL;
+ break;
+ case Opt_nofscache:
+ ctx->options &= ~NFS_OPTION_FSCACHE;
+ kfree(ctx->fscache_uniq);
+ ctx->fscache_uniq = NULL;
+ break;
+ case Opt_migration:
+ ctx->options |= NFS_OPTION_MIGRATION;
+ break;
+ case Opt_nomigration:
+ ctx->options &= ~NFS_OPTION_MIGRATION;
+ break;
/*
* options that take numeric values
*/
- case Opt_port:
- if (nfs_get_option_ul(args, &option) ||
- option > USHRT_MAX)
- goto out_invalid_value;
- ctx->nfs_server.port = option;
- break;
- case Opt_rsize:
- if (nfs_get_option_ul(args, &option))
- goto out_invalid_value;
- ctx->rsize = option;
- break;
- case Opt_wsize:
- if (nfs_get_option_ul(args, &option))
- goto out_invalid_value;
- ctx->wsize = option;
- break;
- case Opt_bsize:
- if (nfs_get_option_ul(args, &option))
- goto out_invalid_value;
- ctx->bsize = option;
- break;
- case Opt_timeo:
- if (nfs_get_option_ul_bound(args, &option, 1, INT_MAX))
- goto out_invalid_value;
- ctx->timeo = option;
- break;
- case Opt_retrans:
- if (nfs_get_option_ul_bound(args, &option, 0, INT_MAX))
- goto out_invalid_value;
- ctx->retrans = option;
- break;
- case Opt_acregmin:
- if (nfs_get_option_ul(args, &option))
- goto out_invalid_value;
- ctx->acregmin = option;
- break;
- case Opt_acregmax:
- if (nfs_get_option_ul(args, &option))
- goto out_invalid_value;
- ctx->acregmax = option;
- break;
- case Opt_acdirmin:
- if (nfs_get_option_ul(args, &option))
- goto out_invalid_value;
- ctx->acdirmin = option;
- break;
- case Opt_acdirmax:
- if (nfs_get_option_ul(args, &option))
- goto out_invalid_value;
- ctx->acdirmax = option;
- break;
- case Opt_actimeo:
- if (nfs_get_option_ul(args, &option))
- goto out_invalid_value;
- ctx->acregmin = ctx->acregmax =
+ case Opt_port:
+ if (nfs_get_option_ul(args, &option) ||
+ option > USHRT_MAX)
+ goto out_invalid_value;
+ ctx->nfs_server.port = option;
+ break;
+ case Opt_rsize:
+ if (nfs_get_option_ul(args, &option))
+ goto out_invalid_value;
+ ctx->rsize = option;
+ break;
+ case Opt_wsize:
+ if (nfs_get_option_ul(args, &option))
+ goto out_invalid_value;
+ ctx->wsize = option;
+ break;
+ case Opt_bsize:
+ if (nfs_get_option_ul(args, &option))
+ goto out_invalid_value;
+ ctx->bsize = option;
+ break;
+ case Opt_timeo:
+ if (nfs_get_option_ul_bound(args, &option, 1, INT_MAX))
+ goto out_invalid_value;
+ ctx->timeo = option;
+ break;
+ case Opt_retrans:
+ if (nfs_get_option_ul_bound(args, &option, 0, INT_MAX))
+ goto out_invalid_value;
+ ctx->retrans = option;
+ break;
+ case Opt_acregmin:
+ if (nfs_get_option_ul(args, &option))
+ goto out_invalid_value;
+ ctx->acregmin = option;
+ break;
+ case Opt_acregmax:
+ if (nfs_get_option_ul(args, &option))
+ goto out_invalid_value;
+ ctx->acregmax = option;
+ break;
+ case Opt_acdirmin:
+ if (nfs_get_option_ul(args, &option))
+ goto out_invalid_value;
+ ctx->acdirmin = option;
+ break;
+ case Opt_acdirmax:
+ if (nfs_get_option_ul(args, &option))
+ goto out_invalid_value;
+ ctx->acdirmax = option;
+ break;
+ case Opt_actimeo:
+ if (nfs_get_option_ul(args, &option))
+ goto out_invalid_value;
+ ctx->acregmin = ctx->acregmax =
ctx->acdirmin = ctx->acdirmax = option;
- break;
- case Opt_namelen:
- if (nfs_get_option_ul(args, &option))
- goto out_invalid_value;
- ctx->namlen = option;
- break;
- case Opt_mountport:
- if (nfs_get_option_ul(args, &option) ||
- option > USHRT_MAX)
- goto out_invalid_value;
- ctx->mount_server.port = option;
- break;
- case Opt_mountvers:
- if (nfs_get_option_ul(args, &option) ||
- option < NFS_MNT_VERSION ||
- option > NFS_MNT3_VERSION)
- goto out_invalid_value;
- ctx->mount_server.version = option;
- break;
- case Opt_minorversion:
- if (nfs_get_option_ul(args, &option))
- goto out_invalid_value;
- if (option > NFS4_MAX_MINOR_VERSION)
- goto out_invalid_value;
- ctx->minorversion = option;
- break;
+ break;
+ case Opt_namelen:
+ if (nfs_get_option_ul(args, &option))
+ goto out_invalid_value;
+ ctx->namlen = option;
+ break;
+ case Opt_mountport:
+ if (nfs_get_option_ul(args, &option) ||
+ option > USHRT_MAX)
+ goto out_invalid_value;
+ ctx->mount_server.port = option;
+ break;
+ case Opt_mountvers:
+ if (nfs_get_option_ul(args, &option) ||
+ option < NFS_MNT_VERSION ||
+ option > NFS_MNT3_VERSION)
+ goto out_invalid_value;
+ ctx->mount_server.version = option;
+ break;
+ case Opt_minorversion:
+ if (nfs_get_option_ul(args, &option))
+ goto out_invalid_value;
+ if (option > NFS4_MAX_MINOR_VERSION)
+ goto out_invalid_value;
+ ctx->minorversion = option;
+ break;
/*
* options that take text values
*/
- case Opt_nfsvers:
- string = match_strdup(args);
- if (string == NULL)
- goto out_nomem;
- rc = nfs_parse_version_string(string, ctx, args);
- kfree(string);
- if (!rc)
- goto out_invalid_value;
+ case Opt_nfsvers:
+ string = match_strdup(args);
+ if (string == NULL)
+ goto out_nomem;
+ rc = nfs_parse_version_string(string, ctx, args);
+ kfree(string);
+ if (!rc)
+ goto out_invalid_value;
+ break;
+ case Opt_sec:
+ string = match_strdup(args);
+ if (string == NULL)
+ goto out_nomem;
+ rc = nfs_parse_security_flavors(string, ctx);
+ kfree(string);
+ if (!rc) {
+ dfprintk(MOUNT, "NFS: unrecognized "
+ "security flavor\n");
+ return -EINVAL;
+ }
+ break;
+ case Opt_proto:
+ string = match_strdup(args);
+ if (string == NULL)
+ goto out_nomem;
+ token = match_token(string,
+ nfs_xprt_protocol_tokens, args);
+
+ ctx->protofamily = AF_INET;
+ switch (token) {
+ case Opt_xprt_udp6:
+ ctx->protofamily = AF_INET6;
+ /* fall through */
+ case Opt_xprt_udp:
+ ctx->flags &= ~NFS_MOUNT_TCP;
+ ctx->nfs_server.protocol = XPRT_TRANSPORT_UDP;
break;
- case Opt_sec:
- string = match_strdup(args);
- if (string == NULL)
- goto out_nomem;
- rc = nfs_parse_security_flavors(string, ctx);
- kfree(string);
- if (!rc) {
- dfprintk(MOUNT, "NFS: unrecognized "
- "security flavor\n");
- return -EINVAL;
- }
+ case Opt_xprt_tcp6:
+ ctx->protofamily = AF_INET6;
+ /* fall through */
+ case Opt_xprt_tcp:
+ ctx->flags |= NFS_MOUNT_TCP;
+ ctx->nfs_server.protocol = XPRT_TRANSPORT_TCP;
break;
- case Opt_proto:
- string = match_strdup(args);
- if (string == NULL)
- goto out_nomem;
- token = match_token(string,
- nfs_xprt_protocol_tokens, args);
-
- ctx->protofamily = AF_INET;
- switch (token) {
- case Opt_xprt_udp6:
- ctx->protofamily = AF_INET6;
- /* fall through */
- case Opt_xprt_udp:
- ctx->flags &= ~NFS_MOUNT_TCP;
- ctx->nfs_server.protocol = XPRT_TRANSPORT_UDP;
- break;
- case Opt_xprt_tcp6:
- ctx->protofamily = AF_INET6;
- /* fall through */
- case Opt_xprt_tcp:
- ctx->flags |= NFS_MOUNT_TCP;
- ctx->nfs_server.protocol = XPRT_TRANSPORT_TCP;
- break;
- case Opt_xprt_rdma6:
- ctx->protofamily = AF_INET6;
- /* fall through */
- case Opt_xprt_rdma:
- /* vector side protocols to TCP */
- ctx->flags |= NFS_MOUNT_TCP;
- ctx->nfs_server.protocol = XPRT_TRANSPORT_RDMA;
- xprt_load_transport(string);
- break;
- default:
- dfprintk(MOUNT, "NFS: unrecognized "
- "transport protocol\n");
- kfree(string);
- return -EINVAL;
- }
- kfree(string);
+ case Opt_xprt_rdma6:
+ ctx->protofamily = AF_INET6;
+ /* fall through */
+ case Opt_xprt_rdma:
+ /* vector side protocols to TCP */
+ ctx->flags |= NFS_MOUNT_TCP;
+ ctx->nfs_server.protocol = XPRT_TRANSPORT_RDMA;
+ xprt_load_transport(string);
break;
- case Opt_mountproto:
- string = match_strdup(args);
- if (string == NULL)
- goto out_nomem;
- token = match_token(string,
- nfs_xprt_protocol_tokens, args);
+ default:
+ dfprintk(MOUNT, "NFS: unrecognized "
+ "transport protocol\n");
kfree(string);
+ return -EINVAL;
+ }
+ kfree(string);
+ break;
+ case Opt_mountproto:
+ string = match_strdup(args);
+ if (string == NULL)
+ goto out_nomem;
+ token = match_token(string,
+ nfs_xprt_protocol_tokens, args);
+ kfree(string);
- ctx->mountfamily = AF_INET;
- switch (token) {
- case Opt_xprt_udp6:
- ctx->mountfamily = AF_INET6;
- /* fall through */
- case Opt_xprt_udp:
- ctx->mount_server.protocol = XPRT_TRANSPORT_UDP;
- break;
- case Opt_xprt_tcp6:
- ctx->mountfamily = AF_INET6;
- /* fall through */
- case Opt_xprt_tcp:
- ctx->mount_server.protocol = XPRT_TRANSPORT_TCP;
- break;
- case Opt_xprt_rdma: /* not used for side protocols */
- default:
- dfprintk(MOUNT, "NFS: unrecognized "
- "transport protocol\n");
- return -EINVAL;
- }
- break;
- case Opt_addr:
- string = match_strdup(args);
- if (string == NULL)
- goto out_nomem;
- ctx->nfs_server.addrlen =
- rpc_pton(ctx->net, string, strlen(string),
- (struct sockaddr *)
- &ctx->nfs_server.address,
- sizeof(ctx->nfs_server.address));
- kfree(string);
- if (ctx->nfs_server.addrlen == 0)
- goto out_invalid_address;
- break;
- case Opt_clientaddr:
- if (nfs_get_option_str(args, &ctx->client_address))
- goto out_nomem;
+ ctx->mountfamily = AF_INET;
+ switch (token) {
+ case Opt_xprt_udp6:
+ ctx->mountfamily = AF_INET6;
+ /* fall through */
+ case Opt_xprt_udp:
+ ctx->mount_server.protocol = XPRT_TRANSPORT_UDP;
+ break;
+ case Opt_xprt_tcp6:
+ ctx->mountfamily = AF_INET6;
+ /* fall through */
+ case Opt_xprt_tcp:
+ ctx->mount_server.protocol = XPRT_TRANSPORT_TCP;
+ break;
+ case Opt_xprt_rdma: /* not used for side protocols */
+ default:
+ dfprintk(MOUNT, "NFS: unrecognized "
+ "transport protocol\n");
+ return -EINVAL;
+ }
+ break;
+ case Opt_addr:
+ string = match_strdup(args);
+ if (string == NULL)
+ goto out_nomem;
+ ctx->nfs_server.addrlen =
+ rpc_pton(ctx->net, string, strlen(string),
+ (struct sockaddr *)
+ &ctx->nfs_server.address,
+ sizeof(ctx->nfs_server.address));
+ kfree(string);
+ if (ctx->nfs_server.addrlen == 0)
+ goto out_invalid_address;
+ break;
+ case Opt_clientaddr:
+ if (nfs_get_option_str(args, &ctx->client_address))
+ goto out_nomem;
+ break;
+ case Opt_mounthost:
+ if (nfs_get_option_str(args,
+ &ctx->mount_server.hostname))
+ goto out_nomem;
+ break;
+ case Opt_mountaddr:
+ string = match_strdup(args);
+ if (string == NULL)
+ goto out_nomem;
+ ctx->mount_server.addrlen =
+ rpc_pton(ctx->net, string, strlen(string),
+ (struct sockaddr *)
+ &ctx->mount_server.address,
+ sizeof(ctx->mount_server.address));
+ kfree(string);
+ if (ctx->mount_server.addrlen == 0)
+ goto out_invalid_address;
+ break;
+ case Opt_nconnect:
+ if (nfs_get_option_ul_bound(args, &option, 1, NFS_MAX_CONNECTIONS))
+ goto out_invalid_value;
+ ctx->nfs_server.nconnect = option;
+ break;
+ case Opt_lookupcache:
+ string = match_strdup(args);
+ if (string == NULL)
+ goto out_nomem;
+ token = match_token(string,
+ nfs_lookupcache_tokens, args);
+ kfree(string);
+ switch (token) {
+ case Opt_lookupcache_all:
+ ctx->flags &= ~(NFS_MOUNT_LOOKUP_CACHE_NONEG|NFS_MOUNT_LOOKUP_CACHE_NONE);
break;
- case Opt_mounthost:
- if (nfs_get_option_str(args,
- &ctx->mount_server.hostname))
- goto out_nomem;
+ case Opt_lookupcache_positive:
+ ctx->flags &= ~NFS_MOUNT_LOOKUP_CACHE_NONE;
+ ctx->flags |= NFS_MOUNT_LOOKUP_CACHE_NONEG;
break;
- case Opt_mountaddr:
- string = match_strdup(args);
- if (string == NULL)
- goto out_nomem;
- ctx->mount_server.addrlen =
- rpc_pton(ctx->net, string, strlen(string),
- (struct sockaddr *)
- &ctx->mount_server.address,
- sizeof(ctx->mount_server.address));
- kfree(string);
- if (ctx->mount_server.addrlen == 0)
- goto out_invalid_address;
+ case Opt_lookupcache_none:
+ ctx->flags |= NFS_MOUNT_LOOKUP_CACHE_NONEG|NFS_MOUNT_LOOKUP_CACHE_NONE;
break;
- case Opt_nconnect:
- if (nfs_get_option_ul_bound(args, &option, 1, NFS_MAX_CONNECTIONS))
- goto out_invalid_value;
- ctx->nfs_server.nconnect = option;
+ default:
+ dfprintk(MOUNT, "NFS: invalid "
+ "lookupcache argument\n");
+ return -EINVAL;
+ }
+ break;
+ case Opt_fscache_uniq:
+ if (nfs_get_option_str(args, &ctx->fscache_uniq))
+ goto out_nomem;
+ ctx->options |= NFS_OPTION_FSCACHE;
+ break;
+ case Opt_local_lock:
+ string = match_strdup(args);
+ if (string == NULL)
+ goto out_nomem;
+ token = match_token(string, nfs_local_lock_tokens,
+ args);
+ kfree(string);
+ switch (token) {
+ case Opt_local_lock_all:
+ ctx->flags |= (NFS_MOUNT_LOCAL_FLOCK |
+ NFS_MOUNT_LOCAL_FCNTL);
break;
- case Opt_lookupcache:
- string = match_strdup(args);
- if (string == NULL)
- goto out_nomem;
- token = match_token(string,
- nfs_lookupcache_tokens, args);
- kfree(string);
- switch (token) {
- case Opt_lookupcache_all:
- ctx->flags &= ~(NFS_MOUNT_LOOKUP_CACHE_NONEG|NFS_MOUNT_LOOKUP_CACHE_NONE);
- break;
- case Opt_lookupcache_positive:
- ctx->flags &= ~NFS_MOUNT_LOOKUP_CACHE_NONE;
- ctx->flags |= NFS_MOUNT_LOOKUP_CACHE_NONEG;
- break;
- case Opt_lookupcache_none:
- ctx->flags |= NFS_MOUNT_LOOKUP_CACHE_NONEG|NFS_MOUNT_LOOKUP_CACHE_NONE;
- break;
- default:
- dfprintk(MOUNT, "NFS: invalid "
- "lookupcache argument\n");
- return -EINVAL;
- }
+ case Opt_local_lock_flock:
+ ctx->flags |= NFS_MOUNT_LOCAL_FLOCK;
break;
- case Opt_fscache_uniq:
- if (nfs_get_option_str(args, &ctx->fscache_uniq))
- goto out_nomem;
- ctx->options |= NFS_OPTION_FSCACHE;
+ case Opt_local_lock_posix:
+ ctx->flags |= NFS_MOUNT_LOCAL_FCNTL;
break;
- case Opt_local_lock:
- string = match_strdup(args);
- if (string == NULL)
- goto out_nomem;
- token = match_token(string, nfs_local_lock_tokens,
- args);
- kfree(string);
- switch (token) {
- case Opt_local_lock_all:
- ctx->flags |= (NFS_MOUNT_LOCAL_FLOCK |
- NFS_MOUNT_LOCAL_FCNTL);
- break;
- case Opt_local_lock_flock:
- ctx->flags |= NFS_MOUNT_LOCAL_FLOCK;
- break;
- case Opt_local_lock_posix:
- ctx->flags |= NFS_MOUNT_LOCAL_FCNTL;
- break;
- case Opt_local_lock_none:
- ctx->flags &= ~(NFS_MOUNT_LOCAL_FLOCK |
- NFS_MOUNT_LOCAL_FCNTL);
- break;
- default:
- dfprintk(MOUNT, "NFS: invalid "
- "local_lock argument\n");
- return -EINVAL;
- }
+ case Opt_local_lock_none:
+ ctx->flags &= ~(NFS_MOUNT_LOCAL_FLOCK |
+ NFS_MOUNT_LOCAL_FCNTL);
break;
+ default:
+ dfprintk(MOUNT, "NFS: invalid "
+ "local_lock argument\n");
+ return -EINVAL;
+ }
+ break;
/*
* Special options
*/
- case Opt_sloppy:
- ctx->sloppy = 1;
- dfprintk(MOUNT, "NFS: relaxing parsing rules\n");
- break;
- case Opt_userspace:
- case Opt_deprecated:
- dfprintk(MOUNT, "NFS: ignoring mount option "
- "'%s'\n", p);
- break;
+ case Opt_sloppy:
+ ctx->sloppy = 1;
+ dfprintk(MOUNT, "NFS: relaxing parsing rules\n");
+ break;
+ case Opt_userspace:
+ case Opt_deprecated:
+ dfprintk(MOUNT, "NFS: ignoring mount option "
+ "'%s'\n", p);
+ break;
- default:
- dfprintk(MOUNT, "NFS: unrecognized mount option "
- "'%s'\n", p);
- return -EINVAL;
- }
+ default:
+ dfprintk(MOUNT, "NFS: unrecognized mount option "
+ "'%s'\n", p);
+ return -EINVAL;
}
return 0;
--
2.17.2
^ permalink raw reply related
* [PATCH v6 09/27] nfs: don't bother passing nfs_subversion to ->try_mount() and nfs_fs_mount_common()
From: Scott Mayhew @ 2019-12-10 12:30 UTC (permalink / raw)
To: anna.schumaker, trond.myklebust
Cc: dhowells, viro, linux-nfs, linux-fsdevel, linux-kernel,
linux-security-module
In-Reply-To: <20191210123115.1655-1-smayhew@redhat.com>
From: Al Viro <viro@zeniv.linux.org.uk>
Reviewed-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/nfs/internal.h | 6 ++----
fs/nfs/nfs4_fs.h | 2 +-
fs/nfs/nfs4super.c | 5 ++---
fs/nfs/super.c | 19 ++++++++-----------
include/linux/nfs_xdr.h | 3 +--
5 files changed, 14 insertions(+), 21 deletions(-)
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 9888e9c7abe2..4a0ba66bc3aa 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -393,12 +393,10 @@ extern struct file_system_type nfs_xdev_fs_type;
extern struct file_system_type nfs4_referral_fs_type;
#endif
bool nfs_auth_info_match(const struct nfs_auth_info *, rpc_authflavor_t);
-struct dentry *nfs_try_mount(int, const char *, struct nfs_mount_info *,
- struct nfs_subversion *);
+struct dentry *nfs_try_mount(int, const char *, struct nfs_mount_info *);
int nfs_set_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *);
int nfs_clone_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *);
-struct dentry *nfs_fs_mount_common(int, const char *,
- struct nfs_mount_info *, struct nfs_subversion *);
+struct dentry *nfs_fs_mount_common(int, const char *, struct nfs_mount_info *);
struct dentry *nfs_fs_mount(struct file_system_type *, int, const char *, void *);
struct dentry * nfs_xdev_mount_common(struct file_system_type *, int,
const char *, struct nfs_mount_info *);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index a7a73b1d1fec..5d539dce9cef 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -526,7 +526,7 @@ extern const nfs4_stateid invalid_stateid;
/* nfs4super.c */
struct nfs_mount_info;
extern struct nfs_subversion nfs_v4;
-struct dentry *nfs4_try_mount(int, const char *, struct nfs_mount_info *, struct nfs_subversion *);
+struct dentry *nfs4_try_mount(int, const char *, struct nfs_mount_info *);
extern bool nfs4_disable_idmapping;
extern unsigned short max_session_slots;
extern unsigned short max_session_cb_slots;
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 6e5417027021..2b34d8e124cd 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -98,7 +98,7 @@ static struct dentry *
nfs4_remote_mount(struct file_system_type *fs_type, int flags,
const char *dev_name, void *info)
{
- return nfs_fs_mount_common(flags, dev_name, info, &nfs_v4);
+ return nfs_fs_mount_common(flags, dev_name, info);
}
struct nfs_referral_count {
@@ -216,8 +216,7 @@ static struct dentry *do_nfs4_mount(struct nfs_server *server, int flags,
}
struct dentry *nfs4_try_mount(int flags, const char *dev_name,
- struct nfs_mount_info *mount_info,
- struct nfs_subversion *nfs_mod)
+ struct nfs_mount_info *mount_info)
{
struct nfs_parsed_mount_data *data = mount_info->parsed;
struct dentry *res;
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 6189f768aa59..cb0ead628842 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -1893,15 +1893,15 @@ static struct nfs_server *nfs_try_mount_request(struct nfs_mount_info *mount_inf
}
struct dentry *nfs_try_mount(int flags, const char *dev_name,
- struct nfs_mount_info *mount_info,
- struct nfs_subversion *nfs_mod)
+ struct nfs_mount_info *mount_info)
{
+ struct nfs_subversion *nfs_mod = mount_info->nfs_mod;
if (mount_info->parsed->need_mount)
mount_info->server = nfs_try_mount_request(mount_info, nfs_mod);
else
mount_info->server = nfs_mod->rpc_ops->create_server(mount_info, nfs_mod);
- return nfs_fs_mount_common(flags, dev_name, mount_info, nfs_mod);
+ return nfs_fs_mount_common(flags, dev_name, mount_info);
}
EXPORT_SYMBOL_GPL(nfs_try_mount);
@@ -2648,8 +2648,7 @@ static void nfs_set_readahead(struct backing_dev_info *bdi,
}
struct dentry *nfs_fs_mount_common(int flags, const char *dev_name,
- struct nfs_mount_info *mount_info,
- struct nfs_subversion *nfs_mod)
+ struct nfs_mount_info *mount_info)
{
struct super_block *s;
struct dentry *mntroot = ERR_PTR(-ENOMEM);
@@ -2677,7 +2676,8 @@ struct dentry *nfs_fs_mount_common(int flags, const char *dev_name,
sb_mntdata.mntflags |= SB_SYNCHRONOUS;
/* Get a superblock - note that we may end up sharing one that already exists */
- s = sget(nfs_mod->nfs_fs, compare_super, nfs_set_super, flags, &sb_mntdata);
+ s = sget(mount_info->nfs_mod->nfs_fs, compare_super, nfs_set_super,
+ flags, &sb_mntdata);
if (IS_ERR(s)) {
mntroot = ERR_CAST(s);
goto out_err_nosb;
@@ -2763,7 +2763,7 @@ struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
}
mount_info.nfs_mod = nfs_mod;
- mntroot = nfs_mod->rpc_ops->try_mount(flags, dev_name, &mount_info, nfs_mod);
+ mntroot = nfs_mod->rpc_ops->try_mount(flags, dev_name, &mount_info);
put_nfs_version(nfs_mod);
out:
@@ -2797,10 +2797,7 @@ static struct dentry *
nfs_xdev_mount(struct file_system_type *fs_type, int flags,
const char *dev_name, void *raw_data)
{
- struct nfs_mount_info *info = raw_data;
- struct nfs_subversion *nfs_mod = NFS_SB(info->cloned->sb)->nfs_client->cl_nfs_mod;
-
- return nfs_fs_mount_common(flags, dev_name, info, nfs_mod);
+ return nfs_fs_mount_common(flags, dev_name, raw_data);
}
#if IS_ENABLED(CONFIG_NFS_V4)
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 72d5695c1b47..3ee2ad642cbc 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1655,8 +1655,7 @@ struct nfs_rpc_ops {
struct nfs_fsinfo *);
struct vfsmount *(*submount) (struct nfs_server *, struct dentry *,
struct nfs_fh *, struct nfs_fattr *);
- struct dentry *(*try_mount) (int, const char *, struct nfs_mount_info *,
- struct nfs_subversion *);
+ struct dentry *(*try_mount) (int, const char *, struct nfs_mount_info *);
int (*getattr) (struct nfs_server *, struct nfs_fh *,
struct nfs_fattr *, struct nfs4_label *,
struct inode *);
--
2.17.2
^ permalink raw reply related
* [PATCH v6 07/27] nfs: lift setting mount_info from nfs_xdev_mount()
From: Scott Mayhew @ 2019-12-10 12:30 UTC (permalink / raw)
To: anna.schumaker, trond.myklebust
Cc: dhowells, viro, linux-nfs, linux-fsdevel, linux-kernel,
linux-security-module
In-Reply-To: <20191210123115.1655-1-smayhew@redhat.com>
From: Al Viro <viro@zeniv.linux.org.uk>
Do it in nfs_do_submount() instead. As a side benefit, nfs_clone_data
doesn't need ->fh and ->fattr anymore.
Reviewed-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/nfs/internal.h | 3 +--
fs/nfs/namespace.c | 35 +++++++++++++++++++++--------------
fs/nfs/super.c | 25 ++++---------------------
3 files changed, 26 insertions(+), 37 deletions(-)
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 8f4900bd04f7..b193dd626c0a 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -34,8 +34,6 @@ static inline int nfs_attr_use_mounted_on_fileid(struct nfs_fattr *fattr)
struct nfs_clone_mount {
const struct super_block *sb;
const struct dentry *dentry;
- struct nfs_fh *fh;
- struct nfs_fattr *fattr;
char *hostname;
char *mnt_path;
struct sockaddr *addr;
@@ -405,6 +403,7 @@ struct dentry * nfs_xdev_mount_common(struct file_system_type *, int,
const char *, struct nfs_mount_info *);
void nfs_kill_super(struct super_block *);
void nfs_fill_super(struct super_block *, struct nfs_mount_info *);
+void nfs_clone_super(struct super_block *, struct nfs_mount_info *);
extern struct rpc_stat nfs_rpcstat;
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 5e0e9d29f5c5..a76aeb0c2923 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -19,6 +19,7 @@
#include <linux/vfs.h>
#include <linux/sunrpc/gss_api.h>
#include "internal.h"
+#include "nfs.h"
#define NFSDBG_FACILITY NFSDBG_VFS
@@ -213,16 +214,6 @@ void nfs_release_automount_timer(void)
cancel_delayed_work(&nfs_automount_task);
}
-/*
- * Clone a mountpoint of the appropriate type
- */
-static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server,
- const char *devname,
- struct nfs_clone_mount *mountdata)
-{
- return vfs_submount(mountdata->dentry, &nfs_xdev_fs_type, devname, mountdata);
-}
-
/**
* nfs_do_submount - set up mountpoint when crossing a filesystem boundary
* @dentry: parent directory
@@ -234,13 +225,20 @@ static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server,
struct vfsmount *nfs_do_submount(struct dentry *dentry, struct nfs_fh *fh,
struct nfs_fattr *fattr, rpc_authflavor_t authflavor)
{
+ struct super_block *sb = dentry->d_sb;
struct nfs_clone_mount mountdata = {
- .sb = dentry->d_sb,
+ .sb = sb,
.dentry = dentry,
- .fh = fh,
- .fattr = fattr,
.authflavor = authflavor,
};
+ struct nfs_mount_info mount_info = {
+ .fill_super = nfs_clone_super,
+ .set_security = nfs_clone_sb_security,
+ .cloned = &mountdata,
+ .mntfh = fh,
+ };
+ struct nfs_subversion *nfs_mod = NFS_SB(sb)->nfs_client->cl_nfs_mod;
+ struct nfs_server *server;
struct vfsmount *mnt;
char *page = (char *) __get_free_page(GFP_USER);
char *devname;
@@ -248,12 +246,21 @@ struct vfsmount *nfs_do_submount(struct dentry *dentry, struct nfs_fh *fh,
if (page == NULL)
return ERR_PTR(-ENOMEM);
+ server = nfs_mod->rpc_ops->clone_server(NFS_SB(sb), fh,
+ fattr, authflavor);
+ if (IS_ERR(server))
+ return ERR_CAST(server);
+
+ mount_info.server = server;
+
devname = nfs_devname(dentry, page, PAGE_SIZE);
if (IS_ERR(devname))
mnt = ERR_CAST(devname);
else
- mnt = nfs_do_clone_mount(NFS_SB(dentry->d_sb), devname, &mountdata);
+ mnt = vfs_submount(dentry, &nfs_xdev_fs_type, devname, &mount_info);
+ if (mount_info.server)
+ nfs_free_server(mount_info.server);
free_page((unsigned long)page);
return mnt;
}
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 379c7b26051d..97dc544eb220 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -2395,7 +2395,7 @@ EXPORT_SYMBOL_GPL(nfs_fill_super);
/*
* Finish setting up a cloned NFS2/3/4 superblock
*/
-static void nfs_clone_super(struct super_block *sb,
+void nfs_clone_super(struct super_block *sb,
struct nfs_mount_info *mount_info)
{
const struct super_block *old_sb = mount_info->cloned->sb;
@@ -2796,27 +2796,10 @@ static struct dentry *
nfs_xdev_mount(struct file_system_type *fs_type, int flags,
const char *dev_name, void *raw_data)
{
- struct nfs_clone_mount *data = raw_data;
- struct nfs_mount_info mount_info = {
- .fill_super = nfs_clone_super,
- .set_security = nfs_clone_sb_security,
- .cloned = data,
- };
- struct dentry *mntroot = ERR_PTR(-ENOMEM);
- struct nfs_subversion *nfs_mod = NFS_SB(data->sb)->nfs_client->cl_nfs_mod;
-
- dprintk("--> nfs_xdev_mount()\n");
+ struct nfs_mount_info *info = raw_data;
+ struct nfs_subversion *nfs_mod = NFS_SB(info->cloned->sb)->nfs_client->cl_nfs_mod;
- mount_info.mntfh = mount_info.cloned->fh;
-
- /* create a new volume representation */
- mount_info.server = nfs_mod->rpc_ops->clone_server(NFS_SB(data->sb), data->fh, data->fattr, data->authflavor);
-
- mntroot = nfs_fs_mount_common(flags, dev_name, &mount_info, nfs_mod);
-
- dprintk("<-- nfs_xdev_mount() = %ld\n",
- IS_ERR(mntroot) ? PTR_ERR(mntroot) : 0L);
- return mntroot;
+ return nfs_fs_mount_common(flags, dev_name, info, nfs_mod);
}
#if IS_ENABLED(CONFIG_NFS_V4)
--
2.17.2
^ permalink raw reply related
* [PATCH v6 03/27] nfs: lift setting mount_info from nfs4_remote{,_referral}_mount
From: Scott Mayhew @ 2019-12-10 12:30 UTC (permalink / raw)
To: anna.schumaker, trond.myklebust
Cc: dhowells, viro, linux-nfs, linux-fsdevel, linux-kernel,
linux-security-module
In-Reply-To: <20191210123115.1655-1-smayhew@redhat.com>
From: Al Viro <viro@zeniv.linux.org.uk>
Do that (fhandle allocation, setting struct server up) in
nfs4_referral_mount() and nfs4_try_mount() resp. and pass the
server and pointer to mount_info into nfs_do_root_mount() so that
nfs4_remote_referral_mount()/nfs_remote_mount() could be merged.
Since we are moving stuff from ->mount() instances to the points
prior to vfs_kern_mount() that would trigger those, we need to
make sure that do_nfs_root_mount() will do the corresponding
cleanup itself if it doesn't trigger those ->mount() instances.
Reviewed-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/nfs/nfs4super.c | 67 ++++++++++++++++++++++++----------------------
1 file changed, 35 insertions(+), 32 deletions(-)
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index e7f2fd1925b1..ac3e8928643d 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -108,32 +108,37 @@ static struct dentry *
nfs4_remote_mount(struct file_system_type *fs_type, int flags,
const char *dev_name, void *info)
{
- struct nfs_mount_info *mount_info = info;
-
- mount_info->set_security = nfs_set_sb_security;
-
- /* Get a volume representation */
- mount_info->server = nfs4_create_server(mount_info, &nfs_v4);
- return nfs_fs_mount_common(flags, dev_name, mount_info, &nfs_v4);
+ return nfs_fs_mount_common(flags, dev_name, info, &nfs_v4);
}
static struct vfsmount *nfs_do_root_mount(struct file_system_type *fs_type,
- int flags, void *data, const char *hostname)
+ struct nfs_server *server, int flags,
+ struct nfs_mount_info *info,
+ const char *hostname)
{
struct vfsmount *root_mnt;
char *root_devname;
size_t len;
+ if (IS_ERR(server))
+ return ERR_CAST(server);
+
len = strlen(hostname) + 5;
root_devname = kmalloc(len, GFP_KERNEL);
- if (root_devname == NULL)
+ if (root_devname == NULL) {
+ nfs_free_server(server);
return ERR_PTR(-ENOMEM);
+ }
/* Does hostname needs to be enclosed in brackets? */
if (strchr(hostname, ':'))
snprintf(root_devname, len, "[%s]:/", hostname);
else
snprintf(root_devname, len, "%s:/", hostname);
- root_mnt = vfs_kern_mount(fs_type, flags, root_devname, data);
+ info->server = server;
+ root_mnt = vfs_kern_mount(fs_type, flags, root_devname, info);
+ if (info->server)
+ nfs_free_server(info->server);
+ info->server = NULL;
kfree(root_devname);
return root_mnt;
}
@@ -234,11 +239,15 @@ struct dentry *nfs4_try_mount(int flags, const char *dev_name,
struct dentry *res;
struct nfs_parsed_mount_data *data = mount_info->parsed;
+ mount_info->set_security = nfs_set_sb_security;
+
dfprintk(MOUNT, "--> nfs4_try_mount()\n");
export_path = data->nfs_server.export_path;
data->nfs_server.export_path = "/";
- root_mnt = nfs_do_root_mount(&nfs4_remote_fs_type, flags, mount_info,
+ root_mnt = nfs_do_root_mount(&nfs4_remote_fs_type,
+ nfs4_create_server(mount_info, &nfs_v4),
+ flags, mount_info,
data->nfs_server.hostname);
data->nfs_server.export_path = export_path;
@@ -254,25 +263,7 @@ static struct dentry *
nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags,
const char *dev_name, void *raw_data)
{
- struct nfs_mount_info mount_info = {
- .fill_super = nfs_fill_super,
- .set_security = nfs_clone_sb_security,
- .cloned = raw_data,
- };
- struct dentry *mntroot = ERR_PTR(-ENOMEM);
-
- dprintk("--> nfs4_referral_get_sb()\n");
-
- mount_info.mntfh = nfs_alloc_fhandle();
- if (mount_info.cloned == NULL || mount_info.mntfh == NULL)
- goto out;
-
- /* create a new volume representation */
- mount_info.server = nfs4_create_referral_server(mount_info.cloned, mount_info.mntfh);
- mntroot = nfs_fs_mount_common(flags, dev_name, &mount_info, &nfs_v4);
-out:
- nfs_free_fhandle(mount_info.mntfh);
- return mntroot;
+ return nfs_fs_mount_common(flags, dev_name, raw_data, &nfs_v4);
}
/*
@@ -282,23 +273,35 @@ static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *raw_data)
{
struct nfs_clone_mount *data = raw_data;
+ struct nfs_mount_info mount_info = {
+ .fill_super = nfs_fill_super,
+ .set_security = nfs_clone_sb_security,
+ .cloned = data,
+ };
char *export_path;
struct vfsmount *root_mnt;
struct dentry *res;
dprintk("--> nfs4_referral_mount()\n");
+ mount_info.mntfh = nfs_alloc_fhandle();
+ if (!mount_info.mntfh)
+ return ERR_PTR(-ENOMEM);
+
export_path = data->mnt_path;
data->mnt_path = "/";
-
root_mnt = nfs_do_root_mount(&nfs4_remote_referral_fs_type,
- flags, data, data->hostname);
+ nfs4_create_referral_server(mount_info.cloned,
+ mount_info.mntfh),
+ flags, &mount_info, data->hostname);
data->mnt_path = export_path;
res = nfs_follow_remote_path(root_mnt, export_path);
dprintk("<-- nfs4_referral_mount() = %d%s\n",
PTR_ERR_OR_ZERO(res),
IS_ERR(res) ? " [error]" : "");
+
+ nfs_free_fhandle(mount_info.mntfh);
return res;
}
--
2.17.2
^ permalink raw reply related
* [PATCH v6 04/27] nfs: fold nfs4_remote_fs_type and nfs4_remote_referral_fs_type
From: Scott Mayhew @ 2019-12-10 12:30 UTC (permalink / raw)
To: anna.schumaker, trond.myklebust
Cc: dhowells, viro, linux-nfs, linux-fsdevel, linux-kernel,
linux-security-module
In-Reply-To: <20191210123115.1655-1-smayhew@redhat.com>
From: Al Viro <viro@zeniv.linux.org.uk>
They are identical now.
Reviewed-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/nfs/nfs4super.c | 26 ++++----------------------
1 file changed, 4 insertions(+), 22 deletions(-)
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index ac3e8928643d..54dbb4561ccc 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -22,8 +22,6 @@ static struct dentry *nfs4_remote_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *raw_data);
static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *raw_data);
-static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *raw_data);
static struct file_system_type nfs4_remote_fs_type = {
.owner = THIS_MODULE,
@@ -33,14 +31,6 @@ static struct file_system_type nfs4_remote_fs_type = {
.fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
};
-static struct file_system_type nfs4_remote_referral_fs_type = {
- .owner = THIS_MODULE,
- .name = "nfs4",
- .mount = nfs4_remote_referral_mount,
- .kill_sb = nfs_kill_super,
- .fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
-};
-
struct file_system_type nfs4_referral_fs_type = {
.owner = THIS_MODULE,
.name = "nfs4",
@@ -111,8 +101,7 @@ nfs4_remote_mount(struct file_system_type *fs_type, int flags,
return nfs_fs_mount_common(flags, dev_name, info, &nfs_v4);
}
-static struct vfsmount *nfs_do_root_mount(struct file_system_type *fs_type,
- struct nfs_server *server, int flags,
+static struct vfsmount *nfs_do_root_mount(struct nfs_server *server, int flags,
struct nfs_mount_info *info,
const char *hostname)
{
@@ -135,7 +124,7 @@ static struct vfsmount *nfs_do_root_mount(struct file_system_type *fs_type,
else
snprintf(root_devname, len, "%s:/", hostname);
info->server = server;
- root_mnt = vfs_kern_mount(fs_type, flags, root_devname, info);
+ root_mnt = vfs_kern_mount(&nfs4_remote_fs_type, flags, root_devname, info);
if (info->server)
nfs_free_server(info->server);
info->server = NULL;
@@ -245,7 +234,7 @@ struct dentry *nfs4_try_mount(int flags, const char *dev_name,
export_path = data->nfs_server.export_path;
data->nfs_server.export_path = "/";
- root_mnt = nfs_do_root_mount(&nfs4_remote_fs_type,
+ root_mnt = nfs_do_root_mount(
nfs4_create_server(mount_info, &nfs_v4),
flags, mount_info,
data->nfs_server.hostname);
@@ -259,13 +248,6 @@ struct dentry *nfs4_try_mount(int flags, const char *dev_name,
return res;
}
-static struct dentry *
-nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags,
- const char *dev_name, void *raw_data)
-{
- return nfs_fs_mount_common(flags, dev_name, raw_data, &nfs_v4);
-}
-
/*
* Create an NFS4 server record on referral traversal
*/
@@ -290,7 +272,7 @@ static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
export_path = data->mnt_path;
data->mnt_path = "/";
- root_mnt = nfs_do_root_mount(&nfs4_remote_referral_fs_type,
+ root_mnt = nfs_do_root_mount(
nfs4_create_referral_server(mount_info.cloned,
mount_info.mntfh),
flags, &mount_info, data->hostname);
--
2.17.2
^ permalink raw reply related
* [PATCH v6 19/27] NFS: Split nfs_parse_mount_options()
From: Scott Mayhew @ 2019-12-10 12:31 UTC (permalink / raw)
To: anna.schumaker, trond.myklebust
Cc: dhowells, viro, linux-nfs, linux-fsdevel, linux-kernel,
linux-security-module
In-Reply-To: <20191210123115.1655-1-smayhew@redhat.com>
From: David Howells <dhowells@redhat.com>
Split nfs_parse_mount_options() to move the prologue, list-splitting and
epilogue into one function and the per-option processing into another.
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/nfs/fs_context.c | 126 ++++++++++++++++++++++++--------------------
fs/nfs/internal.h | 3 ++
2 files changed, 73 insertions(+), 56 deletions(-)
diff --git a/fs/nfs/fs_context.c b/fs/nfs/fs_context.c
index 52aa2b8522f0..a386825c3b0f 100644
--- a/fs/nfs/fs_context.c
+++ b/fs/nfs/fs_context.c
@@ -496,36 +496,18 @@ static int nfs_get_option_ul_bound(substring_t args[], unsigned long *option,
}
/*
- * Error-check and convert a string of mount options from user space into
- * a data structure. The whole mount string is processed; bad options are
- * skipped as they are encountered. If there were no errors, return 1;
- * otherwise return 0 (zero).
+ * Parse a single mount option in "key[=val]" form.
*/
-int nfs_parse_mount_options(char *raw, struct nfs_fs_context *ctx)
+static int nfs_fs_context_parse_option(struct nfs_fs_context *ctx, char *p)
{
- char *p, *string;
- int rc, sloppy = 0, invalid_option = 0;
- unsigned short protofamily = AF_UNSPEC;
- unsigned short mountfamily = AF_UNSPEC;
-
- if (!raw) {
- dfprintk(MOUNT, "NFS: mount options string was NULL.\n");
- return 1;
- }
- dfprintk(MOUNT, "NFS: nfs mount opts='%s'\n", raw);
-
- rc = security_sb_eat_lsm_opts(raw, &ctx->lsm_opts);
- if (rc)
- goto out_security_failure;
+ char *string;
+ int rc;
- while ((p = strsep(&raw, ",")) != NULL) {
+ {
substring_t args[MAX_OPT_ARGS];
unsigned long option;
int token;
- if (!*p)
- continue;
-
dfprintk(MOUNT, "NFS: parsing nfs mount option '%s'\n", p);
token = match_token(p, nfs_mount_option_tokens, args);
@@ -734,7 +716,7 @@ int nfs_parse_mount_options(char *raw, struct nfs_fs_context *ctx)
if (!rc) {
dfprintk(MOUNT, "NFS: unrecognized "
"security flavor\n");
- return 0;
+ return -EINVAL;
}
break;
case Opt_proto:
@@ -744,24 +726,24 @@ int nfs_parse_mount_options(char *raw, struct nfs_fs_context *ctx)
token = match_token(string,
nfs_xprt_protocol_tokens, args);
- protofamily = AF_INET;
+ ctx->protofamily = AF_INET;
switch (token) {
case Opt_xprt_udp6:
- protofamily = AF_INET6;
+ ctx->protofamily = AF_INET6;
/* fall through */
case Opt_xprt_udp:
ctx->flags &= ~NFS_MOUNT_TCP;
ctx->nfs_server.protocol = XPRT_TRANSPORT_UDP;
break;
case Opt_xprt_tcp6:
- protofamily = AF_INET6;
+ ctx->protofamily = AF_INET6;
/* fall through */
case Opt_xprt_tcp:
ctx->flags |= NFS_MOUNT_TCP;
ctx->nfs_server.protocol = XPRT_TRANSPORT_TCP;
break;
case Opt_xprt_rdma6:
- protofamily = AF_INET6;
+ ctx->protofamily = AF_INET6;
/* fall through */
case Opt_xprt_rdma:
/* vector side protocols to TCP */
@@ -773,7 +755,7 @@ int nfs_parse_mount_options(char *raw, struct nfs_fs_context *ctx)
dfprintk(MOUNT, "NFS: unrecognized "
"transport protocol\n");
kfree(string);
- return 0;
+ return -EINVAL;
}
kfree(string);
break;
@@ -785,16 +767,16 @@ int nfs_parse_mount_options(char *raw, struct nfs_fs_context *ctx)
nfs_xprt_protocol_tokens, args);
kfree(string);
- mountfamily = AF_INET;
+ ctx->mountfamily = AF_INET;
switch (token) {
case Opt_xprt_udp6:
- mountfamily = AF_INET6;
+ ctx->mountfamily = AF_INET6;
/* fall through */
case Opt_xprt_udp:
ctx->mount_server.protocol = XPRT_TRANSPORT_UDP;
break;
case Opt_xprt_tcp6:
- mountfamily = AF_INET6;
+ ctx->mountfamily = AF_INET6;
/* fall through */
case Opt_xprt_tcp:
ctx->mount_server.protocol = XPRT_TRANSPORT_TCP;
@@ -803,7 +785,7 @@ int nfs_parse_mount_options(char *raw, struct nfs_fs_context *ctx)
default:
dfprintk(MOUNT, "NFS: unrecognized "
"transport protocol\n");
- return 0;
+ return -EINVAL;
}
break;
case Opt_addr:
@@ -867,7 +849,7 @@ int nfs_parse_mount_options(char *raw, struct nfs_fs_context *ctx)
default:
dfprintk(MOUNT, "NFS: invalid "
"lookupcache argument\n");
- return 0;
+ return -EINVAL;
}
break;
case Opt_fscache_uniq:
@@ -900,7 +882,7 @@ int nfs_parse_mount_options(char *raw, struct nfs_fs_context *ctx)
default:
dfprintk(MOUNT, "NFS: invalid "
"local_lock argument\n");
- return 0;
+ return -EINVAL;
}
break;
@@ -908,7 +890,7 @@ int nfs_parse_mount_options(char *raw, struct nfs_fs_context *ctx)
* Special options
*/
case Opt_sloppy:
- sloppy = 1;
+ ctx->sloppy = 1;
dfprintk(MOUNT, "NFS: relaxing parsing rules\n");
break;
case Opt_userspace:
@@ -918,12 +900,53 @@ int nfs_parse_mount_options(char *raw, struct nfs_fs_context *ctx)
break;
default:
- invalid_option = 1;
dfprintk(MOUNT, "NFS: unrecognized mount option "
"'%s'\n", p);
+ return -EINVAL;
}
}
+ return 0;
+
+out_invalid_address:
+ printk(KERN_INFO "NFS: bad IP address specified: %s\n", p);
+ return -EINVAL;
+out_invalid_value:
+ printk(KERN_INFO "NFS: bad mount option value specified: %s\n", p);
+ return -EINVAL;
+out_nomem:
+ printk(KERN_INFO "NFS: not enough memory to parse option\n");
+ return -ENOMEM;
+}
+
+/*
+ * Error-check and convert a string of mount options from user space into
+ * a data structure. The whole mount string is processed; bad options are
+ * skipped as they are encountered. If there were no errors, return 1;
+ * otherwise return 0 (zero).
+ */
+int nfs_parse_mount_options(char *raw, struct nfs_fs_context *ctx)
+{
+ char *p;
+ int rc, sloppy = 0, invalid_option = 0;
+
+ if (!raw) {
+ dfprintk(MOUNT, "NFS: mount options string was NULL.\n");
+ return 1;
+ }
+ dfprintk(MOUNT, "NFS: nfs mount opts='%s'\n", raw);
+
+ rc = security_sb_eat_lsm_opts(raw, &ctx->lsm_opts);
+ if (rc)
+ goto out_security_failure;
+
+ while ((p = strsep(&raw, ",")) != NULL) {
+ if (!*p)
+ continue;
+ if (nfs_fs_context_parse_option(ctx, p) < 0)
+ invalid_option = true;
+ }
+
if (!sloppy && invalid_option)
return 0;
@@ -938,22 +961,26 @@ int nfs_parse_mount_options(char *raw, struct nfs_fs_context *ctx)
* verify that any proto=/mountproto= options match the address
* families in the addr=/mountaddr= options.
*/
- if (protofamily != AF_UNSPEC &&
- protofamily != ctx->nfs_server.address.ss_family)
+ if (ctx->protofamily != AF_UNSPEC &&
+ ctx->protofamily != ctx->nfs_server.address.ss_family)
goto out_proto_mismatch;
- if (mountfamily != AF_UNSPEC) {
+ if (ctx->mountfamily != AF_UNSPEC) {
if (ctx->mount_server.addrlen) {
- if (mountfamily != ctx->mount_server.address.ss_family)
+ if (ctx->mountfamily != ctx->mount_server.address.ss_family)
goto out_mountproto_mismatch;
} else {
- if (mountfamily != ctx->nfs_server.address.ss_family)
+ if (ctx->mountfamily != ctx->nfs_server.address.ss_family)
goto out_mountproto_mismatch;
}
}
return 1;
+out_minorversion_mismatch:
+ printk(KERN_INFO "NFS: mount option vers=%u does not support "
+ "minorversion=%u\n", ctx->version, ctx->minorversion);
+ return 0;
out_mountproto_mismatch:
printk(KERN_INFO "NFS: mount server address does not match mountproto= "
"option\n");
@@ -961,23 +988,10 @@ int nfs_parse_mount_options(char *raw, struct nfs_fs_context *ctx)
out_proto_mismatch:
printk(KERN_INFO "NFS: server address does not match proto= option\n");
return 0;
-out_invalid_address:
- printk(KERN_INFO "NFS: bad IP address specified: %s\n", p);
- return 0;
-out_invalid_value:
- printk(KERN_INFO "NFS: bad mount option value specified: %s\n", p);
- return 0;
-out_minorversion_mismatch:
- printk(KERN_INFO "NFS: mount option vers=%u does not support "
- "minorversion=%u\n", ctx->version, ctx->minorversion);
- return 0;
out_migration_misuse:
printk(KERN_INFO
"NFS: 'migration' not supported for this NFS version\n");
- return 0;
-out_nomem:
- printk(KERN_INFO "NFS: not enough memory to parse option\n");
- return 0;
+ return -EINVAL;
out_security_failure:
printk(KERN_INFO "NFS: security options invalid: %d\n", rc);
return 0;
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 7131fa150d1b..d0abc7b65cd2 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -96,7 +96,10 @@ struct nfs_fs_context {
unsigned int version;
unsigned int minorversion;
char *fscache_uniq;
+ unsigned short protofamily;
+ unsigned short mountfamily;
bool need_mount;
+ bool sloppy;
struct {
struct sockaddr_storage address;
--
2.17.2
^ permalink raw reply related
* [PATCH v6 21/27] NFS: Add a small buffer in nfs_fs_context to avoid string dup
From: Scott Mayhew @ 2019-12-10 12:31 UTC (permalink / raw)
To: anna.schumaker, trond.myklebust
Cc: dhowells, viro, linux-nfs, linux-fsdevel, linux-kernel,
linux-security-module
In-Reply-To: <20191210123115.1655-1-smayhew@redhat.com>
From: David Howells <dhowells@redhat.com>
Add a small buffer in nfs_fs_context to avoid string duplication when
parsing numbers. Also make the parsing function wrapper place the parsed
integer directly in the appropriate nfs_fs_context struct member.
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/nfs/fs_context.c | 98 +++++++++++++++++++++------------------------
fs/nfs/internal.h | 2 +
2 files changed, 48 insertions(+), 52 deletions(-)
diff --git a/fs/nfs/fs_context.c b/fs/nfs/fs_context.c
index 92a1e4bd9133..2921c5820c31 100644
--- a/fs/nfs/fs_context.c
+++ b/fs/nfs/fs_context.c
@@ -468,27 +468,38 @@ static int nfs_get_option_str(substring_t args[], char **option)
return !*option;
}
-static int nfs_get_option_ul(substring_t args[], unsigned long *option)
+static int nfs_get_option_ui(struct nfs_fs_context *ctx,
+ substring_t args[], unsigned int *option)
{
- int rc;
- char *string;
+ match_strlcpy(ctx->buf, args, sizeof(ctx->buf));
+ return kstrtouint(ctx->buf, 10, option);
+}
- string = match_strdup(args);
- if (string == NULL)
- return -ENOMEM;
- rc = kstrtoul(string, 10, option);
- kfree(string);
+static int nfs_get_option_ui_bound(struct nfs_fs_context *ctx,
+ substring_t args[], unsigned int *option,
+ unsigned int l_bound, unsigned u_bound)
+{
+ int ret;
- return rc;
+ match_strlcpy(ctx->buf, args, sizeof(ctx->buf));
+ ret = kstrtouint(ctx->buf, 10, option);
+ if (ret < 0)
+ return ret;
+ if (*option < l_bound || *option > u_bound)
+ return -ERANGE;
+ return 0;
}
-static int nfs_get_option_ul_bound(substring_t args[], unsigned long *option,
- unsigned long l_bound, unsigned long u_bound)
+static int nfs_get_option_us_bound(struct nfs_fs_context *ctx,
+ substring_t args[], unsigned short *option,
+ unsigned short l_bound,
+ unsigned short u_bound)
{
int ret;
- ret = nfs_get_option_ul(args, option);
- if (ret != 0)
+ match_strlcpy(ctx->buf, args, sizeof(ctx->buf));
+ ret = kstrtou16(ctx->buf, 10, option);
+ if (ret < 0)
return ret;
if (*option < l_bound || *option > u_bound)
return -ERANGE;
@@ -501,7 +512,6 @@ static int nfs_get_option_ul_bound(substring_t args[], unsigned long *option,
static int nfs_fs_context_parse_option(struct nfs_fs_context *ctx, char *p)
{
substring_t args[MAX_OPT_ARGS];
- unsigned long option;
char *string;
int token, rc;
@@ -609,86 +619,70 @@ static int nfs_fs_context_parse_option(struct nfs_fs_context *ctx, char *p)
* options that take numeric values
*/
case Opt_port:
- if (nfs_get_option_ul(args, &option) ||
- option > USHRT_MAX)
+ if (nfs_get_option_ui_bound(ctx, args, &ctx->nfs_server.port,
+ 0, USHRT_MAX))
goto out_invalid_value;
- ctx->nfs_server.port = option;
break;
case Opt_rsize:
- if (nfs_get_option_ul(args, &option))
+ if (nfs_get_option_ui(ctx, args, &ctx->rsize))
goto out_invalid_value;
- ctx->rsize = option;
break;
case Opt_wsize:
- if (nfs_get_option_ul(args, &option))
+ if (nfs_get_option_ui(ctx, args, &ctx->wsize))
goto out_invalid_value;
- ctx->wsize = option;
break;
case Opt_bsize:
- if (nfs_get_option_ul(args, &option))
+ if (nfs_get_option_ui(ctx, args, &ctx->bsize))
goto out_invalid_value;
- ctx->bsize = option;
break;
case Opt_timeo:
- if (nfs_get_option_ul_bound(args, &option, 1, INT_MAX))
+ if (nfs_get_option_ui_bound(ctx, args, &ctx->timeo, 1, INT_MAX))
goto out_invalid_value;
- ctx->timeo = option;
break;
case Opt_retrans:
- if (nfs_get_option_ul_bound(args, &option, 0, INT_MAX))
+ if (nfs_get_option_ui_bound(ctx, args, &ctx->retrans, 0, INT_MAX))
goto out_invalid_value;
- ctx->retrans = option;
break;
case Opt_acregmin:
- if (nfs_get_option_ul(args, &option))
+ if (nfs_get_option_ui(ctx, args, &ctx->acregmin))
goto out_invalid_value;
- ctx->acregmin = option;
break;
case Opt_acregmax:
- if (nfs_get_option_ul(args, &option))
+ if (nfs_get_option_ui(ctx, args, &ctx->acregmax))
goto out_invalid_value;
- ctx->acregmax = option;
break;
case Opt_acdirmin:
- if (nfs_get_option_ul(args, &option))
+ if (nfs_get_option_ui(ctx, args, &ctx->acdirmin))
goto out_invalid_value;
- ctx->acdirmin = option;
break;
case Opt_acdirmax:
- if (nfs_get_option_ul(args, &option))
+ if (nfs_get_option_ui(ctx, args, &ctx->acdirmax))
goto out_invalid_value;
- ctx->acdirmax = option;
break;
case Opt_actimeo:
- if (nfs_get_option_ul(args, &option))
+ if (nfs_get_option_ui(ctx, args, &ctx->acdirmax))
goto out_invalid_value;
ctx->acregmin = ctx->acregmax =
- ctx->acdirmin = ctx->acdirmax = option;
+ ctx->acdirmin = ctx->acdirmax;
break;
case Opt_namelen:
- if (nfs_get_option_ul(args, &option))
+ if (nfs_get_option_ui(ctx, args, &ctx->namlen))
goto out_invalid_value;
- ctx->namlen = option;
break;
case Opt_mountport:
- if (nfs_get_option_ul(args, &option) ||
- option > USHRT_MAX)
+ if (nfs_get_option_ui_bound(ctx, args, &ctx->mount_server.port,
+ 0, USHRT_MAX))
goto out_invalid_value;
- ctx->mount_server.port = option;
break;
case Opt_mountvers:
- if (nfs_get_option_ul(args, &option) ||
- option < NFS_MNT_VERSION ||
- option > NFS_MNT3_VERSION)
+ if (nfs_get_option_ui_bound(ctx, args, &ctx->mount_server.version,
+ NFS_MNT_VERSION, NFS_MNT3_VERSION))
goto out_invalid_value;
- ctx->mount_server.version = option;
break;
case Opt_minorversion:
- if (nfs_get_option_ul(args, &option))
- goto out_invalid_value;
- if (option > NFS4_MAX_MINOR_VERSION)
+ if (nfs_get_option_ui_bound(ctx, args, &ctx->minorversion,
+ 0, NFS4_MAX_MINOR_VERSION))
goto out_invalid_value;
- ctx->minorversion = option;
break;
/*
@@ -820,9 +814,9 @@ static int nfs_fs_context_parse_option(struct nfs_fs_context *ctx, char *p)
goto out_invalid_address;
break;
case Opt_nconnect:
- if (nfs_get_option_ul_bound(args, &option, 1, NFS_MAX_CONNECTIONS))
+ if (nfs_get_option_us_bound(ctx, args, &ctx->nfs_server.nconnect,
+ 1, NFS_MAX_CONNECTIONS))
goto out_invalid_value;
- ctx->nfs_server.nconnect = option;
break;
case Opt_lookupcache:
string = match_strdup(args);
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index d0abc7b65cd2..5342f3e4d565 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -122,6 +122,8 @@ struct nfs_fs_context {
void *lsm_opts;
struct net *net;
+
+ char buf[32]; /* Parse buffer */
};
/* mount_clnt.c */
--
2.17.2
^ permalink raw reply related
* [PATCH v6 27/27] NFS: Attach supplementary error information to fs_context.
From: Scott Mayhew @ 2019-12-10 12:31 UTC (permalink / raw)
To: anna.schumaker, trond.myklebust
Cc: dhowells, viro, linux-nfs, linux-fsdevel, linux-kernel,
linux-security-module
In-Reply-To: <20191210123115.1655-1-smayhew@redhat.com>
Split out from commit "NFS: Add fs_context support."
Add wrappers nfs_errorf(), nfs_invalf(), and nfs_warnf() which log error
information to the fs_context. Convert some printk's to use these new
wrappers instead.
Signed-off-by: Scott Mayhew <smayhew@redhat.com>
---
fs/nfs/fs_context.c | 105 +++++++++++++++-----------------------------
fs/nfs/getroot.c | 3 ++
fs/nfs/internal.h | 4 ++
fs/nfs/namespace.c | 2 +-
fs/nfs/nfs4super.c | 2 +
fs/nfs/super.c | 4 +-
6 files changed, 48 insertions(+), 72 deletions(-)
diff --git a/fs/nfs/fs_context.c b/fs/nfs/fs_context.c
index e472334b978d..429315c011ae 100644
--- a/fs/nfs/fs_context.c
+++ b/fs/nfs/fs_context.c
@@ -318,10 +318,8 @@ static int nfs_auth_info_add(struct fs_context *fc,
return 0;
}
- if (auth_info->flavor_len + 1 >= max_flavor_len) {
- dfprintk(MOUNT, "NFS: too many sec= flavors\n");
- return -EINVAL;
- }
+ if (auth_info->flavor_len + 1 >= max_flavor_len)
+ return nfs_invalf(fc, "NFS: too many sec= flavors");
auth_info->flavors[auth_info->flavor_len++] = flavor;
return 0;
@@ -378,9 +376,7 @@ static int nfs_parse_security_flavors(struct fs_context *fc,
pseudoflavor = RPC_AUTH_GSS_SPKMP;
break;
default:
- dfprintk(MOUNT,
- "NFS: sec= option '%s' not recognized\n", p);
- return -EINVAL;
+ return nfs_invalf(fc, "NFS: sec=%s option not recognized", p);
}
ret = nfs_auth_info_add(fc, &ctx->auth_info, pseudoflavor);
@@ -425,8 +421,7 @@ static int nfs_parse_version_string(struct fs_context *fc,
ctx->minorversion = 2;
break;
default:
- dfprintk(MOUNT, "NFS: Unsupported NFS version\n");
- return -EINVAL;
+ return nfs_invalf(fc, "NFS: Unsupported NFS version");
}
return 0;
}
@@ -451,10 +446,8 @@ static int nfs_fs_context_parse_param(struct fs_context *fc,
switch (opt) {
case Opt_source:
- if (fc->source) {
- dfprintk(MOUNT, "NFS: Multiple sources not supported\n");
- return -EINVAL;
- }
+ if (fc->source)
+ return nfs_invalf(fc, "NFS: Multiple sources not supported");
fc->source = param->string;
param->string = NULL;
break;
@@ -664,8 +657,7 @@ static int nfs_fs_context_parse_param(struct fs_context *fc,
xprt_load_transport(param->string);
break;
default:
- dfprintk(MOUNT, "NFS: unrecognized transport protocol\n");
- return -EINVAL;
+ return nfs_invalf(fc, "NFS: Unrecognized transport protocol");
}
ctx->protofamily = protofamily;
@@ -688,8 +680,7 @@ static int nfs_fs_context_parse_param(struct fs_context *fc,
break;
case Opt_xprt_rdma: /* not used for side protocols */
default:
- dfprintk(MOUNT, "NFS: unrecognized transport protocol\n");
- return -EINVAL;
+ return nfs_invalf(fc, "NFS: Unrecognized transport protocol");
}
ctx->mountfamily = mountfamily;
break;
@@ -774,13 +765,11 @@ static int nfs_fs_context_parse_param(struct fs_context *fc,
return 0;
out_invalid_value:
- printk(KERN_INFO "NFS: Bad mount option value specified\n");
- return -EINVAL;
+ return nfs_invalf(fc, "NFS: Bad mount option value specified");
out_invalid_address:
- printk(KERN_INFO "NFS: Bad IP address specified\n");
- return -EINVAL;
+ return nfs_invalf(fc, "NFS: Bad IP address specified");
out_of_bounds:
- printk(KERN_INFO "NFS: Value for '%s' out of range\n", param->key);
+ nfs_invalf(fc, "NFS: Value for '%s' out of range", param->key);
return -ERANGE;
}
@@ -846,19 +835,15 @@ static int nfs_parse_source(struct fs_context *fc,
return 0;
out_bad_devname:
- dfprintk(MOUNT, "NFS: device name not in host:path format\n");
- return -EINVAL;
-
+ return nfs_invalf(fc, "NFS: device name not in host:path format");
out_nomem:
- dfprintk(MOUNT, "NFS: not enough memory to parse device name\n");
+ nfs_errorf(fc, "NFS: not enough memory to parse device name");
return -ENOMEM;
-
out_hostname:
- dfprintk(MOUNT, "NFS: server hostname too long\n");
+ nfs_errorf(fc, "NFS: server hostname too long");
return -ENAMETOOLONG;
-
out_path:
- dfprintk(MOUNT, "NFS: export pathname too long\n");
+ nfs_errorf(fc, "NFS: export pathname too long");
return -ENAMETOOLONG;
}
@@ -1015,29 +1000,23 @@ static int nfs23_parse_monolithic(struct fs_context *fc,
ctx->skip_reconfig_option_check = true;
return 0;
}
- dfprintk(MOUNT, "NFS: mount program didn't pass any mount data\n");
- return -EINVAL;
+ return nfs_invalf(fc, "NFS: mount program didn't pass any mount data");
out_no_v3:
- dfprintk(MOUNT, "NFS: nfs_mount_data version %d does not support v3\n",
- data->version);
- return -EINVAL;
+ return nfs_invalf(fc, "NFS: nfs_mount_data version does not support v3");
out_no_sec:
- dfprintk(MOUNT, "NFS: nfs_mount_data version supports only AUTH_SYS\n");
- return -EINVAL;
+ return nfs_invalf(fc, "NFS: nfs_mount_data version supports only AUTH_SYS");
out_nomem:
- dfprintk(MOUNT, "NFS: not enough memory to handle mount options\n");
+ dfprintk(MOUNT, "NFS: not enough memory to handle mount options");
return -ENOMEM;
out_no_address:
- dfprintk(MOUNT, "NFS: mount program didn't pass remote address\n");
- return -EINVAL;
+ return nfs_invalf(fc, "NFS: mount program didn't pass remote address");
out_invalid_fh:
- dfprintk(MOUNT, "NFS: invalid root filehandle\n");
- return -EINVAL;
+ return nfs_invalf(fc, "NFS: invalid root filehandle");
}
#if IS_ENABLED(CONFIG_NFS_V4)
@@ -1132,21 +1111,17 @@ static int nfs4_parse_monolithic(struct fs_context *fc,
ctx->skip_reconfig_option_check = true;
return 0;
}
- dfprintk(MOUNT, "NFS4: mount program didn't pass any mount data\n");
- return -EINVAL;
+ return nfs_invalf(fc, "NFS4: mount program didn't pass any mount data");
out_inval_auth:
- dfprintk(MOUNT, "NFS4: Invalid number of RPC auth flavours %d\n",
- data->auth_flavourlen);
- return -EINVAL;
+ return nfs_invalf(fc, "NFS4: Invalid number of RPC auth flavours %d",
+ data->auth_flavourlen);
out_no_address:
- dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n");
- return -EINVAL;
+ return nfs_invalf(fc, "NFS4: mount program didn't pass remote address");
out_invalid_transport_udp:
- dfprintk(MOUNT, "NFSv4: Unsupported transport protocol udp\n");
- return -EINVAL;
+ return nfs_invalf(fc, "NFSv4: Unsupported transport protocol udp");
}
#endif
@@ -1164,8 +1139,7 @@ static int nfs_fs_context_parse_monolithic(struct fs_context *fc,
return nfs4_parse_monolithic(fc, data);
#endif
- dfprintk(MOUNT, "NFS: Unsupported monolithic data version\n");
- return -EINVAL;
+ return nfs_invalf(fc, "NFS: Unsupported monolithic data version");
}
/*
@@ -1253,32 +1227,25 @@ static int nfs_fs_context_validate(struct fs_context *fc)
return 0;
out_no_device_name:
- dfprintk(MOUNT, "NFS: Device name not specified\n");
- return -EINVAL;
+ return nfs_invalf(fc, "NFS: Device name not specified");
out_v4_not_compiled:
- dfprintk(MOUNT, "NFS: NFSv4 is not compiled into kernel\n");
+ nfs_errorf(fc, "NFS: NFSv4 is not compiled into kernel");
return -EPROTONOSUPPORT;
out_invalid_transport_udp:
- dfprintk(MOUNT, "NFSv4: Unsupported transport protocol udp\n");
- return -EINVAL;
+ return nfs_invalf(fc, "NFSv4: Unsupported transport protocol udp");
out_no_address:
- dfprintk(MOUNT, "NFS: mount program didn't pass remote address\n");
- return -EINVAL;
+ return nfs_invalf(fc, "NFS: mount program didn't pass remote address");
out_mountproto_mismatch:
- dfprintk(MOUNT, "NFS: Mount server address does not match mountproto= option\n");
- return -EINVAL;
+ return nfs_invalf(fc, "NFS: Mount server address does not match mountproto= option");
out_proto_mismatch:
- dfprintk(MOUNT, "NFS: Server address does not match proto= option\n");
- return -EINVAL;
+ return nfs_invalf(fc, "NFS: Server address does not match proto= option");
out_minorversion_mismatch:
- dfprintk(MOUNT, "NFS: Mount option vers=%u does not support minorversion=%u\n",
+ return nfs_invalf(fc, "NFS: Mount option vers=%u does not support minorversion=%u",
ctx->version, ctx->minorversion);
- return -EINVAL;
out_migration_misuse:
- dfprintk(MOUNT, "NFS: 'Migration' not supported for this NFS version\n");
- return -EINVAL;
+ return nfs_invalf(fc, "NFS: 'Migration' not supported for this NFS version");
out_version_unavailable:
- dfprintk(MOUNT, "NFS: Version unavailable\n");
+ nfs_errorf(fc, "NFS: Version unavailable");
return ret;
}
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c
index ab45496d23a6..b012c2668a1f 100644
--- a/fs/nfs/getroot.c
+++ b/fs/nfs/getroot.c
@@ -86,6 +86,7 @@ int nfs_get_root(struct super_block *s, struct fs_context *fc)
error = server->nfs_client->rpc_ops->getroot(server, ctx->mntfh, &fsinfo);
if (error < 0) {
dprintk("nfs_get_root: getattr error = %d\n", -error);
+ nfs_errorf(fc, "NFS: Couldn't getattr on root");
goto out_fattr;
}
@@ -93,6 +94,7 @@ int nfs_get_root(struct super_block *s, struct fs_context *fc)
if (IS_ERR(inode)) {
dprintk("nfs_get_root: get root inode failed\n");
error = PTR_ERR(inode);
+ nfs_errorf(fc, "NFS: Couldn't get root inode");
goto out_fattr;
}
@@ -108,6 +110,7 @@ int nfs_get_root(struct super_block *s, struct fs_context *fc)
if (IS_ERR(root)) {
dprintk("nfs_get_root: get root dentry failed\n");
error = PTR_ERR(root);
+ nfs_errorf(fc, "NFS: Couldn't get root dentry");
goto out_fattr;
}
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index a1fd4c3ebc4e..c0257411e158 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -133,6 +133,10 @@ struct nfs_fs_context {
} clone_data;
};
+#define nfs_errorf(fc, fmt, ...) errorf(fc, fmt, ## __VA_ARGS__)
+#define nfs_invalf(fc, fmt, ...) invalf(fc, fmt, ## __VA_ARGS__)
+#define nfs_warnf(fc, fmt, ...) warnf(fc, fmt, ## __VA_ARGS__)
+
static inline struct nfs_fs_context *nfs_fc2context(const struct fs_context *fc)
{
return fc->fs_private;
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index d537350c1fb7..4fd22c0d730c 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -281,7 +281,7 @@ int nfs_do_submount(struct fs_context *fc)
p = nfs_devname(dentry, buffer, 4096);
if (IS_ERR(p)) {
- dprintk("NFS: Couldn't determine submount pathname\n");
+ nfs_errorf(fc, "NFS: Couldn't determine submount pathname");
ret = PTR_ERR(p);
} else {
ret = vfs_parse_fs_string(fc, "source", p, buffer + 4096 - p);
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 7d5ed37633d8..1475f932d7da 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -225,6 +225,7 @@ int nfs4_try_get_tree(struct fs_context *fc)
fc, ctx->nfs_server.hostname,
ctx->nfs_server.export_path);
if (err) {
+ nfs_errorf(fc, "NFS4: Couldn't follow remote path");
dfprintk(MOUNT, "<-- nfs4_try_get_tree() = %d [error]\n", err);
} else {
dfprintk(MOUNT, "<-- nfs4_try_get_tree() = 0\n");
@@ -247,6 +248,7 @@ int nfs4_get_referral_tree(struct fs_context *fc)
fc, ctx->nfs_server.hostname,
ctx->nfs_server.export_path);
if (err) {
+ nfs_errorf(fc, "NFS4: Couldn't follow remote path");
dfprintk(MOUNT, "<-- nfs4_get_referral_tree() = %d [error]\n", err);
} else {
dfprintk(MOUNT, "<-- nfs4_get_referral_tree() = 0\n");
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index ed0290d5ebf3..76e0198adcfa 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -1205,7 +1205,7 @@ int nfs_get_tree_common(struct fs_context *fc)
fc->s_fs_info = NULL;
if (IS_ERR(s)) {
error = PTR_ERR(s);
- dfprintk(MOUNT, "NFS: Couldn't get superblock\n");
+ nfs_errorf(fc, "NFS: Couldn't get superblock");
goto out_err_nosb;
}
@@ -1234,7 +1234,7 @@ int nfs_get_tree_common(struct fs_context *fc)
error = nfs_get_root(s, fc);
if (error < 0) {
- dfprintk(MOUNT, "NFS: Couldn't get root dentry\n");
+ nfs_errorf(fc, "NFS: Couldn't get root dentry");
goto error_splat_super;
}
--
2.17.2
^ permalink raw reply related
* [PATCH v6 08/27] nfs: stash nfs_subversion reference into nfs_mount_info
From: Scott Mayhew @ 2019-12-10 12:30 UTC (permalink / raw)
To: anna.schumaker, trond.myklebust
Cc: dhowells, viro, linux-nfs, linux-fsdevel, linux-kernel,
linux-security-module
In-Reply-To: <20191210123115.1655-1-smayhew@redhat.com>
From: Al Viro <viro@zeniv.linux.org.uk>
That will allow to get rid of passing those references around in
quite a few places. Moreover, that will allow to merge xdev and
remote file_system_type.
Reviewed-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/nfs/internal.h | 1 +
fs/nfs/namespace.c | 6 +++---
fs/nfs/nfs4super.c | 1 +
fs/nfs/super.c | 1 +
4 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index b193dd626c0a..9888e9c7abe2 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -142,6 +142,7 @@ struct nfs_mount_info {
struct nfs_clone_mount *cloned;
struct nfs_server *server;
struct nfs_fh *mntfh;
+ struct nfs_subversion *nfs_mod;
};
extern int nfs_mount(struct nfs_mount_request *info);
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index a76aeb0c2923..a00936dd153b 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -236,8 +236,8 @@ struct vfsmount *nfs_do_submount(struct dentry *dentry, struct nfs_fh *fh,
.set_security = nfs_clone_sb_security,
.cloned = &mountdata,
.mntfh = fh,
+ .nfs_mod = NFS_SB(sb)->nfs_client->cl_nfs_mod,
};
- struct nfs_subversion *nfs_mod = NFS_SB(sb)->nfs_client->cl_nfs_mod;
struct nfs_server *server;
struct vfsmount *mnt;
char *page = (char *) __get_free_page(GFP_USER);
@@ -246,8 +246,8 @@ struct vfsmount *nfs_do_submount(struct dentry *dentry, struct nfs_fh *fh,
if (page == NULL)
return ERR_PTR(-ENOMEM);
- server = nfs_mod->rpc_ops->clone_server(NFS_SB(sb), fh,
- fattr, authflavor);
+ server = mount_info.nfs_mod->rpc_ops->clone_server(NFS_SB(sb), fh,
+ fattr, authflavor);
if (IS_ERR(server))
return ERR_CAST(server);
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index c489942b9069..6e5417027021 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -248,6 +248,7 @@ static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
.fill_super = nfs_fill_super,
.set_security = nfs_clone_sb_security,
.cloned = data,
+ .nfs_mod = &nfs_v4,
};
struct dentry *res;
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 97dc544eb220..6189f768aa59 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -2761,6 +2761,7 @@ struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
mntroot = ERR_CAST(nfs_mod);
goto out;
}
+ mount_info.nfs_mod = nfs_mod;
mntroot = nfs_mod->rpc_ops->try_mount(flags, dev_name, &mount_info, nfs_mod);
--
2.17.2
^ permalink raw reply related
* [PATCH v6 06/27] nfs4: fold nfs_do_root_mount/nfs_follow_remote_path
From: Scott Mayhew @ 2019-12-10 12:30 UTC (permalink / raw)
To: anna.schumaker, trond.myklebust
Cc: dhowells, viro, linux-nfs, linux-fsdevel, linux-kernel,
linux-security-module
In-Reply-To: <20191210123115.1655-1-smayhew@redhat.com>
From: Al Viro <viro@zeniv.linux.org.uk>
Reviewed-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/nfs/nfs4super.c | 88 +++++++++++++++++++---------------------------
1 file changed, 37 insertions(+), 51 deletions(-)
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 8146edf4ce3a..c489942b9069 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -101,37 +101,6 @@ nfs4_remote_mount(struct file_system_type *fs_type, int flags,
return nfs_fs_mount_common(flags, dev_name, info, &nfs_v4);
}
-static struct vfsmount *nfs_do_root_mount(struct nfs_server *server, int flags,
- struct nfs_mount_info *info,
- const char *hostname)
-{
- struct vfsmount *root_mnt;
- char *root_devname;
- size_t len;
-
- if (IS_ERR(server))
- return ERR_CAST(server);
-
- len = strlen(hostname) + 5;
- root_devname = kmalloc(len, GFP_KERNEL);
- if (root_devname == NULL) {
- nfs_free_server(server);
- return ERR_PTR(-ENOMEM);
- }
- /* Does hostname needs to be enclosed in brackets? */
- if (strchr(hostname, ':'))
- snprintf(root_devname, len, "[%s]:/", hostname);
- else
- snprintf(root_devname, len, "%s:/", hostname);
- info->server = server;
- root_mnt = vfs_kern_mount(&nfs4_remote_fs_type, flags, root_devname, info);
- if (info->server)
- nfs_free_server(info->server);
- info->server = NULL;
- kfree(root_devname);
- return root_mnt;
-}
-
struct nfs_referral_count {
struct list_head list;
const struct task_struct *task;
@@ -198,11 +167,38 @@ static void nfs_referral_loop_unprotect(void)
kfree(p);
}
-static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt,
- const char *export_path)
+static struct dentry *do_nfs4_mount(struct nfs_server *server, int flags,
+ struct nfs_mount_info *info,
+ const char *hostname,
+ const char *export_path)
{
+ struct vfsmount *root_mnt;
struct dentry *dentry;
+ char *root_devname;
int err;
+ size_t len;
+
+ if (IS_ERR(server))
+ return ERR_CAST(server);
+
+ len = strlen(hostname) + 5;
+ root_devname = kmalloc(len, GFP_KERNEL);
+ if (root_devname == NULL) {
+ nfs_free_server(server);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ /* Does hostname needs to be enclosed in brackets? */
+ if (strchr(hostname, ':'))
+ snprintf(root_devname, len, "[%s]:/", hostname);
+ else
+ snprintf(root_devname, len, "%s:/", hostname);
+ info->server = server;
+ root_mnt = vfs_kern_mount(&nfs4_remote_fs_type, flags, root_devname, info);
+ if (info->server)
+ nfs_free_server(info->server);
+ info->server = NULL;
+ kfree(root_devname);
if (IS_ERR(root_mnt))
return ERR_CAST(root_mnt);
@@ -223,22 +219,17 @@ struct dentry *nfs4_try_mount(int flags, const char *dev_name,
struct nfs_mount_info *mount_info,
struct nfs_subversion *nfs_mod)
{
- char *export_path;
- struct vfsmount *root_mnt;
- struct dentry *res;
struct nfs_parsed_mount_data *data = mount_info->parsed;
+ struct dentry *res;
mount_info->set_security = nfs_set_sb_security;
dfprintk(MOUNT, "--> nfs4_try_mount()\n");
- export_path = data->nfs_server.export_path;
- root_mnt = nfs_do_root_mount(
- nfs4_create_server(mount_info, &nfs_v4),
- flags, mount_info,
- data->nfs_server.hostname);
-
- res = nfs_follow_remote_path(root_mnt, export_path);
+ res = do_nfs4_mount(nfs4_create_server(mount_info, &nfs_v4),
+ flags, mount_info,
+ data->nfs_server.hostname,
+ data->nfs_server.export_path);
dfprintk(MOUNT, "<-- nfs4_try_mount() = %d%s\n",
PTR_ERR_OR_ZERO(res),
@@ -258,8 +249,6 @@ static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
.set_security = nfs_clone_sb_security,
.cloned = data,
};
- char *export_path;
- struct vfsmount *root_mnt;
struct dentry *res;
dprintk("--> nfs4_referral_mount()\n");
@@ -268,13 +257,10 @@ static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
if (!mount_info.mntfh)
return ERR_PTR(-ENOMEM);
- export_path = data->mnt_path;
- root_mnt = nfs_do_root_mount(
- nfs4_create_referral_server(mount_info.cloned,
- mount_info.mntfh),
- flags, &mount_info, data->hostname);
+ res = do_nfs4_mount(nfs4_create_referral_server(mount_info.cloned,
+ mount_info.mntfh),
+ flags, &mount_info, data->hostname, data->mnt_path);
- res = nfs_follow_remote_path(root_mnt, export_path);
dprintk("<-- nfs4_referral_mount() = %d%s\n",
PTR_ERR_OR_ZERO(res),
IS_ERR(res) ? " [error]" : "");
--
2.17.2
^ permalink raw reply related
* [PATCH v6 05/27] nfs: don't bother setting/restoring export_path around do_nfs_root_mount()
From: Scott Mayhew @ 2019-12-10 12:30 UTC (permalink / raw)
To: anna.schumaker, trond.myklebust
Cc: dhowells, viro, linux-nfs, linux-fsdevel, linux-kernel,
linux-security-module
In-Reply-To: <20191210123115.1655-1-smayhew@redhat.com>
From: Al Viro <viro@zeniv.linux.org.uk>
nothing in it will be looking at that thing anyway
Reviewed-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/nfs/nfs4super.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 54dbb4561ccc..8146edf4ce3a 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -233,12 +233,10 @@ struct dentry *nfs4_try_mount(int flags, const char *dev_name,
dfprintk(MOUNT, "--> nfs4_try_mount()\n");
export_path = data->nfs_server.export_path;
- data->nfs_server.export_path = "/";
root_mnt = nfs_do_root_mount(
nfs4_create_server(mount_info, &nfs_v4),
flags, mount_info,
data->nfs_server.hostname);
- data->nfs_server.export_path = export_path;
res = nfs_follow_remote_path(root_mnt, export_path);
@@ -271,12 +269,10 @@ static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
return ERR_PTR(-ENOMEM);
export_path = data->mnt_path;
- data->mnt_path = "/";
root_mnt = nfs_do_root_mount(
nfs4_create_referral_server(mount_info.cloned,
mount_info.mntfh),
flags, &mount_info, data->hostname);
- data->mnt_path = export_path;
res = nfs_follow_remote_path(root_mnt, export_path);
dprintk("<-- nfs4_referral_mount() = %d%s\n",
--
2.17.2
^ permalink raw reply related
* [PATCH v6 15/27] nfs: get rid of ->set_security()
From: Scott Mayhew @ 2019-12-10 12:31 UTC (permalink / raw)
To: anna.schumaker, trond.myklebust
Cc: dhowells, viro, linux-nfs, linux-fsdevel, linux-kernel,
linux-security-module
In-Reply-To: <20191210123115.1655-1-smayhew@redhat.com>
From: Al Viro <viro@zeniv.linux.org.uk>
it's always either nfs_set_sb_security() or nfs_clone_sb_security(),
the choice being controlled by mount_info->cloned != NULL. No need
to add methods, especially when both instances live right next to
the caller and are never accessed anywhere else.
Reviewed-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/nfs/internal.h | 3 --
fs/nfs/namespace.c | 1 -
fs/nfs/nfs4super.c | 3 --
fs/nfs/super.c | 69 ++++++++++++++--------------------------------
4 files changed, 21 insertions(+), 55 deletions(-)
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 65c8e353cb6b..a467e43fc682 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -137,7 +137,6 @@ struct nfs_mount_request {
struct nfs_mount_info {
unsigned int inherited_bsize;
- int (*set_security)(struct super_block *, struct dentry *, struct nfs_mount_info *);
struct nfs_parsed_mount_data *parsed;
struct nfs_clone_mount *cloned;
struct nfs_server *server;
@@ -391,8 +390,6 @@ extern struct file_system_type nfs4_referral_fs_type;
#endif
bool nfs_auth_info_match(const struct nfs_auth_info *, rpc_authflavor_t);
struct dentry *nfs_try_mount(int, const char *, struct nfs_mount_info *);
-int nfs_set_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *);
-int nfs_clone_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *);
struct dentry *nfs_fs_mount(struct file_system_type *, int, const char *, void *);
void nfs_kill_super(struct super_block *);
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 30331558bd8e..bfe607374feb 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -233,7 +233,6 @@ struct vfsmount *nfs_do_submount(struct dentry *dentry, struct nfs_fh *fh,
};
struct nfs_mount_info mount_info = {
.inherited_bsize = sb->s_blocksize_bits,
- .set_security = nfs_clone_sb_security,
.cloned = &mountdata,
.mntfh = fh,
.nfs_mod = NFS_SB(sb)->nfs_client->cl_nfs_mod,
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 5020a43b31c9..f1c2d294073a 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -201,8 +201,6 @@ struct dentry *nfs4_try_mount(int flags, const char *dev_name,
struct nfs_parsed_mount_data *data = mount_info->parsed;
struct dentry *res;
- mount_info->set_security = nfs_set_sb_security;
-
dfprintk(MOUNT, "--> nfs4_try_mount()\n");
res = do_nfs4_mount(nfs4_create_server(mount_info),
@@ -224,7 +222,6 @@ static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
{
struct nfs_clone_mount *data = raw_data;
struct nfs_mount_info mount_info = {
- .set_security = nfs_clone_sb_security,
.cloned = data,
.nfs_mod = &nfs_v4,
};
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index bec6c341f72c..de00f89dbe6e 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -2550,52 +2550,6 @@ static void nfs_get_cache_cookie(struct super_block *sb,
}
#endif
-int nfs_set_sb_security(struct super_block *s, struct dentry *mntroot,
- struct nfs_mount_info *mount_info)
-{
- int error;
- unsigned long kflags = 0, kflags_out = 0;
- if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL)
- kflags |= SECURITY_LSM_NATIVE_LABELS;
-
- error = security_sb_set_mnt_opts(s, mount_info->parsed->lsm_opts,
- kflags, &kflags_out);
- if (error)
- goto err;
-
- if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL &&
- !(kflags_out & SECURITY_LSM_NATIVE_LABELS))
- NFS_SB(s)->caps &= ~NFS_CAP_SECURITY_LABEL;
-err:
- return error;
-}
-EXPORT_SYMBOL_GPL(nfs_set_sb_security);
-
-int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot,
- struct nfs_mount_info *mount_info)
-{
- int error;
- unsigned long kflags = 0, kflags_out = 0;
-
- /* clone any lsm security options from the parent to the new sb */
- if (d_inode(mntroot)->i_fop != &nfs_dir_operations)
- return -ESTALE;
-
- if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL)
- kflags |= SECURITY_LSM_NATIVE_LABELS;
-
- error = security_sb_clone_mnt_opts(mount_info->cloned->sb, s, kflags,
- &kflags_out);
- if (error)
- return error;
-
- if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL &&
- !(kflags_out & SECURITY_LSM_NATIVE_LABELS))
- NFS_SB(s)->caps &= ~NFS_CAP_SECURITY_LABEL;
- return 0;
-}
-EXPORT_SYMBOL_GPL(nfs_clone_sb_security);
-
static void nfs_set_readahead(struct backing_dev_info *bdi,
unsigned long iomax_pages)
{
@@ -2610,6 +2564,7 @@ static struct dentry *nfs_fs_mount_common(int flags, const char *dev_name,
struct dentry *mntroot = ERR_PTR(-ENOMEM);
int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
struct nfs_server *server = mount_info->server;
+ unsigned long kflags = 0, kflags_out = 0;
struct nfs_sb_mountdata sb_mntdata = {
.mntflags = flags,
.server = server,
@@ -2670,7 +2625,26 @@ static struct dentry *nfs_fs_mount_common(int flags, const char *dev_name,
if (IS_ERR(mntroot))
goto error_splat_super;
- error = mount_info->set_security(s, mntroot, mount_info);
+
+ if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL)
+ kflags |= SECURITY_LSM_NATIVE_LABELS;
+ if (mount_info->cloned) {
+ if (d_inode(mntroot)->i_fop != &nfs_dir_operations) {
+ error = -ESTALE;
+ goto error_splat_root;
+ }
+ /* clone any lsm security options from the parent to the new sb */
+ error = security_sb_clone_mnt_opts(mount_info->cloned->sb, s, kflags,
+ &kflags_out);
+ } else {
+ error = security_sb_set_mnt_opts(s, mount_info->parsed->lsm_opts,
+ kflags, &kflags_out);
+ }
+ if (error)
+ goto error_splat_root;
+ if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL &&
+ !(kflags_out & SECURITY_LSM_NATIVE_LABELS))
+ NFS_SB(s)->caps &= ~NFS_CAP_SECURITY_LABEL;
if (error)
goto error_splat_root;
@@ -2695,7 +2669,6 @@ struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *raw_data)
{
struct nfs_mount_info mount_info = {
- .set_security = nfs_set_sb_security,
};
struct dentry *mntroot = ERR_PTR(-ENOMEM);
struct nfs_subversion *nfs_mod;
--
2.17.2
^ permalink raw reply related
* [PATCH v6 10/27] nfs: merge xdev and remote file_system_type
From: Scott Mayhew @ 2019-12-10 12:30 UTC (permalink / raw)
To: anna.schumaker, trond.myklebust
Cc: dhowells, viro, linux-nfs, linux-fsdevel, linux-kernel,
linux-security-module
In-Reply-To: <20191210123115.1655-1-smayhew@redhat.com>
From: Al Viro <viro@zeniv.linux.org.uk>
they are identical now...
Reviewed-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/nfs/internal.h | 2 +-
fs/nfs/namespace.c | 2 +-
fs/nfs/nfs4super.c | 22 +---------------------
fs/nfs/super.c | 14 ++++++++------
4 files changed, 11 insertions(+), 29 deletions(-)
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 4a0ba66bc3aa..e338558b7908 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -388,7 +388,7 @@ extern int nfs_wait_atomic_killable(atomic_t *p, unsigned int mode);
/* super.c */
extern const struct super_operations nfs_sops;
extern struct file_system_type nfs_fs_type;
-extern struct file_system_type nfs_xdev_fs_type;
+extern struct file_system_type nfs_prepared_fs_type;
#if IS_ENABLED(CONFIG_NFS_V4)
extern struct file_system_type nfs4_referral_fs_type;
#endif
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index a00936dd153b..e5f4f2d760af 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -257,7 +257,7 @@ struct vfsmount *nfs_do_submount(struct dentry *dentry, struct nfs_fh *fh,
if (IS_ERR(devname))
mnt = ERR_CAST(devname);
else
- mnt = vfs_submount(dentry, &nfs_xdev_fs_type, devname, &mount_info);
+ mnt = vfs_submount(dentry, &nfs_prepared_fs_type, devname, &mount_info);
if (mount_info.server)
nfs_free_server(mount_info.server);
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 2b34d8e124cd..1358d8078737 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -18,19 +18,9 @@
static int nfs4_write_inode(struct inode *inode, struct writeback_control *wbc);
static void nfs4_evict_inode(struct inode *inode);
-static struct dentry *nfs4_remote_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *raw_data);
static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *raw_data);
-static struct file_system_type nfs4_remote_fs_type = {
- .owner = THIS_MODULE,
- .name = "nfs4",
- .mount = nfs4_remote_mount,
- .kill_sb = nfs_kill_super,
- .fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
-};
-
struct file_system_type nfs4_referral_fs_type = {
.owner = THIS_MODULE,
.name = "nfs4",
@@ -91,16 +81,6 @@ static void nfs4_evict_inode(struct inode *inode)
nfs_clear_inode(inode);
}
-/*
- * Get the superblock for the NFS4 root partition
- */
-static struct dentry *
-nfs4_remote_mount(struct file_system_type *fs_type, int flags,
- const char *dev_name, void *info)
-{
- return nfs_fs_mount_common(flags, dev_name, info);
-}
-
struct nfs_referral_count {
struct list_head list;
const struct task_struct *task;
@@ -194,7 +174,7 @@ static struct dentry *do_nfs4_mount(struct nfs_server *server, int flags,
else
snprintf(root_devname, len, "%s:/", hostname);
info->server = server;
- root_mnt = vfs_kern_mount(&nfs4_remote_fs_type, flags, root_devname, info);
+ root_mnt = vfs_kern_mount(&nfs_prepared_fs_type, flags, root_devname, info);
if (info->server)
nfs_free_server(info->server);
info->server = NULL;
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index cb0ead628842..60845dc864e7 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -293,7 +293,7 @@ static match_table_t nfs_vers_tokens = {
{ Opt_vers_err, NULL }
};
-static struct dentry *nfs_xdev_mount(struct file_system_type *fs_type,
+static struct dentry *nfs_prepared_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *raw_data);
struct file_system_type nfs_fs_type = {
@@ -306,13 +306,14 @@ struct file_system_type nfs_fs_type = {
MODULE_ALIAS_FS("nfs");
EXPORT_SYMBOL_GPL(nfs_fs_type);
-struct file_system_type nfs_xdev_fs_type = {
+struct file_system_type nfs_prepared_fs_type = {
.owner = THIS_MODULE,
.name = "nfs",
- .mount = nfs_xdev_mount,
+ .mount = nfs_prepared_mount,
.kill_sb = nfs_kill_super,
.fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
};
+EXPORT_SYMBOL_GPL(nfs_prepared_fs_type);
const struct super_operations nfs_sops = {
.alloc_inode = nfs_alloc_inode,
@@ -2791,11 +2792,12 @@ void nfs_kill_super(struct super_block *s)
EXPORT_SYMBOL_GPL(nfs_kill_super);
/*
- * Clone an NFS2/3/4 server record on xdev traversal (FSID-change)
+ * Internal use only: mount_info is already set up by caller.
+ * Used for mountpoint crossings and for nfs4 root.
*/
static struct dentry *
-nfs_xdev_mount(struct file_system_type *fs_type, int flags,
- const char *dev_name, void *raw_data)
+nfs_prepared_mount(struct file_system_type *fs_type, int flags,
+ const char *dev_name, void *raw_data)
{
return nfs_fs_mount_common(flags, dev_name, raw_data);
}
--
2.17.2
^ permalink raw reply related
* [PATCH v6 12/27] nfs: don't pass nfs_subversion to ->create_server()
From: Scott Mayhew @ 2019-12-10 12:31 UTC (permalink / raw)
To: anna.schumaker, trond.myklebust
Cc: dhowells, viro, linux-nfs, linux-fsdevel, linux-kernel,
linux-security-module
In-Reply-To: <20191210123115.1655-1-smayhew@redhat.com>
From: Al Viro <viro@zeniv.linux.org.uk>
pick it from mount_info
Reviewed-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/nfs/client.c | 4 ++--
fs/nfs/internal.h | 7 ++-----
fs/nfs/nfs3_fs.h | 2 +-
fs/nfs/nfs3client.c | 5 ++---
fs/nfs/nfs4client.c | 3 +--
fs/nfs/nfs4super.c | 2 +-
fs/nfs/super.c | 14 +++++++-------
include/linux/nfs_xdr.h | 2 +-
8 files changed, 17 insertions(+), 22 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 02110a30a49e..a2049747adc4 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -951,10 +951,10 @@ EXPORT_SYMBOL_GPL(nfs_free_server);
* Create a version 2 or 3 volume record
* - keyed on server and FSID
*/
-struct nfs_server *nfs_create_server(struct nfs_mount_info *mount_info,
- struct nfs_subversion *nfs_mod)
+struct nfs_server *nfs_create_server(struct nfs_mount_info *mount_info)
{
struct nfs_server *server;
+ struct nfs_subversion *nfs_mod = mount_info->nfs_mod;
struct nfs_fattr *fattr;
int error;
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 310f81a149b2..0bb0493785fc 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -170,11 +170,8 @@ extern struct nfs_client *nfs4_find_client_ident(struct net *, int);
extern struct nfs_client *
nfs4_find_client_sessionid(struct net *, const struct sockaddr *,
struct nfs4_sessionid *, u32);
-extern struct nfs_server *nfs_create_server(struct nfs_mount_info *,
- struct nfs_subversion *);
-extern struct nfs_server *nfs4_create_server(
- struct nfs_mount_info *,
- struct nfs_subversion *);
+extern struct nfs_server *nfs_create_server(struct nfs_mount_info *);
+extern struct nfs_server *nfs4_create_server(struct nfs_mount_info *);
extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *,
struct nfs_fh *);
extern int nfs4_update_server(struct nfs_server *server, const char *hostname,
diff --git a/fs/nfs/nfs3_fs.h b/fs/nfs/nfs3_fs.h
index f82e11c4cb56..09602dc1889f 100644
--- a/fs/nfs/nfs3_fs.h
+++ b/fs/nfs/nfs3_fs.h
@@ -27,7 +27,7 @@ static inline int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
#endif /* CONFIG_NFS_V3_ACL */
/* nfs3client.c */
-struct nfs_server *nfs3_create_server(struct nfs_mount_info *, struct nfs_subversion *);
+struct nfs_server *nfs3_create_server(struct nfs_mount_info *);
struct nfs_server *nfs3_clone_server(struct nfs_server *, struct nfs_fh *,
struct nfs_fattr *, rpc_authflavor_t);
diff --git a/fs/nfs/nfs3client.c b/fs/nfs/nfs3client.c
index 223904bc40a7..54727d3d3042 100644
--- a/fs/nfs/nfs3client.c
+++ b/fs/nfs/nfs3client.c
@@ -46,10 +46,9 @@ static inline void nfs_init_server_aclclient(struct nfs_server *server)
}
#endif
-struct nfs_server *nfs3_create_server(struct nfs_mount_info *mount_info,
- struct nfs_subversion *nfs_mod)
+struct nfs_server *nfs3_create_server(struct nfs_mount_info *mount_info)
{
- struct nfs_server *server = nfs_create_server(mount_info, nfs_mod);
+ struct nfs_server *server = nfs_create_server(mount_info);
/* Create a client RPC handle for the NFS v3 ACL management interface */
if (!IS_ERR(server))
nfs_init_server_aclclient(server);
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index 460d6251c405..538fd036b69d 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -1112,8 +1112,7 @@ static int nfs4_init_server(struct nfs_server *server,
*/
/*struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
struct nfs_fh *mntfh)*/
-struct nfs_server *nfs4_create_server(struct nfs_mount_info *mount_info,
- struct nfs_subversion *nfs_mod)
+struct nfs_server *nfs4_create_server(struct nfs_mount_info *mount_info)
{
struct nfs_server *server;
bool auth_probe;
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 1358d8078737..e5d8a76bd144 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -205,7 +205,7 @@ struct dentry *nfs4_try_mount(int flags, const char *dev_name,
dfprintk(MOUNT, "--> nfs4_try_mount()\n");
- res = do_nfs4_mount(nfs4_create_server(mount_info, &nfs_v4),
+ res = do_nfs4_mount(nfs4_create_server(mount_info),
flags, mount_info,
data->nfs_server.hostname,
data->nfs_server.export_path);
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 0bedac041272..6239c78d8f54 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -1820,8 +1820,7 @@ static int nfs_request_mount(struct nfs_parsed_mount_data *args,
return 0;
}
-static struct nfs_server *nfs_try_mount_request(struct nfs_mount_info *mount_info,
- struct nfs_subversion *nfs_mod)
+static struct nfs_server *nfs_try_mount_request(struct nfs_mount_info *mount_info)
{
int status;
unsigned int i;
@@ -1831,6 +1830,7 @@ static struct nfs_server *nfs_try_mount_request(struct nfs_mount_info *mount_inf
struct nfs_parsed_mount_data *args = mount_info->parsed;
rpc_authflavor_t authlist[NFS_MAX_SECFLAVORS];
unsigned int authlist_len = ARRAY_SIZE(authlist);
+ struct nfs_subversion *nfs_mod = mount_info->nfs_mod;
status = nfs_request_mount(args, mount_info->mntfh, authlist,
&authlist_len);
@@ -1847,7 +1847,7 @@ static struct nfs_server *nfs_try_mount_request(struct nfs_mount_info *mount_inf
args->selected_flavor);
if (status)
return ERR_PTR(status);
- return nfs_mod->rpc_ops->create_server(mount_info, nfs_mod);
+ return nfs_mod->rpc_ops->create_server(mount_info);
}
/*
@@ -1874,7 +1874,7 @@ static struct nfs_server *nfs_try_mount_request(struct nfs_mount_info *mount_inf
}
dfprintk(MOUNT, "NFS: attempting to use auth flavor %u\n", flavor);
args->selected_flavor = flavor;
- server = nfs_mod->rpc_ops->create_server(mount_info, nfs_mod);
+ server = nfs_mod->rpc_ops->create_server(mount_info);
if (!IS_ERR(server))
return server;
}
@@ -1890,7 +1890,7 @@ static struct nfs_server *nfs_try_mount_request(struct nfs_mount_info *mount_inf
/* Last chance! Try AUTH_UNIX */
dfprintk(MOUNT, "NFS: attempting to use auth flavor %u\n", RPC_AUTH_UNIX);
args->selected_flavor = RPC_AUTH_UNIX;
- return nfs_mod->rpc_ops->create_server(mount_info, nfs_mod);
+ return nfs_mod->rpc_ops->create_server(mount_info);
}
static struct dentry *nfs_fs_mount_common(int, const char *, struct nfs_mount_info *);
@@ -1900,9 +1900,9 @@ struct dentry *nfs_try_mount(int flags, const char *dev_name,
{
struct nfs_subversion *nfs_mod = mount_info->nfs_mod;
if (mount_info->parsed->need_mount)
- mount_info->server = nfs_try_mount_request(mount_info, nfs_mod);
+ mount_info->server = nfs_try_mount_request(mount_info);
else
- mount_info->server = nfs_mod->rpc_ops->create_server(mount_info, nfs_mod);
+ mount_info->server = nfs_mod->rpc_ops->create_server(mount_info);
return nfs_fs_mount_common(flags, dev_name, mount_info);
}
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 3ee2ad642cbc..17527f6e6360 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1722,7 +1722,7 @@ struct nfs_rpc_ops {
struct nfs_client *(*init_client) (struct nfs_client *,
const struct nfs_client_initdata *);
void (*free_client) (struct nfs_client *);
- struct nfs_server *(*create_server)(struct nfs_mount_info *, struct nfs_subversion *);
+ struct nfs_server *(*create_server)(struct nfs_mount_info *);
struct nfs_server *(*clone_server)(struct nfs_server *, struct nfs_fh *,
struct nfs_fattr *, rpc_authflavor_t);
};
--
2.17.2
^ permalink raw reply related
* [PATCH v6 11/27] nfs: unexport nfs_fs_mount_common()
From: Scott Mayhew @ 2019-12-10 12:30 UTC (permalink / raw)
To: anna.schumaker, trond.myklebust
Cc: dhowells, viro, linux-nfs, linux-fsdevel, linux-kernel,
linux-security-module
In-Reply-To: <20191210123115.1655-1-smayhew@redhat.com>
From: Al Viro <viro@zeniv.linux.org.uk>
Make it static, even. And remove a stale extern of (long-gone)
nfs_xdev_mount_common() from internal.h, while we are at it.
Reviewed-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/nfs/internal.h | 3 ---
fs/nfs/super.c | 5 +++--
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index e338558b7908..310f81a149b2 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -396,10 +396,7 @@ bool nfs_auth_info_match(const struct nfs_auth_info *, rpc_authflavor_t);
struct dentry *nfs_try_mount(int, const char *, struct nfs_mount_info *);
int nfs_set_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *);
int nfs_clone_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *);
-struct dentry *nfs_fs_mount_common(int, const char *, struct nfs_mount_info *);
struct dentry *nfs_fs_mount(struct file_system_type *, int, const char *, void *);
-struct dentry * nfs_xdev_mount_common(struct file_system_type *, int,
- const char *, struct nfs_mount_info *);
void nfs_kill_super(struct super_block *);
void nfs_fill_super(struct super_block *, struct nfs_mount_info *);
void nfs_clone_super(struct super_block *, struct nfs_mount_info *);
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 60845dc864e7..0bedac041272 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -1893,6 +1893,8 @@ static struct nfs_server *nfs_try_mount_request(struct nfs_mount_info *mount_inf
return nfs_mod->rpc_ops->create_server(mount_info, nfs_mod);
}
+static struct dentry *nfs_fs_mount_common(int, const char *, struct nfs_mount_info *);
+
struct dentry *nfs_try_mount(int flags, const char *dev_name,
struct nfs_mount_info *mount_info)
{
@@ -2648,7 +2650,7 @@ static void nfs_set_readahead(struct backing_dev_info *bdi,
bdi->io_pages = iomax_pages;
}
-struct dentry *nfs_fs_mount_common(int flags, const char *dev_name,
+static struct dentry *nfs_fs_mount_common(int flags, const char *dev_name,
struct nfs_mount_info *mount_info)
{
struct super_block *s;
@@ -2730,7 +2732,6 @@ struct dentry *nfs_fs_mount_common(int flags, const char *dev_name,
deactivate_locked_super(s);
goto out;
}
-EXPORT_SYMBOL_GPL(nfs_fs_mount_common);
struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *raw_data)
--
2.17.2
^ permalink raw reply related
* [PATCH v6 14/27] nfs_clone_sb_security(): simplify the check for server bogosity
From: Scott Mayhew @ 2019-12-10 12:31 UTC (permalink / raw)
To: anna.schumaker, trond.myklebust
Cc: dhowells, viro, linux-nfs, linux-fsdevel, linux-kernel,
linux-security-module
In-Reply-To: <20191210123115.1655-1-smayhew@redhat.com>
From: Al Viro <viro@zeniv.linux.org.uk>
We used to check ->i_op for being nfs_dir_inode_operations. With
separate inode_operations for v3 and v4 that became bogus, but
rather than going for protocol-dependent comparison we could've
just checked ->i_fop instead; _that_ is the same for all protocol
versions.
Reviewed-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/nfs/super.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 2bcf0f8295e0..bec6c341f72c 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -2578,7 +2578,7 @@ int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot,
unsigned long kflags = 0, kflags_out = 0;
/* clone any lsm security options from the parent to the new sb */
- if (d_inode(mntroot)->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops)
+ if (d_inode(mntroot)->i_fop != &nfs_dir_operations)
return -ESTALE;
if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL)
--
2.17.2
^ permalink raw reply related
* [PATCH v6 00/27] nfs: Mount API conversion
From: Scott Mayhew @ 2019-12-10 12:30 UTC (permalink / raw)
To: anna.schumaker, trond.myklebust
Cc: dhowells, viro, linux-nfs, linux-fsdevel, linux-kernel,
linux-security-module
Hi Anna, Trond,
Here's a set of patches that converts NFS to use the mount API. Note that
there are a lot of preliminary patches, some from David and some from Al.
The final patch (the one that does the actual conversion) from the David's
initial posting has been split into 5 separate patches, and the entire set
has been rebased on top of v5.5-rc1.
Changes since v5:
- fixed possible derefence of error pointer in nfs4_validate_fspath()
reported by Dan Carpenter
- rebased on top of v5.5-rc1
Changes since v4:
- further split the original "NFS: Add fs_context support" patch (new
patch is about 25% smaller than the v4 patch)
- fixed NFSv4 referral mounts (broken in the original patch)
- fixed leak of nfs_fattr when fs_context is freed
Changes since v3:
- changed license and copyright text in fs/nfs/fs_context.c
Changes since v2:
- fixed the conversion of the nconnect= option
- added '#if IS_ENABLED(CONFIG_NFS_V4)' around nfs4_parse_monolithic()
to avoid unused-function warning when compiling with v4 disabled
Chagnes since v1:
- split up patch 23 into 4 separate patches
-Scott
Al Viro (15):
saner calling conventions for nfs_fs_mount_common()
nfs: stash server into struct nfs_mount_info
nfs: lift setting mount_info from nfs4_remote{,_referral}_mount
nfs: fold nfs4_remote_fs_type and nfs4_remote_referral_fs_type
nfs: don't bother setting/restoring export_path around
do_nfs_root_mount()
nfs4: fold nfs_do_root_mount/nfs_follow_remote_path
nfs: lift setting mount_info from nfs_xdev_mount()
nfs: stash nfs_subversion reference into nfs_mount_info
nfs: don't bother passing nfs_subversion to ->try_mount() and
nfs_fs_mount_common()
nfs: merge xdev and remote file_system_type
nfs: unexport nfs_fs_mount_common()
nfs: don't pass nfs_subversion to ->create_server()
nfs: get rid of mount_info ->fill_super()
nfs_clone_sb_security(): simplify the check for server bogosity
nfs: get rid of ->set_security()
David Howells (8):
NFS: Move mount parameterisation bits into their own file
NFS: Constify mount argument match tables
NFS: Rename struct nfs_parsed_mount_data to struct nfs_fs_context
NFS: Split nfs_parse_mount_options()
NFS: Deindent nfs_fs_context_parse_option()
NFS: Add a small buffer in nfs_fs_context to avoid string dup
NFS: Do some tidying of the parsing code
NFS: Add fs_context support.
Scott Mayhew (4):
NFS: rename nfs_fs_context pointer arg in a few functions
NFS: Convert mount option parsing to use functionality from
fs_parser.h
NFS: Additional refactoring for fs_context conversion
NFS: Attach supplementary error information to fs_context.
fs/nfs/Makefile | 2 +-
fs/nfs/client.c | 80 +-
fs/nfs/fs_context.c | 1424 +++++++++++++++++++++++++
fs/nfs/fscache.c | 2 +-
fs/nfs/getroot.c | 73 +-
fs/nfs/internal.h | 132 +--
fs/nfs/namespace.c | 146 ++-
fs/nfs/nfs3_fs.h | 2 +-
fs/nfs/nfs3client.c | 6 +-
fs/nfs/nfs3proc.c | 2 +-
fs/nfs/nfs4_fs.h | 9 +-
fs/nfs/nfs4client.c | 99 +-
fs/nfs/nfs4file.c | 1 +
fs/nfs/nfs4namespace.c | 292 +++---
fs/nfs/nfs4proc.c | 2 +-
fs/nfs/nfs4super.c | 257 ++---
fs/nfs/proc.c | 2 +-
fs/nfs/super.c | 2217 +++++----------------------------------
include/linux/nfs_xdr.h | 9 +-
19 files changed, 2287 insertions(+), 2470 deletions(-)
create mode 100644 fs/nfs/fs_context.c
--
2.17.2
^ permalink raw reply
* [PATCH v6 02/27] nfs: stash server into struct nfs_mount_info
From: Scott Mayhew @ 2019-12-10 12:30 UTC (permalink / raw)
To: anna.schumaker, trond.myklebust
Cc: dhowells, viro, linux-nfs, linux-fsdevel, linux-kernel,
linux-security-module
In-Reply-To: <20191210123115.1655-1-smayhew@redhat.com>
From: Al Viro <viro@zeniv.linux.org.uk>
Reviewed-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/nfs/internal.h | 3 ++-
fs/nfs/nfs4super.c | 10 ++++------
fs/nfs/super.c | 19 ++++++++-----------
3 files changed, 14 insertions(+), 18 deletions(-)
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 24a65da58aa9..8f4900bd04f7 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -142,6 +142,7 @@ struct nfs_mount_info {
int (*set_security)(struct super_block *, struct dentry *, struct nfs_mount_info *);
struct nfs_parsed_mount_data *parsed;
struct nfs_clone_mount *cloned;
+ struct nfs_server *server;
struct nfs_fh *mntfh;
};
@@ -397,7 +398,7 @@ struct dentry *nfs_try_mount(int, const char *, struct nfs_mount_info *,
struct nfs_subversion *);
int nfs_set_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *);
int nfs_clone_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *);
-struct dentry *nfs_fs_mount_common(struct nfs_server *, int, const char *,
+struct dentry *nfs_fs_mount_common(int, const char *,
struct nfs_mount_info *, struct nfs_subversion *);
struct dentry *nfs_fs_mount(struct file_system_type *, int, const char *, void *);
struct dentry * nfs_xdev_mount_common(struct file_system_type *, int,
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index beeaed872e6c..e7f2fd1925b1 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -109,13 +109,12 @@ nfs4_remote_mount(struct file_system_type *fs_type, int flags,
const char *dev_name, void *info)
{
struct nfs_mount_info *mount_info = info;
- struct nfs_server *server;
mount_info->set_security = nfs_set_sb_security;
/* Get a volume representation */
- server = nfs4_create_server(mount_info, &nfs_v4);
- return nfs_fs_mount_common(server, flags, dev_name, mount_info, &nfs_v4);
+ mount_info->server = nfs4_create_server(mount_info, &nfs_v4);
+ return nfs_fs_mount_common(flags, dev_name, mount_info, &nfs_v4);
}
static struct vfsmount *nfs_do_root_mount(struct file_system_type *fs_type,
@@ -260,7 +259,6 @@ nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags,
.set_security = nfs_clone_sb_security,
.cloned = raw_data,
};
- struct nfs_server *server;
struct dentry *mntroot = ERR_PTR(-ENOMEM);
dprintk("--> nfs4_referral_get_sb()\n");
@@ -270,8 +268,8 @@ nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags,
goto out;
/* create a new volume representation */
- server = nfs4_create_referral_server(mount_info.cloned, mount_info.mntfh);
- mntroot = nfs_fs_mount_common(server, flags, dev_name, &mount_info, &nfs_v4);
+ mount_info.server = nfs4_create_referral_server(mount_info.cloned, mount_info.mntfh);
+ mntroot = nfs_fs_mount_common(flags, dev_name, &mount_info, &nfs_v4);
out:
nfs_free_fhandle(mount_info.mntfh);
return mntroot;
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index f074c3773f0e..379c7b26051d 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -1896,14 +1896,12 @@ struct dentry *nfs_try_mount(int flags, const char *dev_name,
struct nfs_mount_info *mount_info,
struct nfs_subversion *nfs_mod)
{
- struct nfs_server *server;
-
if (mount_info->parsed->need_mount)
- server = nfs_try_mount_request(mount_info, nfs_mod);
+ mount_info->server = nfs_try_mount_request(mount_info, nfs_mod);
else
- server = nfs_mod->rpc_ops->create_server(mount_info, nfs_mod);
+ mount_info->server = nfs_mod->rpc_ops->create_server(mount_info, nfs_mod);
- return nfs_fs_mount_common(server, flags, dev_name, mount_info, nfs_mod);
+ return nfs_fs_mount_common(flags, dev_name, mount_info, nfs_mod);
}
EXPORT_SYMBOL_GPL(nfs_try_mount);
@@ -2649,20 +2647,21 @@ static void nfs_set_readahead(struct backing_dev_info *bdi,
bdi->io_pages = iomax_pages;
}
-struct dentry *nfs_fs_mount_common(struct nfs_server *server,
- int flags, const char *dev_name,
+struct dentry *nfs_fs_mount_common(int flags, const char *dev_name,
struct nfs_mount_info *mount_info,
struct nfs_subversion *nfs_mod)
{
struct super_block *s;
struct dentry *mntroot = ERR_PTR(-ENOMEM);
int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
+ struct nfs_server *server = mount_info->server;
struct nfs_sb_mountdata sb_mntdata = {
.mntflags = flags,
.server = server,
};
int error;
+ mount_info->server = NULL;
if (IS_ERR(server))
return ERR_CAST(server);
@@ -2803,7 +2802,6 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags,
.set_security = nfs_clone_sb_security,
.cloned = data,
};
- struct nfs_server *server;
struct dentry *mntroot = ERR_PTR(-ENOMEM);
struct nfs_subversion *nfs_mod = NFS_SB(data->sb)->nfs_client->cl_nfs_mod;
@@ -2812,10 +2810,9 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags,
mount_info.mntfh = mount_info.cloned->fh;
/* create a new volume representation */
- server = nfs_mod->rpc_ops->clone_server(NFS_SB(data->sb), data->fh, data->fattr, data->authflavor);
+ mount_info.server = nfs_mod->rpc_ops->clone_server(NFS_SB(data->sb), data->fh, data->fattr, data->authflavor);
- mntroot = nfs_fs_mount_common(server, flags,
- dev_name, &mount_info, nfs_mod);
+ mntroot = nfs_fs_mount_common(flags, dev_name, &mount_info, nfs_mod);
dprintk("<-- nfs_xdev_mount() = %ld\n",
IS_ERR(mntroot) ? PTR_ERR(mntroot) : 0L);
--
2.17.2
^ permalink raw reply related
* Re: [RFC PATCH] selinux: ensure we cleanup the internal AVC counters on error in avc_insert()
From: Stephen Smalley @ 2019-12-10 13:44 UTC (permalink / raw)
To: Paul Moore, selinux; +Cc: rsiddoji, linux-security-module
In-Reply-To: <157594281322.676903.11041338053333686450.stgit@chester>
On 12/9/19 8:53 PM, Paul Moore wrote:
> In AVC insert we don't call avc_node_kill() when avc_xperms_populate()
> fails, resulting in the avc->avc_cache.active_nodes counter having a
> false value.
incorrect value?
This patch corrects this problem and does some cleanup
> in avc_insert() while we are there.
submitting-patches.rst recommends describing in imperative mood and
avoiding the words "patch" in what will eventually just be a commit log,
ala "Correct this problem and perform some cleanup..."
Should probably add a:
Fixes: fa1aa143ac4a ("selinux: extended permissions for ioctls")
Might be easier to back port if you split the cleanup from the fix, but
your call of course.
>
> Reported-by: rsiddoji@codeaurora.org
> Suggested-by: Stephen Smalley <sds@tycho.nsa.gov>
> Signed-off-by: Paul Moore <paul@paul-moore.com>
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
> ---
> security/selinux/avc.c | 51 +++++++++++++++++++++++-------------------------
> 1 file changed, 24 insertions(+), 27 deletions(-)
>
> diff --git a/security/selinux/avc.c b/security/selinux/avc.c
> index 23dc888ae305..6646300f7ccb 100644
> --- a/security/selinux/avc.c
> +++ b/security/selinux/avc.c
> @@ -617,40 +617,37 @@ static struct avc_node *avc_insert(struct selinux_avc *avc,
> struct avc_node *pos, *node = NULL;
> int hvalue;
> unsigned long flag;
> + spinlock_t *lock;
> + struct hlist_head *head;
>
> if (avc_latest_notif_update(avc, avd->seqno, 1))
> - goto out;
> + return NULL;
>
> node = avc_alloc_node(avc);
> - if (node) {
> - struct hlist_head *head;
> - spinlock_t *lock;
> - int rc = 0;
> -
> - hvalue = avc_hash(ssid, tsid, tclass);
> - avc_node_populate(node, ssid, tsid, tclass, avd);
> - rc = avc_xperms_populate(node, xp_node);
> - if (rc) {
> - kmem_cache_free(avc_node_cachep, node);
> - return NULL;
> - }
> - head = &avc->avc_cache.slots[hvalue];
> - lock = &avc->avc_cache.slots_lock[hvalue];
> + if (!node)
> + return NULL;
>
> - spin_lock_irqsave(lock, flag);
> - hlist_for_each_entry(pos, head, list) {
> - if (pos->ae.ssid == ssid &&
> - pos->ae.tsid == tsid &&
> - pos->ae.tclass == tclass) {
> - avc_node_replace(avc, node, pos);
> - goto found;
> - }
> + avc_node_populate(node, ssid, tsid, tclass, avd);
> + if (avc_xperms_populate(node, xp_node)) {
> + avc_node_kill(avc, node);
> + return NULL;
> + }
> +
> + hvalue = avc_hash(ssid, tsid, tclass);
> + head = &avc->avc_cache.slots[hvalue];
> + lock = &avc->avc_cache.slots_lock[hvalue];
> + spin_lock_irqsave(lock, flag);
> + hlist_for_each_entry(pos, head, list) {
> + if (pos->ae.ssid == ssid &&
> + pos->ae.tsid == tsid &&
> + pos->ae.tclass == tclass) {
> + avc_node_replace(avc, node, pos);
> + goto found;
> }
> - hlist_add_head_rcu(&node->list, head);
> -found:
> - spin_unlock_irqrestore(lock, flag);
> }
> -out:
> + hlist_add_head_rcu(&node->list, head);
> +found:
> + spin_unlock_irqrestore(lock, flag);
> return node;
> }
>
>
^ permalink raw reply
* Re: [RFC PATCH] security: add an interface to lookup the lockdown reason
From: Stephen Smalley @ 2019-12-10 14:59 UTC (permalink / raw)
To: Paul Moore, selinux, linux-security-module; +Cc: linux-next, jamorris
In-Reply-To: <157594493094.748324.9234611948545428995.stgit@chester>
On 12/9/19 9:28 PM, Paul Moore wrote:
> With CONFIG_AUDIT enabled but CONFIG_SECURITY disabled we run into
> a problem where the lockdown reason table is missing. This patch
> attempts to fix this by hiding the table behind a lookup function.
Shouldn't lsm_audit.c be conditional on both CONFIG_AUDIT and
CONFIG_SECURITY? When/why would we want it built without
CONFIG_SECURITY enabled?
>
> Signed-off-by: Paul Moore <paul@paul-moore.com>
> ---
> include/linux/security.h | 7 +++++++
> security/lsm_audit.c | 12 +++++++++---
> security/security.c | 5 +++++
> 3 files changed, 21 insertions(+), 3 deletions(-)
>
> diff --git a/include/linux/security.h b/include/linux/security.h
> index 64b19f050343..295509a809d6 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -447,6 +447,8 @@ int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen);
> int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
> int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
> int security_locked_down(enum lockdown_reason what);
> +const char *security_locked_reasonstr(enum lockdown_reason what);
> +
> #else /* CONFIG_SECURITY */
>
> static inline int call_blocking_lsm_notifier(enum lsm_event event, void *data)
> @@ -1274,6 +1276,11 @@ static inline int security_locked_down(enum lockdown_reason what)
> {
> return 0;
> }
> +
> +static inline const char *security_locked_reasonstr(enum lockdown_reason what)
> +{
> + return NULL;
> +}
> #endif /* CONFIG_SECURITY */
>
> #ifdef CONFIG_SECURITY_NETWORK
> diff --git a/security/lsm_audit.c b/security/lsm_audit.c
> index 2d2bf49016f4..519ef6046638 100644
> --- a/security/lsm_audit.c
> +++ b/security/lsm_audit.c
> @@ -426,10 +426,16 @@ static void dump_common_audit_data(struct audit_buffer *ab,
> a->u.ibendport->dev_name,
> a->u.ibendport->port);
> break;
> - case LSM_AUDIT_DATA_LOCKDOWN:
> - audit_log_format(ab, " lockdown_reason=");
> - audit_log_string(ab, lockdown_reasons[a->u.reason]);
> + case LSM_AUDIT_DATA_LOCKDOWN: {
> + const char *str = security_locked_reasonstr(a->u.reason);
> +
> + if (str) {
> + audit_log_format(ab, " lockdown_reason=");
> + audit_log_string(ab, str);
> + } else
> + audit_log_format(ab, " lockdown_reason=?");
> break;
> + }
> } /* switch (a->type) */
> }
>
> diff --git a/security/security.c b/security/security.c
> index 2b5473d92416..2f228fdbebf5 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -2438,6 +2438,11 @@ int security_locked_down(enum lockdown_reason what)
> }
> EXPORT_SYMBOL(security_locked_down);
>
> +const char *security_locked_reasonstr(enum lockdown_reason what)
> +{
> + return lockdown_reasons[what];
> +}
> +
> #ifdef CONFIG_PERF_EVENTS
> int security_perf_event_open(struct perf_event_attr *attr, int type)
> {
>
^ permalink raw reply
* Re: [RFC PATCH] security: add an interface to lookup the lockdown reason
From: Paul Moore @ 2019-12-10 15:04 UTC (permalink / raw)
To: Stephen Smalley; +Cc: selinux, linux-security-module, linux-next, jamorris
In-Reply-To: <285edbb5-b08e-5bdc-f951-841fe1d77521@tycho.nsa.gov>
On Tue, Dec 10, 2019 at 9:59 AM Stephen Smalley <sds@tycho.nsa.gov> wrote:
> On 12/9/19 9:28 PM, Paul Moore wrote:
> > With CONFIG_AUDIT enabled but CONFIG_SECURITY disabled we run into
> > a problem where the lockdown reason table is missing. This patch
> > attempts to fix this by hiding the table behind a lookup function.
>
> Shouldn't lsm_audit.c be conditional on both CONFIG_AUDIT and
> CONFIG_SECURITY? When/why would we want it built without
> CONFIG_SECURITY enabled?
My first thought of a fix was just that, but I remembered that the
capabilities code is built regardless of the CONFIG_SECURITY setting
and I thought there might be some value in allowing for lsm_audit to
be used in commoncap (although in full disclosure commoncap doesn't
currently make use of lsm_audit).
--
paul moore
www.paul-moore.com
^ permalink raw reply
* Re: [RFC PATCH] security: add an interface to lookup the lockdown reason
From: Stephen Smalley @ 2019-12-10 15:45 UTC (permalink / raw)
To: Paul Moore; +Cc: selinux, linux-security-module, linux-next, jamorris
In-Reply-To: <CAHC9VhS4ksmcqBMzwQDArgd9xn_cJ+nyEBrHJcYjoiMaFzCq-Q@mail.gmail.com>
On 12/10/19 10:04 AM, Paul Moore wrote:
> On Tue, Dec 10, 2019 at 9:59 AM Stephen Smalley <sds@tycho.nsa.gov> wrote:
>> On 12/9/19 9:28 PM, Paul Moore wrote:
>>> With CONFIG_AUDIT enabled but CONFIG_SECURITY disabled we run into
>>> a problem where the lockdown reason table is missing. This patch
>>> attempts to fix this by hiding the table behind a lookup function.
>>
>> Shouldn't lsm_audit.c be conditional on both CONFIG_AUDIT and
>> CONFIG_SECURITY? When/why would we want it built without
>> CONFIG_SECURITY enabled?
>
> My first thought of a fix was just that, but I remembered that the
> capabilities code is built regardless of the CONFIG_SECURITY setting
> and I thought there might be some value in allowing for lsm_audit to
> be used in commoncap (although in full disclosure commoncap doesn't
> currently make use of lsm_audit).
Seems contrary to normal practice, i.e. if/when commoncap grows a
dependency, it can be changed then.
^ permalink raw reply
* Re: [RFC PATCH] selinux: ensure we cleanup the internal AVC counters on error in avc_insert()
From: Paul Moore @ 2019-12-10 15:54 UTC (permalink / raw)
To: Stephen Smalley; +Cc: selinux, rsiddoji, linux-security-module
In-Reply-To: <f7e43b67-3f46-e480-f8b0-e86eff85293f@tycho.nsa.gov>
On Tue, Dec 10, 2019 at 8:44 AM Stephen Smalley <sds@tycho.nsa.gov> wrote:
> On 12/9/19 8:53 PM, Paul Moore wrote:
> > In AVC insert we don't call avc_node_kill() when avc_xperms_populate()
> > fails, resulting in the avc->avc_cache.active_nodes counter having a
> > false value.
>
> incorrect value?
>
> This patch corrects this problem and does some cleanup
> > in avc_insert() while we are there.
>
> submitting-patches.rst recommends describing in imperative mood and
> avoiding the words "patch" in what will eventually just be a commit log,
> ala "Correct this problem and perform some cleanup..."
Well, you've made me feel better about my nit-picky comments on patches ;)
Are you okay with the following?
selinux: ensure we cleanup the internal AVC counters on error in avc_insert()
Fix avc_insert() to call avc_node_kill() if we've already allocated
an AVC node and the code fails to insert the node in the cache.
> Should probably add a:
>
> Fixes: fa1aa143ac4a ("selinux: extended permissions for ioctls")
>
> Might be easier to back port if you split the cleanup from the fix, but
> your call of course.
I waffled on that last night when I wrote up the patch, and more
generally if this should go to -stable or -next (despite what is
claimed, adding a "Fixes:" tag means it gets picked up by -stable more
often than not in my experience). At its worst, not fixing this bug
means we could end up effectively shrinking the AVC cache if xperms
are used *and* we happen to fail a memory allocation while adding a
new entry to the AVC; we don't cause an incorrect node to be cached,
we don't crash the system, we don't leak memory. My thinking is that
this isn't a major concern, and not worth the risk to -stable, but if
anyone has any data that shows otherwise, please let me know.
I'll go ahead and add the "Fixes:" tag (technically this is the
*right* thing to do), but I'm going to stick with -next and leave the
cleanup as-is just to raise the bar a bit for the -stable backports
which I'm sure are going to happen.
--
paul moore
www.paul-moore.com
^ permalink raw reply
* Re: [RFC PATCH] security: add an interface to lookup the lockdown reason
From: Paul Moore @ 2019-12-10 15:58 UTC (permalink / raw)
To: Stephen Smalley; +Cc: selinux, linux-security-module, linux-next, jamorris
In-Reply-To: <a11bfefc-c010-36ca-2303-35dcd4e9aa41@tycho.nsa.gov>
On Tue, Dec 10, 2019 at 10:45 AM Stephen Smalley <sds@tycho.nsa.gov> wrote:
> On 12/10/19 10:04 AM, Paul Moore wrote:
> > On Tue, Dec 10, 2019 at 9:59 AM Stephen Smalley <sds@tycho.nsa.gov> wrote:
> >> On 12/9/19 9:28 PM, Paul Moore wrote:
> >>> With CONFIG_AUDIT enabled but CONFIG_SECURITY disabled we run into
> >>> a problem where the lockdown reason table is missing. This patch
> >>> attempts to fix this by hiding the table behind a lookup function.
> >>
> >> Shouldn't lsm_audit.c be conditional on both CONFIG_AUDIT and
> >> CONFIG_SECURITY? When/why would we want it built without
> >> CONFIG_SECURITY enabled?
> >
> > My first thought of a fix was just that, but I remembered that the
> > capabilities code is built regardless of the CONFIG_SECURITY setting
> > and I thought there might be some value in allowing for lsm_audit to
> > be used in commoncap (although in full disclosure commoncap doesn't
> > currently make use of lsm_audit).
>
> Seems contrary to normal practice, i.e. if/when commoncap grows a
> dependency, it can be changed then.
Okay, want to submit a tested patch? I really would like to get this
fixed before today's linux-next run.
--
paul moore
www.paul-moore.com
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox