add comments about lock order
authorKay Sievers <kay@vrfy.org>
Mon, 24 Mar 2014 04:39:34 +0000 (05:39 +0100)
committerKay Sievers <kay@vrfy.org>
Mon, 24 Mar 2014 04:39:34 +0000 (05:39 +0100)
bus.c
connection.c
domain.c
endpoint.c
names.c

diff --git a/bus.c b/bus.c
index 90f764443c46353d33685f2e0d73d9b2abc31267..e82b45f54d6d2ac9dc82daae1ef4e6c82ae95ba4 100644 (file)
--- a/bus.c
+++ b/bus.c
@@ -159,6 +159,7 @@ void kdbus_bus_disconnect(struct kdbus_bus *bus)
                        break;
                }
 
+               /* take reference, release lock, disconnect without lock */
                kdbus_ep_ref(ep);
                mutex_unlock(&bus->lock);
 
@@ -183,8 +184,8 @@ static struct kdbus_bus *kdbus_bus_find(struct kdbus_domain *domain, const char
                bus = kdbus_bus_ref(b);
                break;
        }
-
        mutex_unlock(&domain->lock);
+
        return bus;
 }
 
index 224b0c05ece1395c45bee2f692e78251320d0597..f97847c6770f215f5d77e68f5ec254143753bf77 100644 (file)
@@ -1107,6 +1107,7 @@ int kdbus_cmd_msg_cancel(struct kdbus_conn *conn,
        if (atomic_read(&conn->reply_count) == 0)
                return -ENOENT;
 
+       /* lock order: domain -> bus -> ep -> names -> conn */
        mutex_lock(&conn->bus->lock);
        hash_for_each(conn->bus->conn_hash, i, c, hentry) {
                if (c == conn)
@@ -1500,12 +1501,15 @@ int kdbus_conn_disconnect(struct kdbus_conn *conn, bool ensure_queue_empty)
 
        cancel_delayed_work_sync(&conn->work);
 
-       /* remove from bus and endpoint */
+       /* lock order: domain -> bus -> ep -> names -> conn */
        mutex_lock(&conn->bus->lock);
        mutex_lock(&conn->ep->lock);
+
+       /* remove from bus and endpoint */
        hash_del(&conn->hentry);
        list_del(&conn->monitor_entry);
        list_del(&conn->ep_entry);
+
        mutex_unlock(&conn->ep->lock);
        mutex_unlock(&conn->bus->lock);
 
@@ -2126,17 +2130,21 @@ int kdbus_conn_new(struct kdbus_ep *ep,
                goto exit_unref_user;
        }
 
-       /* link into bus and endpoint */
+       /* lock order: domain -> bus -> ep -> names -> conn */
        mutex_lock(&bus->lock);
        mutex_lock(&ep->lock);
+
        if (bus->disconnected || ep->disconnected) {
                mutex_unlock(&ep->lock);
                mutex_unlock(&bus->lock);
                ret = -ESHUTDOWN;
                goto exit_unref_user;
        }
+
+       /* link into bus and endpoint */
        list_add_tail(&conn->ep_entry, &ep->conn_list);
        hash_add(bus->conn_hash, &conn->hentry, conn->id);
+
        mutex_unlock(&ep->lock);
        mutex_unlock(&bus->lock);
 
index 90feb75a177455795d508875fdb79b98855f962d..317284a132fd4e41a16a44d6dc226a59539496b9 100644 (file)
--- a/domain.c
+++ b/domain.c
@@ -125,6 +125,7 @@ void kdbus_domain_disconnect(struct kdbus_domain *domain)
                        break;
                }
 
+               /* take reference, release lock, disconnect without lock */
                kdbus_domain_ref(dom);
                mutex_unlock(&domain->lock);
 
@@ -145,6 +146,7 @@ void kdbus_domain_disconnect(struct kdbus_domain *domain)
                        break;
                }
 
+               /* take reference, release lock, disconnect without lock */
                kdbus_bus_ref(bus);
                mutex_unlock(&domain->lock);
 
@@ -260,6 +262,7 @@ int kdbus_domain_new(struct kdbus_domain *parent, const char *name,
        atomic64_set(&d->msg_seq_last, 0);
        idr_init(&d->user_idr);
 
+       /* lock order: parent domain -> domain -> subsys_lock */
        if (parent) {
                mutex_lock(&parent->lock);
                if (parent->disconnected) {
@@ -483,6 +486,7 @@ static void __kdbus_domain_user_free(struct kref *kref)
        idr_remove(&user->domain->user_idr, user->idr);
        hash_del(&user->hentry);
        mutex_unlock(&user->domain->lock);
+
        kdbus_domain_unref(user->domain);
        kfree(user);
 }
index 5afabf9d857cddb2e5ee4019777cb7c910e43697..7e807db384f408419d109d43e1225fdd9a25f29e 100644 (file)
@@ -86,6 +86,7 @@ void kdbus_ep_disconnect(struct kdbus_ep *ep)
                        break;
                }
 
+               /* take reference, release lock, disconnect without lock */
                kdbus_conn_ref(conn);
                mutex_unlock(&ep->lock);
 
diff --git a/names.c b/names.c
index bfb9aece7079d1b2d715e1626526f8e273e90287..2216db4db38033acda8355415bb28fb94f0963d1 100644 (file)
--- a/names.c
+++ b/names.c
@@ -290,6 +290,7 @@ void kdbus_name_remove_by_conn(struct kdbus_name_registry *reg,
        list_splice_init(&conn->names_queue_list, &names_queue_list);
        mutex_unlock(&conn->lock);
 
+       /* lock order: domain -> bus -> ep -> names -> conn */
        mutex_lock(&conn->bus->lock);
        mutex_lock(&reg->lock);
        if (conn->flags & KDBUS_HELLO_ACTIVATOR) {
@@ -423,6 +424,7 @@ int kdbus_name_acquire(struct kdbus_name_registry *reg,
        u32 hash;
        int ret = 0;
 
+       /* lock order: domain -> bus -> ep -> names -> conn */
        mutex_lock(&conn->bus->lock);
        mutex_lock(&reg->lock);
 
@@ -653,16 +655,18 @@ int kdbus_cmd_name_release(struct kdbus_name_registry *reg,
        struct kdbus_bus *bus = conn->bus;
        struct kdbus_name_entry *e;
        LIST_HEAD(notify_list);
-       int ret = 0;
        u32 hash;
+       int ret = 0;
 
        if (!kdbus_name_is_valid(cmd->name, false))
                return -EINVAL;
 
        hash = kdbus_str_hash(cmd->name);
 
+       /* lock order: domain -> bus -> ep -> names -> connection */
        mutex_lock(&bus->lock);
        mutex_lock(&reg->lock);
+
        e = __kdbus_name_lookup(reg, hash, cmd->name);
        if (!e) {
                ret = -ESRCH;
@@ -851,6 +855,7 @@ int kdbus_cmd_name_list(struct kdbus_name_registry *reg,
 
        policy_db = conn->ep->policy_db;
 
+       /* lock order: domain -> bus -> ep -> names -> conn */
        mutex_lock(&conn->bus->lock);
        mutex_lock(&reg->lock);