Loading fs/fs_parser.c +124 −104 Original line number Diff line number Diff line Loading @@ -48,7 +48,7 @@ EXPORT_SYMBOL(lookup_constant); static inline bool is_flag(const struct fs_parameter_spec *p) { return p->type == fs_param_is_flag; return p->type == NULL; } static const struct fs_parameter_spec *fs_lookup_key( Loading Loading @@ -106,8 +106,6 @@ int __fs_parse(struct p_log *log, struct fs_parse_result *result) { const struct fs_parameter_spec *p; const struct constant_table *e; int ret = -ENOPARAM, b; result->uint_64 = 0; Loading @@ -121,96 +119,17 @@ int __fs_parse(struct p_log *log, /* Try to turn the type we were given into the type desired by the * parameter and give an error if we can't. */ switch (p->type) { case __fs_param_wasnt_defined: return -EINVAL; case fs_param_is_flag: if (is_flag(p)) { if (param->type != fs_value_is_flag) return inval_plog(log, "Unexpected value for '%s'", param->key); result->boolean = !result->negated; goto okay; case fs_param_is_bool: if (param->type != fs_value_is_string) goto bad_value; b = lookup_constant(bool_names, param->string, -1); if (b == -1) goto bad_value; result->boolean = b; goto okay; case fs_param_is_u32: if (param->type != fs_value_is_string) goto bad_value; ret = kstrtouint(param->string, 0, &result->uint_32); goto maybe_okay; case fs_param_is_u32_octal: if (param->type != fs_value_is_string) goto bad_value; ret = kstrtouint(param->string, 8, &result->uint_32); goto maybe_okay; case fs_param_is_u32_hex: if (param->type != fs_value_is_string) goto bad_value; ret = kstrtouint(param->string, 16, &result->uint_32); goto maybe_okay; case fs_param_is_s32: if (param->type != fs_value_is_string) goto bad_value; ret = kstrtoint(param->string, 0, &result->int_32); goto maybe_okay; case fs_param_is_u64: if (param->type != fs_value_is_string) goto bad_value; ret = kstrtoull(param->string, 0, &result->uint_64); goto maybe_okay; case fs_param_is_enum: if (param->type != fs_value_is_string) goto bad_value; e = __lookup_constant(p->data, param->string); if (e) { result->uint_32 = e->value; goto okay; } goto bad_value; case fs_param_is_string: if (param->type != fs_value_is_string || !*param->string) goto bad_value; goto okay; case fs_param_is_blob: if (param->type != fs_value_is_blob) goto bad_value; goto okay; case fs_param_is_fd: { switch (param->type) { case fs_value_is_string: ret = kstrtouint(param->string, 0, &result->uint_32); break; case fs_value_is_file: result->uint_32 = param->dirfd; ret = 0; default: goto bad_value; } if (result->uint_32 > INT_MAX) goto bad_value; goto maybe_okay; } case fs_param_is_blockdev: case fs_param_is_path: goto okay; default: BUG(); } else { int ret = p->type(log, p, param, result); if (ret) return ret; } maybe_okay: if (ret < 0) goto bad_value; okay: return p->opt; bad_value: return inval_plog(log, "Bad value for '%s'", param->key); } EXPORT_SYMBOL(__fs_parse); Loading Loading @@ -270,6 +189,124 @@ int fs_lookup_param(struct fs_context *fc, } EXPORT_SYMBOL(fs_lookup_param); int fs_param_bad_value(struct p_log *log, struct fs_parameter *param) { return inval_plog(log, "Bad value for '%s'", param->key); } int fs_param_is_bool(struct p_log *log, const struct fs_parameter_spec *p, struct fs_parameter *param, struct fs_parse_result *result) { int b; if (param->type != fs_value_is_string) return fs_param_bad_value(log, param); b = lookup_constant(bool_names, param->string, -1); if (b == -1) return fs_param_bad_value(log, param); result->boolean = b; return 0; } EXPORT_SYMBOL(fs_param_is_bool); int fs_param_is_u32(struct p_log *log, const struct fs_parameter_spec *p, struct fs_parameter *param, struct fs_parse_result *result) { int base = (unsigned long)p->data; if (param->type != fs_value_is_string || kstrtouint(param->string, base, &result->uint_32) < 0) return fs_param_bad_value(log, param); return 0; } EXPORT_SYMBOL(fs_param_is_u32); int fs_param_is_s32(struct p_log *log, const struct fs_parameter_spec *p, struct fs_parameter *param, struct fs_parse_result *result) { if (param->type != fs_value_is_string || kstrtoint(param->string, 0, &result->int_32) < 0) return fs_param_bad_value(log, param); return 0; } EXPORT_SYMBOL(fs_param_is_s32); int fs_param_is_u64(struct p_log *log, const struct fs_parameter_spec *p, struct fs_parameter *param, struct fs_parse_result *result) { if (param->type != fs_value_is_string || kstrtoull(param->string, 0, &result->uint_64) < 0) return fs_param_bad_value(log, param); return 0; } EXPORT_SYMBOL(fs_param_is_u64); int fs_param_is_enum(struct p_log *log, const struct fs_parameter_spec *p, struct fs_parameter *param, struct fs_parse_result *result) { const struct constant_table *c; if (param->type != fs_value_is_string) return fs_param_bad_value(log, param); c = __lookup_constant(p->data, param->string); if (!c) return fs_param_bad_value(log, param); result->uint_32 = c->value; return 0; } EXPORT_SYMBOL(fs_param_is_enum); int fs_param_is_string(struct p_log *log, const struct fs_parameter_spec *p, struct fs_parameter *param, struct fs_parse_result *result) { if (param->type != fs_value_is_string || !*param->string) return fs_param_bad_value(log, param); return 0; } EXPORT_SYMBOL(fs_param_is_string); int fs_param_is_blob(struct p_log *log, const struct fs_parameter_spec *p, struct fs_parameter *param, struct fs_parse_result *result) { if (param->type != fs_value_is_blob) return fs_param_bad_value(log, param); return 0; } EXPORT_SYMBOL(fs_param_is_blob); int fs_param_is_fd(struct p_log *log, const struct fs_parameter_spec *p, struct fs_parameter *param, struct fs_parse_result *result) { switch (param->type) { case fs_value_is_string: if (kstrtouint(param->string, 0, &result->uint_32) < 0) break; if (result->uint_32 <= INT_MAX) return 0; break; case fs_value_is_file: result->uint_32 = param->dirfd; if (result->uint_32 <= INT_MAX) return 0; break; default: break; } return fs_param_bad_value(log, param); } EXPORT_SYMBOL(fs_param_is_fd); int fs_param_is_blockdev(struct p_log *log, const struct fs_parameter_spec *p, struct fs_parameter *param, struct fs_parse_result *result) { return 0; } EXPORT_SYMBOL(fs_param_is_blockdev); int fs_param_is_path(struct p_log *log, const struct fs_parameter_spec *p, struct fs_parameter *param, struct fs_parse_result *result) { return 0; } EXPORT_SYMBOL(fs_param_is_path); #ifdef CONFIG_VALIDATE_FS_PARSER /** * validate_constant_table - Validate a constant table Loading Loading @@ -334,23 +371,6 @@ bool fs_validate_description(const char *name, pr_notice("*** VALIDATE %s ***\n", name); for (param = desc; param->name; param++) { enum fs_parameter_type t = param->type; /* Check that the type is in range */ if (t == __fs_param_wasnt_defined || t >= nr__fs_parameter_type) { pr_err("VALIDATE %s: PARAM[%s] Bad type %u\n", name, param->name, t); good = false; } else if (t == fs_param_is_enum) { const struct constant_table *e = param->data; if (!e || !e->name) { pr_err("VALIDATE %s: PARAM[%s] enum with no values\n", name, param->name); good = false; } } /* Check for duplicate parameter names */ for (p2 = desc; p2 < param; p2++) { if (strcmp(param->name, p2->name) == 0) { Loading fs/nfs/fs_context.c +1 −1 Original line number Diff line number Diff line Loading @@ -129,7 +129,7 @@ static const struct fs_parameter_spec nfs_fs_parameters[] = { fsparam_flag_no("fsc", Opt_fscache_flag), fsparam_string("fsc", Opt_fscache), fsparam_flag ("hard", Opt_hard), __fsparam(fs_param_is_flag, "intr", Opt_intr, __fsparam(NULL, "intr", Opt_intr, fs_param_neg_with_no|fs_param_deprecated, NULL), fsparam_enum ("local_lock", Opt_local_lock, nfs_param_enums_local_lock), fsparam_flag_no("lock", Opt_lock), Loading include/linux/fs_parser.h +14 −24 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -46,8 +38,8 @@ 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_neg_with_no 0x0002 /* "noxxx" is negative param */ #define fs_param_neg_with_empty 0x0004 /* "xxx=" is negative param */ Loading Loading @@ -120,16 +112,15 @@ static inline bool fs_validate_description(const char *name, .data = DATA \ } #define fsparam_flag(NAME, OPT) __fsparam(fs_param_is_flag, NAME, OPT, 0, NULL) #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, NULL) __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, NULL) __fsparam(fs_param_is_u32, NAME, OPT, 0, (void *)8) #define fsparam_u32hex(NAME, OPT) \ __fsparam(fs_param_is_u32_hex, NAME, OPT, 0, NULL) __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) Loading @@ -140,5 +131,4 @@ static inline bool fs_validate_description(const char *name, #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 */ Loading
fs/fs_parser.c +124 −104 Original line number Diff line number Diff line Loading @@ -48,7 +48,7 @@ EXPORT_SYMBOL(lookup_constant); static inline bool is_flag(const struct fs_parameter_spec *p) { return p->type == fs_param_is_flag; return p->type == NULL; } static const struct fs_parameter_spec *fs_lookup_key( Loading Loading @@ -106,8 +106,6 @@ int __fs_parse(struct p_log *log, struct fs_parse_result *result) { const struct fs_parameter_spec *p; const struct constant_table *e; int ret = -ENOPARAM, b; result->uint_64 = 0; Loading @@ -121,96 +119,17 @@ int __fs_parse(struct p_log *log, /* Try to turn the type we were given into the type desired by the * parameter and give an error if we can't. */ switch (p->type) { case __fs_param_wasnt_defined: return -EINVAL; case fs_param_is_flag: if (is_flag(p)) { if (param->type != fs_value_is_flag) return inval_plog(log, "Unexpected value for '%s'", param->key); result->boolean = !result->negated; goto okay; case fs_param_is_bool: if (param->type != fs_value_is_string) goto bad_value; b = lookup_constant(bool_names, param->string, -1); if (b == -1) goto bad_value; result->boolean = b; goto okay; case fs_param_is_u32: if (param->type != fs_value_is_string) goto bad_value; ret = kstrtouint(param->string, 0, &result->uint_32); goto maybe_okay; case fs_param_is_u32_octal: if (param->type != fs_value_is_string) goto bad_value; ret = kstrtouint(param->string, 8, &result->uint_32); goto maybe_okay; case fs_param_is_u32_hex: if (param->type != fs_value_is_string) goto bad_value; ret = kstrtouint(param->string, 16, &result->uint_32); goto maybe_okay; case fs_param_is_s32: if (param->type != fs_value_is_string) goto bad_value; ret = kstrtoint(param->string, 0, &result->int_32); goto maybe_okay; case fs_param_is_u64: if (param->type != fs_value_is_string) goto bad_value; ret = kstrtoull(param->string, 0, &result->uint_64); goto maybe_okay; case fs_param_is_enum: if (param->type != fs_value_is_string) goto bad_value; e = __lookup_constant(p->data, param->string); if (e) { result->uint_32 = e->value; goto okay; } goto bad_value; case fs_param_is_string: if (param->type != fs_value_is_string || !*param->string) goto bad_value; goto okay; case fs_param_is_blob: if (param->type != fs_value_is_blob) goto bad_value; goto okay; case fs_param_is_fd: { switch (param->type) { case fs_value_is_string: ret = kstrtouint(param->string, 0, &result->uint_32); break; case fs_value_is_file: result->uint_32 = param->dirfd; ret = 0; default: goto bad_value; } if (result->uint_32 > INT_MAX) goto bad_value; goto maybe_okay; } case fs_param_is_blockdev: case fs_param_is_path: goto okay; default: BUG(); } else { int ret = p->type(log, p, param, result); if (ret) return ret; } maybe_okay: if (ret < 0) goto bad_value; okay: return p->opt; bad_value: return inval_plog(log, "Bad value for '%s'", param->key); } EXPORT_SYMBOL(__fs_parse); Loading Loading @@ -270,6 +189,124 @@ int fs_lookup_param(struct fs_context *fc, } EXPORT_SYMBOL(fs_lookup_param); int fs_param_bad_value(struct p_log *log, struct fs_parameter *param) { return inval_plog(log, "Bad value for '%s'", param->key); } int fs_param_is_bool(struct p_log *log, const struct fs_parameter_spec *p, struct fs_parameter *param, struct fs_parse_result *result) { int b; if (param->type != fs_value_is_string) return fs_param_bad_value(log, param); b = lookup_constant(bool_names, param->string, -1); if (b == -1) return fs_param_bad_value(log, param); result->boolean = b; return 0; } EXPORT_SYMBOL(fs_param_is_bool); int fs_param_is_u32(struct p_log *log, const struct fs_parameter_spec *p, struct fs_parameter *param, struct fs_parse_result *result) { int base = (unsigned long)p->data; if (param->type != fs_value_is_string || kstrtouint(param->string, base, &result->uint_32) < 0) return fs_param_bad_value(log, param); return 0; } EXPORT_SYMBOL(fs_param_is_u32); int fs_param_is_s32(struct p_log *log, const struct fs_parameter_spec *p, struct fs_parameter *param, struct fs_parse_result *result) { if (param->type != fs_value_is_string || kstrtoint(param->string, 0, &result->int_32) < 0) return fs_param_bad_value(log, param); return 0; } EXPORT_SYMBOL(fs_param_is_s32); int fs_param_is_u64(struct p_log *log, const struct fs_parameter_spec *p, struct fs_parameter *param, struct fs_parse_result *result) { if (param->type != fs_value_is_string || kstrtoull(param->string, 0, &result->uint_64) < 0) return fs_param_bad_value(log, param); return 0; } EXPORT_SYMBOL(fs_param_is_u64); int fs_param_is_enum(struct p_log *log, const struct fs_parameter_spec *p, struct fs_parameter *param, struct fs_parse_result *result) { const struct constant_table *c; if (param->type != fs_value_is_string) return fs_param_bad_value(log, param); c = __lookup_constant(p->data, param->string); if (!c) return fs_param_bad_value(log, param); result->uint_32 = c->value; return 0; } EXPORT_SYMBOL(fs_param_is_enum); int fs_param_is_string(struct p_log *log, const struct fs_parameter_spec *p, struct fs_parameter *param, struct fs_parse_result *result) { if (param->type != fs_value_is_string || !*param->string) return fs_param_bad_value(log, param); return 0; } EXPORT_SYMBOL(fs_param_is_string); int fs_param_is_blob(struct p_log *log, const struct fs_parameter_spec *p, struct fs_parameter *param, struct fs_parse_result *result) { if (param->type != fs_value_is_blob) return fs_param_bad_value(log, param); return 0; } EXPORT_SYMBOL(fs_param_is_blob); int fs_param_is_fd(struct p_log *log, const struct fs_parameter_spec *p, struct fs_parameter *param, struct fs_parse_result *result) { switch (param->type) { case fs_value_is_string: if (kstrtouint(param->string, 0, &result->uint_32) < 0) break; if (result->uint_32 <= INT_MAX) return 0; break; case fs_value_is_file: result->uint_32 = param->dirfd; if (result->uint_32 <= INT_MAX) return 0; break; default: break; } return fs_param_bad_value(log, param); } EXPORT_SYMBOL(fs_param_is_fd); int fs_param_is_blockdev(struct p_log *log, const struct fs_parameter_spec *p, struct fs_parameter *param, struct fs_parse_result *result) { return 0; } EXPORT_SYMBOL(fs_param_is_blockdev); int fs_param_is_path(struct p_log *log, const struct fs_parameter_spec *p, struct fs_parameter *param, struct fs_parse_result *result) { return 0; } EXPORT_SYMBOL(fs_param_is_path); #ifdef CONFIG_VALIDATE_FS_PARSER /** * validate_constant_table - Validate a constant table Loading Loading @@ -334,23 +371,6 @@ bool fs_validate_description(const char *name, pr_notice("*** VALIDATE %s ***\n", name); for (param = desc; param->name; param++) { enum fs_parameter_type t = param->type; /* Check that the type is in range */ if (t == __fs_param_wasnt_defined || t >= nr__fs_parameter_type) { pr_err("VALIDATE %s: PARAM[%s] Bad type %u\n", name, param->name, t); good = false; } else if (t == fs_param_is_enum) { const struct constant_table *e = param->data; if (!e || !e->name) { pr_err("VALIDATE %s: PARAM[%s] enum with no values\n", name, param->name); good = false; } } /* Check for duplicate parameter names */ for (p2 = desc; p2 < param; p2++) { if (strcmp(param->name, p2->name) == 0) { Loading
fs/nfs/fs_context.c +1 −1 Original line number Diff line number Diff line Loading @@ -129,7 +129,7 @@ static const struct fs_parameter_spec nfs_fs_parameters[] = { fsparam_flag_no("fsc", Opt_fscache_flag), fsparam_string("fsc", Opt_fscache), fsparam_flag ("hard", Opt_hard), __fsparam(fs_param_is_flag, "intr", Opt_intr, __fsparam(NULL, "intr", Opt_intr, fs_param_neg_with_no|fs_param_deprecated, NULL), fsparam_enum ("local_lock", Opt_local_lock, nfs_param_enums_local_lock), fsparam_flag_no("lock", Opt_lock), Loading
include/linux/fs_parser.h +14 −24 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -46,8 +38,8 @@ 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_neg_with_no 0x0002 /* "noxxx" is negative param */ #define fs_param_neg_with_empty 0x0004 /* "xxx=" is negative param */ Loading Loading @@ -120,16 +112,15 @@ static inline bool fs_validate_description(const char *name, .data = DATA \ } #define fsparam_flag(NAME, OPT) __fsparam(fs_param_is_flag, NAME, OPT, 0, NULL) #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, NULL) __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, NULL) __fsparam(fs_param_is_u32, NAME, OPT, 0, (void *)8) #define fsparam_u32hex(NAME, OPT) \ __fsparam(fs_param_is_u32_hex, NAME, OPT, 0, NULL) __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) Loading @@ -140,5 +131,4 @@ static inline bool fs_validate_description(const char *name, #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 */