| @@ -46,19 +46,40 @@ int lookup_constant(const struct constant_table *tbl, const char *name, int not_ · 45 unmodified lines |
| 46 | } | 46 | } |
| 47 | EXPORT_SYMBOL(lookup_constant); | 47 | EXPORT_SYMBOL(lookup_constant); |
| 48 | | 48 | |
| | 49 | static inline bool is_flag(const struct fs_parameter_spec *p) |
| | 50 | { |
| | 51 | return p->type == fs_param_is_flag; |
| | 52 | } |
| | 53 | |
| 49 | static const struct fs_parameter_spec *fs_lookup_key( | 54 | static const struct fs_parameter_spec *fs_lookup_key( |
| 50 | const struct fs_parameter_spec *desc, | 55 | const struct fs_parameter_spec *desc, |
| 51 | const char *name) | 56 | struct fs_parameter *param, bool *negated) |
| 52 | { | 57 | { |
| 53 | const struct fs_parameter_spec *p; | 58 | const struct fs_parameter_spec *p, *other = NULL; |
| 54 | if (!desc) | 59 | const char *name = param->key; |
| 55 | return NULL; | 60 | bool want_flag = param->type == fs_value_is_flag; |
| 56 | | 61 | |
| 57 | for (p = desc; p->name; p++) | 62 | *negated = false; |
| 58 | if (strcmp(p->name, name) == 0) | 63 | for (p = desc; p->name; p++) { |
| | 64 | if (strcmp(p->name, name) != 0) |
| | 65 | continue; |
| | 66 | if (likely(is_flag(p) == want_flag)) |
| 59 | return p; | 67 | return p; |
| 60 | | 68 | other = p; |
| 61 | return NULL; | 69 | } |
| | 70 | if (want_flag) { |
| | 71 | if (name[0] == 'n' && name[1] == 'o' && name[2]) { |
| | 72 | for (p = desc; p->name; p++) { |
| | 73 | if (strcmp(p->name, name + 2) != 0) |
| | 74 | continue; |
| | 75 | if (!(p->flags & fs_param_neg_with_no)) |
| | 76 | continue; |
| | 77 | *negated = true; |
| | 78 | return p; |
| | 79 | } |
| | 80 | } |
| | 81 | } |
| | 82 | return other; |
| 62 | } | 83 | } |
| 63 | | 84 | |
| 64 | /* | 85 | /* |
| @@ -88,123 +109,77 @@ int __fs_parse(struct p_log *log, · 23 unmodified lines |
| 88 | const struct constant_table *e; | 109 | const struct constant_table *e; |
| 89 | int ret = -ENOPARAM, b; | 110 | int ret = -ENOPARAM, b; |
| 90 | | 111 | |
| 91 | result->negated = false; | | |
| 92 | result->uint_64 = 0; | 112 | result->uint_64 = 0; |
| 93 | | 113 | |
| 94 | p = fs_lookup_key(desc, param->key); | 114 | p = fs_lookup_key(desc, param, &result->negated); |
| 95 | if (!p) { | 115 | if (!p) |
| 96 | /* If we didn't find something that looks like "noxxx", see if | 116 | return -ENOPARAM; |
| 97 | * "xxx" takes the "no"-form negative - but only if there | | |
| 98 | * wasn't an value. | | |
| 99 | */ | | |
| 100 | if (param->type != fs_value_is_flag) | | |
| 101 | goto unknown_parameter; | | |
| 102 | if (param->key[0] != 'n' || param->key[1] != 'o' || !param->key[2]) | | |
| 103 | goto unknown_parameter; | | |
| 104 | | | |
| 105 | p = fs_lookup_key(desc, param->key + 2); | | |
| 106 | if (!p) | | |
| 107 | goto unknown_parameter; | | |
| 108 | if (!(p->flags & fs_param_neg_with_no)) | | |
| 109 | goto unknown_parameter; | | |
| 110 | result->boolean = false; | | |
| 111 | result->negated = true; | | |
| 112 | } | | |
| 113 | | 117 | |
| 114 | if (p->flags & fs_param_deprecated) | 118 | if (p->flags & fs_param_deprecated) |
| 115 | warn_plog(log, "Deprecated parameter '%s'", param->key); | 119 | warn_plog(log, "Deprecated parameter '%s'", param->key); |
| 116 | | 120 | |
| 117 | if (result->negated) | | |
| 118 | goto okay; | | |
| 119 | | | |
| 120 | /* Certain parameter types only take a string and convert it. */ | | |
| 121 | switch (p->type) { | | |
| 122 | case __fs_param_wasnt_defined: | | |
| 123 | return -EINVAL; | | |
| 124 | case fs_param_is_u32: | | |
| 125 | case fs_param_is_u32_octal: | | |
| 126 | case fs_param_is_u32_hex: | | |
| 127 | case fs_param_is_s32: | | |
| 128 | case fs_param_is_u64: | | |
| 129 | case fs_param_is_enum: | | |
| 130 | case fs_param_is_string: | | |
| 131 | if (param->type == fs_value_is_string) { | | |
| 132 | if (p->flags & fs_param_v_optional) | | |
| 133 | break; | | |
| 134 | if (!*param->string) | | |
| 135 | goto bad_value; | | |
| 136 | break; | | |
| 137 | } | | |
| 138 | if (param->type == fs_value_is_flag) { | | |
| 139 | if (p->flags & fs_param_v_optional) | | |
| 140 | goto okay; | | |
| 141 | } | | |
| 142 | goto bad_value; | | |
| 143 | default: | | |
| 144 | break; | | |
| 145 | } | | |
| 146 | | | |
| 147 | /* Try to turn the type we were given into the type desired by the | 121 | /* Try to turn the type we were given into the type desired by the |
| 148 | * parameter and give an error if we can't. | 122 | * parameter and give an error if we can't. |
| 149 | */ | 123 | */ |
| 150 | switch (p->type) { | 124 | switch (p->type) { |
| | 125 | case __fs_param_wasnt_defined: |
| | 126 | return -EINVAL; |
| 151 | case fs_param_is_flag: | 127 | case fs_param_is_flag: |
| 152 | if (param->type != fs_value_is_flag) | 128 | if (param->type != fs_value_is_flag) |
| 153 | return inval_plog(log, "Unexpected value for '%s'", | 129 | return inval_plog(log, "Unexpected value for '%s'", |
| 154 | param->key); | 130 | param->key); |
| 155 | result->boolean = true; | 131 | result->boolean = !result->negated; |
| 156 | goto okay; | 132 | goto okay; |
| 157 | | | |
| 158 | case fs_param_is_bool: | 133 | case fs_param_is_bool: |
| 159 | switch (param->type) { | 134 | if (param->type != fs_value_is_string) |
| 160 | case fs_value_is_flag: | | |
| 161 | result->boolean = true; | | |
| 162 | goto okay; | | |
| 163 | case fs_value_is_string: | | |
| 164 | if (param->size == 0) { | | |
| 165 | result->boolean = true; | | |
| 166 | goto okay; | | |
| 167 | } | | |
| 168 | b = lookup_constant(bool_names, param->string, -1); | | |
| 169 | if (b == -1) | | |
| 170 | goto bad_value; | | |
| 171 | result->boolean = b; | | |
| 172 | goto okay; | | |
| 173 | default: | | |
| 174 | goto bad_value; | 135 | goto bad_value; |
| 175 | } | 136 | b = lookup_constant(bool_names, param->string, -1); |
| 176 | | 137 | if (b == -1) |
| | 138 | goto bad_value; |
| | 139 | result->boolean = b; |
| | 140 | goto okay; |
| 177 | case fs_param_is_u32: | 141 | case fs_param_is_u32: |
| | 142 | if (param->type != fs_value_is_string) |
| | 143 | goto bad_value; |
| 178 | ret = kstrtouint(param->string, 0, &result->uint_32); | 144 | ret = kstrtouint(param->string, 0, &result->uint_32); |
| 179 | goto maybe_okay; | 145 | goto maybe_okay; |
| 180 | case fs_param_is_u32_octal: | 146 | case fs_param_is_u32_octal: |
| | 147 | if (param->type != fs_value_is_string) |
| | 148 | goto bad_value; |
| 181 | ret = kstrtouint(param->string, 8, &result->uint_32); | 149 | ret = kstrtouint(param->string, 8, &result->uint_32); |
| 182 | goto maybe_okay; | 150 | goto maybe_okay; |
| 183 | case fs_param_is_u32_hex: | 151 | case fs_param_is_u32_hex: |
| | 152 | if (param->type != fs_value_is_string) |
| | 153 | goto bad_value; |
| 184 | ret = kstrtouint(param->string, 16, &result->uint_32); | 154 | ret = kstrtouint(param->string, 16, &result->uint_32); |
| 185 | goto maybe_okay; | 155 | goto maybe_okay; |
| 186 | case fs_param_is_s32: | 156 | case fs_param_is_s32: |
| | 157 | if (param->type != fs_value_is_string) |
| | 158 | goto bad_value; |
| 187 | ret = kstrtoint(param->string, 0, &result->int_32); | 159 | ret = kstrtoint(param->string, 0, &result->int_32); |
| 188 | goto maybe_okay; | 160 | goto maybe_okay; |
| 189 | case fs_param_is_u64: | 161 | case fs_param_is_u64: |
| | 162 | if (param->type != fs_value_is_string) |
| | 163 | goto bad_value; |
| 190 | ret = kstrtoull(param->string, 0, &result->uint_64); | 164 | ret = kstrtoull(param->string, 0, &result->uint_64); |
| 191 | goto maybe_okay; | 165 | goto maybe_okay; |
| 192 | | | |
| 193 | case fs_param_is_enum: | 166 | case fs_param_is_enum: |
| | 167 | if (param->type != fs_value_is_string) |
| | 168 | goto bad_value; |
| 194 | e = __lookup_constant(p->data, param->string); | 169 | e = __lookup_constant(p->data, param->string); |
| 195 | if (e) { | 170 | if (e) { |
| 196 | result->uint_32 = e->value; | 171 | result->uint_32 = e->value; |
| 197 | goto okay; | 172 | goto okay; |
| 198 | } | 173 | } |
| 199 | goto bad_value; | 174 | goto bad_value; |
| 200 | | | |
| 201 | case fs_param_is_string: | 175 | case fs_param_is_string: |
| | 176 | if (param->type != fs_value_is_string || !*param->string) |
| | 177 | goto bad_value; |
| 202 | goto okay; | 178 | goto okay; |
| 203 | case fs_param_is_blob: | 179 | case fs_param_is_blob: |
| 204 | if (param->type != fs_value_is_blob) | 180 | if (param->type != fs_value_is_blob) |
| 205 | goto bad_value; | 181 | goto bad_value; |
| 206 | goto okay; | 182 | goto okay; |
| 207 | | | |
| 208 | case fs_param_is_fd: { | 183 | case fs_param_is_fd: { |
| 209 | switch (param->type) { | 184 | switch (param->type) { |
| 210 | case fs_value_is_string: | 185 | case fs_value_is_string: |
| @@ -221,7 +196,6 @@ int __fs_parse(struct p_log *log, · 10 unmodified lines |
| 221 | goto bad_value; | 196 | goto bad_value; |
| 222 | goto maybe_okay; | 197 | goto maybe_okay; |
| 223 | } | 198 | } |
| 224 | | | |
| 225 | case fs_param_is_blockdev: | 199 | case fs_param_is_blockdev: |
| 226 | case fs_param_is_path: | 200 | case fs_param_is_path: |
| 227 | goto okay; | 201 | goto okay; |
| @@ -237,8 +211,6 @@ okay: · 9 unmodified lines |
| 237 | | 211 | |
| 238 | bad_value: | 212 | bad_value: |
| 239 | return inval_plog(log, "Bad value for '%s'", param->key); | 213 | return inval_plog(log, "Bad value for '%s'", param->key); |
| 240 | unknown_parameter: | | |
| 241 | return -ENOPARAM; | | |
| 242 | } | 214 | } |
| 243 | EXPORT_SYMBOL(__fs_parse); | 215 | EXPORT_SYMBOL(__fs_parse); |
| 244 | | 216 | |
| @@ -382,6 +354,8 @@ bool fs_validate_description(const char *name, · 137 unmodified lines |
| 382 | /* Check for duplicate parameter names */ | 354 | /* Check for duplicate parameter names */ |
| 383 | for (p2 = desc; p2 < param; p2++) { | 355 | for (p2 = desc; p2 < param; p2++) { |
| 384 | if (strcmp(param->name, p2->name) == 0) { | 356 | if (strcmp(param->name, p2->name) == 0) { |
| | 357 | if (is_flag(param) != is_flag(p2)) |
| | 358 | continue; |
| 385 | pr_err("VALIDATE %s: PARAM[%s]: Duplicate\n", | 359 | pr_err("VALIDATE %s: PARAM[%s]: Duplicate\n", |
| 386 | name, param->name); | 360 | name, param->name); |
| 387 | good = false; | 361 | good = false; |