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