diff options
| -rw-r--r-- | drivers/base/core.c | 76 | ||||
| -rw-r--r-- | fs/sysfs/dir.c | 6 | ||||
| -rw-r--r-- | lib/kobject.c | 6 |
3 files changed, 52 insertions, 36 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index 36eedfdeb547..c60114dbe5f5 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
| @@ -390,22 +390,23 @@ void device_initialize(struct device *dev) | |||
| 390 | } | 390 | } |
| 391 | 391 | ||
| 392 | #ifdef CONFIG_SYSFS_DEPRECATED | 392 | #ifdef CONFIG_SYSFS_DEPRECATED |
| 393 | static int setup_parent(struct device *dev, struct device *parent) | 393 | static struct kobject * get_device_parent(struct device *dev, |
| 394 | struct device *parent) | ||
| 394 | { | 395 | { |
| 395 | /* Set the parent to the class, not the parent device */ | 396 | /* Set the parent to the class, not the parent device */ |
| 396 | /* this keeps sysfs from having a symlink to make old udevs happy */ | 397 | /* this keeps sysfs from having a symlink to make old udevs happy */ |
| 397 | if (dev->class) | 398 | if (dev->class) |
| 398 | dev->kobj.parent = &dev->class->subsys.kset.kobj; | 399 | return &dev->class->subsys.kset.kobj; |
| 399 | else if (parent) | 400 | else if (parent) |
| 400 | dev->kobj.parent = &parent->kobj; | 401 | return &parent->kobj; |
| 401 | 402 | ||
| 402 | return 0; | 403 | return NULL; |
| 403 | } | 404 | } |
| 404 | #else | 405 | #else |
| 405 | static int virtual_device_parent(struct device *dev) | 406 | static struct kobject * virtual_device_parent(struct device *dev) |
| 406 | { | 407 | { |
| 407 | if (!dev->class) | 408 | if (!dev->class) |
| 408 | return -ENODEV; | 409 | return ERR_PTR(-ENODEV); |
| 409 | 410 | ||
| 410 | if (!dev->class->virtual_dir) { | 411 | if (!dev->class->virtual_dir) { |
| 411 | static struct kobject *virtual_dir = NULL; | 412 | static struct kobject *virtual_dir = NULL; |
| @@ -415,25 +416,31 @@ static int virtual_device_parent(struct device *dev) | |||
| 415 | dev->class->virtual_dir = kobject_add_dir(virtual_dir, dev->class->name); | 416 | dev->class->virtual_dir = kobject_add_dir(virtual_dir, dev->class->name); |
| 416 | } | 417 | } |
| 417 | 418 | ||
| 418 | dev->kobj.parent = dev->class->virtual_dir; | 419 | return dev->class->virtual_dir; |
| 419 | return 0; | ||
| 420 | } | 420 | } |
| 421 | 421 | ||
| 422 | static int setup_parent(struct device *dev, struct device *parent) | 422 | static struct kobject * get_device_parent(struct device *dev, |
| 423 | struct device *parent) | ||
| 423 | { | 424 | { |
| 424 | int error; | ||
| 425 | |||
| 426 | /* if this is a class device, and has no parent, create one */ | 425 | /* if this is a class device, and has no parent, create one */ |
| 427 | if ((dev->class) && (parent == NULL)) { | 426 | if ((dev->class) && (parent == NULL)) { |
| 428 | error = virtual_device_parent(dev); | 427 | return virtual_device_parent(dev); |
| 429 | if (error) | ||
| 430 | return error; | ||
| 431 | } else if (parent) | 428 | } else if (parent) |
| 432 | dev->kobj.parent = &parent->kobj; | 429 | return &parent->kobj; |
| 430 | return NULL; | ||
| 431 | } | ||
| 433 | 432 | ||
| 433 | #endif | ||
| 434 | static int setup_parent(struct device *dev, struct device *parent) | ||
| 435 | { | ||
| 436 | struct kobject *kobj; | ||
| 437 | kobj = get_device_parent(dev, parent); | ||
| 438 | if (IS_ERR(kobj)) | ||
| 439 | return PTR_ERR(kobj); | ||
| 440 | if (kobj) | ||
| 441 | dev->kobj.parent = kobj; | ||
| 434 | return 0; | 442 | return 0; |
| 435 | } | 443 | } |
| 436 | #endif | ||
| 437 | 444 | ||
| 438 | /** | 445 | /** |
| 439 | * device_add - add device to device hierarchy. | 446 | * device_add - add device to device hierarchy. |
| @@ -976,12 +983,18 @@ static int device_move_class_links(struct device *dev, | |||
| 976 | sysfs_remove_link(&dev->kobj, "device"); | 983 | sysfs_remove_link(&dev->kobj, "device"); |
| 977 | sysfs_remove_link(&old_parent->kobj, class_name); | 984 | sysfs_remove_link(&old_parent->kobj, class_name); |
| 978 | } | 985 | } |
| 979 | error = sysfs_create_link(&dev->kobj, &new_parent->kobj, "device"); | 986 | if (new_parent) { |
| 980 | if (error) | 987 | error = sysfs_create_link(&dev->kobj, &new_parent->kobj, |
| 981 | goto out; | 988 | "device"); |
| 982 | error = sysfs_create_link(&new_parent->kobj, &dev->kobj, class_name); | 989 | if (error) |
| 983 | if (error) | 990 | goto out; |
| 984 | sysfs_remove_link(&dev->kobj, "device"); | 991 | error = sysfs_create_link(&new_parent->kobj, &dev->kobj, |
| 992 | class_name); | ||
| 993 | if (error) | ||
| 994 | sysfs_remove_link(&dev->kobj, "device"); | ||
| 995 | } | ||
| 996 | else | ||
| 997 | error = 0; | ||
| 985 | out: | 998 | out: |
| 986 | kfree(class_name); | 999 | kfree(class_name); |
| 987 | return error; | 1000 | return error; |
| @@ -993,25 +1006,28 @@ out: | |||
| 993 | /** | 1006 | /** |
| 994 | * device_move - moves a device to a new parent | 1007 | * device_move - moves a device to a new parent |
| 995 | * @dev: the pointer to the struct device to be moved | 1008 | * @dev: the pointer to the struct device to be moved |
| 996 | * @new_parent: the new parent of the device | 1009 | * @new_parent: the new parent of the device (can by NULL) |
| 997 | */ | 1010 | */ |
| 998 | int device_move(struct device *dev, struct device *new_parent) | 1011 | int device_move(struct device *dev, struct device *new_parent) |
| 999 | { | 1012 | { |
| 1000 | int error; | 1013 | int error; |
| 1001 | struct device *old_parent; | 1014 | struct device *old_parent; |
| 1015 | struct kobject *new_parent_kobj; | ||
| 1002 | 1016 | ||
| 1003 | dev = get_device(dev); | 1017 | dev = get_device(dev); |
| 1004 | if (!dev) | 1018 | if (!dev) |
| 1005 | return -EINVAL; | 1019 | return -EINVAL; |
| 1006 | 1020 | ||
| 1007 | new_parent = get_device(new_parent); | 1021 | new_parent = get_device(new_parent); |
| 1008 | if (!new_parent) { | 1022 | new_parent_kobj = get_device_parent (dev, new_parent); |
| 1009 | error = -EINVAL; | 1023 | if (IS_ERR(new_parent_kobj)) { |
| 1024 | error = PTR_ERR(new_parent_kobj); | ||
| 1025 | put_device(new_parent); | ||
| 1010 | goto out; | 1026 | goto out; |
| 1011 | } | 1027 | } |
| 1012 | pr_debug("DEVICE: moving '%s' to '%s'\n", dev->bus_id, | 1028 | pr_debug("DEVICE: moving '%s' to '%s'\n", dev->bus_id, |
| 1013 | new_parent->bus_id); | 1029 | new_parent ? new_parent->bus_id : "<NULL>"); |
| 1014 | error = kobject_move(&dev->kobj, &new_parent->kobj); | 1030 | error = kobject_move(&dev->kobj, new_parent_kobj); |
| 1015 | if (error) { | 1031 | if (error) { |
| 1016 | put_device(new_parent); | 1032 | put_device(new_parent); |
| 1017 | goto out; | 1033 | goto out; |
| @@ -1020,7 +1036,8 @@ int device_move(struct device *dev, struct device *new_parent) | |||
| 1020 | dev->parent = new_parent; | 1036 | dev->parent = new_parent; |
| 1021 | if (old_parent) | 1037 | if (old_parent) |
| 1022 | klist_remove(&dev->knode_parent); | 1038 | klist_remove(&dev->knode_parent); |
| 1023 | klist_add_tail(&dev->knode_parent, &new_parent->klist_children); | 1039 | if (new_parent) |
| 1040 | klist_add_tail(&dev->knode_parent, &new_parent->klist_children); | ||
| 1024 | if (!dev->class) | 1041 | if (!dev->class) |
| 1025 | goto out_put; | 1042 | goto out_put; |
| 1026 | error = device_move_class_links(dev, old_parent, new_parent); | 1043 | error = device_move_class_links(dev, old_parent, new_parent); |
| @@ -1028,7 +1045,8 @@ int device_move(struct device *dev, struct device *new_parent) | |||
| 1028 | /* We ignore errors on cleanup since we're hosed anyway... */ | 1045 | /* We ignore errors on cleanup since we're hosed anyway... */ |
| 1029 | device_move_class_links(dev, new_parent, old_parent); | 1046 | device_move_class_links(dev, new_parent, old_parent); |
| 1030 | if (!kobject_move(&dev->kobj, &old_parent->kobj)) { | 1047 | if (!kobject_move(&dev->kobj, &old_parent->kobj)) { |
| 1031 | klist_remove(&dev->knode_parent); | 1048 | if (new_parent) |
| 1049 | klist_remove(&dev->knode_parent); | ||
| 1032 | if (old_parent) | 1050 | if (old_parent) |
| 1033 | klist_add_tail(&dev->knode_parent, | 1051 | klist_add_tail(&dev->knode_parent, |
| 1034 | &old_parent->klist_children); | 1052 | &old_parent->klist_children); |
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 511edef8b321..2bab1b4ddf5a 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
| @@ -378,12 +378,10 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent) | |||
| 378 | struct sysfs_dirent *new_parent_sd, *sd; | 378 | struct sysfs_dirent *new_parent_sd, *sd; |
| 379 | int error; | 379 | int error; |
| 380 | 380 | ||
| 381 | if (!new_parent) | ||
| 382 | return -EINVAL; | ||
| 383 | |||
| 384 | old_parent_dentry = kobj->parent ? | 381 | old_parent_dentry = kobj->parent ? |
| 385 | kobj->parent->dentry : sysfs_mount->mnt_sb->s_root; | 382 | kobj->parent->dentry : sysfs_mount->mnt_sb->s_root; |
| 386 | new_parent_dentry = new_parent->dentry; | 383 | new_parent_dentry = new_parent ? |
| 384 | new_parent->dentry : sysfs_mount->mnt_sb->s_root; | ||
| 387 | 385 | ||
| 388 | again: | 386 | again: |
| 389 | mutex_lock(&old_parent_dentry->d_inode->i_mutex); | 387 | mutex_lock(&old_parent_dentry->d_inode->i_mutex); |
diff --git a/lib/kobject.c b/lib/kobject.c index 9aed594bfcac..c033dc8fa9af 100644 --- a/lib/kobject.c +++ b/lib/kobject.c | |||
| @@ -314,7 +314,7 @@ int kobject_rename(struct kobject * | |||
