aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kobject.c
diff options
context:
space:
mode:
authorKay Sievers <kay.sievers@vrfy.org>2007-12-18 19:40:42 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2008-01-24 23:40:39 -0500
commit0f4dafc0563c6c49e17fe14b3f5f356e4c4b8806 (patch)
treef4ded2831853cb6ea328d15d72871db6f8c22610 /lib/kobject.c
parent12e339ac6e31a34fe42396aec8fb1c0b43caf61e (diff)
Kobject: auto-cleanup on final unref
We save the current state in the object itself, so we can do proper cleanup when the last reference is dropped. If the initial reference is dropped, the object will be removed from sysfs if needed, if an "add" event was sent, "remove" will be send, and the allocated resources are released. This allows us to clean up some driver core usage as well as allowing us to do other such changes to the rest of the kernel. Signed-off-by: Kay Sievers <kay.sievers@vrfy.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'lib/kobject.c')
-rw-r--r--lib/kobject.c170
1 files changed, 96 insertions, 74 deletions
diff --git a/lib/kobject.c b/lib/kobject.c
index c321f1910cc2..4fce5ca42c2e 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -124,85 +124,74 @@ char *kobject_get_path(struct kobject *kobj, gfp_t gfp_mask)
124} 124}
125EXPORT_SYMBOL_GPL(kobject_get_path); 125EXPORT_SYMBOL_GPL(kobject_get_path);
126 126
127static void kobject_init_internal(struct kobject * kobj) 127/* add the kobject to its kset's list */
128static void kobj_kset_join(struct kobject *kobj)
128{ 129{
129 if (!kobj) 130 if (!kobj->kset)
130 return; 131 return;
131 kref_init(&kobj->kref); 132
132 INIT_LIST_HEAD(&kobj->entry); 133 kset_get(kobj->kset);
134 spin_lock(&kobj->kset->list_lock);
135 list_add_tail(&kobj->entry, &kobj->kset->list);
136 spin_unlock(&kobj->kset->list_lock);
133} 137}
134 138
139/* remove the kobject from its kset's list */
140static void kobj_kset_leave(struct kobject *kobj)
141{
142 if (!kobj->kset)
143 return;
135 144
136/** 145 spin_lock(&kobj->kset->list_lock);
137 * unlink - remove kobject from kset list. 146 list_del_init(&kobj->entry);
138 * @kobj: kobject. 147 spin_unlock(&kobj->kset->list_lock);
139 * 148 kset_put(kobj->kset);
140 * Remove the kobject from the kset list and decrement 149}
141 * its parent's refcount.
142 * This is separated out, so we can use it in both
143 * kobject_del() and kobject_add_internal() on error.
144 */
145 150
146static void unlink(struct kobject * kobj) 151static void kobject_init_internal(struct kobject * kobj)
147{ 152{
148 struct kobject *parent = kobj->parent; 153 if (!kobj)
149 154 return;
150 if (kobj->kset) { 155 kref_init(&kobj->kref);
151 spin_lock(&kobj->kset->list_lock); 156 INIT_LIST_HEAD(&kobj->entry);
152 list_del_init(&kobj->entry);
153 spin_unlock(&kobj->kset->list_lock);
154 }
155 kobj->parent = NULL;
156 kobject_put(kobj);
157 kobject_put(parent);
158} 157}
159 158
159
160static int kobject_add_internal(struct kobject *kobj) 160static int kobject_add_internal(struct kobject *kobj)
161{ 161{
162 int error = 0; 162 int error = 0;
163 struct kobject * parent; 163 struct kobject * parent;
164 164
165 if (!(kobj = kobject_get(kobj))) 165 if (!kobj)
166 return -ENOENT; 166 return -ENOENT;
167 if (!kobj->k_name) 167
168 kobject_set_name(kobj, "NO_NAME"); 168 if (!kobj->k_name || !kobj->k_name[0]) {
169 if (!*kobj->k_name) { 169 pr_debug("kobject: (%p): attempted to be registered with empty "
170 pr_debug("kobject (%p) attempted to be registered with no "
171 "name!\n", kobj); 170 "name!\n", kobj);
172 WARN_ON(1); 171 WARN_ON(1);
173 kobject_put(kobj);
174 return -EINVAL; 172 return -EINVAL;
175 } 173 }
176 parent = kobject_get(kobj->parent);
177 174
178 pr_debug("kobject: '%s' (%p): %s: parent: '%s', set: '%s'\n", 175 parent = kobject_get(kobj->parent);
179 kobject_name(kobj), kobj, __FUNCTION__,
180 parent ? kobject_name(parent) : "<NULL>",
181 kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>" );
182 176
177 /* join kset if set, use it as parent if we do not already have one */
183 if (kobj->kset) { 178 if (kobj->kset) {
184 kobj->kset = kset_get(kobj->kset); 179 if (!parent)
185
186 if (!parent) {
187 parent = kobject_get(&kobj->kset->kobj); 180 parent = kobject_get(&kobj->kset->kobj);
188 /* 181 kobj_kset_join(kobj);
189 * If the kset is our parent, get a second
190 * reference, we drop both the kset and the
191 * parent ref on cleanup
192 */
193 kobject_get(parent);
194 }
195
196 spin_lock(&kobj->kset->list_lock);
197 list_add_tail(&kobj->entry, &kobj->kset->list);
198 spin_unlock(&kobj->kset->list_lock);
199 kobj->parent = parent; 182 kobj->parent = parent;
200 } 183 }
201 184
185 pr_debug("kobject: '%s' (%p): %s: parent: '%s', set: '%s'\n",
186 kobject_name(kobj), kobj, __FUNCTION__,
187 parent ? kobject_name(parent) : "<NULL>",
188 kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>" );
189
202 error = create_dir(kobj); 190 error = create_dir(kobj);
203 if (error) { 191 if (error) {
204 /* unlink does the kobject_put() for us */ 192 kobj_kset_leave(kobj);
205 unlink(kobj); 193 kobject_put(parent);
194 kobj->parent = NULL;
206 195
207 /* be noisy on error issues */ 196 /* be noisy on error issues */
208 if (error == -EEXIST) 197 if (error == -EEXIST)
@@ -214,7 +203,8 @@ static int kobject_add_internal(struct kobject *kobj)
214 printk(KERN_ERR "%s failed for %s (%d)\n", 203 printk(KERN_ERR "%s failed for %s (%d)\n",
215 __FUNCTION__, kobject_name(kobj), error); 204 __FUNCTION__, kobject_name(kobj), error);
216 dump_stack(); 205 dump_stack();
217 } 206 } else
207 kobj->state_in_sysfs = 1;
218 208
219 return error; 209 return error;
220} 210}
@@ -238,11 +228,13 @@ static int kobject_set_name_vargs(struct kobject *kobj, const char *fmt,
238 if (!name) 228 if (!name)
239 return -ENOMEM; 229 return -ENOMEM;
240 230
231
241 /* Free the old name, if necessary. */ 232 /* Free the old name, if necessary. */
242 kfree(kobj->k_name); 233 kfree(kobj->k_name);
243 234
244 /* Now, set the new name */ 235 /* Now, set the new name */
245 kobj->k_name = name; 236 kobj->k_name = name;
237 kobj->state_name_set = 1;
246 238
247 return 0; 239 return 0;
248} 240}
@@ -293,20 +285,25 @@ void kobject_init(struct kobject *kobj, struct kobj_type *ktype)
293 err_str = "must have a ktype to be initialized properly!\n"; 285 err_str = "must have a ktype to be initialized properly!\n";
294 goto error; 286 goto error;
295 } 287 }
296 if (atomic_read(&kobj->kref.refcount)) { 288 if (kobj->state_initialized) {
297 /* do not error out as sometimes we can recover */ 289 /* do not error out as sometimes we can recover */
298 printk(KERN_ERR "kobject: reference count is already set, " 290 printk(KERN_ERR "kobject (%p): tried to init an initialized "
299 "something is seriously wrong.\n"); 291 "object, something is seriously wrong.\n", kobj);
300 dump_stack(); 292 dump_stack();
301 } 293 }
302 294
303 kref_init(&kobj->kref); 295 kref_init(&kobj->kref);
304 INIT_LIST_HEAD(&kobj->entry); 296 INIT_LIST_HEAD(&kobj->entry);
305 kobj->ktype = ktype; 297 kobj->ktype = ktype;
298 kobj->state_name_set = 0;
299 kobj->state_in_sysfs = 0;
300 kobj->state_add_uevent_sent = 0;
301 kobj->state_remove_uevent_sent = 0;
302 kobj->state_initialized = 1;
306 return; 303 return;
307 304
308error: 305error:
309 printk(KERN_ERR "kobject: %s\n", err_str); 306 printk(KERN_ERR "kobject (%p): %s\n", kobj, err_str);
310 dump_stack(); 307 dump_stack();
311} 308}
312EXPORT_SYMBOL(kobject_init); 309EXPORT_SYMBOL(kobject_init);
@@ -345,17 +342,10 @@ static int kobject_add_varg(struct kobject *kobj, struct kobject *parent,
345 * 342 *
346 * If this function returns an error, kobject_put() must be called to 343 * If this function returns an error, kobject_put() must be called to
347 * properly clean up the memory associated with the object. 344 * properly clean up the memory associated with the object.
348 *
349 * If the function is successful, the only way to properly clean up the
350 * memory is with a call to kobject_del(), in which case, a call to
351 * kobject_put() is not necessary (kobject_del() does the final
352 * kobject_put() to call the release function in the ktype's release
353 * pointer.)
354 *
355 * Under no instance should the kobject that is passed to this function 345 * Under no instance should the kobject that is passed to this function
356 * be directly freed with a call to kfree(), that can leak memory. 346 * be directly freed with a call to kfree(), that can leak memory.
357 * 347 *
358 * Note, no uevent will be created with this call, the caller should set 348 * Note, no "add" uevent will be created with this call, the caller should set
359 * up all of the necessary sysfs files for the object and then call 349 * up all of the necessary sysfs files for the object and then call
360 * kobject_uevent() with the UEVENT_ADD parameter to ensure that 350 * kobject_uevent() with the UEVENT_ADD parameter to ensure that
361 * userspace is properly notified of this kobject's creation. 351 * userspace is properly notified of this kobject's creation.
@@ -369,6 +359,13 @@ int kobject_add(struct kobject *kobj, struct kobject *parent,
369 if (!kobj) 359 if (!kobj)
370 return -EINVAL; 360 return -EINVAL;
371 361
362 if (!kobj->state_initialized) {
363 printk(KERN_ERR "kobject '%s' (%p): tried to add an "
364 "uninitialized object, something is seriously wrong.\n",
365 kobject_name(kobj), kobj);
366 dump_stack();
367 return -EINVAL;
368 }
372 va_start(args, fmt); 369 va_start(args, fmt);
373 retval = kobject_add_varg(kobj, parent, fmt, args); 370 retval = kobject_add_varg(kobj, parent, fmt, args);
374 va_end(args); 371 va_end(args);
@@ -527,8 +524,12 @@ void kobject_del(struct kobject * kobj)
527{ 524{
528 if (!kobj) 525 if (!kobj)
529 return; 526 return;
527
530 sysfs_remove_dir(kobj); 528 sysfs_remove_dir(kobj);
531 unlink(kobj); 529 kobj->state_in_sysfs = 0;
530 kobj_kset_leave(kobj);
531 kobject_put(kobj->parent);
532 kobj->parent = NULL;
532} 533}
533 534
534/** 535/**
@@ -565,21 +566,43 @@ struct kobject * kobject_get(struct kobject * kobj)
565 */ 566 */
566static void kobject_cleanup(struct kobject *kobj) 567static void kobject_cleanup(struct kobject *kobj)
567{ 568{
568 struct kobj_type * t = get_ktype(kobj); 569 struct kobj_type *t = get_ktype(kobj);
569 struct kset * s = kobj->kset;
570 const char *name = kobj->k_name; 570 const char *name = kobj->k_name;
571 int name_set = kobj->state_name_set;
571 572
572 pr_debug("kobject: '%s' (%p): %s\n", 573 pr_debug("kobject: '%s' (%p): %s\n",
573 kobject_name(kobj), kobj, __FUNCTION__); 574 kobject_name(kobj), kobj, __FUNCTION__);
575
576 if (t && !t->release)
577 pr_debug("kobject: '%s' (%p): does not have a release() "
578 "function, it is broken and must be fixed.\n",
579 kobject_name(kobj), kobj);
580
581 /* send "remove" if the caller did not do it but sent "add" */
582 if (kobj->state_add_uevent_sent && !kobj->state_remove_uevent_sent) {
583 pr_debug("kobject: '%s' (%p): auto cleanup 'remove' event\n",
584 kobject_name(kobj), kobj);
585 kobject_uevent(kobj, KOBJ_REMOVE);
586 }
587
588 /* remove from sysfs if the caller did not do it */
589 if (kobj->state_in_sysfs) {
590 pr_debug("kobject: '%s' (%p): auto cleanup kobject_del\n",
591 kobject_name(kobj), kobj);
592 kobject_del(kobj);
593 }
594
574 if (t && t->release) { 595 if (t && t->release) {
596 pr_debug("kobject: '%s' (%p): calling ktype release\n",
597 kobject_name(kobj), kobj);
575 t->release(kobj); 598 t->release(kobj);
576 /* If we have a release function, we can guess that this was 599 }
577 * not a statically allocated kobject, so we should be safe to 600
578 * free the name */ 601 /* free name if we allocated it */
602 if (name_set && name) {
603 pr_debug("kobject: '%s': free name\n", name);
579 kfree(name); 604 kfree(name);
580 } 605 }
581 if (s)
582 kset_put(s);
583} 606}
584 607
585static void kobject_release(struct kref *kref) 608static void kobject_release(struct kref *kref)
@@ -601,8 +624,7 @@ void kobject_put(struct kobject * kobj)
601 624
602static void dynamic_kobj_release(struct kobject *kobj) 625static void dynamic_kobj_release(struct kobject *kobj)
603{ 626{
604 pr_debug("kobject: '%s' (%p): %s\n", 627 pr_debug("kobject: (%p): %s\n", kobj, __FUNCTION__);
605 kobject_name(kobj), kobj, __FUNCTION__);
606 kfree(kobj); 628 kfree(kobj);
607} 629}
608 630