1 /* SPDX-License-Identifier: (GPL-2.0-only or LGPL-2.1-only)
5 * LTTng trace/channel/event context management.
7 * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
10 #include <linux/module.h>
11 #include <linux/list.h>
12 #include <linux/mutex.h>
13 #include <linux/slab.h>
14 #include <wrapper/vmalloc.h> /* for wrapper_vmalloc_sync_mappings() */
15 #include <lttng-events.h>
16 #include <lttng-tracer.h>
19 * The filter implementation requires that two consecutive "get" for the
20 * same context performed by the same thread return the same result.
24 * Static array of contexts, for $ctx filters.
26 struct lttng_ctx
*lttng_static_ctx
;
28 int lttng_find_context(struct lttng_ctx
*ctx
, const char *name
)
32 for (i
= 0; i
< ctx
->nr_fields
; i
++) {
33 /* Skip allocated (but non-initialized) contexts */
34 if (!ctx
->fields
[i
].event_field
.name
)
36 if (!strcmp(ctx
->fields
[i
].event_field
.name
, name
))
41 EXPORT_SYMBOL_GPL(lttng_find_context
);
43 int lttng_get_context_index(struct lttng_ctx
*ctx
, const char *name
)
50 if (strncmp(name
, "$ctx.", strlen("$ctx.")) == 0) {
51 subname
= name
+ strlen("$ctx.");
55 for (i
= 0; i
< ctx
->nr_fields
; i
++) {
56 /* Skip allocated (but non-initialized) contexts */
57 if (!ctx
->fields
[i
].event_field
.name
)
59 if (!strcmp(ctx
->fields
[i
].event_field
.name
, subname
))
64 EXPORT_SYMBOL_GPL(lttng_get_context_index
);
67 * Note: as we append context information, the pointer location may change.
69 struct lttng_ctx_field
*lttng_append_context(struct lttng_ctx
**ctx_p
)
71 struct lttng_ctx_field
*field
;
72 struct lttng_ctx
*ctx
;
75 *ctx_p
= kzalloc(sizeof(struct lttng_ctx
), GFP_KERNEL
);
78 (*ctx_p
)->largest_align
= 1;
81 if (ctx
->nr_fields
+ 1 > ctx
->allocated_fields
) {
82 struct lttng_ctx_field
*new_fields
;
84 ctx
->allocated_fields
= max_t(size_t, 1, 2 * ctx
->allocated_fields
);
85 new_fields
= lttng_kvzalloc(ctx
->allocated_fields
* sizeof(struct lttng_ctx_field
), GFP_KERNEL
);
89 memcpy(new_fields
, ctx
->fields
, sizeof(*ctx
->fields
) * ctx
->nr_fields
);
90 lttng_kvfree(ctx
->fields
);
91 ctx
->fields
= new_fields
;
93 field
= &ctx
->fields
[ctx
->nr_fields
];
97 EXPORT_SYMBOL_GPL(lttng_append_context
);
100 * lttng_context_update() should be called at least once between context
101 * modification and trace start.
103 void lttng_context_update(struct lttng_ctx
*ctx
)
106 size_t largest_align
= 8; /* in bits */
108 for (i
= 0; i
< ctx
->nr_fields
; i
++) {
109 struct lttng_type
*type
;
110 size_t field_align
= 8;
112 type
= &ctx
->fields
[i
].event_field
.type
;
113 switch (type
->atype
) {
115 field_align
= type
->u
.integer
.alignment
;
117 case atype_array_nestable
:
119 const struct lttng_type
*nested_type
;
121 nested_type
= type
->u
.array_nestable
.elem_type
;
122 switch (nested_type
->atype
) {
124 field_align
= nested_type
->u
.integer
.alignment
;
129 case atype_array_nestable
:
130 case atype_sequence_nestable
:
131 case atype_struct_nestable
:
132 case atype_variant_nestable
:
137 field_align
= max_t(size_t, field_align
,
138 type
->u
.array_nestable
.alignment
);
141 case atype_sequence_nestable
:
143 const struct lttng_type
*nested_type
;
145 nested_type
= type
->u
.sequence_nestable
.elem_type
;
146 switch (nested_type
->atype
) {
148 field_align
= nested_type
->u
.integer
.alignment
;
154 case atype_array_nestable
:
155 case atype_sequence_nestable
:
156 case atype_struct_nestable
:
157 case atype_variant_nestable
:
162 field_align
= max_t(size_t, field_align
,
163 type
->u
.sequence_nestable
.alignment
);
169 case atype_struct_nestable
:
170 case atype_variant_nestable
:
173 case atype_enum_nestable
:
178 largest_align
= max_t(size_t, largest_align
, field_align
);
180 ctx
->largest_align
= largest_align
>> 3; /* bits to bytes */
184 * Remove last context field.
186 void lttng_remove_context_field(struct lttng_ctx
**ctx_p
,
187 struct lttng_ctx_field
*field
)
189 struct lttng_ctx
*ctx
;
193 WARN_ON_ONCE(&ctx
->fields
[ctx
->nr_fields
] != field
);
194 memset(&ctx
->fields
[ctx
->nr_fields
], 0, sizeof(struct lttng_ctx_field
));
196 EXPORT_SYMBOL_GPL(lttng_remove_context_field
);
198 void lttng_destroy_context(struct lttng_ctx
*ctx
)
204 for (i
= 0; i
< ctx
->nr_fields
; i
++) {
205 if (ctx
->fields
[i
].destroy
)
206 ctx
->fields
[i
].destroy(&ctx
->fields
[i
]);
208 lttng_kvfree(ctx
->fields
);
212 int lttng_context_init(void)
216 ret
= lttng_add_hostname_to_ctx(<tng_static_ctx
);
218 printk(KERN_WARNING
"Cannot add context lttng_add_hostname_to_ctx");
220 ret
= lttng_add_nice_to_ctx(<tng_static_ctx
);
222 printk(KERN_WARNING
"Cannot add context lttng_add_nice_to_ctx");
224 ret
= lttng_add_pid_to_ctx(<tng_static_ctx
);
226 printk(KERN_WARNING
"Cannot add context lttng_add_pid_to_ctx");
228 ret
= lttng_add_ppid_to_ctx(<tng_static_ctx
);
230 printk(KERN_WARNING
"Cannot add context lttng_add_ppid_to_ctx");
232 ret
= lttng_add_prio_to_ctx(<tng_static_ctx
);
234 printk(KERN_WARNING
"Cannot add context lttng_add_prio_to_ctx");
236 ret
= lttng_add_procname_to_ctx(<tng_static_ctx
);
238 printk(KERN_WARNING
"Cannot add context lttng_add_procname_to_ctx");
240 ret
= lttng_add_tid_to_ctx(<tng_static_ctx
);
242 printk(KERN_WARNING
"Cannot add context lttng_add_tid_to_ctx");
244 ret
= lttng_add_vppid_to_ctx(<tng_static_ctx
);
246 printk(KERN_WARNING
"Cannot add context lttng_add_vppid_to_ctx");
248 ret
= lttng_add_vtid_to_ctx(<tng_static_ctx
);
250 printk(KERN_WARNING
"Cannot add context lttng_add_vtid_to_ctx");
252 ret
= lttng_add_vpid_to_ctx(<tng_static_ctx
);
254 printk(KERN_WARNING
"Cannot add context lttng_add_vpid_to_ctx");
256 ret
= lttng_add_cpu_id_to_ctx(<tng_static_ctx
);
258 printk(KERN_WARNING
"Cannot add context lttng_add_cpu_id_to_ctx");
260 ret
= lttng_add_interruptible_to_ctx(<tng_static_ctx
);
262 printk(KERN_WARNING
"Cannot add context lttng_add_interruptible_to_ctx");
264 ret
= lttng_add_need_reschedule_to_ctx(<tng_static_ctx
);
266 printk(KERN_WARNING
"Cannot add context lttng_add_need_reschedule_to_ctx");
268 ret
= lttng_add_preemptible_to_ctx(<tng_static_ctx
);
269 if (ret
&& ret
!= -ENOSYS
) {
270 printk(KERN_WARNING
"Cannot add context lttng_add_preemptible_to_ctx");
272 ret
= lttng_add_migratable_to_ctx(<tng_static_ctx
);
273 if (ret
&& ret
!= -ENOSYS
) {
274 printk(KERN_WARNING
"Cannot add context lttng_add_migratable_to_ctx");
276 ret
= lttng_add_cgroup_ns_to_ctx(<tng_static_ctx
);
277 if (ret
&& ret
!= -ENOSYS
) {
278 printk(KERN_WARNING
"Cannot add context lttng_add_cgroup_ns_to_ctx");
280 ret
= lttng_add_ipc_ns_to_ctx(<tng_static_ctx
);
281 if (ret
&& ret
!= -ENOSYS
) {
282 printk(KERN_WARNING
"Cannot add context lttng_add_ipc_ns_to_ctx");
284 ret
= lttng_add_mnt_ns_to_ctx(<tng_static_ctx
);
285 if (ret
&& ret
!= -ENOSYS
) {
286 printk(KERN_WARNING
"Cannot add context lttng_add_mnt_ns_to_ctx");
288 ret
= lttng_add_net_ns_to_ctx(<tng_static_ctx
);
289 if (ret
&& ret
!= -ENOSYS
) {
290 printk(KERN_WARNING
"Cannot add context lttng_add_net_ns_to_ctx");
292 ret
= lttng_add_pid_ns_to_ctx(<tng_static_ctx
);
293 if (ret
&& ret
!= -ENOSYS
) {
294 printk(KERN_WARNING
"Cannot add context lttng_add_pid_ns_to_ctx");
296 ret
= lttng_add_user_ns_to_ctx(<tng_static_ctx
);
297 if (ret
&& ret
!= -ENOSYS
) {
298 printk(KERN_WARNING
"Cannot add context lttng_add_user_ns_to_ctx");
300 ret
= lttng_add_uts_ns_to_ctx(<tng_static_ctx
);
301 if (ret
&& ret
!= -ENOSYS
) {
302 printk(KERN_WARNING
"Cannot add context lttng_add_uts_ns_to_ctx");
304 /* TODO: perf counters for filtering */
308 void lttng_context_exit(void)
310 lttng_destroy_context(lttng_static_ctx
);
311 lttng_static_ctx
= NULL
;