From 35925199d21d41a08ffb44489afca32882ac8aa8 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Wed, 7 Jan 2015 17:44:37 +0100 Subject: [PATCH] connection: introduce kdbus_conn_lock2() 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 --- connection.h | 42 ++++++++++++++++++++++++++++++++++++++++++ names.c | 13 ++----------- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/connection.h b/connection.h index 6c1fcdb..4d88ec0 100644 --- a/connection.h +++ b/connection.h @@ -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 6f2b20f..be51911 100644 --- 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; } -- 2.34.1