summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2020-02-08 13:26:41 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2020-02-08 13:26:41 -0800
commitc9d35ee049b40f1d73e890bf88dd55f83b1e9be8 (patch)
tree7b942b7ee530f5a183df80f506d1292b9966d53c /include
parent236f45329460f76d058111de1a1cea12f5a8b734 (diff)
parentf35aa2bc809eacc44c3cee41b52cef1c451d4a89 (diff)
Merge branch 'merge.nfs-fs_parse.1' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs file system parameter updates from Al Viro: "Saner fs_parser.c guts and data structures. The system-wide registry of syntax types (string/enum/int32/oct32/.../etc.) is gone and so is the horror switch() in fs_parse() that would have to grow another case every time something got added to that system-wide registry. New syntax types can be added by filesystems easily now, and their namespace is that of functions - not of system-wide enum members. IOW, they can be shared or kept private and if some turn out to be widely useful, we can make them common library helpers, etc., without having to do anything whatsoever to fs_parse() itself. And we already get that kind of requests - the thing that finally pushed me into doing that was "oh, and let's add one for timeouts - things like 15s or 2h". If some filesystem really wants that, let them do it. Without somebody having to play gatekeeper for the variants blessed by direct support in fs_parse(), TYVM. Quite a bit of boilerplate is gone. And IMO the data structures make a lot more sense now. -200LoC, while we are at it" * 'merge.nfs-fs_parse.1' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (25 commits) tmpfs: switch to use of invalfc() cgroup1: switch to use of errorfc() et.al. procfs: switch to use of invalfc() hugetlbfs: switch to use of invalfc() cramfs: switch to use of errofc() et.al. gfs2: switch to use of errorfc() et.al. fuse: switch to use errorfc() et.al. ceph: use errorfc() and friends instead of spelling the prefix out prefix-handling analogues of errorf() and friends turn fs_param_is_... into functions fs_parse: handle optional arguments sanely fs_parse: fold fs_parameter_desc/fs_parameter_spec fs_parser: remove fs_parameter_description name field add prefix to fs_context->log ceph_parse_param(), ceph_parse_mon_ips(): switch to passing fc_log new primitive: __fs_parse() switch rbd and libceph to p_log-based primitives struct p_log, variants of warnf() et.al. taking that one instead teach logfc() to handle prefices, give it saner calling conventions get rid of cg_invalf() ...
Diffstat (limited to 'include')
-rw-r--r--include/linux/ceph/libceph.h5
-rw-r--r--include/linux/fs.h4
-rw-r--r--include/linux/fs_context.h32
-rw-r--r--include/linux/fs_parser.h101
-rw-r--r--include/linux/ramfs.h4
-rw-r--r--include/linux/shmem_fs.h3
6 files changed, 78 insertions, 71 deletions
diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h
index 8fe9b80e80a5..ec73ebc4827d 100644
--- a/include/linux/ceph/libceph.h
+++ b/include/linux/ceph/libceph.h
@@ -281,11 +281,12 @@ extern int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid);
extern void *ceph_kvmalloc(size_t size, gfp_t flags);
struct fs_parameter;
+struct fc_log;
struct ceph_options *ceph_alloc_options(void);
int ceph_parse_mon_ips(const char *buf, size_t len, struct ceph_options *opt,
- struct fs_context *fc);
+ struct fc_log *l);
int ceph_parse_param(struct fs_parameter *param, struct ceph_options *opt,
- struct fs_context *fc);
+ struct fc_log *l);
int ceph_print_client_options(struct seq_file *m, struct ceph_client *client,
bool show_all);
extern void ceph_destroy_options(struct ceph_options *opt);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 320d51b24325..3cd4fe6b845e 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -67,7 +67,7 @@ struct fscrypt_operations;
struct fsverity_info;
struct fsverity_operations;
struct fs_context;
-struct fs_parameter_description;
+struct fs_parameter_spec;
extern void __init inode_init(void);
extern void __init inode_init_early(void);
@@ -2235,7 +2235,7 @@ struct file_system_type {
#define FS_DISALLOW_NOTIFY_PERM 16 /* Disable fanotify permission events */
#define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() during rename() internally. */
int (*init_fs_context)(struct fs_context *);
- const struct fs_parameter_description *parameters;
+ const struct fs_parameter_spec *parameters;
struct dentry *(*mount) (struct file_system_type *, int,
const char *, void *);
void (*kill_sb) (struct super_block *);
diff --git a/include/linux/fs_context.h b/include/linux/fs_context.h
index e5c14e2c53d3..e6c3e4c61dad 100644
--- a/include/linux/fs_context.h
+++ b/include/linux/fs_context.h
@@ -54,7 +54,6 @@ enum fs_value_type {
fs_value_is_string, /* Value is a string */
fs_value_is_blob, /* Value is a binary blob */
fs_value_is_filename, /* Value is a filename* + dirfd */
- fs_value_is_filename_empty, /* Value is a filename* + dirfd + AT_EMPTY_PATH */
fs_value_is_file, /* Value is a file* */
};
@@ -74,6 +73,11 @@ struct fs_parameter {
int dirfd;
};
+struct p_log {
+ const char *prefix;
+ struct fc_log *log;
+};
+
/*
* Filesystem context for holding the parameters used in the creation or
* reconfiguration of a superblock.
@@ -93,7 +97,7 @@ struct fs_context {
struct user_namespace *user_ns; /* The user namespace for this mount */
struct net *net_ns; /* The network namespace for this mount */
const struct cred *cred; /* The mounter's credentials */
- struct fc_log *log; /* Logging buffer */
+ struct p_log log; /* Logging buffer */
const char *source; /* The source name (eg. dev path) */
void *security; /* Linux S&M options */
void *s_fs_info; /* Proposed s_fs_info */
@@ -182,9 +186,13 @@ struct fc_log {
char *buffer[8];
};
-extern __attribute__((format(printf, 2, 3)))
-void logfc(struct fs_context *fc, const char *fmt, ...);
+extern __attribute__((format(printf, 4, 5)))
+void logfc(struct fc_log *log, const char *prefix, char level, const char *fmt, ...);
+#define __logfc(fc, l, fmt, ...) logfc((fc)->log.log, NULL, \
+ l, fmt, ## __VA_ARGS__)
+#define __plog(p, l, fmt, ...) logfc((p)->log, (p)->prefix, \
+ l, fmt, ## __VA_ARGS__)
/**
* infof - Store supplementary informational message
* @fc: The context in which to log the informational message
@@ -193,7 +201,9 @@ void logfc(struct fs_context *fc, const char *fmt, ...);
* Store the supplementary informational message for the process if the process
* has enabled the facility.
*/
-#define infof(fc, fmt, ...) ({ logfc(fc, "i "fmt, ## __VA_ARGS__); })
+#define infof(fc, fmt, ...) __logfc(fc, 'i', fmt, ## __VA_ARGS__)
+#define info_plog(p, fmt, ...) __plog(p, 'i', fmt, ## __VA_ARGS__)
+#define infofc(p, fmt, ...) __plog((&(fc)->log), 'i', fmt, ## __VA_ARGS__)
/**
* warnf - Store supplementary warning message
@@ -203,7 +213,9 @@ void logfc(struct fs_context *fc, const char *fmt, ...);
* Store the supplementary warning message for the process if the process has
* enabled the facility.
*/
-#define warnf(fc, fmt, ...) ({ logfc(fc, "w "fmt, ## __VA_ARGS__); })
+#define warnf(fc, fmt, ...) __logfc(fc, 'w', fmt, ## __VA_ARGS__)
+#define warn_plog(p, fmt, ...) __plog(p, 'w', fmt, ## __VA_ARGS__)
+#define warnfc(fc, fmt, ...) __plog((&(fc)->log), 'w', fmt, ## __VA_ARGS__)
/**
* errorf - Store supplementary error message
@@ -213,7 +225,9 @@ void logfc(struct fs_context *fc, const char *fmt, ...);
* Store the supplementary error message for the process if the process has
* enabled the facility.
*/
-#define errorf(fc, fmt, ...) ({ logfc(fc, "e "fmt, ## __VA_ARGS__); })
+#define errorf(fc, fmt, ...) __logfc(fc, 'e', fmt, ## __VA_ARGS__)
+#define error_plog(p, fmt, ...) __plog(p, 'e', fmt, ## __VA_ARGS__)
+#define errorfc(fc, fmt, ...) __plog((&(fc)->log), 'e', fmt, ## __VA_ARGS__)
/**
* invalf - Store supplementary invalid argument error message
@@ -223,6 +237,8 @@ void logfc(struct fs_context *fc, const char *fmt, ...);
* Store the supplementary error message for the process if the process has
* enabled the facility and return -EINVAL.
*/
-#define invalf(fc, fmt, ...) ({ errorf(fc, fmt, ## __VA_ARGS__); -EINVAL; })
+#define invalf(fc, fmt, ...) (errorf(fc, fmt, ## __VA_ARGS__), -EINVAL)
+#define inval_plog(p, fmt, ...) (error_plog(p, fmt, ## __VA_ARGS__), -EINVAL)
+#define invalfc(fc, fmt, ...) (errorfc(fc, fmt, ## __VA_ARGS__), -EINVAL)
#endif /* _LINUX_FS_CONTEXT_H */
diff --git a/include/linux/fs_parser.h b/include/linux/fs_parser.h
index dee140db6240..2eab6d5f6736 100644
--- a/include/linux/fs_parser.h
+++ b/include/linux/fs_parser.h
@@ -17,26 +17,18 @@ struct constant_table {
int value;
};
+struct fs_parameter_spec;
+struct fs_parse_result;
+typedef int fs_param_type(struct p_log *,
+ const struct fs_parameter_spec *,
+ struct fs_parameter *,
+ struct fs_parse_result *);
/*
* The type of parameter expected.
*/
-enum fs_parameter_type {
- __fs_param_wasnt_defined,
- fs_param_is_flag,
- fs_param_is_bool,
- fs_param_is_u32,
- fs_param_is_u32_octal,
- fs_param_is_u32_hex,
- fs_param_is_s32,
- fs_param_is_u64,
- fs_param_is_enum,
- fs_param_is_string,
- fs_param_is_blob,
- fs_param_is_blockdev,
- fs_param_is_path,
- fs_param_is_fd,
- nr__fs_parameter_type,
-};
+fs_param_type fs_param_is_bool, fs_param_is_u32, fs_param_is_s32, fs_param_is_u64,
+ fs_param_is_enum, fs_param_is_string, fs_param_is_blob, fs_param_is_blockdev,
+ fs_param_is_path, fs_param_is_fd;
/*
* Specification of the type of value a parameter wants.
@@ -46,25 +38,13 @@ enum fs_parameter_type {
*/
struct fs_parameter_spec {
const char *name;
+ fs_param_type *type; /* The desired parameter type */
u8 opt; /* Option number (returned by fs_parse()) */
- enum fs_parameter_type type:8; /* The desired parameter type */
unsigned short flags;
-#define fs_param_v_optional 0x0001 /* The value is optional */
#define fs_param_neg_with_no 0x0002 /* "noxxx" is negative param */
#define fs_param_neg_with_empty 0x0004 /* "xxx=" is negative param */
#define fs_param_deprecated 0x0008 /* The param is deprecated */
-};
-
-struct fs_parameter_enum {
- u8 opt; /* Option number (as fs_parameter_spec::opt) */
- char name[14];
- u8 value;
-};
-
-struct fs_parameter_description {
- const char name[16]; /* Name for logging purposes */
- const struct fs_parameter_spec *specs; /* List of param specifications */
- const struct fs_parameter_enum *enums; /* Enum values */
+ const void *data;
};
/*
@@ -72,7 +52,6 @@ struct fs_parameter_description {
*/
struct fs_parse_result {
bool negated; /* T if param was "noxxx" */
- bool has_value; /* T if value supplied to param */
union {
bool boolean; /* For spec_bool */
int int_32; /* For spec_s32/spec_enum */
@@ -81,28 +60,37 @@ struct fs_parse_result {
};
};
-extern int fs_parse(struct fs_context *fc,
- const struct fs_parameter_description *desc,
+extern int __fs_parse(struct p_log *log,
+ const struct fs_parameter_spec *desc,
struct fs_parameter *value,
struct fs_parse_result *result);
+
+static inline int fs_parse(struct fs_context *fc,
+ const struct fs_parameter_spec *desc,
+ struct fs_parameter *param,
+ struct fs_parse_result *result)
+{
+ return __fs_parse(&fc->log, desc, param, result);
+}
+
extern int fs_lookup_param(struct fs_context *fc,
struct fs_parameter *param,
bool want_bdev,
struct path *_path);
-extern int __lookup_constant(const struct constant_table tbl[], size_t tbl_size,
- const char *name, int not_found);
-#define lookup_constant(t, n, nf) __lookup_constant(t, ARRAY_SIZE(t), (n), (nf))
+extern int lookup_constant(const struct constant_table tbl[], const char *name, int not_found);
#ifdef CONFIG_VALIDATE_FS_PARSER
extern bool validate_constant_table(const struct constant_table *tbl, size_t tbl_size,
int low, int high, int special);
-extern bool fs_validate_description(const struct fs_parameter_description *desc);
+extern bool fs_validate_description(const char *name,
+ const struct fs_parameter_spec *desc);
#else
static inline bool validate_constant_table(const struct constant_table *tbl, size_t tbl_size,
int low, int high, int special)
{ return true; }
-static inline bool fs_validate_description(const struct fs_parameter_description *desc)
+static inline bool fs_validate_description(const char *name,
+ const struct fs_parameter_spec *desc)
{ return true; }
#endif
@@ -115,33 +103,32 @@ static inline bool fs_validate_description(const struct fs_parameter_description
* work, but any such case is probably a sign that new helper is needed.
* Helpers will remain stable; low-level implementation may change.
*/
-#define __fsparam(TYPE, NAME, OPT, FLAGS) \
+#define __fsparam(TYPE, NAME, OPT, FLAGS, DATA) \
{ \
.name = NAME, \
.opt = OPT, \
.type = TYPE, \
- .flags = FLAGS \
+ .flags = FLAGS, \
+ .data = DATA \
}
-#define fsparam_flag(NAME, OPT) __fsparam(fs_param_is_flag, NAME, OPT, 0)
+#define fsparam_flag(NAME, OPT) __fsparam(NULL, NAME, OPT, 0, NULL)
#define fsparam_flag_no(NAME, OPT) \
- __fsparam(fs_param_is_flag, NAME, OPT, \
- fs_param_neg_with_no)
-#define fsparam_bool(NAME, OPT) __fsparam(fs_param_is_bool, NAME, OPT, 0)
-#define fsparam_u32(NAME, OPT) __fsparam(fs_param_is_u32, NAME, OPT, 0)
+ __fsparam(NULL, NAME, OPT, fs_param_neg_with_no, NULL)
+#define fsparam_bool(NAME, OPT) __fsparam(fs_param_is_bool, NAME, OPT, 0, NULL)
+#define fsparam_u32(NAME, OPT) __fsparam(fs_param_is_u32, NAME, OPT, 0, NULL)
#define fsparam_u32oct(NAME, OPT) \
- __fsparam(fs_param_is_u32_octal, NAME, OPT, 0)
+ __fsparam(fs_param_is_u32, NAME, OPT, 0, (void *)8)
#define fsparam_u32hex(NAME, OPT) \
- __fsparam(fs_param_is_u32_hex, NAME, OPT, 0)
-#define fsparam_s32(NAME, OPT) __fsparam(fs_param_is_s32, NAME, OPT, 0)
-#define fsparam_u64(NAME, OPT) __fsparam(fs_param_is_u64, NAME, OPT, 0)
-#define fsparam_enum(NAME, OPT) __fsparam(fs_param_is_enum, NAME, OPT, 0)
+ __fsparam(fs_param_is_u32_hex, NAME, OPT, 0, (void *16))
+#define fsparam_s32(NAME, OPT) __fsparam(fs_param_is_s32, NAME, OPT, 0, NULL)
+#define fsparam_u64(NAME, OPT) __fsparam(fs_param_is_u64, NAME, OPT, 0, NULL)
+#define fsparam_enum(NAME, OPT, array) __fsparam(fs_param_is_enum, NAME, OPT, 0, array)
#define fsparam_string(NAME, OPT) \
- __fsparam(fs_param_is_string, NAME, OPT, 0)
-#define fsparam_blob(NAME, OPT) __fsparam(fs_param_is_blob, NAME, OPT, 0)
-#define fsparam_bdev(NAME, OPT) __fsparam(fs_param_is_blockdev, NAME, OPT, 0)
-#define fsparam_path(NAME, OPT) __fsparam(fs_param_is_path, NAME, OPT, 0)
-#define fsparam_fd(NAME, OPT) __fsparam(fs_param_is_fd, NAME, OPT, 0)
-
+ __fsparam(fs_param_is_string, NAME, OPT, 0, NULL)
+#define fsparam_blob(NAME, OPT) __fsparam(fs_param_is_blob, NAME, OPT, 0, NULL)
+#define fsparam_bdev(NAME, OPT) __fsparam(fs_param_is_blockdev, NAME, OPT, 0, NULL)
+#define fsparam_path(NAME, OPT) __fsparam(fs_param_is_path, NAME, OPT, 0, NULL)
+#define fsparam_fd(NAME, OPT) __fsparam(fs_param_is_fd, NAME, OPT, 0, NULL)
#endif /* _LINUX_FS_PARSER_H */
diff --git a/include/linux/ramfs.h b/include/linux/ramfs.h
index b806a0ff6554..917528d102c4 100644
--- a/include/linux/ramfs.h
+++ b/include/linux/ramfs.h
@@ -2,6 +2,8 @@
#ifndef _LINUX_RAMFS_H
#define _LINUX_RAMFS_H
+#include <linux/fs_parser.h> // bleh...
+
struct inode *ramfs_get_inode(struct super_block *sb, const struct inode *dir,
umode_t mode, dev_t dev);
extern int ramfs_init_fs_context(struct fs_context *fc);
@@ -16,7 +18,7 @@ ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize)
extern int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize);
#endif
-extern const struct fs_parameter_description ramfs_fs_parameters;
+extern const struct fs_parameter_spec ramfs_fs_parameters[];
extern const struct file_operations ramfs_file_operations;
extern const struct vm_operations_struct generic_file_vm_ops;
diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
index de8e4b71e3ba..d56fefef8905 100644
--- a/include/linux/shmem_fs.h
+++ b/include/linux/shmem_fs.h
@@ -8,6 +8,7 @@
#include <linux/pagemap.h>
#include <linux/percpu_counter.h>
#include <linux/xattr.h>
+#include <linux/fs_parser.h>
/* inode in-kernel data */
@@ -49,7 +50,7 @@ static inline struct shmem_inode_info *SHMEM_I(struct inode *inode)
/*
* Functions in mm/shmem.c called directly from elsewhere:
*/
-extern const struct fs_parameter_description shmem_fs_parameters;
+extern const struct fs_parameter_spec shmem_fs_parameters[];
extern int shmem_init(void);
extern int shmem_init_fs_context(struct fs_context *fc);
extern struct file *shmem_file_setup(const char *name,