2 * Copyright (C) 2018 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
3 * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 * SPDX-License-Identifier: GPL-2.0-only
9 #include "lttng/tracker.h"
10 #include "common/dynamic-array.hpp"
11 #include "common/macros.hpp"
15 #include <sys/types.h>
18 #include <urcu/list.h>
19 #include <urcu/rculfhash.h>
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>
29 struct process_attr_tracker
{
30 enum lttng_tracking_policy policy
;
31 struct cds_lfht
*inclusion_set_ht
;
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
;
42 static void process_attr_tracker_value_node_rcu_free(struct rcu_head
*rcu_head
)
44 struct process_attr_tracker_value_node
*node
= lttng::utils::container_of(
45 rcu_head
, &process_attr_tracker_value_node::rcu_head
);
50 struct process_attr_tracker
*process_attr_tracker_create(void)
52 struct process_attr_tracker
*tracker
;
54 tracker
= zmalloc
<process_attr_tracker
>();
59 (void) process_attr_tracker_set_tracking_policy(
60 tracker
, LTTNG_TRACKING_POLICY_INCLUDE_ALL
);
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
) {
70 process_attr_tracker_destroy(tracker
);
74 static void process_attr_tracker_remove_value_node(
75 struct process_attr_tracker
*tracker
,
76 struct process_attr_tracker_value_node
*value_node
)
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
);
85 static void process_attr_tracker_clear_inclusion_set(
86 struct process_attr_tracker
*tracker
)
89 struct lttng_ht_iter iter
;
90 struct process_attr_tracker_value_node
*value_node
;
92 if (!tracker
->inclusion_set_ht
) {
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
);
102 ret
= cds_lfht_destroy(tracker
->inclusion_set_ht
, NULL
);
103 LTTNG_ASSERT(ret
== 0);
104 tracker
->inclusion_set_ht
= NULL
;
107 static int process_attr_tracker_create_inclusion_set(
108 struct process_attr_tracker
*tracker
)
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;
116 void process_attr_tracker_destroy(struct process_attr_tracker
*tracker
)
122 process_attr_tracker_clear_inclusion_set(tracker
);
126 enum lttng_tracking_policy
process_attr_tracker_get_tracking_policy(
127 const struct process_attr_tracker
*tracker
)
129 return tracker
->policy
;
132 int process_attr_tracker_set_tracking_policy(
133 struct process_attr_tracker
*tracker
,
134 enum lttng_tracking_policy tracking_policy
)
138 if (tracker
->policy
== tracking_policy
) {
142 process_attr_tracker_clear_inclusion_set(tracker
);
143 ret
= process_attr_tracker_create_inclusion_set(tracker
);
147 tracker
->policy
= tracking_policy
;
152 static int match_inclusion_set_value(
153 struct cds_lfht_node
*node
, const void *key
)
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
);
161 return process_attr_tracker_value_equal(value_node
->value
, value_key
);
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
)
168 struct cds_lfht_iter iter
;
169 struct cds_lfht_node
*node
;
171 LTTNG_ASSERT(tracker
->policy
== LTTNG_TRACKING_POLICY_INCLUDE_SET
);
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
);
180 return node
? lttng::utils::container_of(node
,
181 &process_attr_tracker_value_node::inclusion_set_ht_node
) :
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
)
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
;
196 if (tracker
->policy
!= LTTNG_TRACKING_POLICY_INCLUDE_SET
) {
197 status
= PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY
;
201 if (process_attr_tracker_lookup(tracker
, value
)) {
202 status
= PROCESS_ATTR_TRACKER_STATUS_EXISTS
;
206 value_node
= zmalloc
<process_attr_tracker_value_node
>();
208 status
= PROCESS_ATTR_TRACKER_STATUS_ERROR
;
212 value_copy
= process_attr_value_copy(value
);
214 status
= PROCESS_ATTR_TRACKER_STATUS_ERROR
;
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
);
226 process_attr_value_destroy(value_copy
);
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
)
241 struct process_attr_tracker_value_node
*value_node
;
242 enum process_attr_tracker_status status
=
243 PROCESS_ATTR_TRACKER_STATUS_OK
;
246 if (tracker
->policy
!= LTTNG_TRACKING_POLICY_INCLUDE_SET
) {
247 status
= PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY
;
251 value_node
= process_attr_tracker_lookup(tracker
, value
);
253 status
= PROCESS_ATTR_TRACKER_STATUS_MISSING
;
257 process_attr_tracker_remove_value_node(tracker
, value_node
);
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
)
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
;
274 values
= lttng_process_attr_values_create();
276 status
= PROCESS_ATTR_TRACKER_STATUS_ERROR
;
280 if (tracker
->policy
!= LTTNG_TRACKING_POLICY_INCLUDE_SET
) {
281 status
= PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY
;
286 cds_lfht_for_each_entry (tracker
->inclusion_set_ht
, &iter
.iter
,
287 value_node
, inclusion_set_ht_node
) {
290 new_value
= process_attr_value_copy(value_node
->value
);
292 status
= PROCESS_ATTR_TRACKER_STATUS_ERROR
;
296 ret
= lttng_dynamic_pointer_array_add_pointer(
297 &values
->array
, new_value
);
299 status
= PROCESS_ATTR_TRACKER_STATUS_ERROR
;
311 lttng_process_attr_values_destroy(values
);
312 process_attr_value_destroy(new_value
);