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 "common/dynamic-array.hpp"
10 #include "common/macros.hpp"
11 #include "lttng/tracker.h"
13 #include "tracker.hpp"
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>
21 #include <lttng/lttng-error.h>
25 #include <sys/types.h>
28 #include <urcu/list.h>
29 #include <urcu/rculfhash.h>
31 struct process_attr_tracker
{
32 enum lttng_tracking_policy policy
;
33 struct cds_lfht
*inclusion_set_ht
;
37 struct process_attr_tracker_value_node
{
38 struct process_attr_value
*value
;
39 struct cds_lfht_node inclusion_set_ht_node
;
40 struct rcu_head rcu_head
;
44 static void process_attr_tracker_value_node_rcu_free(struct rcu_head
*rcu_head
)
46 struct process_attr_tracker_value_node
*node
=
47 lttng::utils::container_of(rcu_head
, &process_attr_tracker_value_node::rcu_head
);
52 struct process_attr_tracker
*process_attr_tracker_create()
54 struct process_attr_tracker
*tracker
;
56 tracker
= zmalloc
<process_attr_tracker
>();
61 (void) process_attr_tracker_set_tracking_policy(tracker
, LTTNG_TRACKING_POLICY_INCLUDE_ALL
);
63 tracker
->inclusion_set_ht
= cds_lfht_new(
64 DEFAULT_HT_SIZE
, 1, 0, CDS_LFHT_AUTO_RESIZE
| CDS_LFHT_ACCOUNTING
, nullptr);
65 if (!tracker
->inclusion_set_ht
) {
71 process_attr_tracker_destroy(tracker
);
76 process_attr_tracker_remove_value_node(struct process_attr_tracker
*tracker
,
77 struct process_attr_tracker_value_node
*value_node
)
79 cds_lfht_del(tracker
->inclusion_set_ht
, &value_node
->inclusion_set_ht_node
);
80 process_attr_value_destroy(value_node
->value
);
81 call_rcu(&value_node
->rcu_head
, process_attr_tracker_value_node_rcu_free
);
84 static void process_attr_tracker_clear_inclusion_set(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 (
96 tracker
->inclusion_set_ht
, &iter
.iter
, 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
, nullptr);
101 LTTNG_ASSERT(ret
== 0);
102 tracker
->inclusion_set_ht
= nullptr;
105 static int process_attr_tracker_create_inclusion_set(struct process_attr_tracker
*tracker
)
107 LTTNG_ASSERT(!tracker
->inclusion_set_ht
);
108 tracker
->inclusion_set_ht
= cds_lfht_new(
109 DEFAULT_HT_SIZE
, 1, 0, CDS_LFHT_AUTO_RESIZE
| CDS_LFHT_ACCOUNTING
, nullptr);
110 return tracker
->inclusion_set_ht
? 0 : -1;
113 void process_attr_tracker_destroy(struct process_attr_tracker
*tracker
)
119 process_attr_tracker_clear_inclusion_set(tracker
);
123 enum lttng_tracking_policy
124 process_attr_tracker_get_tracking_policy(const struct process_attr_tracker
*tracker
)
126 return tracker
->policy
;
129 int process_attr_tracker_set_tracking_policy(struct process_attr_tracker
*tracker
,
130 enum lttng_tracking_policy tracking_policy
)
134 if (tracker
->policy
== tracking_policy
) {
138 process_attr_tracker_clear_inclusion_set(tracker
);
139 ret
= process_attr_tracker_create_inclusion_set(tracker
);
143 tracker
->policy
= tracking_policy
;
148 static int match_inclusion_set_value(struct cds_lfht_node
*node
, const void *key
)
150 const struct process_attr_value
*value_key
= (process_attr_value
*) key
;
151 const struct process_attr_tracker_value_node
*value_node
= caa_container_of(
152 node
, struct process_attr_tracker_value_node
, inclusion_set_ht_node
);
154 return process_attr_tracker_value_equal(value_node
->value
, value_key
);
157 static struct process_attr_tracker_value_node
*
158 process_attr_tracker_lookup(const struct process_attr_tracker
*tracker
,
159 const struct process_attr_value
*value
)
161 struct cds_lfht_iter iter
;
162 struct cds_lfht_node
*node
;
164 LTTNG_ASSERT(tracker
->policy
== LTTNG_TRACKING_POLICY_INCLUDE_SET
);
167 cds_lfht_lookup(tracker
->inclusion_set_ht
,
168 process_attr_value_hash(value
),
169 match_inclusion_set_value
,
172 node
= cds_lfht_iter_get_node(&iter
);
175 return node
? lttng::utils::container_of(
176 node
, &process_attr_tracker_value_node::inclusion_set_ht_node
) :
180 /* Protected by session mutex held by caller. */
181 enum process_attr_tracker_status
182 process_attr_tracker_inclusion_set_add_value(struct process_attr_tracker
*tracker
,
183 const struct process_attr_value
*value
)
185 enum process_attr_tracker_status status
= PROCESS_ATTR_TRACKER_STATUS_OK
;
186 struct process_attr_value
*value_copy
= nullptr;
187 struct process_attr_tracker_value_node
*value_node
= nullptr;
190 if (tracker
->policy
!= LTTNG_TRACKING_POLICY_INCLUDE_SET
) {
191 status
= PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY
;
195 if (process_attr_tracker_lookup(tracker
, value
)) {
196 status
= PROCESS_ATTR_TRACKER_STATUS_EXISTS
;
200 value_node
= zmalloc
<process_attr_tracker_value_node
>();
202 status
= PROCESS_ATTR_TRACKER_STATUS_ERROR
;
206 value_copy
= process_attr_value_copy(value
);
208 status
= PROCESS_ATTR_TRACKER_STATUS_ERROR
;
212 value_node
->value
= value_copy
;
213 cds_lfht_add(tracker
->inclusion_set_ht
,
214 process_attr_value_hash(value_copy
),
215 &value_node
->inclusion_set_ht_node
);
216 value_copy
= nullptr;
217 value_node
= nullptr;
220 process_attr_value_destroy(value_copy
);
229 /* Protected by session mutex held by caller. */
230 enum process_attr_tracker_status
231 process_attr_tracker_inclusion_set_remove_value(struct process_attr_tracker
*tracker
,
232 const struct process_attr_value
*value
)
234 struct process_attr_tracker_value_node
*value_node
;
235 enum process_attr_tracker_status status
= PROCESS_ATTR_TRACKER_STATUS_OK
;
238 if (tracker
->policy
!= LTTNG_TRACKING_POLICY_INCLUDE_SET
) {
239 status
= PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY
;
243 value_node
= process_attr_tracker_lookup(tracker
, value
);
245 status
= PROCESS_ATTR_TRACKER_STATUS_MISSING
;
249 process_attr_tracker_remove_value_node(tracker
, value_node
);
255 enum process_attr_tracker_status
256 process_attr_tracker_get_inclusion_set(const struct process_attr_tracker
*tracker
,
257 struct lttng_process_attr_values
**_values
)
259 struct lttng_ht_iter iter
;
260 struct process_attr_tracker_value_node
*value_node
;
261 enum process_attr_tracker_status status
= PROCESS_ATTR_TRACKER_STATUS_OK
;
262 struct lttng_process_attr_values
*values
;
263 struct process_attr_value
*new_value
= nullptr;
265 values
= lttng_process_attr_values_create();
267 status
= PROCESS_ATTR_TRACKER_STATUS_ERROR
;
271 if (tracker
->policy
!= LTTNG_TRACKING_POLICY_INCLUDE_SET
) {
272 status
= PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY
;
277 cds_lfht_for_each_entry (
278 tracker
->inclusion_set_ht
, &iter
.iter
, value_node
, inclusion_set_ht_node
) {
281 new_value
= process_attr_value_copy(value_node
->value
);
283 status
= PROCESS_ATTR_TRACKER_STATUS_ERROR
;
287 ret
= lttng_dynamic_pointer_array_add_pointer(&values
->array
, new_value
);
289 status
= PROCESS_ATTR_TRACKER_STATUS_ERROR
;
301 lttng_process_attr_values_destroy(values
);
302 process_attr_value_destroy(new_value
);