connection: introduce kdbus_conn_lock2()
authorDavid Herrmann <dh.herrmann@gmail.com>
Wed, 7 Jan 2015 16:44:37 +0000 (17:44 +0100)
committerDavid Herrmann <dh.herrmann@gmail.com>
Wed, 7 Jan 2015 16:45:26 +0000 (17:45 +0100)
Lets not hard-code locking behavior of connections somewhere deep down in
names.c. Use kdbus_conn_lock2() to lock 2 connections at the same time.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
connection.h
names.c

index 6c1fcdbf9090e3abe4cfcc68c8adf301036cb9bc..4d88ec0d92c95700afe14ed6da2ccc3b006c9346 100644 (file)
@@ -197,4 +197,46 @@ static inline int kdbus_conn_is_monitor(const struct kdbus_conn *conn)
        return conn->flags & KDBUS_HELLO_MONITOR;
 }
 
+/**
+ * kdbus_conn_lock2() - Lock two connections
+ * @a:         connection A to lock
+ * @b:         connection B to lock
+ *
+ * Lock two connections at once. As we need to have a stable locking order, we
+ * always lock the connection with lower memory address first.
+ */
+static inline void kdbus_conn_lock2(struct kdbus_conn *a, struct kdbus_conn *b)
+{
+       if (a < b) {
+               mutex_lock(&a->lock);
+               mutex_lock_nested(&b->lock, 1);
+       } else if (a == b) {
+               mutex_lock(&a->lock);
+       } else {
+               mutex_lock(&b->lock);
+               mutex_lock_nested(&a->lock, 1);
+       }
+}
+
+/**
+ * kdbus_conn_unlock2() - Unlock two connections
+ * @a:         connection A to unlock
+ * @b:         connection B to unlock
+ *
+ * Unlock two connections at once. See kdbus_conn_lock2().
+ */
+static inline void kdbus_conn_unlock2(struct kdbus_conn *a,
+                                     struct kdbus_conn *b)
+{
+       if (a < b) {
+               mutex_unlock(&b->lock);
+               mutex_unlock(&a->lock);
+       } else if (a == b) {
+               mutex_unlock(&a->lock);
+       } else {
+               mutex_unlock(&a->lock);
+               mutex_unlock(&b->lock);
+       }
+}
+
 #endif
diff --git a/names.c b/names.c
index 6f2b20f6dd159e1d436fbcafc2491f29bf51e95e..be519118b1a9c3eac2caf4b8edd7f44cd1d55aef 100644 (file)
--- a/names.c
+++ b/names.c
@@ -161,14 +161,7 @@ static int kdbus_name_replace_owner(struct kdbus_name_entry *e,
        if (WARN_ON(!conn_old))
                return -EINVAL;
 
-       /* take lock of both connections in a defined order */
-       if (conn < conn_old) {
-               mutex_lock(&conn->lock);
-               mutex_lock_nested(&conn_old->lock, 1);
-       } else {
-               mutex_lock(&conn_old->lock);
-               mutex_lock_nested(&conn->lock, 1);
-       }
+       kdbus_conn_lock2(conn, conn_old);
 
        if (!kdbus_conn_active(conn)) {
                ret = -ECONNRESET;
@@ -185,9 +178,7 @@ static int kdbus_name_replace_owner(struct kdbus_name_entry *e,
        e->flags = flags;
 
 exit_unlock:
-       mutex_unlock(&conn_old->lock);
-       mutex_unlock(&conn->lock);
-
+       kdbus_conn_unlock2(conn, conn_old);
        kdbus_conn_unref(conn_old);
        return ret;
 }