···1+2+krefs allow you to add reference counters to your objects. If you3+have objects that are used in multiple places and passed around, and4+you don't have refcounts, your code is almost certainly broken. If5+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_data10+{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, call21+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 following33+rules:34+35+1) If you make a non-temporary copy of a pointer, especially if36+ it can be passed to another thread of execution, you must37+ 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 (the40+ 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 release45+ routine will be called. If the code never tries to get46+ a valid pointer to a kref-ed structure without already47+ holding a valid pointer, it is safe to do this without48+ a lock.49+50+3) If the code attempts to gain a reference to a kref-ed structure51+ without already holding a valid pointer, it must serialize access52+ where a kref_put() cannot occur during the kref_get(), and the53+ structure must remain valid during the kref_get().54+55+For example, if you allocate some data and then pass it to another56+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 here69+ .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 here93+ .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 the100+data, the kref_put() handles knowing when the data is not referenced101+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. The103+put needs no lock because nothing tries to get the data without104+already holding a pointer.105+106+Note that the "before" in rule 1 is very important. You should never107+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+ } else114+ /* 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 may119+know what you are doing (there are some situations where locking is120+involved where the above may be legal) but someone else who doesn't121+know what they are doing may change the code or copy the code. It's122+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 for126+something else or passing it off to something else, there is no reason127+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 off138+ to the queue. DON'T TOUCH obj AFTER HERE! */139+140+The last rule (rule 3) is the nastiest one to handle. Say, for141+instance, you have a list of items that are each kref-ed, and you wish142+to get the first one. You can't just pull the first item off the list143+and kref_get() it. That violates rule 3 because you are not already144+holding a valid pointer. You must add locks or semaphores. For145+instance:146+147+static DECLARE_MUTEX(sem);148+static LIST_HEAD(q);149+struct my_data150+{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 the183+lock during the whole release operation. Say you didn't want to call184+kfree() with the lock held in the example above (since it is kind of185+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+ } else200+ up(&sem);201+}202+203+This is really more useful if you have to call other routines as part204+of the free operations that could take a long time or might claim the205+same lock. Note that doing everything in the release routine is still206+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 and212+presentation on krefs, which can be found at:213+ http://www.kroah.com/linux/talks/ols_2004_kref_paper/Reprint-Kroah-Hartman-OLS2004.pdf214+and:215+ http://www.kroah.com/linux/talks/ols_2004_kref_talk/216+
+2
drivers/base/class.c
···430 sysfs_create_link(&class_dev->kobj,431 &class_dev->dev->kobj, "device");4320433 register_done:434 if (error && parent)435 class_put(parent);···462 sysfs_remove_link(&class_dev->kobj, "device");463 class_device_remove_attrs(class_dev);4640465 kobject_del(&class_dev->kobj);466467 if (parent)
···430 sysfs_create_link(&class_dev->kobj,431 &class_dev->dev->kobj, "device");432433+ kobject_hotplug(&class_dev->kobj, KOBJ_ADD);434 register_done:435 if (error && parent)436 class_put(parent);···461 sysfs_remove_link(&class_dev->kobj, "device");462 class_device_remove_attrs(class_dev);463464+ kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE);465 kobject_del(&class_dev->kobj);466467 if (parent)
+3
drivers/base/core.c
···260 /* notify platform of device entry */261 if (platform_notify)262 platform_notify(dev);00263 Done:264 put_device(dev);265 return error;···351 platform_notify_remove(dev);352 bus_remove_device(dev);353 device_pm_remove(dev);0354 kobject_del(&dev->kobj);355 if (parent)356 put_device(parent);
···260 /* notify platform of device entry */261 if (platform_notify)262 platform_notify(dev);263+264+ kobject_hotplug(&dev->kobj, KOBJ_ADD);265 Done:266 put_device(dev);267 return error;···349 platform_notify_remove(dev);350 bus_remove_device(dev);351 device_pm_remove(dev);352+ kobject_hotplug(&dev->kobj, KOBJ_REMOVE);353 kobject_del(&dev->kobj);354 if (parent)355 put_device(parent);
···337 if ((err = kobject_add(&disk->kobj)))338 return;339 disk_sysfs_symlinks(disk);0340341 /* No minors to use for partitions */342 if (disk->minors == 1) {···442 sysfs_remove_link(&disk->driverfs_dev->kobj, "block");443 put_device(disk->driverfs_dev);444 }0445 kobject_del(&disk->kobj);446}
···337 if ((err = kobject_add(&disk->kobj)))338 return;339 disk_sysfs_symlinks(disk);340+ kobject_hotplug(&disk->kobj, KOBJ_ADD);341342 /* No minors to use for partitions */343 if (disk->minors == 1) {···441 sysfs_remove_link(&disk->driverfs_dev->kobj, "block");442 put_device(disk->driverfs_dev);443 }444+ kobject_hotplug(&disk->kobj, KOBJ_REMOVE);445 kobject_del(&disk->kobj);446}