endpoint: when disconnecting, disconnect all connections
authorKay Sievers <kay@vrfy.org>
Mon, 17 Mar 2014 18:46:08 +0000 (19:46 +0100)
committerKay Sievers <kay@vrfy.org>
Mon, 17 Mar 2014 18:46:08 +0000 (19:46 +0100)
TODO
bus.c
connection.c
connection.h
endpoint.c
endpoint.h
handle.c

diff --git a/TODO b/TODO
index adc9e055f49dce1df568be056203b8fc7cac0eb0..9fed5aedca479e7e068ccb8f23a14cf714bfa6ff 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,7 +1,5 @@
 Bugs:
   - replace memfd ioctls with shmem memfd_create() + fcntl() logic
-  - disconnect connections with kdbus_ep_disconnect(), remove
-    ep->disconnected checks
 
 Features:
   - test kdbus_match_bloom() multi-generation bloom masks, we need to
diff --git a/bus.c b/bus.c
index d9bb81d6355736c0969a5abed5f90534375f8a1f..1b5b0471eefb7366ba8c29b5b8e3ec06adfa508e 100644 (file)
--- a/bus.c
+++ b/bus.c
@@ -162,29 +162,6 @@ void kdbus_bus_disconnect(struct kdbus_bus *bus)
                kdbus_ep_unref(ep);
        }
 
-
-       /* disconnect all connections to this bus */
-       for (;;) {
-               struct kdbus_conn *conn = NULL, *c;
-               unsigned int i;
-
-               mutex_lock(&bus->lock);
-               hash_for_each(bus->conn_hash, i, c, hentry) {
-                       conn = c;
-                       break;
-               }
-               if (!conn) {
-                       mutex_unlock(&bus->lock);
-                       break;
-               }
-
-               kdbus_conn_ref(conn);
-               mutex_unlock(&bus->lock);
-
-               kdbus_conn_disconnect(conn, false);
-               kdbus_conn_unref(conn);
-       }
-
        /* drop reference for our "bus" endpoint after we disconnected */
        bus->ep = kdbus_ep_unref(bus->ep);
 }
index 99f7ee6df7f8384b681eb2ff327917da00cd4506..5538191b4cfb1fb126afcf620c48c917b1998b2f 100644 (file)
@@ -1001,11 +1001,6 @@ int kdbus_cmd_msg_recv(struct kdbus_conn *conn,
        int ret = 0;
 
        mutex_lock(&conn->lock);
-       if (unlikely(conn->ep->disconnected)) {
-               ret = -ECONNRESET;
-               goto exit_unlock;
-       }
-
        if (conn->msg_count == 0) {
                ret = -EAGAIN;
                goto exit_unlock;
@@ -1493,6 +1488,11 @@ int kdbus_conn_disconnect(struct kdbus_conn *conn, bool ensure_queue_empty)
        list_del(&conn->monitor_entry);
        mutex_unlock(&conn->bus->lock);
 
+       /* remove from endpoint */
+       mutex_lock(&conn->ep->lock);
+       list_del(&conn->ep_entry);
+       mutex_unlock(&conn->ep->lock);
+
        /* if we die while other connections wait for our reply, notify them */
        mutex_lock(&conn->lock);
        list_for_each_entry_safe(queue, tmp, &conn->msg_list, entry) {
@@ -2092,6 +2092,11 @@ int kdbus_conn_new(struct kdbus_ep *ep,
                goto exit_unref_user;
        }
 
+       /* link into endpoint */
+       mutex_lock(&ep->lock);
+       list_add_tail(&conn->ep_entry, &ep->conn_list);
+       mutex_unlock(&ep->lock);
+
        /* link into bus */
        mutex_lock(&bus->lock);
        hash_add(bus->conn_hash, &conn->hentry, conn->id);
index a7780d8efc9f756d9ec14770ec34e51c3c7a25d3..43a9b6191d36552ef1af6d63c9e7f6eff0310ed0 100644 (file)
@@ -36,6 +36,7 @@
  *                     individual user
  * @msg_users_max:     Size of the users array
  * @hentry:            Entry in ID <-> connection map
+ * @ep_entry:          The enpoint this connection belongs to
  * @monitor_entry:     The connection is a monitor
  * @names_list:                List of well-known names
  * @names_queue_list:  Well-known names this connection waits for
@@ -74,6 +75,7 @@ struct kdbus_conn {
        unsigned int *msg_users;
        unsigned int msg_users_max;
        struct hlist_node hentry;
+       struct list_head ep_entry;
        struct list_head monitor_entry;
        struct list_head names_list;
        struct list_head names_queue_list;
index 69718989b5dbe819de316be9b59308ff1eeb4f98..876e5e30c38467f9ddb6f1b2f1b157815cca9a47 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/slab.h>
 #include <linux/uaccess.h>
 
+#include "connection.h"
 #include "bus.h"
 #include "endpoint.h"
 #include "domain.h"
@@ -72,6 +73,26 @@ void kdbus_ep_disconnect(struct kdbus_ep *ep)
        ep->disconnected = true;
        mutex_unlock(&ep->lock);
 
+       /* disconnect all connections to this endpoint */
+       for (;;) {
+               struct kdbus_conn *conn;
+
+               mutex_lock(&ep->lock);
+               conn = list_first_entry_or_null(&ep->conn_list,
+                                               struct kdbus_conn,
+                                               ep_entry);
+               if (!conn) {
+                       mutex_unlock(&ep->lock);
+                       break;
+               }
+
+               kdbus_conn_ref(conn);
+               mutex_unlock(&ep->lock);
+
+               kdbus_conn_disconnect(conn, false);
+               kdbus_conn_unref(conn);
+       }
+
        /* disconnect from bus */
        mutex_lock(&ep->bus->lock);
        list_del(&ep->bus_entry);
@@ -158,6 +179,7 @@ int kdbus_ep_new(struct kdbus_bus *bus, const char *name,
 
        mutex_init(&e->lock);
        kref_init(&e->kref);
+       INIT_LIST_HEAD(&e->conn_list);
        e->uid = uid;
        e->gid = gid;
        e->mode = mode;
index 7385a09525369d3c67a22f4f6b25127d21baf4a9..cd2ebe181f21dac4f3bc66033447aeabc6622d4e 100644 (file)
@@ -28,6 +28,7 @@
  * @mode:              File mode of this endpoint device node
  * @uid:               UID owning this endpoint
  * @gid:               GID owning this endpoint
+ * @conn_list:         Connections of this endpoint
  * @bus_entry:         bus' endpoints
  * @lock:              Endpoint data lock
  * @user:              Custom enpoints account against an anonymous user
@@ -48,6 +49,7 @@ struct kdbus_ep {
        umode_t mode;
        kuid_t uid;
        kgid_t gid;
+       struct list_head conn_list;
        struct list_head bus_entry;
        struct mutex lock;
        struct kdbus_domain_user *user;
index b0b95aaea384cc214a0bfea56f8eb3711016618e..17ccf0f03f20e901569209048cf95e15a63b6319 100644 (file)
--- a/handle.c
+++ b/handle.c
@@ -813,24 +813,20 @@ static unsigned int kdbus_handle_poll(struct file *file,
                                      struct poll_table_struct *wait)
 {
        struct kdbus_handle *handle = file->private_data;
-       struct kdbus_conn *conn;
+       struct kdbus_conn *conn = handle->conn;
        unsigned int mask = 0;
 
        /* Only a connected endpoint can read/write data */
        if (handle->type != KDBUS_HANDLE_EP_CONNECTED)
                return POLLERR | POLLHUP;
 
-       conn = handle->conn;
-
        poll_wait(file, &conn->wait, wait);
 
        mutex_lock(&conn->lock);
-
        if (unlikely(conn->disconnected))
                mask |= POLLERR | POLLHUP;
        else if (!list_empty(&conn->msg_list))
                mask |= POLLIN | POLLRDNORM;
-
        mutex_unlock(&conn->lock);
 
        return mask;