sessiond: Replace uses of session_trylock_list by a dedicated assert macro
[lttng-tools.git] / src / bin / lttng-sessiond / tracker.cpp
1 /*
2 * Copyright (C) 2018 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
3 * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 *
5 * SPDX-License-Identifier: GPL-2.0-only
6 *
7 */
8
9 #include "lttng/tracker.h"
10 #include "common/dynamic-array.hpp"
11 #include "common/macros.hpp"
12 #define _LGPL_SOURCE
13 #include <grp.h>
14 #include <pwd.h>
15 #include <sys/types.h>
16 #include <unistd.h>
17 #include <urcu.h>
18 #include <urcu/list.h>
19 #include <urcu/rculfhash.h>
20
21 #include "tracker.hpp"
22 #include <common/defaults.hpp>
23 #include <common/error.hpp>
24 #include <common/hashtable/hashtable.hpp>
25 #include <common/hashtable/utils.hpp>
26 #include <common/tracker.hpp>
27 #include <lttng/lttng-error.h>
28
29 struct process_attr_tracker {
30 enum lttng_tracking_policy policy;
31 struct cds_lfht *inclusion_set_ht;
32 };
33
34 namespace {
35 struct process_attr_tracker_value_node {
36 struct process_attr_value *value;
37 struct cds_lfht_node inclusion_set_ht_node;
38 struct rcu_head rcu_head;
39 };
40 } /* namespace */
41
42 static void process_attr_tracker_value_node_rcu_free(struct rcu_head *rcu_head)
43 {
44 struct process_attr_tracker_value_node *node =
45 container_of(rcu_head, typeof(*node), rcu_head);
46
47 free(node);
48 }
49
50 struct process_attr_tracker *process_attr_tracker_create(void)
51 {
52 struct process_attr_tracker *tracker;
53
54 tracker = zmalloc<process_attr_tracker>();
55 if (!tracker) {
56 return NULL;
57 }
58
59 (void) process_attr_tracker_set_tracking_policy(
60 tracker, LTTNG_TRACKING_POLICY_INCLUDE_ALL);
61
62 tracker->inclusion_set_ht = cds_lfht_new(DEFAULT_HT_SIZE, 1, 0,
63 CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, NULL);
64 if (!tracker->inclusion_set_ht) {
65 goto error;
66 }
67
68 return tracker;
69 error:
70 process_attr_tracker_destroy(tracker);
71 return NULL;
72 }
73
74 static void process_attr_tracker_remove_value_node(
75 struct process_attr_tracker *tracker,
76 struct process_attr_tracker_value_node *value_node)
77 {
78 cds_lfht_del(tracker->inclusion_set_ht,
79 &value_node->inclusion_set_ht_node);
80 process_attr_value_destroy(value_node->value);
81 call_rcu(&value_node->rcu_head,
82 process_attr_tracker_value_node_rcu_free);
83 }
84
85 static void process_attr_tracker_clear_inclusion_set(
86 struct process_attr_tracker *tracker)
87 {
88 int ret;
89 struct lttng_ht_iter iter;
90 struct process_attr_tracker_value_node *value_node;
91
92 if (!tracker->inclusion_set_ht) {
93 return;
94 }
95
96 rcu_read_lock();
97 cds_lfht_for_each_entry (tracker->inclusion_set_ht, &iter.iter,
98 value_node, inclusion_set_ht_node) {
99 process_attr_tracker_remove_value_node(tracker, value_node);
100 }
101 rcu_read_unlock();
102 ret = cds_lfht_destroy(tracker->inclusion_set_ht, NULL);
103 LTTNG_ASSERT(ret == 0);
104 tracker->inclusion_set_ht = NULL;
105 }
106
107 static int process_attr_tracker_create_inclusion_set(
108 struct process_attr_tracker *tracker)
109 {
110 LTTNG_ASSERT(!tracker->inclusion_set_ht);
111 tracker->inclusion_set_ht = cds_lfht_new(DEFAULT_HT_SIZE, 1, 0,
112 CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, NULL);
113 return tracker->inclusion_set_ht ? 0 : -1;
114 }
115
116 void process_attr_tracker_destroy(struct process_attr_tracker *tracker)
117 {
118 if (!tracker) {
119 return;
120 }
121
122 process_attr_tracker_clear_inclusion_set(tracker);
123 free(tracker);
124 }
125
126 enum lttng_tracking_policy process_attr_tracker_get_tracking_policy(
127 const struct process_attr_tracker *tracker)
128 {
129 return tracker->policy;
130 }
131
132 int process_attr_tracker_set_tracking_policy(
133 struct process_attr_tracker *tracker,
134 enum lttng_tracking_policy tracking_policy)
135 {
136 int ret = 0;
137
138 if (tracker->policy == tracking_policy) {
139 goto end;
140 }
141
142 process_attr_tracker_clear_inclusion_set(tracker);
143 ret = process_attr_tracker_create_inclusion_set(tracker);
144 if (ret) {
145 goto end;
146 }
147 tracker->policy = tracking_policy;
148 end:
149 return ret;
150 }
151
152 static int match_inclusion_set_value(
153 struct cds_lfht_node *node, const void *key)
154 {
155 const struct process_attr_value *value_key = (process_attr_value *) key;
156 const struct process_attr_tracker_value_node *value_node =
157 caa_container_of(node,
158 struct process_attr_tracker_value_node,
159 inclusion_set_ht_node);
160
161 return process_attr_tracker_value_equal(value_node->value, value_key);
162 }
163
164 static struct process_attr_tracker_value_node *process_attr_tracker_lookup(
165 const struct process_attr_tracker *tracker,
166 const struct process_attr_value *value)
167 {
168 struct cds_lfht_iter iter;
169 struct cds_lfht_node *node;
170
171 LTTNG_ASSERT(tracker->policy == LTTNG_TRACKING_POLICY_INCLUDE_SET);
172
173 rcu_read_lock();
174 cds_lfht_lookup(tracker->inclusion_set_ht,
175 process_attr_value_hash(value),
176 match_inclusion_set_value, value, &iter);
177 node = cds_lfht_iter_get_node(&iter);
178 rcu_read_unlock();
179
180 return node ? container_of(node, struct process_attr_tracker_value_node,
181 inclusion_set_ht_node) :
182 NULL;
183 }
184
185 /* Protected by session mutex held by caller. */
186 enum process_attr_tracker_status process_attr_tracker_inclusion_set_add_value(
187 struct process_attr_tracker *tracker,
188 const struct process_attr_value *value)
189 {
190 enum process_attr_tracker_status status =
191 PROCESS_ATTR_TRACKER_STATUS_OK;
192 struct process_attr_value *value_copy = NULL;
193 struct process_attr_tracker_value_node *value_node = NULL;
194
195 rcu_read_lock();
196 if (tracker->policy != LTTNG_TRACKING_POLICY_INCLUDE_SET) {
197 status = PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY;
198 goto end;
199 }
200
201 if (process_attr_tracker_lookup(tracker, value)) {
202 status = PROCESS_ATTR_TRACKER_STATUS_EXISTS;
203 goto end;
204 }
205
206 value_node = zmalloc<process_attr_tracker_value_node>();
207 if (!value_node) {
208 status = PROCESS_ATTR_TRACKER_STATUS_ERROR;
209 goto end;
210 }
211
212 value_copy = process_attr_value_copy(value);
213 if (!value_copy) {
214 status = PROCESS_ATTR_TRACKER_STATUS_ERROR;
215 goto end;
216 }
217
218 value_node->value = value_copy;
219 cds_lfht_add(tracker->inclusion_set_ht,
220 process_attr_value_hash(value_copy),
221 &value_node->inclusion_set_ht_node);
222 value_copy = NULL;
223 value_node = NULL;
224 end:
225 if (value_copy) {
226 process_attr_value_destroy(value_copy);
227 }
228 if (value_node) {
229 free(value_node);
230 }
231 rcu_read_unlock();
232 return status;
233 }
234
235 /* Protected by session mutex held by caller. */
236 enum process_attr_tracker_status
237 process_attr_tracker_inclusion_set_remove_value(
238 struct process_attr_tracker *tracker,
239 const struct process_attr_value *value)
240 {
241 struct process_attr_tracker_value_node *value_node;
242 enum process_attr_tracker_status status =
243 PROCESS_ATTR_TRACKER_STATUS_OK;
244
245 rcu_read_lock();
246 if (tracker->policy != LTTNG_TRACKING_POLICY_INCLUDE_SET) {
247 status = PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY;
248 goto end;
249 }
250
251 value_node = process_attr_tracker_lookup(tracker, value);
252 if (!value_node) {
253 status = PROCESS_ATTR_TRACKER_STATUS_MISSING;
254 goto end;
255 }
256
257 process_attr_tracker_remove_value_node(tracker, value_node);
258 end:
259 rcu_read_unlock();
260 return status;
261 }
262
263 enum process_attr_tracker_status process_attr_tracker_get_inclusion_set(
264 const struct process_attr_tracker *tracker,
265 struct lttng_process_attr_values **_values)
266 {
267 struct lttng_ht_iter iter;
268 struct process_attr_tracker_value_node *value_node;
269 enum process_attr_tracker_status status =
270 PROCESS_ATTR_TRACKER_STATUS_OK;
271 struct lttng_process_attr_values *values;
272 struct process_attr_value *new_value = NULL;
273
274 values = lttng_process_attr_values_create();
275 if (!values) {
276 status = PROCESS_ATTR_TRACKER_STATUS_ERROR;
277 goto error;
278 }
279
280 if (tracker->policy != LTTNG_TRACKING_POLICY_INCLUDE_SET) {
281 status = PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY;
282 goto error;
283 }
284
285 rcu_read_lock();
286 cds_lfht_for_each_entry (tracker->inclusion_set_ht, &iter.iter,
287 value_node, inclusion_set_ht_node) {
288 int ret;
289
290 new_value = process_attr_value_copy(value_node->value);
291 if (!new_value) {
292 status = PROCESS_ATTR_TRACKER_STATUS_ERROR;
293 goto error_unlock;
294 }
295
296 ret = lttng_dynamic_pointer_array_add_pointer(
297 &values->array, new_value);
298 if (ret) {
299 status = PROCESS_ATTR_TRACKER_STATUS_ERROR;
300 goto error_unlock;
301 }
302
303 new_value = NULL;
304 }
305 rcu_read_unlock();
306 *_values = values;
307 return status;
308 error_unlock:
309 rcu_read_unlock();
310 error:
311 lttng_process_attr_values_destroy(values);
312 process_attr_value_destroy(new_value);
313 return status;
314 }
This page took 0.03551 seconds and 4 git commands to generate.