diff options
author | Kay Sievers <kay.sievers@vrfy.org> | 2007-08-14 09:15:12 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-10-12 17:51:01 -0400 |
commit | 7eff2e7a8b65c25920207324e56611150eb1cd9a (patch) | |
tree | 02a0eeba9d25d996233e30c18f258dfae0ae2139 /drivers/base/class.c | |
parent | 8380770c842faef3001e44662953d64ad9a93663 (diff) |
Driver core: change add_uevent_var to use a struct
This changes the uevent buffer functions to use a struct instead of a
long list of parameters. It does no longer require the caller to do the
proper buffer termination and size accounting, which is currently wrong
in some places. It fixes a known bug where parts of the uevent
environment are overwritten because of wrong index calculations.
Many thanks to Mathieu Desnoyers for finding bugs and improving the
error handling.
Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
Cc: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Cc: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/base/class.c')
-rw-r--r-- | drivers/base/class.c | 42 |
1 files changed, 10 insertions, 32 deletions
diff --git a/drivers/base/class.c b/drivers/base/class.c index 4d2222618b78..ecd6336bffea 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c | |||
@@ -180,8 +180,7 @@ static void class_device_create_release(struct class_device *class_dev) | |||
180 | 180 | ||
181 | /* needed to allow these devices to have parent class devices */ | 181 | /* needed to allow these devices to have parent class devices */ |
182 | static int class_device_create_uevent(struct class_device *class_dev, | 182 | static int class_device_create_uevent(struct class_device *class_dev, |
183 | char **envp, int num_envp, | 183 | struct kobj_uevent_env *env) |
184 | char *buffer, int buffer_size) | ||
185 | { | 184 | { |
186 | pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id); | 185 | pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id); |
187 | return 0; | 186 | return 0; |
@@ -403,64 +402,43 @@ static void remove_deprecated_class_device_links(struct class_device *cd) | |||
403 | { } | 402 | { } |
404 | #endif | 403 | #endif |
405 | 404 | ||
406 | static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp, | 405 | static int class_uevent(struct kset *kset, struct kobject *kobj, |
407 | int num_envp, char *buffer, int buffer_size) | 406 | struct kobj_uevent_env *env) |
408 | { | 407 | { |
409 | struct class_device *class_dev = to_class_dev(kobj); | 408 | struct class_device *class_dev = to_class_dev(kobj); |
410 | struct device *dev = class_dev->dev; | 409 | struct device *dev = class_dev->dev; |
411 | int i = 0; | ||
412 | int length = 0; | ||
413 | int retval = 0; | 410 | int retval = 0; |
414 | 411 | ||
415 | pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id); | 412 | pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id); |
416 | 413 | ||
417 | if (MAJOR(class_dev->devt)) { | 414 | if (MAJOR(class_dev->devt)) { |
418 | add_uevent_var(envp, num_envp, &i, | 415 | add_uevent_var(env, "MAJOR=%u", MAJOR(class_dev->devt)); |
419 | buffer, buffer_size, &length, | ||
420 | "MAJOR=%u", MAJOR(class_dev->devt)); | ||
421 | 416 | ||
422 | add_uevent_var(envp, num_envp, &i, | 417 | add_uevent_var(env, "MINOR=%u", MINOR(class_dev->devt)); |
423 | buffer, buffer_size, &length, | ||
424 | "MINOR=%u", MINOR(class_dev->devt)); | ||
425 | } | 418 | } |
426 | 419 | ||
427 | if (dev) { | 420 | if (dev) { |
428 | const char *path = kobject_get_path(&dev->kobj, GFP_KERNEL); | 421 | const char *path = kobject_get_path(&dev->kobj, GFP_KERNEL); |
429 | if (path) { | 422 | if (path) { |
430 | add_uevent_var(envp, num_envp, &i, | 423 | add_uevent_var(env, "PHYSDEVPATH=%s", path); |
431 | buffer, buffer_size, &length, | ||
432 | "PHYSDEVPATH=%s", path); | ||
433 | kfree(path); | 424 | kfree(path); |
434 | } | 425 | } |
435 | 426 | ||
436 | if (dev->bus) | 427 | if (dev->bus) |
437 | add_uevent_var(envp, num_envp, &i, | 428 | add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name); |
438 | buffer, buffer_size, &length, | ||
439 | "PHYSDEVBUS=%s", dev->bus->name); | ||
440 | 429 | ||
441 | if (dev->driver) | 430 | if (dev->driver) |
442 | add_uevent_var(envp, num_envp, &i, | 431 | add_uevent_var(env, "PHYSDEVDRIVER=%s", dev->driver->name); |
443 | buffer, buffer_size, &length, | ||
444 | "PHYSDEVDRIVER=%s", dev->driver->name); | ||
445 | } | 432 | } |
446 | 433 | ||
447 | /* terminate, set to next free slot, shrink available space */ | ||
448 | envp[i] = NULL; | ||
449 | envp = &envp[i]; | ||
450 | num_envp -= i; | ||
451 | buffer = &buffer[length]; | ||
452 | buffer_size -= length; | ||
453 | |||
454 | if (class_dev->uevent) { | 434 | if (class_dev->uevent) { |
455 | /* have the class device specific function add its stuff */ | 435 | /* have the class device specific function add its stuff */ |
456 | retval = class_dev->uevent(class_dev, envp, num_envp, | 436 | retval = class_dev->uevent(class_dev, env); |
457 | buffer, buffer_size); | ||
458 | if (retval) | 437 | if (retval) |
459 | pr_debug("class_dev->uevent() returned %d\n", retval); | 438 | pr_debug("class_dev->uevent() returned %d\n", retval); |
460 | } else if (class_dev->class->uevent) { | 439 | } else if (class_dev->class->uevent) { |
461 | /* have the class specific function add its stuff */ | 440 | /* have the class specific function add its stuff */ |
462 | retval = class_dev->class->uevent(class_dev, envp, num_envp, | 441 | retval = class_dev->class->uevent(class_dev, env); |
463 | buffer, buffer_size); | ||
464 | if (retval) | 442 | if (retval) |
465 | pr_debug("class->uevent() returned %d\n", retval); | 443 | pr_debug("class->uevent() returned %d\n", retval); |
466 | } | 444 | } |