Commit | Line | Data |
---|---|---|
91d76f53 DG |
1 | /* |
2 | * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca> | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or | |
5 | * modify it under the terms of the GNU General Public License | |
82a3637f DG |
6 | * as published by the Free Software Foundation; only version 2 |
7 | * of the License. | |
91d76f53 DG |
8 | * |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License | |
15 | * along with this program; if not, write to the Free Software | |
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
17 | */ | |
18 | ||
19 | #define _GNU_SOURCE | |
20 | #include <errno.h> | |
21 | #include <pthread.h> | |
22 | #include <stdio.h> | |
23 | #include <stdlib.h> | |
099e26bd DG |
24 | #include <string.h> |
25 | #include <unistd.h> | |
91d76f53 | 26 | |
1e307fab DG |
27 | #include <lttngerr.h> |
28 | ||
f6a9efaa | 29 | #include "hashtable.h" |
56fff090 | 30 | #include "ust-app.h" |
f6a9efaa | 31 | #include "../hashtable/hash.h" |
91d76f53 DG |
32 | |
33 | /* | |
099e26bd | 34 | * Delete a traceable application structure from the global list. |
91d76f53 | 35 | */ |
f6a9efaa | 36 | static void delete_ust_app(struct ust_app *lta) |
91d76f53 | 37 | { |
f6a9efaa DG |
38 | int ret; |
39 | struct cds_lfht_node *node; | |
40 | struct cds_lfht_iter iter; | |
44d3bd01 | 41 | |
f6a9efaa | 42 | rcu_read_lock(); |
44d3bd01 | 43 | |
f6a9efaa DG |
44 | hashtable_get_first(lta->channels, &iter); |
45 | while ((node = hashtable_iter_get_node(&iter)) != NULL) { | |
46 | ret = hashtable_del(lta->channels, &iter); | |
47 | if (!ret) { | |
48 | trace_ust_destroy_channel( | |
49 | caa_container_of(node, struct ltt_ust_channel, node)); | |
50 | } | |
51 | hashtable_get_next(lta->channels, &iter); | |
44d3bd01 | 52 | } |
099e26bd | 53 | |
f6a9efaa DG |
54 | free(lta->channels); |
55 | close(lta->key.sock); | |
56fff090 | 56 | |
f6a9efaa DG |
57 | /* Remove from apps hash table */ |
58 | node = hashtable_lookup(ust_app_ht, | |
59 | (void *) ((unsigned long) lta->key.pid), sizeof(void *), &iter); | |
60 | if (node == NULL) { | |
61 | ERR("UST app pid %d not found in hash table", lta->key.pid); | |
62 | } else { | |
63 | ret = hashtable_del(ust_app_ht, &iter); | |
64 | if (ret) { | |
65 | ERR("UST app unable to delete app %d from hash table", | |
66 | lta->key.pid); | |
67 | } else { | |
68 | DBG2("UST app pid %d deleted", lta->key.pid); | |
56fff090 DG |
69 | } |
70 | } | |
71 | ||
f6a9efaa DG |
72 | /* Remove from key hash table */ |
73 | node = hashtable_lookup(ust_app_sock_key_map, | |
74 | (void *) ((unsigned long) lta->key.sock), sizeof(void *), &iter); | |
75 | if (node == NULL) { | |
76 | ERR("UST app key %d not found in key hash table", lta->key.sock); | |
77 | } else { | |
78 | ret = hashtable_del(ust_app_sock_key_map, &iter); | |
79 | if (ret) { | |
80 | ERR("UST app unable to delete app sock %d from key hash table", | |
81 | lta->key.sock); | |
82 | } else { | |
83 | DBG2("UST app pair sock %d key %d deleted", | |
84 | lta->key.sock, lta->key.pid); | |
85 | } | |
86 | } | |
87 | ||
88 | free(lta); | |
89 | ||
90 | rcu_read_unlock(); | |
099e26bd DG |
91 | } |
92 | ||
93 | /* | |
f6a9efaa | 94 | * URCU intermediate call to delete an UST app. |
099e26bd | 95 | */ |
f6a9efaa | 96 | static void delete_ust_app_rcu(struct rcu_head *head) |
099e26bd | 97 | { |
f6a9efaa DG |
98 | struct cds_lfht_node *node = |
99 | caa_container_of(head, struct cds_lfht_node, head); | |
100 | struct ust_app *app = | |
101 | caa_container_of(node, struct ust_app, node); | |
102 | ||
103 | delete_ust_app(app); | |
099e26bd DG |
104 | } |
105 | ||
106 | /* | |
f6a9efaa | 107 | * Find an ust_app using the sock and return it. |
099e26bd | 108 | */ |
f6a9efaa | 109 | static struct ust_app *find_app_by_sock(int sock) |
099e26bd | 110 | { |
f6a9efaa DG |
111 | struct cds_lfht_node *node; |
112 | struct ust_app_key *key; | |
113 | struct cds_lfht_iter iter; | |
114 | //struct ust_app *app; | |
115 | ||
116 | rcu_read_lock(); | |
117 | ||
118 | node = hashtable_lookup(ust_app_sock_key_map, | |
119 | (void *)((unsigned long) sock), sizeof(void *), &iter); | |
120 | if (node == NULL) { | |
121 | DBG2("UST app find by sock %d key not found", sock); | |
122 | rcu_read_unlock(); | |
123 | goto error; | |
124 | } | |
125 | ||
126 | key = caa_container_of(node, struct ust_app_key, node); | |
127 | ||
128 | node = hashtable_lookup(ust_app_ht, | |
129 | (void *)((unsigned long) key->pid), sizeof(void *), &iter); | |
130 | if (node == NULL) { | |
131 | DBG2("UST app find by sock %d not found", sock); | |
132 | rcu_read_unlock(); | |
133 | goto error; | |
134 | } | |
135 | rcu_read_unlock(); | |
136 | ||
137 | return caa_container_of(node, struct ust_app, node); | |
138 | ||
139 | error: | |
140 | return NULL; | |
099e26bd DG |
141 | } |
142 | ||
143 | /* | |
f6a9efaa | 144 | * Return pointer to traceable apps list. |
099e26bd | 145 | */ |
f6a9efaa | 146 | struct cds_lfht *ust_app_get_ht(void) |
099e26bd | 147 | { |
f6a9efaa | 148 | return ust_app_ht; |
91d76f53 DG |
149 | } |
150 | ||
0177d773 | 151 | /* |
f6a9efaa | 152 | * Return ust app pointer or NULL if not found. |
0177d773 | 153 | */ |
f6a9efaa | 154 | struct ust_app *ust_app_find_by_pid(pid_t pid) |
0177d773 | 155 | { |
f6a9efaa DG |
156 | struct cds_lfht_node *node; |
157 | struct cds_lfht_iter iter; | |
0177d773 | 158 | |
f6a9efaa DG |
159 | rcu_read_lock(); |
160 | node = hashtable_lookup(ust_app_ht, | |
161 | (void *)((unsigned long) pid), sizeof(void *), &iter); | |
162 | if (node == NULL) { | |
163 | rcu_read_unlock(); | |
164 | DBG2("UST app no found with pid %d", pid); | |
165 | goto error; | |
0177d773 | 166 | } |
f6a9efaa | 167 | rcu_read_unlock(); |
0177d773 | 168 | |
f6a9efaa | 169 | DBG2("Found UST app by pid %d", pid); |
44d3bd01 | 170 | |
f6a9efaa DG |
171 | return caa_container_of(node, struct ust_app, node); |
172 | ||
173 | error: | |
0177d773 DG |
174 | return NULL; |
175 | } | |
176 | ||
91d76f53 | 177 | /* |
56fff090 | 178 | * Using pid and uid (of the app), allocate a new ust_app struct and |
050349bb | 179 | * add it to the global traceable app list. |
91d76f53 | 180 | * |
050349bb | 181 | * On success, return 0, else return malloc ENOMEM. |
91d76f53 | 182 | */ |
56fff090 | 183 | int ust_app_register(struct ust_register_msg *msg, int sock) |
91d76f53 | 184 | { |
56fff090 | 185 | struct ust_app *lta; |
91d76f53 | 186 | |
56fff090 | 187 | lta = malloc(sizeof(struct ust_app)); |
91d76f53 DG |
188 | if (lta == NULL) { |
189 | perror("malloc"); | |
190 | return -ENOMEM; | |
191 | } | |
192 | ||
099e26bd DG |
193 | lta->uid = msg->uid; |
194 | lta->gid = msg->gid; | |
f6a9efaa | 195 | lta->key.pid = msg->pid; |
099e26bd DG |
196 | lta->ppid = msg->ppid; |
197 | lta->v_major = msg->major; | |
198 | lta->v_minor = msg->minor; | |
f6a9efaa | 199 | lta->key.sock = sock; |
099e26bd DG |
200 | strncpy(lta->name, msg->name, sizeof(lta->name)); |
201 | lta->name[16] = '\0'; | |
f6a9efaa DG |
202 | hashtable_node_init(<a->node, (void *)((unsigned long)lta->key.pid), |
203 | sizeof(void *)); | |
204 | lta->channels = hashtable_new_str(0); | |
205 | ||
206 | /* Set sock key map */ | |
207 | hashtable_node_init(<a->key.node, (void *)((unsigned long)lta->key.sock), | |
208 | sizeof(void *)); | |
099e26bd | 209 | |
f6a9efaa DG |
210 | rcu_read_lock(); |
211 | hashtable_add_unique(ust_app_ht, <a->node); | |
212 | hashtable_add_unique(ust_app_sock_key_map, <a->key.node); | |
213 | rcu_read_unlock(); | |
099e26bd DG |
214 | |
215 | DBG("App registered with pid:%d ppid:%d uid:%d gid:%d sock:%d name:%s" | |
f6a9efaa DG |
216 | " (version %d.%d)", lta->key.pid, lta->ppid, lta->uid, lta->gid, |
217 | lta->key.sock, lta->name, lta->v_major, lta->v_minor); | |
91d76f53 DG |
218 | |
219 | return 0; | |
220 | } | |
221 | ||
222 | /* | |
050349bb DG |
223 | * Unregister app by removing it from the global traceable app list and freeing |
224 | * the data struct. | |
099e26bd DG |
225 | * |
226 | * The socket is already closed at this point so no close to sock. | |
91d76f53 | 227 | */ |
56fff090 | 228 | void ust_app_unregister(int sock) |
91d76f53 | 229 | { |
56fff090 | 230 | struct ust_app *lta; |
91d76f53 | 231 | |
f6a9efaa DG |
232 | DBG2("UST app unregistering sock %d", sock); |
233 | ||
099e26bd DG |
234 | lta = find_app_by_sock(sock); |
235 | if (lta) { | |
f6a9efaa DG |
236 | DBG("PID %d unregistering with sock %d", lta->key.pid, sock); |
237 | /* FIXME: Better use a call_rcu here ? */ | |
238 | delete_ust_app(lta); | |
91d76f53 DG |
239 | } |
240 | } | |
241 | ||
242 | /* | |
050349bb | 243 | * Return traceable_app_count |
91d76f53 | 244 | */ |
f6a9efaa | 245 | unsigned long ust_app_list_count(void) |
91d76f53 | 246 | { |
f6a9efaa | 247 | unsigned long count; |
91d76f53 | 248 | |
f6a9efaa DG |
249 | rcu_read_lock(); |
250 | count = hashtable_get_count(ust_app_ht); | |
251 | rcu_read_unlock(); | |
91d76f53 | 252 | |
099e26bd | 253 | return count; |
91d76f53 DG |
254 | } |
255 | ||
256 | /* | |
099e26bd | 257 | * Free and clean all traceable apps of the global list. |
91d76f53 | 258 | */ |
56fff090 | 259 | void ust_app_clean_list(void) |
91d76f53 | 260 | { |
f6a9efaa DG |
261 | int ret; |
262 | struct cds_lfht_node *node; | |
263 | struct cds_lfht_iter iter; | |
264 | ||
265 | DBG2("UST app clean hash table"); | |
266 | ||
267 | rcu_read_lock(); | |
268 | ||
269 | hashtable_get_first(ust_app_ht, &iter); | |
270 | while ((node = hashtable_iter_get_node(&iter)) != NULL) { | |
271 | ret = hashtable_del(ust_app_ht, &iter); | |
272 | if (!ret) { | |
273 | call_rcu(&node->head, delete_ust_app_rcu); | |
274 | } | |
275 | hashtable_get_next(ust_app_ht, &iter); | |
91d76f53 | 276 | } |
f6a9efaa DG |
277 | |
278 | rcu_read_unlock(); | |
279 | } | |
280 | ||
281 | /* | |
282 | * Init UST app hash table. | |
283 | */ | |
284 | void ust_app_ht_alloc(void) | |
285 | { | |
286 | ust_app_ht = hashtable_new(0); | |
287 | ust_app_sock_key_map = hashtable_new(0); | |
91d76f53 | 288 | } |