diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2014-10-23 12:16:25 +0200 |
---|---|---|
committer | David Herrmann <dh.herrmann@gmail.com> | 2014-10-23 12:16:25 +0200 |
commit | a8adec5ddeb21dae91bab180abf3e2dc879f9102 (patch) | |
tree | 13a153904a498a4d59e24a6619c4506696cff81f | |
parent | aa81005e886a6d3f29645053f90d8bf56faca4c4 (diff) | |
download | kdbus-bus-a8adec5ddeb21dae91bab180abf3e2dc879f9102.tar.gz kdbus-bus-a8adec5ddeb21dae91bab180abf3e2dc879f9102.tar.bz2 kdbus-bus-a8adec5ddeb21dae91bab180abf3e2dc879f9102.zip |
connection: simplify reply cleanups
There is no reason why we cannot destroy replies while holding a
connection lock. If the reply points to the connection whose lock we hold,
we also have another ref on that connection due to our context. If the
lock points to another connection, we can simply unref it at any time.
Note that we never cause disconnects on the connection. We only unref it!
The object destruction is a simple memory cleanup. Nothing fancy is done
there, and no inter-object refs can exist anymore (otherwise, it would not
get freed). Therefore, fix all our callers to free replies directly,
instead of releasing the locks first.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
-rw-r--r-- | connection.c | 38 |
1 files changed, 11 insertions, 27 deletions
diff --git a/connection.c b/connection.c index d40b6ae6bc4..52c4d9b76b1 100644 --- a/connection.c +++ b/connection.c @@ -144,7 +144,6 @@ static void kdbus_conn_work(struct work_struct *work) { struct kdbus_conn *conn; struct kdbus_conn_reply *reply, *reply_tmp; - LIST_HEAD(reply_list); u64 deadline = ~0ULL; struct timespec64 ts; u64 now; @@ -177,21 +176,15 @@ static void kdbus_conn_work(struct work_struct *work) } /* - * Move to temporary cleanup list; we cannot unref and - * possibly cleanup a connection that is holding a ref - * back to us, while we are locking ourselves. - */ - list_move_tail(&reply->entry, &reply_list); - - /* * A zero deadline means the connection died, was * cleaned up already and the notification was sent. */ - if (reply->deadline_ns == 0) - continue; + if (reply->deadline_ns != 0) + kdbus_notify_reply_timeout(conn->bus, reply->conn->id, + reply->cookie); - kdbus_notify_reply_timeout(conn->bus, reply->conn->id, - reply->cookie); + list_del_init(&reply->entry); + kdbus_conn_reply_free(reply); } /* rearm delayed work with next timeout */ @@ -202,9 +195,6 @@ static void kdbus_conn_work(struct work_struct *work) mutex_unlock(&conn->lock); kdbus_notify_flush(conn->bus); - - list_for_each_entry_safe(reply, reply_tmp, &reply_list, entry) - kdbus_conn_reply_free(reply); } /** @@ -234,7 +224,6 @@ int kdbus_cmd_msg_recv(struct kdbus_conn *conn, /* just drop the message */ if (recv->flags & KDBUS_RECV_DROP) { - struct kdbus_conn_reply *reply = NULL; bool reply_found = false; if (entry->reply) { @@ -261,7 +250,7 @@ int kdbus_cmd_msg_recv(struct kdbus_conn *conn, kdbus_conn_reply_sync(entry->reply, -EPIPE); } else { list_del_init(&entry->reply->entry); - reply = entry->reply; + kdbus_conn_reply_free(entry->reply); } kdbus_notify_reply_dead(conn->bus, @@ -273,9 +262,6 @@ int kdbus_cmd_msg_recv(struct kdbus_conn *conn, kdbus_pool_slice_free(entry->slice); mutex_unlock(&conn->lock); - if (reply) - kdbus_conn_reply_free(reply); - kdbus_queue_entry_free(entry); goto exit; @@ -368,25 +354,23 @@ static int kdbus_conn_check_access(struct kdbus_ep *ep, */ if (reply_wake && msg->cookie_reply > 0) { struct kdbus_conn_reply *r, *tmp; - LIST_HEAD(reply_list); mutex_lock(&conn_src->lock); list_for_each_entry_safe(r, tmp, &conn_src->reply_list, entry) { if (r->conn == conn_dst && r->cookie == msg->cookie_reply) { - if (r->sync) + if (r->sync) { *reply_wake = r; - else - list_move_tail(&r->entry, &reply_list); + } else { + list_del_init(&r->entry); + kdbus_conn_reply_free(r); + } allowed = true; break; } } mutex_unlock(&conn_src->lock); - - list_for_each_entry_safe(r, tmp, &reply_list, entry) - kdbus_conn_reply_free(r); } if (allowed) |