Fix: Initialize global agent_apps_ht_by_sock on session daemon launch
[lttng-tools.git] / src / bin / lttng-sessiond / agent.c
index cf8264a307b7029f479b779dd846221212922567..7349d09f0e7edd9dbfad5e082e89a0825f440a26 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #define _GNU_SOURCE
+#define _LGPL_SOURCE
 #include <assert.h>
 #include <urcu/uatomic.h>
 
@@ -452,7 +453,8 @@ int agent_send_registration_done(struct agent_app *app)
  *
  * Return LTTNG_OK on success or else a LTTNG_ERR* code.
  */
-int agent_enable_event(struct agent_event *event)
+int agent_enable_event(struct agent_event *event,
+               enum lttng_domain_type domain)
 {
        int ret;
        struct agent_app *app;
@@ -464,6 +466,10 @@ int agent_enable_event(struct agent_event *event)
 
        cds_lfht_for_each_entry(agent_apps_ht_by_sock->ht, &iter.iter, app,
                        node.node) {
+               if (app->domain != domain) {
+                       continue;
+               }
+
                /* Enable event on agent application through TCP socket. */
                ret = enable_event(app, event);
                if (ret != LTTNG_OK) {
@@ -485,7 +491,8 @@ error:
  *
  * Return LTTNG_OK on success or else a LTTNG_ERR* code.
  */
-int agent_disable_event(struct agent_event *event)
+int agent_disable_event(struct agent_event *event,
+               enum lttng_domain_type domain)
 {
        int ret;
        struct agent_app *app;
@@ -497,6 +504,10 @@ int agent_disable_event(struct agent_event *event)
 
        cds_lfht_for_each_entry(agent_apps_ht_by_sock->ht, &iter.iter, app,
                        node.node) {
+               if (app->domain != domain) {
+                       continue;
+               }
+
                /* Enable event on agent application through TCP socket. */
                ret = disable_event(app, event);
                if (ret != LTTNG_OK) {
@@ -518,7 +529,8 @@ error:
  *
  * Return the number of events or else a negative value.
  */
-int agent_list_events(struct lttng_event **events)
+int agent_list_events(struct lttng_event **events,
+               enum lttng_domain_type domain)
 {
        int ret;
        size_t nbmem, count = 0;
@@ -528,6 +540,8 @@ int agent_list_events(struct lttng_event **events)
 
        assert(events);
 
+       DBG2("Agent listing events for domain %d", domain);
+
        nbmem = UST_APP_EVENT_LIST_SIZE;
        tmp_events = zmalloc(nbmem * sizeof(*tmp_events));
        if (!tmp_events) {
@@ -542,6 +556,11 @@ int agent_list_events(struct lttng_event **events)
                ssize_t nb_ev;
                struct lttng_event *agent_events;
 
+               /* Skip domain not asked by the list. */
+               if (app->domain != domain) {
+                       continue;
+               }
+
                nb_ev = list_events(app, &agent_events);
                if (nb_ev < 0) {
                        ret = nb_ev;
@@ -593,7 +612,8 @@ error:
  *
  * Return newly allocated object or else NULL on error.
  */
-struct agent_app *agent_create_app(pid_t pid, struct lttcomm_sock *sock)
+struct agent_app *agent_create_app(pid_t pid, enum lttng_domain_type domain,
+               struct lttcomm_sock *sock)
 {
        struct agent_app *app;
 
@@ -606,6 +626,7 @@ struct agent_app *agent_create_app(pid_t pid, struct lttcomm_sock *sock)
        }
 
        app->pid = pid;
+       app->domain = domain;
        app->sock = sock;
        lttng_ht_node_init_ulong(&app->node, (unsigned long) app->sock->fd);
 
@@ -659,6 +680,8 @@ void agent_add_app(struct agent_app *app)
 
 /*
  * Delete agent application from the global hash table.
+ *
+ * rcu_read_lock() must be held by the caller.
  */
 void agent_delete_app(struct agent_app *app)
 {
@@ -670,14 +693,12 @@ void agent_delete_app(struct agent_app *app)
        DBG3("Agent deleting app pid: %d and sock: %d", app->pid, app->sock->fd);
 
        iter.iter.node = &app->node.node;
-       rcu_read_lock();
        ret = lttng_ht_del(agent_apps_ht_by_sock, &iter);
-       rcu_read_unlock();
        assert(!ret);
 }
 
 /*
- * Destroy a agent application object by detaching it from its corresponding
+ * Destroy an agent application object by detaching it from its corresponding
  * UST app if one is connected by closing the socket. Finally, perform a
  * delayed memory reclaim.
  */
@@ -709,6 +730,7 @@ int agent_init(struct agent *agt)
                ret = -ENOMEM;
                goto error;
        }
+       lttng_ht_node_init_u64(&agt->node, agt->domain);
 
        return 0;
 
@@ -716,6 +738,48 @@ error:
        return ret;
 }
 
+/*
+ * Add agent object to the given hash table.
+ */
+void agent_add(struct agent *agt, struct lttng_ht *ht)
+{
+       assert(agt);
+       assert(ht);
+
+       DBG3("Agent adding from domain %d", agt->domain);
+
+       rcu_read_lock();
+       lttng_ht_add_unique_u64(ht, &agt->node);
+       rcu_read_unlock();
+}
+
+/*
+ * Create an agent object for the given domain.
+ *
+ * Return the allocated agent or NULL on error.
+ */
+struct agent *agent_create(enum lttng_domain_type domain)
+{
+       int ret;
+       struct agent *agt;
+
+       agt = zmalloc(sizeof(*agt));
+       if (!agt) {
+               goto error;
+       }
+       agt->domain = domain;
+
+       ret = agent_init(agt);
+       if (ret < 0) {
+               free(agt);
+               agt = NULL;
+               goto error;
+       }
+
+error:
+       return agt;
+}
+
 /*
  * Create a newly allocated agent event data structure. If name is valid, it's
  * copied into the created event.
@@ -836,7 +900,7 @@ struct agent_event *agent_find_event(const char *name, int loglevel,
        return caa_container_of(node, struct agent_event, node);
 
 error:
-       DBG3("Agent NOT found %s.", name);
+       DBG3("Agent event NOT found %s.", name);
        return NULL;
 }
 
@@ -849,6 +913,7 @@ void agent_destroy_event(struct agent_event *event)
 {
        assert(event);
 
+       free(event->filter);
        free(event);
 }
 
@@ -892,20 +957,71 @@ void agent_destroy(struct agent *agt)
        }
        rcu_read_unlock();
 
-       lttng_ht_destroy(agt->events);
+       ht_cleanup_push(agt->events);
 }
 
 /*
- * Initialize agent subsystem.
+ * Allocate agent_apps_ht_by_sock.
  */
-int agent_setup(void)
+int agent_app_ht_alloc(void)
 {
+       int ret = 0;
+
        agent_apps_ht_by_sock = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG);
        if (!agent_apps_ht_by_sock) {
-               return -1;
+               ret = -1;
        }
 
-       return 0;
+       return ret;
+}
+
+/*
+ * Destroy a agent application by socket.
+ */
+void agent_destroy_app_by_sock(int sock)
+{
+       struct agent_app *app;
+
+       assert(sock >= 0);
+
+       /*
+        * Not finding an application is a very important error that should NEVER
+        * happen. The hash table deletion is ONLY done through this call when the
+        * main sessiond thread is torn down.
+        */
+       rcu_read_lock();
+       app = agent_find_app_by_sock(sock);
+       assert(app);
+
+       /* RCU read side lock is assumed to be held by this function. */
+       agent_delete_app(app);
+
+       /* The application is freed in a RCU call but the socket is closed here. */
+       agent_destroy_app(app);
+       rcu_read_unlock();
+}
+
+/*
+ * Clean-up the agent app hash table and destroy it.
+ */
+void agent_app_ht_clean(void)
+{
+       struct lttng_ht_node_ulong *node;
+       struct lttng_ht_iter iter;
+
+       if (!agent_apps_ht_by_sock) {
+               return;
+       }
+       rcu_read_lock();
+       cds_lfht_for_each_entry(agent_apps_ht_by_sock->ht, &iter.iter, node, node) {
+               struct agent_app *app;
+
+               app = caa_container_of(node, struct agent_app, node);
+               agent_destroy_app_by_sock(app->sock->fd);
+       }
+       rcu_read_unlock();
+
+       lttng_ht_destroy(agent_apps_ht_by_sock);
 }
 
 /*
This page took 0.025988 seconds and 4 git commands to generate.