diff options
author | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-21 03:02:03 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-21 03:02:03 -0500 |
commit | 28cb5ccd306e6cffd4498ba350bc7c82f5fbee44 (patch) | |
tree | dc64b074f3fcd51430f5161d6074fc3a6e85dc09 | |
parent | de9b2fccb6a1efdf1665ebbcb28cad61467b308a (diff) | |
parent | 1f21782e63da81f56401a813a52091ef2703838f (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6:
Driver core: proper prototype for drivers/base/init.c:driver_init()
kobject: kobject_uevent() returns manageable value
kref refcnt and false positives
-rw-r--r-- | drivers/acpi/ibm_acpi.c | 4 | ||||
-rw-r--r-- | include/linux/device.h | 2 | ||||
-rw-r--r-- | include/linux/kobject.h | 11 | ||||
-rw-r--r-- | init/main.c | 2 | ||||
-rw-r--r-- | lib/kobject_uevent.c | 44 | ||||
-rw-r--r-- | lib/kref.c | 7 |
6 files changed, 42 insertions, 28 deletions
diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 003a9876c968..5a8445959f67 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c | |||
@@ -352,7 +352,7 @@ static char *next_cmd(char **cmds) | |||
352 | return start; | 352 | return start; |
353 | } | 353 | } |
354 | 354 | ||
355 | static int driver_init(void) | 355 | static int ibm_acpi_driver_init(void) |
356 | { | 356 | { |
357 | printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION); | 357 | printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION); |
358 | printk(IBM_INFO "%s\n", IBM_URL); | 358 | printk(IBM_INFO "%s\n", IBM_URL); |
@@ -1605,7 +1605,7 @@ static int fan_write(char *buf) | |||
1605 | static struct ibm_struct ibms[] = { | 1605 | static struct ibm_struct ibms[] = { |
1606 | { | 1606 | { |
1607 | .name = "driver", | 1607 | .name = "driver", |
1608 | .init = driver_init, | 1608 | .init = ibm_acpi_driver_init, |
1609 | .read = driver_read, | 1609 | .read = driver_read, |
1610 | }, | 1610 | }, |
1611 | { | 1611 | { |
diff --git a/include/linux/device.h b/include/linux/device.h index 49ab53ce92dc..f44247fe8135 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -433,6 +433,8 @@ static inline int device_is_registered(struct device *dev) | |||
433 | return dev->is_registered; | 433 | return dev->is_registered; |
434 | } | 434 | } |
435 | 435 | ||
436 | void driver_init(void); | ||
437 | |||
436 | /* | 438 | /* |
437 | * High level routines for use by the bus drivers | 439 | * High level routines for use by the bus drivers |
438 | */ | 440 | */ |
diff --git a/include/linux/kobject.h b/include/linux/kobject.h index d1c8d28fa92e..76538fcf2c4e 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h | |||
@@ -265,8 +265,8 @@ extern int __must_check subsys_create_file(struct subsystem * , | |||
265 | struct subsys_attribute *); | 265 | struct subsys_attribute *); |
266 | 266 | ||
267 | #if defined(CONFIG_HOTPLUG) | 267 | #if defined(CONFIG_HOTPLUG) |
268 | void kobject_uevent(struct kobject *kobj, enum kobject_action action); | 268 | int kobject_uevent(struct kobject *kobj, enum kobject_action action); |
269 | void kobject_uevent_env(struct kobject *kobj, enum kobject_action action, | 269 | int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, |
270 | char *envp[]); | 270 | char *envp[]); |
271 | 271 | ||
272 | int add_uevent_var(char **envp, int num_envp, int *cur_index, | 272 | int add_uevent_var(char **envp, int num_envp, int *cur_index, |
@@ -274,11 +274,12 @@ int add_uevent_var(char **envp, int num_envp, int *cur_index, | |||
274 | const char *format, ...) | 274 | const char *format, ...) |
275 | __attribute__((format (printf, 7, 8))); | 275 | __attribute__((format (printf, 7, 8))); |
276 | #else | 276 | #else |
277 | static inline void kobject_uevent(struct kobject *kobj, enum kobject_action action) { } | 277 | static inline int kobject_uevent(struct kobject *kobj, enum kobject_action action) |
278 | static inline void kobject_uevent_env(struct kobject *kobj, | 278 | { return 0; } |
279 | static inline int kobject_uevent_env(struct kobject *kobj, | ||
279 | enum kobject_action action, | 280 | enum kobject_action action, |
280 | char *envp[]) | 281 | char *envp[]) |
281 | { } | 282 | { return 0; } |
282 | 283 | ||
283 | static inline int add_uevent_var(char **envp, int num_envp, int *cur_index, | 284 | static inline int add_uevent_var(char **envp, int num_envp, int *cur_index, |
284 | char *buffer, int buffer_size, int *cur_len, | 285 | char *buffer, int buffer_size, int *cur_len, |
diff --git a/init/main.c b/init/main.c index e3f0bb20b4dd..2b1cdaab45e6 100644 --- a/init/main.c +++ b/init/main.c | |||
@@ -53,6 +53,7 @@ | |||
53 | #include <linux/utsrelease.h> | 53 | #include <linux/utsrelease.h> |
54 | #include <linux/pid_namespace.h> | 54 | #include <linux/pid_namespace.h> |
55 | #include <linux/compile.h> | 55 | #include <linux/compile.h> |
56 | #include <linux/device.h> | ||
56 | 57 | ||
57 | #include <asm/io.h> | 58 | #include <asm/io.h> |
58 | #include <asm/bugs.h> | 59 | #include <asm/bugs.h> |
@@ -94,7 +95,6 @@ extern void pidmap_init(void); | |||
94 | extern void prio_tree_init(void); | 95 | extern void prio_tree_init(void); |
95 | extern void radix_tree_init(void); | 96 | extern void radix_tree_init(void); |
96 | extern void free_initmem(void); | 97 | extern void free_initmem(void); |
97 | extern void driver_init(void); | ||
98 | extern void prepare_namespace(void); | 98 | extern void prepare_namespace(void); |
99 | #ifdef CONFIG_ACPI | 99 | #ifdef CONFIG_ACPI |
100 | extern void acpi_early_init(void); | 100 | extern void acpi_early_init(void); |
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c index a1922765ff31..84272ed77f03 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c | |||
@@ -63,8 +63,11 @@ static char *action_to_string(enum kobject_action action) | |||
63 | * @action: action that is happening (usually KOBJ_MOVE) | 63 | * @action: action that is happening (usually KOBJ_MOVE) |
64 | * @kobj: struct kobject that the action is happening to | 64 | * @kobj: struct kobject that the action is happening to |
65 | * @envp_ext: pointer to environmental data | 65 | * @envp_ext: pointer to environmental data |
66 | * | ||
67 | * Returns 0 if kobject_uevent() is completed with success or the | ||
68 | * corresponding error when it fails. | ||
66 | */ | 69 | */ |
67 | void kobject_uevent_env(struct kobject *kobj, enum kobject_action action, | 70 | int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, |
68 | char *envp_ext[]) | 71 | char *envp_ext[]) |
69 | { | 72 | { |
70 | char **envp; | 73 | char **envp; |
@@ -79,14 +82,16 @@ void kobject_uevent_env(struct kobject *kobj, enum kobject_action action, | |||
79 | u64 seq; | 82 | u64 seq; |
80 | char *seq_buff; | 83 | char *seq_buff; |
81 | int i = 0; | 84 | int i = 0; |
82 | int retval; | 85 | int retval = 0; |
83 | int j; | 86 | int j; |
84 | 87 | ||
85 | pr_debug("%s\n", __FUNCTION__); | 88 | pr_debug("%s\n", __FUNCTION__); |
86 | 89 | ||
87 | action_string = action_to_string(action); | 90 | action_string = action_to_string(action); |
88 | if (!action_string) | 91 | if (!action_string) { |
89 | return; | 92 | pr_debug("kobject attempted to send uevent without action_string!\n"); |
93 | return -EINVAL; | ||
94 | } | ||
90 | 95 | ||
91 | /* search the kset we belong to */ | 96 | /* search the kset we belong to */ |
92 | top_kobj = kobj; | 97 | top_kobj = kobj; |
@@ -95,31 +100,39 @@ void kobject_uevent_env(struct kobject *kobj, enum kobject_action action, | |||
95 | top_kobj = top_kobj->parent; | 100 | top_kobj = top_kobj->parent; |
96 | } while (!top_kobj->kset && top_kobj->parent); | 101 | } while (!top_kobj->kset && top_kobj->parent); |
97 | } | 102 | } |
98 | if (!top_kobj->kset) | 103 | if (!top_kobj->kset) { |
99 | return; | 104 | pr_debug("kobject attempted to send uevent without kset!\n"); |
105 | return -EINVAL; | ||
106 | } | ||
100 | 107 | ||
101 | kset = top_kobj->kset; | 108 | kset = top_kobj->kset; |
102 | uevent_ops = kset->uevent_ops; | 109 | uevent_ops = kset->uevent_ops; |
103 | 110 | ||
104 | /* skip the event, if the filter returns zero. */ | 111 | /* skip the event, if the filter returns zero. */ |
105 | if (uevent_ops && uevent_ops->filter) | 112 | if (uevent_ops && uevent_ops->filter) |
106 | if (!uevent_ops->filter(kset, kobj)) | 113 | if (!uevent_ops->filter(kset, kobj)) { |
107 | return; | 114 | pr_debug("kobject filter function caused the event to drop!\n"); |
115 | return 0; | ||
116 | } | ||
108 | 117 | ||
109 | /* environment index */ | 118 | /* environment index */ |
110 | envp = kzalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL); | 119 | envp = kzalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL); |
111 | if (!envp) | 120 | if (!envp) |
112 | return; | 121 | return -ENOMEM; |
113 | 122 | ||
114 | /* environment values */ | 123 | /* environment values */ |
115 | buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL); | 124 | buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL); |
116 | if (!buffer) | 125 | if (!buffer) { |
126 | retval = -ENOMEM; | ||
117 | goto exit; | 127 | goto exit; |
128 | } | ||
118 | 129 | ||
119 | /* complete object path */ | 130 | /* complete object path */ |
120 | devpath = kobject_get_path(kobj, GFP_KERNEL); | 131 | devpath = kobject_get_path(kobj, GFP_KERNEL); |
121 | if (!devpath) | 132 | if (!devpath) { |
133 | retval = -ENOENT; | ||
122 | goto exit; | 134 | goto exit; |
135 | } | ||
123 | 136 | ||
124 | /* originating subsystem */ | 137 | /* originating subsystem */ |
125 | if (uevent_ops && uevent_ops->name) | 138 | if (uevent_ops && uevent_ops->name) |
@@ -204,7 +217,7 @@ exit: | |||
204 | kfree(devpath); | 217 | kfree(devpath); |
205 | kfree(buffer); | 218 | kfree(buffer); |
206 | kfree(envp); | 219 | kfree(envp); |
207 | return; | 220 | return retval; |
208 | } | 221 | } |
209 | 222 | ||
210 | EXPORT_SYMBOL_GPL(kobject_uevent_env); | 223 | EXPORT_SYMBOL_GPL(kobject_uevent_env); |
@@ -214,10 +227,13 @@ EXPORT_SYMBOL_GPL(kobject_uevent_env); | |||
214 | * | 227 | * |
215 | * @action: action that is happening (usually KOBJ_ADD and KOBJ_REMOVE) | 228 | * @action: action that is happening (usually KOBJ_ADD and KOBJ_REMOVE) |
216 | * @kobj: struct kobject that the action is happening to | 229 | * @kobj: struct kobject that the action is happening to |
230 | * | ||
231 | * Returns 0 if kobject_uevent() is completed with success or the | ||
232 | * corresponding error when it fails. | ||
217 | */ | 233 | */ |
218 | void kobject_uevent(struct kobject *kobj, enum kobject_action action) | 234 | int kobject_uevent(struct kobject *kobj, enum kobject_action action) |
219 | { | 235 | { |
220 | kobject_uevent_env(kobj, action, NULL); | 236 | return kobject_uevent_env(kobj, action, NULL); |
221 | } | 237 | } |
222 | 238 | ||
223 | EXPORT_SYMBOL_GPL(kobject_uevent); | 239 | EXPORT_SYMBOL_GPL(kobject_uevent); |
diff --git a/lib/kref.c b/lib/kref.c index 4a467faf1367..0d07cc31c818 100644 --- a/lib/kref.c +++ b/lib/kref.c | |||
@@ -52,12 +52,7 @@ int kref_put(struct kref *kref, void (*release)(struct kref *kref)) | |||
52 | WARN_ON(release == NULL); | 52 | WARN_ON(release == NULL); |
53 | WARN_ON(release == (void (*)(struct kref *))kfree); | 53 | WARN_ON(release == (void (*)(struct kref *))kfree); |
54 | 54 | ||
55 | /* | 55 | if (atomic_dec_and_test(&kref->refcount)) { |
56 | * if current count is one, we are the last user and can release object | ||
57 | * right now, avoiding an atomic operation on 'refcount' | ||
58 | */ | ||
59 | if ((atomic_read(&kref->refcount) == 1) || | ||
60 | (atomic_dec_and_test(&kref->refcount))) { | ||
61 | release(kref); | 56 | release(kref); |
62 | return 1; | 57 | return 1; |
63 | } | 58 | } |