Refactoring: type description structures
[lttng-modules.git] / src / lttng-context.c
1 /* SPDX-License-Identifier: (GPL-2.0-only or LGPL-2.1-only)
2 *
3 * lttng-context.c
4 *
5 * LTTng trace/channel/event context management.
6 *
7 * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 */
9
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/events-internal.h>
17 #include <lttng/tracer.h>
18
19 /*
20 * The filter implementation requires that two consecutive "get" for the
21 * same context performed by the same thread return the same result.
22 */
23
24 /*
25 * Static array of contexts, for $ctx filters.
26 */
27 struct lttng_kernel_ctx *lttng_static_ctx;
28
29 int lttng_kernel_find_context(struct lttng_kernel_ctx *ctx, const char *name)
30 {
31 unsigned int i;
32 const char *subname;
33
34 if (!ctx)
35 return 0;
36 if (strncmp(name, "$ctx.", strlen("$ctx.")) == 0) {
37 subname = name + strlen("$ctx.");
38 } else {
39 subname = name;
40 }
41 for (i = 0; i < ctx->nr_fields; i++) {
42 /* Skip allocated (but non-initialized) contexts */
43 if (!ctx->fields[i].event_field->name)
44 continue;
45 if (!strcmp(ctx->fields[i].event_field->name, subname))
46 return 1;
47 }
48 return 0;
49 }
50 EXPORT_SYMBOL_GPL(lttng_kernel_find_context);
51
52 int lttng_kernel_get_context_index(struct lttng_kernel_ctx *ctx, const char *name)
53 {
54 unsigned int i;
55 const char *subname;
56
57 if (!ctx)
58 return -1;
59 if (strncmp(name, "$ctx.", strlen("$ctx.")) == 0) {
60 subname = name + strlen("$ctx.");
61 } else {
62 subname = name;
63 }
64 for (i = 0; i < ctx->nr_fields; i++) {
65 /* Skip allocated (but non-initialized) contexts */
66 if (!ctx->fields[i].event_field->name)
67 continue;
68 if (!strcmp(ctx->fields[i].event_field->name, subname))
69 return i;
70 }
71 return -1;
72 }
73 EXPORT_SYMBOL_GPL(lttng_kernel_get_context_index);
74
75 struct lttng_kernel_ctx_field *lttng_kernel_get_context_field_from_index(struct lttng_kernel_ctx *ctx,
76 size_t index)
77 {
78 if (index >= ctx->nr_fields)
79 return NULL;
80 return &ctx->fields[index];
81 }
82 EXPORT_SYMBOL_GPL(lttng_kernel_get_context_field_from_index);
83
84 /*
85 * Note: as we append context information, the pointer location may change.
86 * lttng_kernel_context_add_field leaves the new last context initialized to NULL.
87 */
88 static
89 int lttng_kernel_context_add_field(struct lttng_kernel_ctx **ctx_p)
90 {
91 struct lttng_kernel_ctx *ctx;
92
93 if (!*ctx_p) {
94 *ctx_p = kzalloc(sizeof(struct lttng_kernel_ctx), GFP_KERNEL);
95 if (!*ctx_p)
96 return -ENOMEM;
97 (*ctx_p)->largest_align = 1;
98 }
99 ctx = *ctx_p;
100 if (ctx->nr_fields + 1 > ctx->allocated_fields) {
101 struct lttng_kernel_ctx_field *new_fields;
102
103 ctx->allocated_fields = max_t(size_t, 1, 2 * ctx->allocated_fields);
104 new_fields = lttng_kvzalloc(ctx->allocated_fields * sizeof(*new_fields), GFP_KERNEL);
105 if (!new_fields)
106 return -ENOMEM;
107 if (ctx->fields)
108 memcpy(new_fields, ctx->fields, sizeof(*ctx->fields) * ctx->nr_fields);
109 lttng_kvfree(ctx->fields);
110 ctx->fields = new_fields;
111 }
112 ctx->nr_fields++;
113 return 0;
114 }
115
116 static size_t get_type_max_align(const struct lttng_kernel_type_common *type)
117 {
118 switch (type->type) {
119 case lttng_kernel_type_integer:
120 return lttng_kernel_get_type_integer(type)->alignment;
121 case lttng_kernel_type_string:
122 return CHAR_BIT;
123 case lttng_kernel_type_enum:
124 return get_type_max_align(lttng_kernel_get_type_enum(type)->container_type);
125 case lttng_kernel_type_array:
126 return max_t(size_t, get_type_max_align(lttng_kernel_get_type_array(type)->elem_type),
127 lttng_kernel_get_type_array(type)->alignment);
128 case lttng_kernel_type_sequence:
129 return max_t(size_t, get_type_max_align(lttng_kernel_get_type_sequence(type)->elem_type),
130 lttng_kernel_get_type_sequence(type)->alignment);
131 case lttng_kernel_type_struct:
132 {
133 unsigned int i;
134 size_t field_align = 0;
135 const struct lttng_kernel_type_struct *struct_type = lttng_kernel_get_type_struct(type);
136
137 for (i = 0; i < struct_type->nr_fields; i++) {
138 field_align = max_t(size_t,
139 get_type_max_align(struct_type->fields[i]->type),
140 field_align);
141 }
142 return field_align;
143 }
144 case lttng_kernel_type_variant:
145 /* Variants are not accounted in the overall alignment of the type they are embedded in. */
146 return 0;
147 default:
148 WARN_ON_ONCE(1);
149 return 0;
150 }
151 }
152
153 /*
154 * lttng_context_update() should be called at least once between context
155 * modification and trace start.
156 */
157 static
158 void lttng_context_update(struct lttng_kernel_ctx *ctx)
159 {
160 int i;
161 size_t largest_align = 8; /* in bits */
162
163 for (i = 0; i < ctx->nr_fields; i++) {
164 size_t field_align = 8;
165
166 field_align = get_type_max_align(ctx->fields[i].event_field->type);
167 largest_align = max_t(size_t, largest_align, field_align);
168 }
169 ctx->largest_align = largest_align >> 3; /* bits to bytes */
170 }
171
172 int lttng_kernel_context_append(struct lttng_kernel_ctx **ctx_p,
173 const struct lttng_kernel_ctx_field *f)
174 {
175 int ret;
176
177 ret = lttng_kernel_context_add_field(ctx_p);
178 if (ret)
179 return ret;
180 (*ctx_p)->fields[(*ctx_p)->nr_fields - 1] = *f;
181 lttng_context_update(*ctx_p);
182 return 0;
183 }
184
185 void lttng_kernel_context_remove_last(struct lttng_kernel_ctx **ctx_p)
186 {
187 struct lttng_kernel_ctx *ctx = *ctx_p;
188
189 if (!ctx->nr_fields)
190 return;
191 memset(&ctx->fields[ctx->nr_fields - 1], 0, sizeof(struct lttng_kernel_ctx_field));
192 ctx->nr_fields--;
193 lttng_context_update(ctx);
194 }
195
196 void lttng_kernel_destroy_context(struct lttng_kernel_ctx *ctx)
197 {
198 int i;
199
200 if (!ctx)
201 return;
202 for (i = 0; i < ctx->nr_fields; i++) {
203 if (ctx->fields[i].destroy)
204 ctx->fields[i].destroy(&ctx->fields[i]);
205 }
206 lttng_kvfree(ctx->fields);
207 kfree(ctx);
208 }
209
210 int lttng_context_init(void)
211 {
212 int ret;
213
214 ret = lttng_add_hostname_to_ctx(&lttng_static_ctx);
215 if (ret) {
216 printk(KERN_WARNING "LTTng: Cannot add context lttng_add_hostname_to_ctx");
217 }
218 ret = lttng_add_nice_to_ctx(&lttng_static_ctx);
219 if (ret) {
220 printk(KERN_WARNING "LTTng: Cannot add context lttng_add_nice_to_ctx");
221 }
222 ret = lttng_add_pid_to_ctx(&lttng_static_ctx);
223 if (ret) {
224 printk(KERN_WARNING "LTTng: Cannot add context lttng_add_pid_to_ctx");
225 }
226 ret = lttng_add_ppid_to_ctx(&lttng_static_ctx);
227 if (ret) {
228 printk(KERN_WARNING "LTTng: Cannot add context lttng_add_ppid_to_ctx");
229 }
230 ret = lttng_add_prio_to_ctx(&lttng_static_ctx);
231 if (ret) {
232 printk(KERN_WARNING "LTTng: Cannot add context lttng_add_prio_to_ctx");
233 }
234 ret = lttng_add_procname_to_ctx(&lttng_static_ctx);
235 if (ret) {
236 printk(KERN_WARNING "LTTng: Cannot add context lttng_add_procname_to_ctx");
237 }
238 ret = lttng_add_tid_to_ctx(&lttng_static_ctx);
239 if (ret) {
240 printk(KERN_WARNING "LTTng: Cannot add context lttng_add_tid_to_ctx");
241 }
242 ret = lttng_add_vppid_to_ctx(&lttng_static_ctx);
243 if (ret) {
244 printk(KERN_WARNING "LTTng: Cannot add context lttng_add_vppid_to_ctx");
245 }
246 ret = lttng_add_vtid_to_ctx(&lttng_static_ctx);
247 if (ret) {
248 printk(KERN_WARNING "LTTng: Cannot add context lttng_add_vtid_to_ctx");
249 }
250 ret = lttng_add_vpid_to_ctx(&lttng_static_ctx);
251 if (ret) {
252 printk(KERN_WARNING "LTTng: Cannot add context lttng_add_vpid_to_ctx");
253 }
254 ret = lttng_add_cpu_id_to_ctx(&lttng_static_ctx);
255 if (ret) {
256 printk(KERN_WARNING "LTTng: Cannot add context lttng_add_cpu_id_to_ctx");
257 }
258 ret = lttng_add_interruptible_to_ctx(&lttng_static_ctx);
259 if (ret) {
260 printk(KERN_WARNING "LTTng: Cannot add context lttng_add_interruptible_to_ctx");
261 }
262 ret = lttng_add_need_reschedule_to_ctx(&lttng_static_ctx);
263 if (ret) {
264 printk(KERN_WARNING "LTTng: Cannot add context lttng_add_need_reschedule_to_ctx");
265 }
266 ret = lttng_add_preemptible_to_ctx(&lttng_static_ctx);
267 if (ret && ret != -ENOSYS) {
268 printk(KERN_WARNING "LTTng: Cannot add context lttng_add_preemptible_to_ctx");
269 }
270 ret = lttng_add_migratable_to_ctx(&lttng_static_ctx);
271 if (ret && ret != -ENOSYS) {
272 printk(KERN_WARNING "LTTng: Cannot add context lttng_add_migratable_to_ctx");
273 }
274 ret = lttng_add_cgroup_ns_to_ctx(&lttng_static_ctx);
275 if (ret && ret != -ENOSYS) {
276 printk(KERN_WARNING "LTTng: Cannot add context lttng_add_cgroup_ns_to_ctx");
277 }
278 ret = lttng_add_ipc_ns_to_ctx(&lttng_static_ctx);
279 if (ret && ret != -ENOSYS) {
280 printk(KERN_WARNING "LTTng: Cannot add context lttng_add_ipc_ns_to_ctx");
281 }
282 ret = lttng_add_mnt_ns_to_ctx(&lttng_static_ctx);
283 if (ret && ret != -ENOSYS) {
284 printk(KERN_WARNING "LTTng: Cannot add context lttng_add_mnt_ns_to_ctx");
285 }
286 ret = lttng_add_net_ns_to_ctx(&lttng_static_ctx);
287 if (ret && ret != -ENOSYS) {
288 printk(KERN_WARNING "LTTng: Cannot add context lttng_add_net_ns_to_ctx");
289 }
290 ret = lttng_add_pid_ns_to_ctx(&lttng_static_ctx);
291 if (ret && ret != -ENOSYS) {
292 printk(KERN_WARNING "LTTng: Cannot add context lttng_add_pid_ns_to_ctx");
293 }
294 ret = lttng_add_user_ns_to_ctx(&lttng_static_ctx);
295 if (ret && ret != -ENOSYS) {
296 printk(KERN_WARNING "LTTng: Cannot add context lttng_add_user_ns_to_ctx");
297 }
298 ret = lttng_add_uts_ns_to_ctx(&lttng_static_ctx);
299 if (ret && ret != -ENOSYS) {
300 printk(KERN_WARNING "LTTng: Cannot add context lttng_add_uts_ns_to_ctx");
301 }
302 ret = lttng_add_time_ns_to_ctx(&lttng_static_ctx);
303 if (ret && ret != -ENOSYS) {
304 printk(KERN_WARNING "LTTng: Cannot add context lttng_add_time_ns_to_ctx");
305 }
306 /* TODO: perf counters for filtering */
307 return 0;
308 }
309
310 void lttng_context_exit(void)
311 {
312 lttng_kernel_destroy_context(lttng_static_ctx);
313 lttng_static_ctx = NULL;
314 }
This page took 0.035992 seconds and 4 git commands to generate.