diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org.(none)> | 2005-04-19 16:14:28 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org.(none)> | 2005-04-19 16:14:28 -0400 |
commit | 9f6c6fc505560465be0964eb4da1b6ca97bd3951 (patch) | |
tree | 9660991b5e417ad7bb74e105c037ff358f60ba27 | |
parent | c3c661932cd53582c5b03692b99649300977248a (diff) | |
parent | f0e035f4b6940aae6836500b642029c289ed4535 (diff) |
Merge with kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6.git/
for 13 driver core, sysfs, and debugfs fixes.
-rw-r--r-- | Documentation/kref.txt | 216 | ||||
-rw-r--r-- | drivers/base/class.c | 2 | ||||
-rw-r--r-- | drivers/base/core.c | 3 | ||||
-rw-r--r-- | drivers/base/firmware_class.c | 3 | ||||
-rw-r--r-- | drivers/base/platform.c | 1 | ||||
-rw-r--r-- | drivers/usb/host/hc_crisv10.c | 1 | ||||
-rw-r--r-- | fs/partitions/check.c | 2 | ||||
-rw-r--r-- | fs/sysfs/file.c | 35 | ||||
-rw-r--r-- | include/linux/debugfs.h | 13 | ||||
-rw-r--r-- | include/linux/sysfs.h | 7 | ||||
-rw-r--r-- | lib/kobject.c | 7 | ||||
-rw-r--r-- | net/bridge/br_sysfs_if.c | 2 | ||||
-rwxr-xr-x | scripts/ver_linux | 2 |
13 files changed, 286 insertions, 8 deletions
diff --git a/Documentation/kref.txt b/Documentation/kref.txt new file mode 100644 index 000000000000..42fe28445916 --- /dev/null +++ b/Documentation/kref.txt | |||
@@ -0,0 +1,216 @@ | |||
1 | |||
2 | krefs allow you to add reference counters to your objects. If you | ||
3 | have objects that are used in multiple places and passed around, and | ||
4 | you don't have refcounts, your code is almost certainly broken. If | ||
5 | you want refcounts, krefs are the way to go. | ||
6 | |||
7 | To use a kref, add one to your data structures like: | ||
8 | |||
9 | struct my_data | ||
10 | { | ||
11 | . | ||
12 | . | ||
13 | struct kref refcount; | ||
14 | . | ||
15 | . | ||
16 | }; | ||
17 | |||
18 | The kref can occur anywhere within the data structure. | ||
19 | |||
20 | You must initialize the kref after you allocate it. To do this, call | ||
21 | kref_init as so: | ||
22 | |||
23 | struct my_data *data; | ||
24 | |||
25 | data = kmalloc(sizeof(*data), GFP_KERNEL); | ||
26 | if (!data) | ||
27 | return -ENOMEM; | ||
28 | kref_init(&data->refcount); | ||
29 | |||
30 | This sets the refcount in the kref to 1. | ||
31 | |||
32 | Once you have an initialized kref, you must follow the following | ||
33 | rules: | ||
34 | |||
35 | 1) If you make a non-temporary copy of a pointer, especially if | ||
36 | it can be passed to another thread of execution, you must | ||
37 | increment the refcount with kref_get() before passing it off: | ||
38 | kref_get(&data->refcount); | ||
39 | If you already have a valid pointer to a kref-ed structure (the | ||
40 | refcount cannot go to zero) you may do this without a lock. | ||
41 | |||
42 | 2) When you are done with a pointer, you must call kref_put(): | ||
43 | kref_put(&data->refcount, data_release); | ||
44 | If this is the last reference to the pointer, the release | ||
45 | routine will be called. If the code never tries to get | ||
46 | a valid pointer to a kref-ed structure without already | ||
47 | holding a valid pointer, it is safe to do this without | ||
48 | a lock. | ||
49 | |||
50 | 3) If the code attempts to gain a reference to a kref-ed structure | ||
51 | without already holding a valid pointer, it must serialize access | ||
52 | where a kref_put() cannot occur during the kref_get(), and the | ||
53 | structure must remain valid during the kref_get(). | ||
54 | |||
55 | For example, if you allocate some data and then pass it to another | ||
56 | thread to process: | ||
57 | |||
58 | void data_release(struct kref *ref) | ||
59 | { | ||
60 | struct my_data *data = container_of(ref, struct my_data, refcount); | ||
61 | kfree(data); | ||
62 | } | ||
63 | |||
64 | void more_data_handling(void *cb_data) | ||
65 | { | ||
66 | struct my_data *data = cb_data; | ||
67 | . | ||
68 | . do stuff with data here | ||
69 | . | ||
70 | kref_put(data, data_release); | ||
71 | } | ||
72 | |||
73 | int my_data_handler(void) | ||
74 | { | ||
75 | int rv = 0; | ||
76 | struct my_data *data; | ||
77 | struct task_struct *task; | ||
78 | data = kmalloc(sizeof(*data), GFP_KERNEL); | ||
79 | if (!data) | ||
80 | return -ENOMEM; | ||
81 | kref_init(&data->refcount); | ||
82 | |||
83 | kref_get(&data->refcount); | ||
84 | task = kthread_run(more_data_handling, data, "more_data_handling"); | ||
85 | if (task == ERR_PTR(-ENOMEM)) { | ||
86 | rv = -ENOMEM; | ||
87 | kref_put(&data->refcount, data_release); | ||
88 | goto out; | ||
89 | } | ||
90 | |||
91 | . | ||
92 | . do stuff with data here | ||
93 | . | ||
94 | out: | ||
95 | kref_put(&data->refcount, data_release); | ||
96 | return rv; | ||
97 | } | ||
98 | |||
99 | This way, it doesn't matter what order the two threads handle the | ||
100 | data, the kref_put() handles knowing when the data is not referenced | ||
101 | any more and releasing it. The kref_get() does not require a lock, | ||
102 | since we already have a valid pointer that we own a refcount for. The | ||
103 | put needs no lock because nothing tries to get the data without | ||
104 | already holding a pointer. | ||
105 | |||
106 | Note that the "before" in rule 1 is very important. You should never | ||
107 | do something like: | ||
108 | |||
109 | task = kthread_run(more_data_handling, data, "more_data_handling"); | ||
110 | if (task == ERR_PTR(-ENOMEM)) { | ||
111 | rv = -ENOMEM; | ||
112 | goto out; | ||
113 | } else | ||
114 | /* BAD BAD BAD - get is after the handoff */ | ||
115 | kref_get(&data->refcount); | ||
116 | |||
117 | Don't assume you know what you are doing and use the above construct. | ||
118 | First of all, you may not know what you are doing. Second, you may | ||
119 | know what you are doing (there are some situations where locking is | ||
120 | involved where the above may be legal) but someone else who doesn't | ||
121 | know what they are doing may change the code or copy the code. It's | ||
122 | bad style. Don't do it. | ||
123 | |||
124 | There are some situations where you can optimize the gets and puts. | ||
125 | For instance, if you are done with an object and enqueuing it for | ||
126 | something else or passing it off to something else, there is no reason | ||
127 | to do a get then a put: | ||
128 | |||
129 | /* Silly extra get and put */ | ||
130 | kref_get(&obj->ref); | ||
131 | enqueue(obj); | ||
132 | kref_put(&obj->ref, obj_cleanup); | ||
133 | |||
134 | Just do the enqueue. A comment about this is always welcome: | ||
135 | |||
136 | enqueue(obj); | ||
137 | /* We are done with obj, so we pass our refcount off | ||
138 | to the queue. DON'T TOUCH obj AFTER HERE! */ | ||
139 | |||
140 | The last rule (rule 3) is the nastiest one to handle. Say, for | ||
141 | instance, you have a list of items that are each kref-ed, and you wish | ||
142 | to get the first one. You can't just pull the first item off the list | ||
143 | and kref_get() it. That violates rule 3 because you are not already | ||
144 | holding a valid pointer. You must add locks or semaphores. For | ||
145 | instance: | ||
146 | |||
147 | static DECLARE_MUTEX(sem); | ||
148 | static LIST_HEAD(q); | ||
149 | struct my_data | ||
150 | { | ||
151 | struct kref refcount; | ||
152 | struct list_head link; | ||
153 | }; | ||
154 | |||
155 | static struct my_data *get_entry() | ||
156 | { | ||
157 | struct my_data *entry = NULL; | ||
158 | down(&sem); | ||
159 | if (!list_empty(&q)) { | ||
160 | entry = container_of(q.next, struct my_q_entry, link); | ||
161 | kref_get(&entry->refcount); | ||
162 | } | ||
163 | up(&sem); | ||
164 | return entry; | ||
165 | } | ||
166 | |||
167 | static void release_entry(struct kref *ref) | ||
168 | { | ||
169 | struct my_data *entry = container_of(ref, struct my_data, refcount); | ||
170 | |||
171 | list_del(&entry->link); | ||
172 | kfree(entry); | ||
173 | } | ||
174 | |||
175 | static void put_entry(struct my_data *entry) | ||
176 | { | ||
177 | down(&sem); | ||
178 | kref_put(&entry->refcount, release_entry); | ||
179 | up(&sem); | ||
180 | } | ||
181 | |||
182 | The kref_put() return value is useful if you do not want to hold the | ||
183 | lock during the whole release operation. Say you didn't want to call | ||
184 | kfree() with the lock held in the example above (since it is kind of | ||
185 | pointless to do so). You could use kref_put() as follows: | ||
186 | |||
187 | static void release_entry(struct kref *ref) | ||
188 | { | ||
189 | /* All work is done after the return from kref_put(). */ | ||
190 | } | ||
191 | |||
192 | static void put_entry(struct my_data *entry) | ||
193 | { | ||
194 | down(&sem); | ||
195 | if (kref_put(&entry->refcount, release_entry)) { | ||
196 | list_del(&entry->link); | ||
197 | up(&sem); | ||
198 | kfree(entry); | ||
199 | } else | ||
200 | up(&sem); | ||
201 | } | ||
202 | |||
203 | This is really more useful if you have to call other routines as part | ||
204 | of the free operations that could take a long time or might claim the | ||
205 | same lock. Note that doing everything in the release routine is still | ||
206 | preferred as it is a little neater. | ||
207 | |||
208 | |||
209 | Corey Minyard <minyard@acm.org> | ||
210 | |||
211 | A lot of this was lifted from Greg Kroah-Hartman's 2004 OLS paper and | ||
212 | presentation on krefs, which can be found at: | ||
213 | http://www.kroah.com/linux/talks/ols_2004_kref_paper/Reprint-Kroah-Hartman-OLS2004.pdf | ||
214 | and: | ||
215 | http://www.kroah.com/linux/talks/ols_2004_kref_talk/ | ||
216 | |||
diff --git a/drivers/base/class.c b/drivers/base/class.c index 6bf650fce78c..d2a2f8f2b4ed 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c | |||
@@ -430,6 +430,7 @@ int class_device_add(struct class_device *class_dev) | |||
430 | sysfs_create_link(&class_dev->kobj, | 430 | sysfs_create_link(&class_dev->kobj, |
431 | &class_dev->dev->kobj, "device"); | 431 | &class_dev->dev->kobj, "device"); |
432 | 432 | ||
433 | kobject_hotplug(&class_dev->kobj, KOBJ_ADD); | ||
433 | register_done: | 434 | register_done: |
434 | if (error && parent) | 435 | if (error && parent) |
435 | class_put(parent); | 436 | class_put(parent); |
@@ -461,6 +462,7 @@ void class_device_del(struct class_device *class_dev) | |||
461 | sysfs_remove_link(&class_dev->kobj, "device"); | 462 | sysfs_remove_link(&class_dev->kobj, "device"); |
462 | class_device_remove_attrs(class_dev); | 463 | class_device_remove_attrs(class_dev); |
463 | 464 | ||
465 | kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE); | ||
464 | kobject_del(&class_dev->kobj); | 466 | kobject_del(&class_dev->kobj); |
465 | 467 | ||
466 | if (parent) | 468 | if (parent) |
diff --git a/drivers/base/core.c b/drivers/base/core.c index 4e6cce8e6d35..a7cedd8cefe5 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -260,6 +260,8 @@ int device_add(struct device *dev) | |||
260 | /* notify platform of device entry */ | 260 | /* notify platform of device entry */ |
261 | if (platform_notify) | 261 | if (platform_notify) |
262 | platform_notify(dev); | 262 | platform_notify(dev); |
263 | |||
264 | kobject_hotplug(&dev->kobj, KOBJ_ADD); | ||
263 | Done: | 265 | Done: |
264 | put_device(dev); | 266 | put_device(dev); |
265 | return error; | 267 | return error; |
@@ -349,6 +351,7 @@ void device_del(struct device * dev) | |||
349 | platform_notify_remove(dev); | 351 | platform_notify_remove(dev); |
350 | bus_remove_device(dev); | 352 | bus_remove_device(dev); |
351 | device_pm_remove(dev); | 353 | device_pm_remove(dev); |
354 | kobject_hotplug(&dev->kobj, KOBJ_REMOVE); | ||
352 | kobject_del(&dev->kobj); | 355 | kobject_del(&dev->kobj); |
353 | if (parent) | 356 | if (parent) |
354 | put_device(parent); | 357 | put_device(parent); |
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 26c9464af80a..97fe13f7f07c 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -102,6 +102,9 @@ firmware_class_hotplug(struct class_device *class_dev, char **envp, | |||
102 | if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len, | 102 | if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len, |
103 | "FIRMWARE=%s", fw_priv->fw_id)) | 103 | "FIRMWARE=%s", fw_priv->fw_id)) |
104 | return -ENOMEM; | 104 | return -ENOMEM; |
105 | if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len, | ||
106 | "TIMEOUT=%i", loading_timeout)) | ||
107 | return -ENOMEM; | ||
105 | 108 | ||
106 | envp[i] = NULL; | 109 | envp[i] = NULL; |
107 | 110 | ||
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 996cbb4d5087..cd6453905a9b 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -341,6 +341,7 @@ EXPORT_SYMBOL_GPL(dma_get_required_mask); | |||
341 | 341 | ||
342 | EXPORT_SYMBOL_GPL(platform_bus); | 342 | EXPORT_SYMBOL_GPL(platform_bus); |
343 | EXPORT_SYMBOL_GPL(platform_bus_type); | 343 | EXPORT_SYMBOL_GPL(platform_bus_type); |
344 | EXPORT_SYMBOL_GPL(platform_add_devices); | ||
344 | EXPORT_SYMBOL_GPL(platform_device_register); | 345 | EXPORT_SYMBOL_GPL(platform_device_register); |
345 | EXPORT_SYMBOL_GPL(platform_device_register_simple); | 346 | EXPORT_SYMBOL_GPL(platform_device_register_simple); |
346 | EXPORT_SYMBOL_GPL(platform_device_unregister); | 347 | EXPORT_SYMBOL_GPL(platform_device_unregister); |
diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c index 4b12be822bd4..376f8a034f65 100644 --- a/drivers/usb/host/hc_crisv10.c +++ b/drivers/usb/host/hc_crisv10.c | |||
@@ -4396,6 +4396,7 @@ static int __init etrax_usb_hc_init(void) | |||
4396 | device_initialize(&fake_device); | 4396 | device_initialize(&fake_device); |
4397 | kobject_set_name(&fake_device.kobj, "etrax_usb"); | 4397 | kobject_set_name(&fake_device.kobj, "etrax_usb"); |
4398 | kobject_add(&fake_device.kobj); | 4398 | kobject_add(&fake_device.kobj); |
4399 | kobject_hotplug(&fake_device.kobj, KOBJ_ADD); | ||
4399 | hc->bus->controller = &fake_device; | 4400 | hc->bus->controller = &fake_device; |
4400 | usb_register_bus(hc->bus); | 4401 | usb_register_bus(hc->bus); |
4401 | 4402 | ||
diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 31cff785b3bd..2cab98a9a621 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c | |||
@@ -337,6 +337,7 @@ void register_disk(struct gendisk *disk) | |||
337 | if ((err = kobject_add(&disk->kobj))) | 337 | if ((err = kobject_add(&disk->kobj))) |
338 | return; | 338 | return; |
339 | disk_sysfs_symlinks(disk); | 339 | disk_sysfs_symlinks(disk); |
340 | kobject_hotplug(&disk->kobj, KOBJ_ADD); | ||
340 | 341 | ||
341 | /* No minors to use for partitions */ | 342 | /* No minors to use for partitions */ |
342 | if (disk->minors == 1) { | 343 | if (disk->minors == 1) { |
@@ -441,5 +442,6 @@ void del_gendisk(struct gendisk *disk) | |||
441 | sysfs_remove_link(&disk->driverfs_dev->kobj, "block"); | 442 | sysfs_remove_link(&disk->driverfs_dev->kobj, "block"); |
442 | put_device(disk->driverfs_dev); | 443 | put_device(disk->driverfs_dev); |
443 | } | 444 | } |
445 | kobject_hotplug(&disk->kobj, KOBJ_REMOVE); | ||
444 | kobject_del(&disk->kobj); | 446 | kobject_del(&disk->kobj); |
445 | } | 447 | } |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 352f966a1174..da25aeb0e062 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -428,6 +428,41 @@ int sysfs_update_file(struct kobject * kobj, const struct attribute * attr) | |||
428 | 428 | ||
429 | 429 | ||
430 | /** | 430 | /** |
431 | * sysfs_chmod_file - update the modified mode value on an object attribute. | ||
432 | * @kobj: object we're acting for. | ||
433 | * @attr: attribute descriptor. | ||
434 | * @mode: file permissions. | ||
435 | * | ||
436 | */ | ||
437 | int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) | ||
438 | { | ||
439 | struct dentry *dir = kobj->dentry; | ||
440 | struct dentry *victim; | ||
441 | struct sysfs_dirent *sd; | ||
442 | umode_t umode = (mode & S_IALLUGO) | S_IFREG; | ||
443 | int res = -ENOENT; | ||
444 | |||
445 | down(&dir->d_inode->i_sem); | ||
446 | victim = sysfs_get_dentry(dir, attr->name); | ||
447 | if (!IS_ERR(victim)) { | ||
448 | if (victim->d_inode && | ||
449 | (victim->d_parent->d_inode == dir->d_inode)) { | ||
450 | sd = victim->d_fsdata; | ||
451 | attr->mode = mode; | ||
452 | sd->s_mode = umode; | ||
453 | victim->d_inode->i_mode = umode; | ||
454 | dput(victim); | ||
455 | res = 0; | ||
456 | } | ||
457 | } | ||
458 | up(&dir->d_inode->i_sem); | ||
459 | |||
460 | return res; | ||
461 | } | ||
462 | EXPORT_SYMBOL_GPL(sysfs_chmod_file); | ||
463 | |||
464 | |||
465 | /** | ||
431 | * sysfs_remove_file - remove an object attribute. | 466 | * sysfs_remove_file - remove an object attribute. |
432 | * @kobj: object we're acting for. | 467 | * @kobj: object we're acting for. |
433 | * @attr: attribute descriptor. | 468 | * @attr: attribute descriptor. |
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index f7a7b86f6eef..a5fa6a6eede8 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h | |||
@@ -17,6 +17,10 @@ | |||
17 | 17 | ||
18 | #include <linux/fs.h> | 18 | #include <linux/fs.h> |
19 | 19 | ||
20 | #include <linux/types.h> | ||
21 | |||
22 | struct file_operations; | ||
23 | |||
20 | #if defined(CONFIG_DEBUG_FS) | 24 | #if defined(CONFIG_DEBUG_FS) |
21 | struct dentry *debugfs_create_file(const char *name, mode_t mode, | 25 | struct dentry *debugfs_create_file(const char *name, mode_t mode, |
22 | struct dentry *parent, void *data, | 26 | struct dentry *parent, void *data, |
@@ -36,6 +40,9 @@ struct dentry *debugfs_create_bool(const char *name, mode_t mode, | |||
36 | struct dentry *parent, u32 *value); | 40 | struct dentry *parent, u32 *value); |
37 | 41 | ||
38 | #else | 42 | #else |
43 | |||
44 | #include <linux/err.h> | ||
45 | |||
39 | /* | 46 | /* |
40 | * We do not return NULL from these functions if CONFIG_DEBUG_FS is not enabled | 47 | * We do not return NULL from these functions if CONFIG_DEBUG_FS is not enabled |
41 | * so users have a chance to detect if there was a real error or not. We don't | 48 | * so users have a chance to detect if there was a real error or not. We don't |
@@ -68,21 +75,21 @@ static inline struct dentry *debugfs_create_u8(const char *name, mode_t mode, | |||
68 | 75 | ||
69 | static inline struct dentry *debugfs_create_u16(const char *name, mode_t mode, | 76 | static inline struct dentry *debugfs_create_u16(const char *name, mode_t mode, |
70 | struct dentry *parent, | 77 | struct dentry *parent, |
71 | u8 *value) | 78 | u16 *value) |
72 | { | 79 | { |
73 | return ERR_PTR(-ENODEV); | 80 | return ERR_PTR(-ENODEV); |
74 | } | 81 | } |
75 | 82 | ||
76 | static inline struct dentry *debugfs_create_u32(const char *name, mode_t mode, | 83 | static inline struct dentry *debugfs_create_u32(const char *name, mode_t mode, |
77 | struct dentry *parent, | 84 | struct dentry *parent, |
78 | u8 *value) | 85 | u32 *value) |
79 | { | 86 | { |
80 | return ERR_PTR(-ENODEV); | 87 | return ERR_PTR(-ENODEV); |
81 | } | 88 | } |
82 | 89 | ||
83 | static inline struct dentry *debugfs_create_bool(const char *name, mode_t mode, | 90 | static inline struct dentry *debugfs_create_bool(const char *name, mode_t mode, |
84 | struct dentry *parent, | 91 | struct dentry *parent, |
85 | u8 *value) | 92 | u32 *value) |
86 | { | 93 | { |
87 | return ERR_PTR(-ENODEV); | 94 | return ERR_PTR(-ENODEV); |
88 | } | 95 | } |
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 6f502ff7902a..38b58b30814a 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h | |||
@@ -99,6 +99,9 @@ sysfs_create_file(struct kobject *, const struct attribute *); | |||
99 | extern int | 99 | extern int |
100 | sysfs_update_file(struct kobject *, const struct attribute *); | 100 | sysfs_update_file(struct kobject *, const struct attribute *); |
101 | 101 | ||
102 | extern int | ||
103 | sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode); | ||
104 | |||
102 | extern void | 105 | extern void |
103 | sysfs_remove_file(struct kobject *, const struct attribute *); | 106 | sysfs_remove_file(struct kobject *, const struct attribute *); |
104 | 107 | ||
@@ -140,6 +143,10 @@ static inline int sysfs_update_file(struct kobject * k, const struct attribute * | |||
140 | { | 143 | { |
141 | return 0; | 144 | return 0; |
142 | } | 145 | } |
146 | static inline int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) | ||
147 | { | ||
148 | return 0; | ||
149 | } | ||
143 | 150 | ||
144 | static inline void sysfs_remove_file(struct kobject * k, const struct attribute * a) | 151 | static inline void sysfs_remove_file(struct kobject * k, const struct attribute * a) |
145 | { | 152 | { |
diff --git a/lib/kobject.c b/lib/kobject.c index ff9491986b38..5df8441c44e7 100644 --- a/lib/kobject.c +++ b/lib/kobject.c | |||
@@ -184,8 +184,6 @@ int kobject_add(struct kobject * kobj) | |||
184 | unlink(kobj); | 184 | unlink(kobj); |
185 | if (parent) | 185 | if (parent) |
186 | kobject_put(parent); | 186 | kobject_put(parent); |
187 | } else { | ||
188 | kobject_hotplug(kobj, KOBJ_ADD); | ||
189 | } | 187 | } |
190 | 188 | ||
191 | return error; | 189 | return error; |
@@ -207,7 +205,8 @@ int kobject_register(struct kobject * kobj) | |||
207 | printk("kobject_register failed for %s (%d)\n", | 205 | printk("kobject_register failed for %s (%d)\n", |
208 | kobject_name(kobj),error); | 206 | kobject_name(kobj),error); |
209 | dump_stack(); | 207 | dump_stack(); |
210 | } | 208 | } else |
209 | kobject_hotplug(kobj, KOBJ_ADD); | ||
211 | } else | 210 | } else |
212 | error = -EINVAL; | 211 | error = -EINVAL; |
213 | return error; | 212 | return error; |
@@ -301,7 +300,6 @@ int kobject_rename(struct kobject * kobj, char *new_name) | |||
301 | 300 | ||
302 | void kobject_del(struct kobject * kobj) | 301 | void kobject_del(struct kobject * kobj) |
303 | { | 302 | { |
304 | kobject_hotplug(kobj, KOBJ_REMOVE); | ||
305 | sysfs_remove_dir(kobj); | 303 | sysfs_remove_dir(kobj); |
306 | unlink(kobj); | 304 | unlink(kobj); |
307 | } | 305 | } |
@@ -314,6 +312,7 @@ void kobject_del(struct kobject * kobj) | |||
314 | void kobject_unregister(struct kobject * kobj) | 312 | void kobject_unregister(struct kobject * kobj) |
315 | { | 313 | { |
316 | pr_debug("kobject %s: unregistering\n",kobject_name(kobj)); | 314 | pr_debug("kobject %s: unregistering\n",kobject_name(kobj)); |
315 | kobject_hotplug(kobj, KOBJ_REMOVE); | ||
317 | kobject_del(kobj); | 316 | kobject_del(kobj); |
318 | kobject_put(kobj); | 317 | kobject_put(kobj); |
319 | } | 318 | } |
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index 567249bf9331..f6a19d53eaeb 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c | |||
@@ -248,6 +248,7 @@ int br_sysfs_addif(struct net_bridge_port *p) | |||
248 | if (err) | 248 | if (err) |
249 | goto out2; | 249 | goto out2; |
250 | 250 | ||
251 | kobject_hotplug(&p->kobj, KOBJ_ADD); | ||
251 | return 0; | 252 | return 0; |
252 | out2: | 253 | out2: |
253 | kobject_del(&p->kobj); | 254 | kobject_del(&p->kobj); |
@@ -259,6 +260,7 @@ void br_sysfs_removeif(struct net_bridge_port *p) | |||
259 | { | 260 | { |
260 | pr_debug("br_sysfs_removeif\n"); | 261 | pr_debug("br_sysfs_removeif\n"); |
261 | sysfs_remove_link(&p->br->ifobj, p->dev->name); | 262 | sysfs_remove_link(&p->br->ifobj, p->dev->name); |
263 | kobject_hotplug(&p->kobj, KOBJ_REMOVE); | ||
262 | kobject_del(&p->kobj); | 264 | kobject_del(&p->kobj); |
263 | } | 265 | } |
264 | 266 | ||
diff --git a/scripts/ver_linux b/scripts/ver_linux index bb195a1c0f2d..a28c279c49dd 100755 --- a/scripts/ver_linux +++ b/scripts/ver_linux | |||
@@ -87,7 +87,7 @@ loadkeys -V 2>&1 | awk \ | |||
87 | 87 | ||
88 | expr --v 2>&1 | awk 'NR==1{print "Sh-utils ", $NF}' | 88 | expr --v 2>&1 | awk 'NR==1{print "Sh-utils ", $NF}' |
89 | 89 | ||
90 | udevinfo -V | awk '{print "udev ", $3}' | 90 | udevinfo -V 2>&1 | grep version | awk '{print "udev ", $3}' |
91 | 91 | ||
92 | if [ -e /proc/modules ]; then | 92 | if [ -e /proc/modules ]; then |
93 | X=`cat /proc/modules | sed -e "s/ .*$//"` | 93 | X=`cat /proc/modules | sed -e "s/ .*$//"` |