diff options
Diffstat (limited to 'kernel/params.c')
| -rw-r--r-- | kernel/params.c | 233 |
1 files changed, 161 insertions, 72 deletions
diff --git a/kernel/params.c b/kernel/params.c index 0b30ecd53a52..08107d181758 100644 --- a/kernel/params.c +++ b/kernel/params.c | |||
| @@ -31,6 +31,42 @@ | |||
| 31 | #define DEBUGP(fmt, a...) | 31 | #define DEBUGP(fmt, a...) |
| 32 | #endif | 32 | #endif |
| 33 | 33 | ||
| 34 | /* Protects all parameters, and incidentally kmalloced_param list. */ | ||
| 35 | static DEFINE_MUTEX(param_lock); | ||
| 36 | |||
| 37 | /* This just allows us to keep track of which parameters are kmalloced. */ | ||
| 38 | struct kmalloced_param { | ||
| 39 | struct list_head list; | ||
| 40 | char val[]; | ||
| 41 | }; | ||
| 42 | static LIST_HEAD(kmalloced_params); | ||
| 43 | |||
| 44 | static void *kmalloc_parameter(unsigned int size) | ||
| 45 | { | ||
| 46 | struct kmalloced_param *p; | ||
| 47 | |||
| 48 | p = kmalloc(sizeof(*p) + size, GFP_KERNEL); | ||
| 49 | if (!p) | ||
| 50 | return NULL; | ||
| 51 | |||
| 52 | list_add(&p->list, &kmalloced_params); | ||
| 53 | return p->val; | ||
| 54 | } | ||
| 55 | |||
| 56 | /* Does nothing if parameter wasn't kmalloced above. */ | ||
| 57 | static void maybe_kfree_parameter(void *param) | ||
| 58 | { | ||
| 59 | struct kmalloced_param *p; | ||
| 60 | |||
| 61 | list_for_each_entry(p, &kmalloced_params, list) { | ||
| 62 | if (p->val == param) { | ||
| 63 | list_del(&p->list); | ||
| 64 | kfree(p); | ||
| 65 | break; | ||
| 66 | } | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 34 | static inline char dash2underscore(char c) | 70 | static inline char dash2underscore(char c) |
| 35 | { | 71 | { |
| 36 | if (c == '-') | 72 | if (c == '-') |
| @@ -49,18 +85,25 @@ static inline int parameq(const char *input, const char *paramname) | |||
| 49 | 85 | ||
| 50 | static int parse_one(char *param, | 86 | static int parse_one(char *param, |
| 51 | char *val, | 87 | char *val, |
| 52 | struct kernel_param *params, | 88 | const struct kernel_param *params, |
| 53 | unsigned num_params, | 89 | unsigned num_params, |
| 54 | int (*handle_unknown)(char *param, char *val)) | 90 | int (*handle_unknown)(char *param, char *val)) |
| 55 | { | 91 | { |
| 56 | unsigned int i; | 92 | unsigned int i; |
| 93 | int err; | ||
| 57 | 94 | ||
| 58 | /* Find parameter */ | 95 | /* Find parameter */ |
| 59 | for (i = 0; i < num_params; i++) { | 96 | for (i = 0; i < num_params; i++) { |
| 60 | if (parameq(param, params[i].name)) { | 97 | if (parameq(param, params[i].name)) { |
| 98 | /* Noone handled NULL, so do it here. */ | ||
| 99 | if (!val && params[i].ops->set != param_set_bool) | ||
| 100 | return -EINVAL; | ||
| 61 | DEBUGP("They are equal! Calling %p\n", | 101 | DEBUGP("They are equal! Calling %p\n", |
| 62 | params[i].set); | 102 | params[i].ops->set); |
| 63 | return params[i].set(val, ¶ms[i]); | 103 | mutex_lock(¶m_lock); |
| 104 | err = params[i].ops->set(val, ¶ms[i]); | ||
| 105 | mutex_unlock(¶m_lock); | ||
| 106 | return err; | ||
| 64 | } | 107 | } |
| 65 | } | 108 | } |
| 66 | 109 | ||
| @@ -128,7 +171,7 @@ static char *next_arg(char *args, char **param, char **val) | |||
| 128 | /* Args looks like "foo=bar,bar2 baz=fuz wiz". */ | 171 | /* Args looks like "foo=bar,bar2 baz=fuz wiz". */ |
| 129 | int parse_args(const char *name, | 172 | int parse_args(const char *name, |
| 130 | char *args, | 173 | char *args, |
| 131 | struct kernel_param *params, | 174 | const struct kernel_param *params, |
| 132 | unsigned num, | 175 | unsigned num, |
| 133 | int (*unknown)(char *param, char *val)) | 176 | int (*unknown)(char *param, char *val)) |
| 134 | { | 177 | { |
| @@ -176,22 +219,29 @@ int parse_args(const char *name, | |||
| 176 | 219 | ||
| 177 | /* Lazy bastard, eh? */ | 220 | /* Lazy bastard, eh? */ |
| 178 | #define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn) \ | 221 | #define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn) \ |
| 179 | int param_set_##name(const char *val, struct kernel_param *kp) \ | 222 | int param_set_##name(const char *val, const struct kernel_param *kp) \ |
| 180 | { \ | 223 | { \ |
| 181 | tmptype l; \ | 224 | tmptype l; \ |
| 182 | int ret; \ | 225 | int ret; \ |
| 183 | \ | 226 | \ |
| 184 | if (!val) return -EINVAL; \ | ||
| 185 | ret = strtolfn(val, 0, &l); \ | 227 | ret = strtolfn(val, 0, &l); \ |
| 186 | if (ret == -EINVAL || ((type)l != l)) \ | 228 | if (ret == -EINVAL || ((type)l != l)) \ |
| 187 | return -EINVAL; \ | 229 | return -EINVAL; \ |
| 188 | *((type *)kp->arg) = l; \ | 230 | *((type *)kp->arg) = l; \ |
| 189 | return 0; \ | 231 | return 0; \ |
| 190 | } \ | 232 | } \ |
| 191 | int param_get_##name(char *buffer, struct kernel_param *kp) \ | 233 | int param_get_##name(char *buffer, const struct kernel_param *kp) \ |
| 192 | { \ | 234 | { \ |
| 193 | return sprintf(buffer, format, *((type *)kp->arg)); \ | 235 | return sprintf(buffer, format, *((type *)kp->arg)); \ |
| 194 | } | 236 | } \ |
| 237 | struct kernel_param_ops param_ops_##name = { \ | ||
| 238 | .set = param_set_##name, \ | ||
| 239 | .get = param_get_##name, \ | ||
| 240 | }; \ | ||
| 241 | EXPORT_SYMBOL(param_set_##name); \ | ||
| 242 | EXPORT_SYMBOL(param_get_##name); \ | ||
| 243 | EXPORT_SYMBOL(param_ops_##name) | ||
| 244 | |||
| 195 | 245 | ||
| 196 | STANDARD_PARAM_DEF(byte, unsigned char, "%c", unsigned long, strict_strtoul); | 246 | STANDARD_PARAM_DEF(byte, unsigned char, "%c", unsigned long, strict_strtoul); |
| 197 | STANDARD_PARAM_DEF(short, short, "%hi", long, strict_strtol); | 247 | STANDARD_PARAM_DEF(short, short, "%hi", long, strict_strtol); |
| @@ -201,39 +251,50 @@ STANDARD_PARAM_DEF(uint, unsigned int, "%u", unsigned long, strict_strtoul); | |||
| 201 | STANDARD_PARAM_DEF(long, long, "%li", long, strict_strtol); | 251 | STANDARD_PARAM_DEF(long, long, "%li", long, strict_strtol); |
| 202 | STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", unsigned long, strict_strtoul); | 252 | STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", unsigned long, strict_strtoul); |
| 203 | 253 | ||
| 204 | int param_set_charp(const char *val, struct kernel_param *kp) | 254 | int param_set_charp(const char *val, const struct kernel_param *kp) |
| 205 | { | 255 | { |
| 206 | if (!val) { | ||
| 207 | printk(KERN_ERR "%s: string parameter expected\n", | ||
| 208 | kp->name); | ||
| 209 | return -EINVAL; | ||
| 210 | } | ||
| 211 | |||
| 212 | if (strlen(val) > 1024) { | 256 | if (strlen(val) > 1024) { |
| 213 | printk(KERN_ERR "%s: string parameter too long\n", | 257 | printk(KERN_ERR "%s: string parameter too long\n", |
| 214 | kp->name); | 258 | kp->name); |
| 215 | return -ENOSPC; | 259 | return -ENOSPC; |
| 216 | } | 260 | } |
| 217 | 261 | ||
| 218 | /* This is a hack. We can't need to strdup in early boot, and we | 262 | maybe_kfree_parameter(*(char **)kp->arg); |
| 263 | |||
| 264 | /* This is a hack. We can't kmalloc in early boot, and we | ||
| 219 | * don't need to; this mangled commandline is preserved. */ | 265 | * don't need to; this mangled commandline is preserved. */ |
| 220 | if (slab_is_available()) { | 266 | if (slab_is_available()) { |
| 221 | *(char **)kp->arg = kstrdup(val, GFP_KERNEL); | 267 | *(char **)kp->arg = kmalloc_parameter(strlen(val)+1); |
| 222 | if (!*(char **)kp->arg) | 268 | if (!*(char **)kp->arg) |
| 223 | return -ENOMEM; | 269 | return -ENOMEM; |
| 270 | strcpy(*(char **)kp->arg, val); | ||
| 224 | } else | 271 | } else |
| 225 | *(const char **)kp->arg = val; | 272 | *(const char **)kp->arg = val; |
| 226 | 273 | ||
| 227 | return 0; | 274 | return 0; |
| 228 | } | 275 | } |
| 276 | EXPORT_SYMBOL(param_set_charp); | ||
| 229 | 277 | ||
| 230 | int param_get_charp(char *buffer, struct kernel_param *kp) | 278 | int param_get_charp(char *buffer, const struct kernel_param *kp) |
| 231 | { | 279 | { |
| 232 | return sprintf(buffer, "%s", *((char **)kp->arg)); | 280 | return sprintf(buffer, "%s", *((char **)kp->arg)); |
| 233 | } | 281 | } |
| 282 | EXPORT_SYMBOL(param_get_charp); | ||
| 283 | |||
| 284 | static void param_free_charp(void *arg) | ||
| 285 | { | ||
| 286 | maybe_kfree_parameter(*((char **)arg)); | ||
| 287 | } | ||
| 288 | |||
| 289 | struct kernel_param_ops param_ops_charp = { | ||
| 290 | .set = param_set_charp, | ||
| 291 | .get = param_get_charp, | ||
| 292 | .free = param_free_charp, | ||
| 293 | }; | ||
| 294 | EXPORT_SYMBOL(param_ops_charp); | ||
| 234 | 295 | ||
| 235 | /* Actually could be a bool or an int, for historical reasons. */ | 296 | /* Actually could be a bool or an int, for historical reasons. */ |
| 236 | int param_set_bool(const char *val, struct kernel_param *kp) | 297 | int param_set_bool(const char *val, const struct kernel_param *kp) |
| 237 | { | 298 | { |
| 238 | bool v; | 299 | bool v; |
| 239 | 300 | ||
| @@ -258,8 +319,9 @@ int param_set_bool(const char *val, struct kernel_param *kp) | |||
| 258 | *(int *)kp->arg = v; | 319 | *(int *)kp->arg = v; |
| 259 | return 0; | 320 | return 0; |
| 260 | } | 321 | } |
| 322 | EXPORT_SYMBOL(param_set_bool); | ||
| 261 | 323 | ||
| 262 | int param_get_bool(char *buffer, struct kernel_param *kp) | 324 | int param_get_bool(char *buffer, const struct kernel_param *kp) |
| 263 | { | 325 | { |
| 264 | bool val; | 326 | bool val; |
| 265 | if (kp->flags & KPARAM_ISBOOL) | 327 | if (kp->flags & KPARAM_ISBOOL) |
| @@ -270,9 +332,16 @@ int param_get_bool(char *buffer, struct kernel_param *kp) | |||
| 270 | /* Y and N chosen as being relatively non-coder friendly */ | 332 | /* Y and N chosen as being relatively non-coder friendly */ |
| 271 | return sprintf(buffer, "%c", val ? 'Y' : 'N'); | 333 | return sprintf(buffer, "%c", val ? 'Y' : 'N'); |
| 272 | } | 334 | } |
| 335 | EXPORT_SYMBOL(param_get_bool); | ||
| 336 | |||
| 337 | struct kernel_param_ops param_ops_bool = { | ||
| 338 | .set = param_set_bool, | ||
| 339 | .get = param_get_bool, | ||
| 340 | }; | ||
| 341 | EXPORT_SYMBOL(param_ops_bool); | ||
| 273 | 342 | ||
| 274 | /* This one must be bool. */ | 343 | /* This one must be bool. */ |
| 275 | int param_set_invbool(const char *val, struct kernel_param *kp) | 344 | int param_set_invbool(const char *val, const struct kernel_param *kp) |
| 276 | { | 345 | { |
| 277 | int ret; | 346 | int ret; |
| 278 | bool boolval; | 347 | bool boolval; |
| @@ -285,18 +354,26 @@ int param_set_invbool(const char *val, struct kernel_param *kp) | |||
| 285 | *(bool *)kp->arg = !boolval; | 354 | *(bool *)kp->arg = !boolval; |
| 286 | return ret; | 355 | return ret; |
| 287 | } | 356 | } |
| 357 | EXPORT_SYMBOL(param_set_invbool); | ||
| 288 | 358 | ||
| 289 | int param_get_invbool(char *buffer, struct kernel_param *kp) | 359 | int param_get_invbool(char *buffer, const struct kernel_param *kp) |
| 290 | { | 360 | { |
| 291 | return sprintf(buffer, "%c", (*(bool *)kp->arg) ? 'N' : 'Y'); | 361 | return sprintf(buffer, "%c", (*(bool *)kp->arg) ? 'N' : 'Y'); |
| 292 | } | 362 | } |
| 363 | EXPORT_SYMBOL(param_get_invbool); | ||
| 364 | |||
| 365 | struct kernel_param_ops param_ops_invbool = { | ||
| 366 | .set = param_set_invbool, | ||
| 367 | .get = param_get_invbool, | ||
| 368 | }; | ||
| 369 | EXPORT_SYMBOL(param_ops_invbool); | ||
| 293 | 370 | ||
| 294 | /* We break the rule and mangle the string. */ | 371 | /* We break the rule and mangle the string. */ |
| 295 | static int param_array(const char *name, | 372 | static int param_array(const char *name, |
| 296 | const char *val, | 373 | const char *val, |
| 297 | unsigned int min, unsigned int max, | 374 | unsigned int min, unsigned int max, |
| 298 | void *elem, int elemsize, | 375 | void *elem, int elemsize, |
| 299 | int (*set)(const char *, struct kernel_param *kp), | 376 | int (*set)(const char *, const struct kernel_param *kp), |
| 300 | u16 flags, | 377 | u16 flags, |
| 301 | unsigned int *num) | 378 | unsigned int *num) |
| 302 | { | 379 | { |
| @@ -309,12 +386,6 @@ static int param_array(const char *name, | |||
| 309 | kp.arg = elem; | 386 | kp.arg = elem; |
| 310 | kp.flags = flags; | 387 | kp.flags = flags; |
| 311 | 388 | ||
| 312 | /* No equals sign? */ | ||
| 313 | if (!val) { | ||
| 314 | printk(KERN_ERR "%s: expects arguments\n", name); | ||
| 315 | return -EINVAL; | ||
| 316 | } | ||
| 317 | |||
| 318 | *num = 0; | 389 | *num = 0; |
| 319 | /* We expect a comma-separated list of values. */ | 390 | /* We expect a comma-separated list of values. */ |
| 320 | do { | 391 | do { |
| @@ -330,6 +401,7 @@ static int param_array(const char *name, | |||
| 330 | /* nul-terminate and parse */ | 401 | /* nul-terminate and parse */ |
| 331 | save = val[len]; | 402 | save = val[len]; |
| 332 | ((char *)val)[len] = '\0'; | 403 | ((char *)val)[len] = '\0'; |
| 404 | BUG_ON(!mutex_is_locked(¶m_lock)); | ||
| 333 | ret = set(val, &kp); | 405 | ret = set(val, &kp); |
| 334 | 406 | ||
| 335 | if (ret != 0) | 407 | if (ret != 0) |
| @@ -347,17 +419,17 @@ static int param_array(const char *name, | |||
| 347 | return 0; | 419 | return 0; |
| 348 | } | 420 | } |
| 349 | 421 | ||
| 350 | int param_array_set(const char *val, struct kernel_param *kp) | 422 | static int param_array_set(const char *val, const struct kernel_param *kp) |
| 351 | { | 423 | { |
| 352 | const struct kparam_array *arr = kp->arr; | 424 | const struct kparam_array *arr = kp->arr; |
| 353 | unsigned int temp_num; | 425 | unsigned int temp_num; |
| 354 | 426 | ||
| 355 | return param_array(kp->name, val, 1, arr->max, arr->elem, | 427 | return param_array(kp->name, val, 1, arr->max, arr->elem, |
| 356 | arr->elemsize, arr->set, kp->flags, | 428 | arr->elemsize, arr->ops->set, kp->flags, |
| 357 | arr->num ?: &temp_num); | 429 | arr->num ?: &temp_num); |
| 358 | } | 430 | } |
| 359 | 431 | ||
| 360 | int param_array_get(char *buffer, struct kernel_param *kp) | 432 | static int param_array_get(char *buffer, const struct kernel_param *kp) |
| 361 | { | 433 | { |
| 362 | int i, off, ret; | 434 | int i, off, ret; |
| 363 | const struct kparam_array *arr = kp->arr; | 435 | const struct kparam_array *arr = kp->arr; |
| @@ -368,7 +440,8 @@ int param_array_get(char *buffer, struct kernel_param *kp) | |||
| 368 | if (i) | 440 | if (i) |
| 369 | buffer[off++] = ','; | 441 | buffer[off++] = ','; |
| 370 | p.arg = arr->elem + arr->elemsize * i; | 442 | p.arg = arr->elem + arr->elemsize * i; |
| 371 | ret = arr->get(buffer + off, &p); | 443 | BUG_ON(!mutex_is_locked(¶m_lock)); |
| 444 | ret = arr->ops->get(buffer + off, &p); | ||
| 372 | if (ret < 0) | 445 | if (ret < 0) |
| 373 | return ret; | 446 | return ret; |
| 374 | off += ret; | 447 | off += ret; |
| @@ -377,14 +450,27 @@ int param_array_get(char *buffer, struct kernel_param *kp) | |||
| 377 | return off; | 450 | return off; |
| 378 | } | 451 | } |
| 379 | 452 | ||
| 380 | int param_set_copystring(const char *val, struct kernel_param *kp) | 453 | static void param_array_free(void *arg) |
| 454 | { | ||
| 455 | unsigned int i; | ||
| 456 | const struct kparam_array *arr = arg; | ||
| 457 | |||
| 458 | if (arr->ops->free) | ||
| 459 | for (i = 0; i < (arr->num ? *arr->num : arr->max); i++) | ||
| 460 | arr->ops->free(arr->elem + arr->elemsize * i); | ||
| 461 | } | ||
| 462 | |||
| 463 | struct kernel_param_ops param_array_ops = { | ||
| 464 | .set = param_array_set, | ||
| 465 | .get = param_array_get, | ||
| 466 | .free = param_array_free, | ||
| 467 | }; | ||
| 468 | EXPORT_SYMBOL(param_array_ops); | ||
| 469 | |||
| 470 | int param_set_copystring(const char *val, const struct kernel_param *kp) | ||
| 381 | { | 471 | { |
| 382 | const struct kparam_string *kps = kp->str; | 472 | const struct kparam_string *kps = kp->str; |
| 383 | 473 | ||
| 384 | if (!val) { | ||
| 385 | printk(KERN_ERR "%s: missing param set value\n", kp->name); | ||
| 386 | return -EINVAL; | ||
| 387 | } | ||
| 388 | if (strlen(val)+1 > kps->maxlen) { | 474 | if (strlen(val)+1 > kps->maxlen) { |
| 389 | printk(KERN_ERR "%s: string doesn't fit in %u chars.\n", | 475 | printk(KERN_ERR "%s: string doesn't fit in %u chars.\n", |
| 390 | kp->name, kps->maxlen-1); | 476 | kp->name, kps->maxlen-1); |
| @@ -393,12 +479,20 @@ int param_set_copystring(const char *val, struct kernel_param *kp) | |||
| 393 | strcpy(kps->string, val); | 479 | strcpy(kps->string, val); |
| 394 | return 0; | 480 | return 0; |
| 395 | } | 481 | } |
| 482 | EXPORT_SYMBOL(param_set_copystring); | ||
| 396 | 483 | ||
| 397 | int param_get_string(char *buffer, struct kernel_param *kp) | 484 | int param_get_string(char *buffer, const struct kernel_param *kp) |
| 398 | { | 485 | { |
| 399 | const struct kparam_string *kps = kp->str; | 486 | const struct kparam_string *kps = kp->str; |
| 400 | return strlcpy(buffer, kps->string, kps->maxlen); | 487 | return strlcpy(buffer, kps->string, kps->maxlen); |
| 401 | } | 488 | } |
| 489 | EXPORT_SYMBOL(param_get_string); | ||
| 490 | |||
| 491 | struct kernel_param_ops param_ops_string = { | ||
| 492 | .set = param_set_copystring, | ||
| 493 | .get = param_get_string, | ||
| 494 | }; | ||
| 495 | EXPORT_SYMBOL(param_ops_string); | ||
| 402 | 496 | ||
| 403 | /* sysfs output in /sys/modules/XYZ/parameters/ */ | 497 | /* sysfs output in /sys/modules/XYZ/parameters/ */ |
| 404 | #define to_module_attr(n) container_of(n, struct module_attribute, attr) | 498 | #define to_module_attr(n) container_of(n, struct module_attribute, attr) |
| @@ -409,7 +503,7 @@ extern struct kernel_param __start___param[], __stop___param[]; | |||
| 409 | struct param_attribute | 503 | struct param_attribute |
| 410 | { | 504 | { |
| 411 | struct module_attribute mattr; | 505 | struct module_attribute mattr; |
| 412 | struct kernel_param *param; | 506 | const struct kernel_param *param; |
| 413 | }; | 507 | }; |
| 414 | 508 | ||
| 415 | struct module_param_attrs | 509 | struct module_param_attrs |
| @@ -428,10 +522,12 @@ static ssize_t param_attr_show(struct module_attribute *mattr, | |||
| 428 | int count; | 522 | int count; |
| 429 | struct param_attribute *attribute = to_param_attr(mattr); | 523 | struct param_attribute *attribute = to_param_attr(mattr); |
| 430 | 524 | ||
| 431 | if (!attribute->param->get) | 525 | if (!attribute->param->ops->get) |
| 432 | return -EPERM; | 526 | return -EPERM; |
| 433 | 527 | ||
| 434 | count = attribute->param->get(buf, attribute->param); | 528 | mutex_lock(¶m_lock); |
| 529 | count = attribute->param->ops->get(buf, attribute->param); | ||
| 530 | mutex_unlock(¶m_lock); | ||
| 435 | if (count > 0) { | 531 | if (count > 0) { |
| 436 | strcat(buf, "\n"); | 532 | strcat(buf, "\n"); |
| 437 | ++count; | 533 | ++count; |
| @@ -447,10 +543,12 @@ static ssize_t param_attr_store(struct module_attribute *mattr, | |||
| 447 | int err; | 543 | int err; |
| 448 | struct param_attribute *attribute = to_param_attr(mattr); | 544 | struct param_attribute *attribute = to_param_attr(mattr); |
| 449 | 545 | ||
| 450 | if (!attribute->param->set) | 546 | if (!attribute->param->ops->set) |
| 451 | return -EPERM; | 547 | return -EPERM; |
| 452 | 548 | ||
| 453 | err = attribute->param->set(buf, attribute->param); | 549 | mutex_lock(¶m_lock); |
| 550 | err = attribute->param->ops->set(buf, attribute->param); | ||
| 551 | mutex_unlock(¶m_lock); | ||
| 454 | if (!err) | 552 | if (!err) |
| 455 | return len; | 553 | return len; |
| 456 | return err; | 554 | return err; |
| @@ -464,6 +562,18 @@ static ssize_t param_attr_store(struct module_attribute *mattr, | |||
| 464 | #endif | 562 | #endif |
| 465 | 563 | ||
| 466 | #ifdef CONFIG_SYSFS | 564 | #ifdef CONFIG_SYSFS |
| 565 | void __kernel_param_lock(void) | ||
| 566 | { | ||
| 567 | mutex_lock(¶m_lock); | ||
| 568 | } | ||
| 569 | EXPORT_SYMBOL(__kernel_param_lock); | ||
| 570 | |||
| 571 | void __kernel_param_unlock(void) | ||
| 572 | { | ||
| 573 | mutex_unlock(¶m_lock); | ||
| 574 | } | ||
| 575 | EXPORT_SYMBOL(__kernel_param_unlock); | ||
| 576 | |||
| 467 | /* | 577 | /* |
| 468 | * add_sysfs_param - add a parameter to sysfs | 578 | * add_sysfs_param - add a parameter to sysfs |
| 469 | * @mk: struct module_kobject | 579 | * @mk: struct module_kobject |
| @@ -475,7 +585,7 @@ static ssize_t param_attr_store(struct module_attribute *mattr, | |||
| 475 | * if there's an error. | 585 | * if there's an error. |
| 476 | */ | 586 | */ |
| 477 | static __modinit int add_sysfs_param(struct module_kobject *mk, | 587 | static __modinit int add_sysfs_param(struct module_kobject *mk, |
| 478 | struct kernel_param *kp, | 588 | const struct kernel_param *kp, |
| 479 | const char *name) | 589 | const char *name) |
| 480 | { | 590 | { |
| 481 | struct module_param_attrs *new; | 591 | struct module_param_attrs *new; |
| @@ -557,7 +667,7 @@ static void free_module_param_attrs(struct module_kobject *mk) | |||
| 557 | * /sys/module/[mod->name]/parameters/ | 667 | * /sys/module/[mod->name]/parameters/ |
| 558 | */ | 668 | */ |
| 559 | int module_param_sysfs_setup(struct module *mod, | 669 | int module_param_sysfs_setup(struct module *mod, |
| 560 | struct kernel_param *kparam, | 670 | const struct kernel_param *kparam, |
| 561 | unsigned int num_params) | 671 | unsigned int num_params) |
| 562 | { | 672 | { |
| 563 | int i, err; | 673 | int i, err; |
| @@ -602,7 +712,11 @@ void module_param_sysfs_remove(struct module *mod) | |||
| 602 | 712 | ||
| 603 | void destroy_params(const struct kernel_param *params, unsigned num) | 713 | void destroy_params(const struct kernel_param *params, unsigned num) |
| 604 | { | 714 | { |
| 605 | /* FIXME: This should free kmalloced charp parameters. It doesn't. */ | 715 | unsigned int i; |
| 716 | |||
| 717 | for (i = 0; i < num; i++) | ||
| 718 | if (params[i].ops->free) | ||
| 719 | params[i].ops->free(params[i].arg); | ||
| 606 | } | 720 | } |
| 607 | 721 | ||
| 608 | static void __init kernel_add_sysfs_param(const char *name, | 722 | static void __init kernel_add_sysfs_param(const char *name, |
| @@ -768,28 +882,3 @@ static int __init param_sysfs_init(void) | |||
| 768 | subsys_initcall(param_sysfs_init); | 882 | subsys_initcall(param_sysfs_init); |
| 769 | 883 | ||
| 770 | #endif /* CONFIG_SYSFS */ | 884 | #endif /* CONFIG_SYSFS */ |
| 771 | |||
| 772 | EXPORT_SYMBOL(param_set_byte); | ||
| 773 | EXPORT_SYMBOL(param_get_byte); | ||
| 774 | EXPORT_SYMBOL(param_set_short); | ||
| 775 | EXPORT_SYMBOL(param_get_short); | ||
| 776 | EXPORT_SYMBOL(param_set_ushort); | ||
| 777 | EXPORT_SYMBOL(param_get_ushort); | ||
| 778 | EXPORT_SYMBOL(param_set_int); | ||
| 779 | EXPORT_SYMBOL(param_get_int); | ||
| 780 | EXPORT_SYMBOL(param_set_uint); | ||
| 781 | EXPORT_SYMBOL(param_get_uint); | ||
| 782 | EXPORT_SYMBOL(param_set_long); | ||
| 783 | EXPORT_SYMBOL(param_get_long); | ||
| 784 | EXPORT_SYMBOL(param_set_ulong); | ||
| 785 | EXPORT_SYMBOL(param_get_ulong); | ||
| 786 | EXPORT_SYMBOL(param_set_charp); | ||
| 787 | EXPORT_SYMBOL(param_get_charp); | ||
| 788 | EXPORT_SYMBOL(param_set_bool); | ||
| 789 | EXPORT_SYMBOL(param_get_bool); | ||
| 790 | EXPORT_SYMBOL(param_set_invbool); | ||
| 791 | EXPORT_SYMBOL(param_get_invbool); | ||
| 792 | EXPORT_SYMBOL(param_array_set); | ||
| 793 | EXPORT_SYMBOL(param_array_get); | ||
| 794 | EXPORT_SYMBOL(param_set_copystring); | ||
| 795 | EXPORT_SYMBOL(param_get_string); | ||
