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.h"
11 #include "common/macros.h"
15 #include <sys/types.h>
18 #include <urcu/list.h>
19 #include <urcu/rculfhash.h>
22 #include <common/defaults.h>
23 #include <common/error.h>
24 #include <common/hashtable/hashtable.h>
25 #include <common/hashtable/utils.h>
26 #include <common/tracker.h>
27 #include <lttng/lttng-error.h>
29 struct process_attr_tracker_value_node
{
30 struct process_attr_value
*value
;
31 struct cds_lfht_node inclusion_set_ht_node
;
32 struct rcu_head rcu_head
;
35 struct process_attr_tracker
{
36 enum lttng_tracking_policy policy
;
37 struct cds_lfht
*inclusion_set_ht
;
40 static void process_attr_tracker_value_node_rcu_free(struct rcu_head
*rcu_head
)
42 struct process_attr_tracker_value_node
*node
=
43 container_of(rcu_head
, typeof(*node
), rcu_head
);
48 struct process_attr_tracker
*process_attr_tracker_create(void)
50 struct process_attr_tracker
*tracker
;
52 tracker
= zmalloc(sizeof(*tracker
));
57 (void) process_attr_tracker_set_tracking_policy(
58 tracker
, LTTNG_TRACKING_POLICY_INCLUDE_ALL
);
60 tracker
->inclusion_set_ht
= cds_lfht_new(DEFAULT_HT_SIZE
, 1, 0,
61 CDS_LFHT_AUTO_RESIZE
| CDS_LFHT_ACCOUNTING
, NULL
);
62 if (!tracker
->inclusion_set_ht
) {
68 process_attr_tracker_destroy(tracker
);
72 static void process_attr_tracker_remove_value_node(
73 struct process_attr_tracker
*tracker
,
74 struct process_attr_tracker_value_node
*value_node
)
76 cds_lfht_del(tracker
->inclusion_set_ht
,
77 &value_node
->inclusion_set_ht_node
);
78 process_attr_value_destroy(value_node
->value
);
79 call_rcu(&value_node
->rcu_head
,
80 process_attr_tracker_value_node_rcu_free
);
83 static void process_attr_tracker_clear_inclusion_set(
84 struct process_attr_tracker
*tracker
)
87 struct lttng_ht_iter iter
;
88 struct process_attr_tracker_value_node
*value_node
;
90 if (!tracker
->inclusion_set_ht
) {
95 cds_lfht_for_each_entry (tracker
->inclusion_set_ht
, &iter
.iter
,
96 value_node
, inclusion_set_ht_node
) {
97 process_attr_tracker_remove_value_node(tracker
, value_node
);
100 ret
= cds_lfht_destroy(tracker
->inclusion_set_ht
, NULL
);
102 tracker
->inclusion_set_ht
= NULL
;
105 static int process_attr_tracker_create_inclusion_set(
106 struct process_attr_tracker
*tracker
)
108 assert(!tracker
->inclusion_set_ht
);
109 tracker
->inclusion_set_ht
= cds_lfht_new(DEFAULT_HT_SIZE
, 1, 0,
110 CDS_LFHT_AUTO_RESIZE
| CDS_LFHT_ACCOUNTING
, NULL
);
111 return tracker
->inclusion_set_ht
? 0 : -1;
114 void process_attr_tracker_destroy(struct process_attr_tracker
*tracker
)
120 process_attr_tracker_clear_inclusion_set(tracker
);
124 enum lttng_tracking_policy
process_attr_tracker_get_tracking_policy(
125 const struct process_attr_tracker
*tracker
)
127 return tracker
->policy
;
130 int process_attr_tracker_set_tracking_policy(
131 struct process_attr_tracker
*tracker
,
132 enum lttng_tracking_policy tracking_policy
)
136 if (tracker
->policy
== tracking_policy
) {
140 process_attr_tracker_clear_inclusion_set(tracker
);
141 ret
= process_attr_tracker_create_inclusion_set(tracker
);
145 tracker
->policy
= tracking_policy
;
150 static int match_inclusion_set_value(
151 struct cds_lfht_node
*node
, const void *key
)
153 const struct process_attr_value
*value_key
= key
;
154 const struct process_attr_tracker_value_node
*value_node
=
155 caa_container_of(node
,
156 struct process_attr_tracker_value_node
,
157 inclusion_set_ht_node
);
159 return process_attr_tracker_value_equal(value_node
->value
, value_key
);
162 static struct process_attr_tracker_value_node
*process_attr_tracker_lookup(
163 const struct process_attr_tracker
*tracker
,
164 const struct process_attr_value
*value
)
166 struct cds_lfht_iter iter
;
167 struct cds_lfht_node
*node
;
169 assert(tracker
->policy
== LTTNG_TRACKING_POLICY_INCLUDE_SET
);
172 cds_lfht_lookup(tracker
->inclusion_set_ht
,
173 process_attr_value_hash(value
),
174 match_inclusion_set_value
, value
, &iter
);
175 node
= cds_lfht_iter_get_node(&iter
);
178 return node
? container_of(node
, struct process_attr_tracker_value_node
,
179 inclusion_set_ht_node
) :
183 /* Protected by session mutex held by caller. */
184 enum process_attr_tracker_status
process_attr_tracker_inclusion_set_add_value(
185 struct process_attr_tracker
*tracker
,
186 const struct process_attr_value
*value
)
188 enum process_attr_tracker_status status
=
189 PROCESS_ATTR_TRACKER_STATUS_OK
;
190 struct process_attr_value
*value_copy
= NULL
;
191 struct process_attr_tracker_value_node
*value_node
= NULL
;
194 if (tracker
->policy
!= LTTNG_TRACKING_POLICY_INCLUDE_SET
) {
195 status
= PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY
;
199 if (process_attr_tracker_lookup(tracker
, value
)) {
200 status
= PROCESS_ATTR_TRACKER_STATUS_EXISTS
;
204 value_node
= zmalloc(sizeof(*value_node
));
206 status
= PROCESS_ATTR_TRACKER_STATUS_ERROR
;
210 value_copy
= process_attr_value_copy(value
);
212 status
= PROCESS_ATTR_TRACKER_STATUS_ERROR
;
216 value_node
->value
= value_copy
;
217 cds_lfht_add(tracker
->inclusion_set_ht
,
218 process_attr_value_hash(value_copy
),
219 &value_node
->inclusion_set_ht_node
);
224 process_attr_value_destroy(value_copy
);
233 /* Protected by session mutex held by caller. */
234 enum process_attr_tracker_status
235 process_attr_tracker_inclusion_set_remove_value(
236 struct process_attr_tracker
*tracker
,
237 const struct process_attr_value
*value
)
239 struct process_attr_tracker_value_node
*value_node
;
240 enum process_attr_tracker_status status
=
241 PROCESS_ATTR_TRACKER_STATUS_OK
;
244 if (tracker
->policy
!= LTTNG_TRACKING_POLICY_INCLUDE_SET
) {
245 status
= PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY
;
249 value_node
= process_attr_tracker_lookup(tracker
, value
);
251 status
= PROCESS_ATTR_TRACKER_STATUS_MISSING
;
255 process_attr_tracker_remove_value_node(tracker
, value_node
);
261 enum process_attr_tracker_status
process_attr_tracker_get_inclusion_set(
262 const struct process_attr_tracker
*tracker
,
263 struct lttng_process_attr_values
**_values
)
265 struct lttng_ht_iter iter
;
266 struct process_attr_tracker_value_node
*value_node
;
267 enum process_attr_tracker_status status
=
268 PROCESS_ATTR_TRACKER_STATUS_OK
;
269 struct lttng_process_attr_values
*values
;
270 struct process_attr_value
*new_value
= NULL
;
272 values
= lttng_process_attr_values_create();
274 status
= PROCESS_ATTR_TRACKER_STATUS_ERROR
;
278 if (tracker
->policy
!= LTTNG_TRACKING_POLICY_INCLUDE_SET
) {
279 status
= PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY
;
284 cds_lfht_for_each_entry (tracker
->inclusion_set_ht
, &iter
.iter
,
285 value_node
, inclusion_set_ht_node
) {
288 new_value
= process_attr_value_copy(value_node
->value
);
290 status
= PROCESS_ATTR_TRACKER_STATUS_ERROR
;
294 ret
= lttng_dynamic_pointer_array_add_pointer(
295 &values
->array
, new_value
);
297 status
= PROCESS_ATTR_TRACKER_STATUS_ERROR
;
309 lttng_process_attr_values_destroy(values
);
310 process_attr_value_destroy(new_value
);