Thread (89 messages) flat view 89 messages, 18 authors, 2014-11-17

Re: How Not To Use kref (was Re: kdbus: add code for buses, domains and endpoints)

From: David Herrmann <hidden>
Date: 2014-11-04 09:11:14
Also in: lkml

Hi Al

On Fri, Oct 31, 2014 at 12:38 AM, Al Viro [off-list ref] wrote:
On Wed, Oct 29, 2014 at 03:00:52PM -0700, Greg Kroah-Hartman wrote:
quoted
+static void __kdbus_domain_user_free(struct kref *kref)
+{
+     struct kdbus_domain_user *user =
+             container_of(kref, struct kdbus_domain_user, kref);
+
+     BUG_ON(atomic_read(&user->buses) > 0);
+     BUG_ON(atomic_read(&user->connections) > 0);
+
+     mutex_lock(&user->domain->lock);
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
quoted
+     idr_remove(&user->domain->user_idr, user->idr);
+     hash_del(&user->hentry);
        ^^^^^^^^^^^^^^^^^^^^^^^^
quoted
+     mutex_unlock(&user->domain->lock);
+
+     kdbus_domain_unref(user->domain);
+     kfree(user);
+}
quoted
+struct kdbus_domain_user *kdbus_domain_user_unref(struct kdbus_domain_user *u)
+{
+     if (u)
+             kref_put(&u->kref, __kdbus_domain_user_free);
+     return NULL;
+}
If you remove an object from some search structures, taking the lock in
destructor is Too Fucking Late(tm).  Somebody might have already found
that puppy and decided to pick it (all under that lock) just as we'd
got to that point in destructor and blocked there.  Oops...
Nice catch! I fixed it up via kref_get_unless_zero(). This has the
side-effect that there might be multiple domain_user objects for the
same user, but all but one will have ref==0. They don't carry and
valuable data in those cases, so we're fine. We will just end up using
the next one, or creating a new one.

Thanks a lot!
David
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help