lttng-modules v0.19-stable: setup_trace_write: Fix recursive locking
[lttng-modules.git] / ltt-trace-control.c
CommitLineData
1c8284eb
MD
1/*
2 * LTT trace control module over debugfs.
3 *
4 * Copyright 2008 - Zhaolei <zhaolei@cn.fujitsu.com>
5 *
6 * Copyright 2009 - Gui Jianfeng <guijianfeng@cn.fujitsu.com>
7 * Make mark-control work in debugfs
8 *
9 * Dual LGPL v2.1/GPL v2 license.
10 */
11
12/*
13 * Todo:
14 * Impl read operations for control file to read attributes
15 * Create a README file in ltt control dir, for display help info
16 */
17
18#include <linux/module.h>
19#include <linux/fs.h>
20#include <linux/uaccess.h>
21#include <linux/debugfs.h>
22#include <linux/notifier.h>
23#include <linux/jiffies.h>
24#include <linux/marker.h>
25
26#include "ltt-tracer.h"
27
28#define LTT_CONTROL_DIR "control"
29#define MARKERS_CONTROL_DIR "markers"
30#define LTT_SETUP_TRACE_FILE "setup_trace"
31#define LTT_DESTROY_TRACE_FILE "destroy_trace"
32
33#define LTT_WRITE_MAXLEN (128)
34
35struct dentry *ltt_control_dir, *ltt_setup_trace_file, *ltt_destroy_trace_file,
36 *markers_control_dir;
37
38/*
39 * the traces_lock nests inside control_lock.
40 * control_lock protects the consistency of directories presented in ltt
41 * directory.
42 */
43static DEFINE_MUTEX(control_lock);
44
45/*
46 * big note about locking for marker control files :
47 * If a marker control file is added/removed manually racing with module
48 * load/unload, there may be warning messages appearing, but those two
49 * operations should be able to execute concurrently without any lock
50 * synchronizing their operation one wrt another.
51 * Locking the marker mutex, module mutex and also keeping a mutex here
52 * from mkdir/rmdir _and_ from the notifier called from module load/unload makes
53 * life miserable and just asks for deadlocks.
54 */
55
56/*
57 * lookup a file/dir in parent dir.
58 * only designed to work well for debugfs.
59 * (although it maybe ok for other fs)
60 *
61 * return:
62 * file/dir's dentry on success
63 * NULL on failure
64 */
65static struct dentry *dir_lookup(struct dentry *parent, const char *name)
66{
67 struct qstr q;
68 struct dentry *d;
69
70 q.name = name;
71 q.len = strlen(name);
72 q.hash = full_name_hash(q.name, q.len);
73
74 d = d_lookup(parent, &q);
75 if (d)
76 dput(d);
77
78 return d;
79}
80
81
82static ssize_t alloc_write(struct file *file, const char __user *user_buf,
83 size_t count, loff_t *ppos)
84{
85 int err = 0;
86 int buf_size;
87 char *buf = (char *)__get_free_page(GFP_KERNEL);
88 char *cmd = (char *)__get_free_page(GFP_KERNEL);
89
90 buf_size = min_t(size_t, count, PAGE_SIZE - 1);
91 err = copy_from_user(buf, user_buf, buf_size);
92 if (err)
93 goto err_copy_from_user;
94 buf[buf_size] = 0;
95
96 if (sscanf(buf, "%s", cmd) != 1) {
97 err = -EPERM;
98 goto err_get_cmd;
99 }
100
101 if ((cmd[0] != 'Y' && cmd[0] != 'y' && cmd[0] != '1') || cmd[1]) {
102 err = -EPERM;
103 goto err_bad_cmd;
104 }
105
106 err = ltt_trace_alloc(file->f_dentry->d_parent->d_name.name);
107 if (IS_ERR_VALUE(err)) {
108 printk(KERN_ERR "alloc_write: ltt_trace_alloc failed: %d\n",
109 err);
110 goto err_alloc_trace;
111 }
112
113 free_page((unsigned long)buf);
114 free_page((unsigned long)cmd);
115 return count;
116
117err_alloc_trace:
118err_bad_cmd:
119err_get_cmd:
120err_copy_from_user:
121 free_page((unsigned long)buf);
122 free_page((unsigned long)cmd);
123 return err;
124}
125
126static const struct file_operations ltt_alloc_operations = {
127 .write = alloc_write,
128};
129
130
131static ssize_t enabled_write(struct file *file, const char __user *user_buf,
132 size_t count, loff_t *ppos)
133{
134 int err = 0;
135 int buf_size;
136 char *buf = (char *)__get_free_page(GFP_KERNEL);
137 char *cmd = (char *)__get_free_page(GFP_KERNEL);
138
139 buf_size = min_t(size_t, count, PAGE_SIZE - 1);
140 err = copy_from_user(buf, user_buf, buf_size);
141 if (err)
142 goto err_copy_from_user;
143 buf[buf_size] = 0;
144
145 if (sscanf(buf, "%s", cmd) != 1) {
146 err = -EPERM;
147 goto err_get_cmd;
148 }
149
150 if (cmd[1]) {
151 err = -EPERM;
152 goto err_bad_cmd;
153 }
154
155 switch (cmd[0]) {
156 case 'Y':
157 case 'y':
158 case '1':
159 err = ltt_trace_start(file->f_dentry->d_parent->d_name.name);
160 if (IS_ERR_VALUE(err)) {
161 printk(KERN_ERR
162 "enabled_write: ltt_trace_start failed: %d\n",
163 err);
164 err = -EPERM;
165 goto err_start_trace;
166 }
167 break;
168 case 'N':
169 case 'n':
170 case '0':
171 err = ltt_trace_stop(file->f_dentry->d_parent->d_name.name);
172 if (IS_ERR_VALUE(err)) {
173 printk(KERN_ERR
174 "enabled_write: ltt_trace_stop failed: %d\n",
175 err);
176 err = -EPERM;
177 goto err_stop_trace;
178 }
179 break;
180 default:
181 err = -EPERM;
182 goto err_bad_cmd;
183 }
184
185 free_page((unsigned long)buf);
186 free_page((unsigned long)cmd);
187 return count;
188
189err_stop_trace:
190err_start_trace:
191err_bad_cmd:
192err_get_cmd:
193err_copy_from_user:
194 free_page((unsigned long)buf);
195 free_page((unsigned long)cmd);
196 return err;
197}
198
199static const struct file_operations ltt_enabled_operations = {
200 .write = enabled_write,
201};
202
203
204static ssize_t trans_write(struct file *file, const char __user *user_buf,
205 size_t count, loff_t *ppos)
206{
207 char *buf = (char *)__get_free_page(GFP_KERNEL);
208 char *trans_name = (char *)__get_free_page(GFP_KERNEL);
209 int err = 0;
210 int buf_size;
211
212 buf_size = min_t(size_t, count, PAGE_SIZE - 1);
213 err = copy_from_user(buf, user_buf, buf_size);
214 if (err)
215 goto err_copy_from_user;
216 buf[buf_size] = 0;
217
218 if (sscanf(buf, "%s", trans_name) != 1) {
219 err = -EPERM;
220 goto err_get_transname;
221 }
222
223 err = ltt_trace_set_type(file->f_dentry->d_parent->d_name.name,
224 trans_name);
225 if (IS_ERR_VALUE(err)) {
226 printk(KERN_ERR "trans_write: ltt_trace_set_type failed: %d\n",
227 err);
228 goto err_set_trans;
229 }
230
231 free_page((unsigned long)buf);
232 free_page((unsigned long)trans_name);
233 return count;
234
235err_set_trans:
236err_get_transname:
237err_copy_from_user:
238 free_page((unsigned long)buf);
239 free_page((unsigned long)trans_name);
240 return err;
241}
242
243static const struct file_operations ltt_trans_operations = {
244 .write = trans_write,
245};
246
247
248static ssize_t channel_subbuf_num_write(struct file *file,
249 const char __user *user_buf, size_t count, loff_t *ppos)
250{
251 int err = 0;
252 int buf_size;
253 unsigned int num;
254 const char *channel_name;
255 const char *trace_name;
256 char *buf = (char *)__get_free_page(GFP_KERNEL);
257
258 buf_size = min_t(size_t, count, PAGE_SIZE - 1);
259 err = copy_from_user(buf, user_buf, buf_size);
260 if (err)
261 goto err_copy_from_user;
262 buf[buf_size] = 0;
263
264 if (sscanf(buf, "%u", &num) != 1) {
265 err = -EPERM;
266 goto err_get_number;
267 }
268
269 channel_name = file->f_dentry->d_parent->d_name.name;
270 trace_name = file->f_dentry->d_parent->d_parent->d_parent->d_name.name;
271
272 err = ltt_trace_set_channel_subbufcount(trace_name, channel_name, num);
273 if (IS_ERR_VALUE(err)) {
274 printk(KERN_ERR "channel_subbuf_num_write: "
275 "ltt_trace_set_channel_subbufcount failed: %d\n", err);
276 goto err_set_subbufcount;
277 }
278
279 free_page((unsigned long)buf);
280 return count;
281
282err_set_subbufcount:
283err_get_number:
284err_copy_from_user:
285 free_page((unsigned long)buf);
286 return err;
287}
288
289static const struct file_operations ltt_channel_subbuf_num_operations = {
290 .write = channel_subbuf_num_write,
291};
292
293
294static
295ssize_t channel_subbuf_size_write(struct file *file,
296 const char __user *user_buf,
297 size_t count, loff_t *ppos)
298{
299 int err = 0;
300 int buf_size;
301 unsigned int num;
302 const char *channel_name;
303 const char *trace_name;
304 char *buf = (char *)__get_free_page(GFP_KERNEL);
305
306 buf_size = min_t(size_t, count, PAGE_SIZE - 1);
307 err = copy_from_user(buf, user_buf, buf_size);
308 if (err)
309 goto err_copy_from_user;
310 buf[buf_size] = 0;
311
312 if (sscanf(buf, "%u", &num) != 1) {
313 err = -EPERM;
314 goto err_get_number;
315 }
316
317 channel_name = file->f_dentry->d_parent->d_name.name;
318 trace_name = file->f_dentry->d_parent->d_parent->d_parent->d_name.name;
319
320 err = ltt_trace_set_channel_subbufsize(trace_name, channel_name, num);
321 if (IS_ERR_VALUE(err)) {
322 printk(KERN_ERR "channel_subbuf_size_write: "
323 "ltt_trace_set_channel_subbufsize failed: %d\n", err);
324 goto err_set_subbufsize;
325 }
326
327 free_page((unsigned long)buf);
328 return count;
329
330err_set_subbufsize:
331err_get_number:
332err_copy_from_user:
333 free_page((unsigned long)buf);
334 return err;
335}
336
337static const struct file_operations ltt_channel_subbuf_size_operations = {
338 .write = channel_subbuf_size_write,
339};
340
341static
342ssize_t channel_switch_timer_write(struct file *file,
343 const char __user *user_buf,
344 size_t count, loff_t *ppos)
345{
346 int err = 0;
347 int buf_size;
348 unsigned long num;
349 const char *channel_name;
350 const char *trace_name;
351 char *buf = (char *)__get_free_page(GFP_KERNEL);
352
353 buf_size = min_t(size_t, count, PAGE_SIZE - 1);
354 err = copy_from_user(buf, user_buf, buf_size);
355 if (err)
356 goto err_copy_from_user;
357 buf[buf_size] = 0;
358
359 if (sscanf(buf, "%lu", &num) != 1) {
360 err = -EPERM;
361 goto err_get_number;
362 }
363
364 channel_name = file->f_dentry->d_parent->d_name.name;
365 trace_name = file->f_dentry->d_parent->d_parent->d_parent->d_name.name;
366
367 /* Convert from ms to jiffies */
368 num = msecs_to_jiffies(num);
369
370 err = ltt_trace_set_channel_switch_timer(trace_name, channel_name, num);
371 if (IS_ERR_VALUE(err)) {
372 printk(KERN_ERR "channel_switch_timer_write: "
373 "ltt_trace_set_channel_switch_timer failed: %d\n", err);
374 goto err_set_switch_timer;
375 }
376
377 free_page((unsigned long)buf);
378 return count;
379
380err_set_switch_timer:
381err_get_number:
382err_copy_from_user:
383 free_page((unsigned long)buf);
384 return err;
385}
386
387static struct file_operations ltt_channel_switch_timer_operations = {
388 .write = channel_switch_timer_write,
389};
390
391static
392ssize_t channel_overwrite_write(struct file *file,
393 const char __user *user_buf, size_t count,
394 loff_t *ppos)
395{
396 int err = 0;
397 int buf_size;
398 const char *channel_name;
399 const char *trace_name;
400 char *buf = (char *)__get_free_page(GFP_KERNEL);
401 char *cmd = (char *)__get_free_page(GFP_KERNEL);
402
403 buf_size = min_t(size_t, count, PAGE_SIZE - 1);
404 err = copy_from_user(buf, user_buf, buf_size);
405 if (err)
406 goto err_copy_from_user;
407 buf[buf_size] = 0;
408
409 if (sscanf(buf, "%s", cmd) != 1) {
410 err = -EPERM;
411 goto err_get_cmd;
412 }
413
414 if (cmd[1]) {
415 err = -EPERM;
416 goto err_bad_cmd;
417 }
418
419 channel_name = file->f_dentry->d_parent->d_name.name;
420 trace_name = file->f_dentry->d_parent->d_parent->d_parent->d_name.name;
421
422 switch (cmd[0]) {
423 case 'Y':
424 case 'y':
425 case '1':
426 err = ltt_trace_set_channel_overwrite(trace_name, channel_name,
427 1);
428 if (IS_ERR_VALUE(err)) {
429 printk(KERN_ERR "channel_overwrite_write: "
430 "ltt_trace_set_channel_overwrite failed: %d\n",
431 err);
432 goto err_set_subbufsize;
433 }
434 break;
435 case 'N':
436 case 'n':
437 case '0':
438 err = ltt_trace_set_channel_overwrite(trace_name, channel_name,
439 0);
440 if (IS_ERR_VALUE(err)) {
441 printk(KERN_ERR "channel_overwrite_write: "
442 "ltt_trace_set_channel_overwrite failed: %d\n",
443 err);
444 goto err_set_subbufsize;
445 }
446 break;
447 default:
448 err = -EPERM;
449 goto err_bad_cmd;
450 }
451
452 free_page((unsigned long)buf);
453 free_page((unsigned long)cmd);
454 return count;
455
456err_set_subbufsize:
457err_bad_cmd:
458err_get_cmd:
459err_copy_from_user:
460 free_page((unsigned long)buf);
461 free_page((unsigned long)cmd);
462 return err;
463}
464
465static const struct file_operations ltt_channel_overwrite_operations = {
466 .write = channel_overwrite_write,
467};
468
469
470static
471ssize_t channel_enable_write(struct file *file,
472 const char __user *user_buf, size_t count,
473 loff_t *ppos)
474{
475 int err = 0;
476 int buf_size;
477 const char *channel_name;
478 const char *trace_name;
479 char *buf = (char *)__get_free_page(GFP_KERNEL);
480 char *cmd = (char *)__get_free_page(GFP_KERNEL);
481
482 buf_size = min_t(size_t, count, PAGE_SIZE - 1);
483 err = copy_from_user(buf, user_buf, buf_size);
484 if (err)
485 goto err_copy_from_user;
486 buf[buf_size] = 0;
487
488 if (sscanf(buf, "%s", cmd) != 1) {
489 err = -EPERM;
490 goto err_get_cmd;
491 }
492
493 if (cmd[1]) {
494 err = -EPERM;
495 goto err_bad_cmd;
496 }
497
498 channel_name = file->f_dentry->d_parent->d_name.name;
499 trace_name = file->f_dentry->d_parent->d_parent->d_parent->d_name.name;
500
501 switch (cmd[0]) {
502 case 'Y':
503 case 'y':
504 case '1':
505 err = ltt_trace_set_channel_enable(trace_name, channel_name,
506 1);
507 if (IS_ERR_VALUE(err)) {
508 printk(KERN_ERR "channel_enable_write: "
509 "ltt_trace_set_channel_enable failed: %d\n",
510 err);
511 goto err_set_subbufsize;
512 }
513 break;
514 case 'N':
515 case 'n':
516 case '0':
517 err = ltt_trace_set_channel_enable(trace_name, channel_name,
518 0);
519 if (IS_ERR_VALUE(err)) {
520 printk(KERN_ERR "channel_enable_write: "
521 "ltt_trace_set_channel_enable failed: %d\n",
522 err);
523 goto err_set_subbufsize;
524 }
525 break;
526 default:
527 err = -EPERM;
528 goto err_bad_cmd;
529 }
530
531 free_page((unsigned long)buf);
532 free_page((unsigned long)cmd);
533 return count;
534
535err_set_subbufsize:
536err_bad_cmd:
537err_get_cmd:
538err_copy_from_user:
539 free_page((unsigned long)buf);
540 free_page((unsigned long)cmd);
541 return err;
542}
543
544static const struct file_operations ltt_channel_enable_operations = {
545 .write = channel_enable_write,
546};
547
548
549static int _create_trace_control_dir(const char *trace_name,
550 struct ltt_trace *trace)
551{
552 int err;
553 struct dentry *trace_root, *channel_root;
554 struct dentry *tmp_den;
555 int i;
556
557 /* debugfs/control/trace_name */
558 trace_root = debugfs_create_dir(trace_name, ltt_control_dir);
559 if (IS_ERR(trace_root) || !trace_root) {
560 printk(KERN_ERR "_create_trace_control_dir: "
561 "create control root dir of %s failed\n", trace_name);
562 err = -ENOMEM;
563 goto err_create_trace_root;
564 }
565
566 /* debugfs/control/trace_name/alloc */
567 tmp_den = debugfs_create_file("alloc", S_IWUSR, trace_root, NULL,
568 &ltt_alloc_operations);
569 if (IS_ERR(tmp_den) || !tmp_den) {
570 printk(KERN_ERR "_create_trace_control_dir: "
571 "create file of alloc failed\n");
572 err = -ENOMEM;
573 goto err_create_subdir;
574 }
575
576 /* debugfs/control/trace_name/trans */
577 tmp_den = debugfs_create_file("trans", S_IWUSR, trace_root, NULL,
578 &ltt_trans_operations);
579 if (IS_ERR(tmp_den) || !tmp_den) {
580 printk(KERN_ERR "_create_trace_control_dir: "
581 "create file of trans failed\n");
582 err = -ENOMEM;
583 goto err_create_subdir;
584 }
585
586 /* debugfs/control/trace_name/enabled */
587 tmp_den = debugfs_create_file("enabled", S_IWUSR, trace_root, NULL,
588 &ltt_enabled_operations);
589 if (IS_ERR(tmp_den) || !tmp_den) {
590 printk(KERN_ERR "_create_trace_control_dir: "
591 "create file of enabled failed\n");
592 err = -ENOMEM;
593 goto err_create_subdir;
594 }
595
596 /* debugfs/control/trace_name/channel/ */
597 channel_root = debugfs_create_dir("channel", trace_root);
598 if (IS_ERR(channel_root) || !channel_root) {
599 printk(KERN_ERR "_create_trace_control_dir: "
600 "create dir of channel failed\n");
601 err = -ENOMEM;
602 goto err_create_subdir;
603 }
604
605 /*
606 * Create dir and files in debugfs/ltt/control/trace_name/channel/
607 * Following things(without <>) will be created:
608 * `-- <control>
609 * `-- <trace_name>
610 * `-- <channel>
611 * |-- <channel_name>
612 * | |-- enable
613 * | |-- overwrite
614 * | |-- subbuf_num
615 * | |-- subbuf_size
616 * | `-- switch_timer
617 * `-- ...
618 */
619
620 for (i = 0; i < trace->nr_channels; i++) {
621 struct dentry *channel_den;
622 struct ltt_chan *chan;
623
624 chan = &trace->channels[i];
625 if (!chan->active)
626 continue;
627 channel_den = debugfs_create_dir(chan->a.filename,
628 channel_root);
629 if (IS_ERR(channel_den) || !channel_den) {
630 printk(KERN_ERR "_create_trace_control_dir: "
631 "create channel dir of %s failed\n",
632 chan->a.filename);
633 err = -ENOMEM;
634 goto err_create_subdir;
635 }
636
637 tmp_den = debugfs_create_file("subbuf_num", S_IWUSR,
638 channel_den, NULL,
639 &ltt_channel_subbuf_num_operations);
640 if (IS_ERR(tmp_den) || !tmp_den) {
641 printk(KERN_ERR "_create_trace_control_dir: "
642 "create subbuf_num in %s failed\n",
643 chan->a.filename);
644 err = -ENOMEM;
645 goto err_create_subdir;
646 }
647
648 tmp_den = debugfs_create_file("subbuf_size", S_IWUSR,
649 channel_den, NULL,
650 &ltt_channel_subbuf_size_operations);
651 if (IS_ERR(tmp_den) || !tmp_den) {
652 printk(KERN_ERR "_create_trace_control_dir: "
653 "create subbuf_size in %s failed\n",
654 chan->a.filename);
655 err = -ENOMEM;
656 goto err_create_subdir;
657 }
658
659 tmp_den = debugfs_create_file("enable", S_IWUSR, channel_den,
660 NULL,
661 &ltt_channel_enable_operations);
662 if (IS_ERR(tmp_den) || !tmp_den) {
663 printk(KERN_ERR "_create_trace_control_dir: "
664 "create enable in %s failed\n",
665 chan->a.filename);
666 err = -ENOMEM;
667 goto err_create_subdir;
668 }
669
670 tmp_den = debugfs_create_file("overwrite", S_IWUSR, channel_den,
671 NULL,
672 &ltt_channel_overwrite_operations);
673 if (IS_ERR(tmp_den) || !tmp_den) {
674 printk(KERN_ERR "_create_trace_control_dir: "
675 "create overwrite in %s failed\n",
676 chan->a.filename);
677 err = -ENOMEM;
678 goto err_create_subdir;
679 }
680
681 tmp_den = debugfs_create_file("switch_timer", S_IWUSR,
682 channel_den, NULL,
683 &ltt_channel_switch_timer_operations);
684 if (IS_ERR(tmp_den) || !tmp_den) {
685 printk(KERN_ERR "_create_trace_control_dir: "
686 "create switch_timer in %s failed\n",
687 chan->a.filename);
688 err = -ENOMEM;
689 goto err_create_subdir;
690 }
691 }
692
693 return 0;
694
695err_create_subdir:
696 debugfs_remove_recursive(trace_root);
697err_create_trace_root:
698 return err;
699}
700
701static
702ssize_t setup_trace_write(struct file *file, const char __user *user_buf,
703 size_t count, loff_t *ppos)
704{
705 int err = 0;
706 int buf_size;
707 struct ltt_trace *trace;
708 char *buf = (char *)__get_free_page(GFP_KERNEL);
709 char *trace_name = (char *)__get_free_page(GFP_KERNEL);
710
711 buf_size = min_t(size_t, count, PAGE_SIZE - 1);
712 err = copy_from_user(buf, user_buf, buf_size);
713 if (err)
714 goto err_copy_from_user;
715 buf[buf_size] = 0;
716
717 if (sscanf(buf, "%s", trace_name) != 1) {
718 err = -EPERM;
719 goto err_get_tracename;
720 }
721
722 mutex_lock(&control_lock);
723 ltt_lock_traces();
724
725 err = _ltt_trace_setup(trace_name);
726 if (IS_ERR_VALUE(err)) {
727 printk(KERN_ERR
728 "setup_trace_write: ltt_trace_setup failed: %d\n", err);
729 goto err_setup_trace;
730 }
731 trace = _ltt_trace_find_setup(trace_name);
732 BUG_ON(!trace);
733 err = _create_trace_control_dir(trace_name, trace);
734 if (IS_ERR_VALUE(err)) {
735 printk(KERN_ERR "setup_trace_write: "
736 "_create_trace_control_dir failed: %d\n", err);
1a28fb65
JN
737 ltt_unlock_traces();
738 ltt_trace_destroy(trace_name);
1c8284eb
MD
739 goto err_create_trace_control_dir;
740 }
741
742 ltt_unlock_traces();
743 mutex_unlock(&control_lock);
744
745 free_page((unsigned long)buf);
746 free_page((unsigned long)trace_name);
747 return count;
748
1c8284eb
MD
749err_setup_trace:
750 ltt_unlock_traces();
1a28fb65 751err_create_trace_control_dir:
1c8284eb
MD
752 mutex_unlock(&control_lock);
753err_get_tracename:
754err_copy_from_user:
755 free_page((unsigned long)buf);
756 free_page((unsigned long)trace_name);
757 return err;
758}
759
760static const struct file_operations ltt_setup_trace_operations = {
761 .write = setup_trace_write,
762};
763
764static
765ssize_t destroy_trace_write(struct file *file, const char __user *user_buf,
766 size_t count, loff_t *ppos)
767{
768 struct dentry *trace_den;
769 int buf_size;
770 int err = 0;
771 char *buf = (char *)__get_free_page(GFP_KERNEL);
772 char *trace_name = (char *)__get_free_page(GFP_KERNEL);
773
774 buf_size = min_t(size_t, count, PAGE_SIZE - 1);
775 err = copy_from_user(buf, user_buf, buf_size);
776 if (err)
777 goto err_copy_from_user;
778 buf[buf_size] = 0;
779
780 if (sscanf(buf, "%s", trace_name) != 1) {
781 err = -EPERM;
782 goto err_get_tracename;
783 }
784
785 mutex_lock(&control_lock);
786
787 err = ltt_trace_destroy(trace_name);
788 if (IS_ERR_VALUE(err)) {
789 printk(KERN_ERR
790 "destroy_trace_write: ltt_trace_destroy failed: %d\n",
791 err);
792 err = -EPERM;
793 goto err_destroy_trace;
794 }
795
796 trace_den = dir_lookup(ltt_control_dir, trace_name);
797 if (!trace_den) {
798 printk(KERN_ERR
799 "destroy_trace_write: lookup for %s's dentry failed\n",
800 trace_name);
801 err = -ENOENT;
802 goto err_get_dentry;
803 }
804
805 debugfs_remove_recursive(trace_den);
806
807 mutex_unlock(&control_lock);
808
809 free_page((unsigned long)buf);
810 free_page((unsigned long)trace_name);
811 return count;
812
813err_get_dentry:
814err_destroy_trace:
815 mutex_unlock(&control_lock);
816err_get_tracename:
817err_copy_from_user:
818 free_page((unsigned long)buf);
819 free_page((unsigned long)trace_name);
820 return err;
821}
822
823static const struct file_operations ltt_destroy_trace_operations = {
824 .write = destroy_trace_write,
825};
826
827static void init_marker_dir(struct dentry *dentry,
828 const struct inode_operations *opt)
829{
830 dentry->d_inode->i_op = opt;
831}
832
833static
834ssize_t marker_enable_read(struct file *filp, char __user *ubuf,
835 size_t cnt, loff_t *ppos)
836{
837 char *buf;
838 const char *channel, *marker;
839 int len, enabled, present;
840
841 marker = filp->f_dentry->d_parent->d_name.name;
842 channel = filp->f_dentry->d_parent->d_parent->d_name.name;
843
844 len = 0;
845 buf = (char *)__get_free_page(GFP_KERNEL);
846
847 /*
848 * Note: we cannot take the marker lock to make these two checks
849 * atomic, because the marker mutex nests inside the module mutex, taken
850 * inside the marker present check.
851 */
852 enabled = is_marker_enabled(channel, marker);
853 present = is_marker_present(channel, marker);
854
855 if (enabled && present)
856 len = snprintf(buf, PAGE_SIZE, "%d\n", 1);
857 else if (enabled && !present)
858 len = snprintf(buf, PAGE_SIZE, "%d\n", 2);
859 else
860 len = snprintf(buf, PAGE_SIZE, "%d\n", 0);
861
862
863 if (len >= PAGE_SIZE) {
864 len = PAGE_SIZE;
865 buf[PAGE_SIZE] = '\0';
866 }
867 len = simple_read_from_buffer(ubuf, cnt, ppos, buf, len);
868 free_page((unsigned long)buf);
869
870 return len;
871}
872
873static
874ssize_t marker_enable_write(struct file *filp, const char __user *ubuf,
875 size_t cnt, loff_t *ppos)
876{
877 char *buf = (char *)__get_free_page(GFP_KERNEL);
878 int buf_size;
879 ssize_t ret = 0;
880 const char *channel, *marker;
881
882 marker = filp->f_dentry->d_parent->d_name.name;
883 channel = filp->f_dentry->d_parent->d_parent->d_name.name;
884
885 buf_size = min_t(size_t, cnt, PAGE_SIZE - 1);
886 ret = copy_from_user(buf, ubuf, buf_size);
887 if (ret)
888 goto end;
889
890 buf[buf_size] = 0;
891
892 switch (buf[0]) {
893 case 'Y':
894 case 'y':
895 case '1':
896 ret = ltt_marker_connect(channel, marker, "default");
897 if (ret)
898 goto end;
899 break;
900 case 'N':
901 case 'n':
902 case '0':
903 ret = ltt_marker_disconnect(channel, marker, "default");
904 if (ret)
905 goto end;
906 break;
907 default:
908 ret = -EPERM;
909 goto end;
910 }
911 ret = cnt;
912end:
913 free_page((unsigned long)buf);
914 return ret;
915}
916
917static const struct file_operations enable_fops = {
918 .read = marker_enable_read,
919 .write = marker_enable_write,
920};
921
922/*
923 * In practice, the output size should never be larger than 4096 kB. If it
924 * ever happens, the output will simply be truncated.
925 */
926static
927ssize_t marker_info_read(struct file *filp, char __user *ubuf,
928 size_t cnt, loff_t *ppos)
929{
930 char *buf;
931 const char *channel, *marker;
932 int len;
933 struct marker_iter iter;
934
935 marker = filp->f_dentry->d_parent->d_name.name;
936 channel = filp->f_dentry->d_parent->d_parent->d_name.name;
937
938 len = 0;
939 buf = (char *)__get_free_page(GFP_KERNEL);
940
941 if (is_marker_enabled(channel, marker) &&
942 !is_marker_present(channel, marker)) {
943 len += snprintf(buf + len, PAGE_SIZE - len,
944 "Marker Pre-enabled\n");
945 goto out;
946 }
947
948 marker_iter_reset(&iter);
949 marker_iter_start(&iter);
950 for (; iter.marker != NULL; marker_iter_next(&iter)) {
951 if (!strcmp(iter.marker->channel, channel) &&
952 !strcmp(iter.marker->name, marker))
953 len += snprintf(buf + len, PAGE_SIZE - len,
954 "Location: %s\n"
955 "format: \"%s\"\nstate: %d\n"
956 "event_id: %hu\n"
957 "call: 0x%p\n"
958 "probe %s : 0x%p\n\n",
959#ifdef CONFIG_MODULES
960 iter.module ? iter.module->name :
961#endif
962 "Core Kernel",
963 iter.marker->format,
964 _imv_read(iter.marker->state),
965 iter.marker->event_id,
966 iter.marker->call,
967 iter.marker->ptype ?
968 "multi" : "single", iter.marker->ptype ?
969 (void *)iter.marker->multi :
970 (void *)iter.marker->single.func);
971 if (len >= PAGE_SIZE)
972 break;
973 }
974 marker_iter_stop(&iter);
975
976out:
977 if (len >= PAGE_SIZE) {
978 len = PAGE_SIZE;
979 buf[PAGE_SIZE] = '\0';
980 }
981
982 len = simple_read_from_buffer(ubuf, cnt, ppos, buf, len);
983 free_page((unsigned long)buf);
984
985 return len;
986}
987
988static const struct file_operations info_fops = {
989 .read = marker_info_read,
990};
991
992static int marker_mkdir(struct inode *dir, struct dentry *dentry, int mode)
993{
994 struct dentry *marker_d, *enable_d, *info_d, *channel_d;
995 int ret;
996
997 ret = 0;
998 channel_d = (struct dentry *)dir->i_private;
999 mutex_unlock(&dir->i_mutex);
1000
1001 marker_d = debugfs_create_dir(dentry->d_name.name,
1002 channel_d);
1003 if (IS_ERR(marker_d)) {
1004 ret = PTR_ERR(marker_d);
1005 goto out;
1006 }
1007
1008 enable_d = debugfs_create_file("enable", 0644, marker_d,
1009 NULL, &enable_fops);
1010 if (IS_ERR(enable_d) || !enable_d) {
1011 printk(KERN_ERR
1012 "%s: create file of %s failed\n",
1013 __func__, "enable");
1014 ret = -ENOMEM;
1015 goto remove_marker_dir;
1016 }
1017
1018 info_d = debugfs_create_file("info", 0644, marker_d,
1019 NULL, &info_fops);
1020 if (IS_ERR(info_d) || !info_d) {
1021 printk(KERN_ERR
1022 "%s: create file of %s failed\n",
1023 __func__, "info");
1024 ret = -ENOMEM;
1025 goto remove_enable_dir;
1026 }
1027
1028 goto out;
1029
1030remove_enable_dir:
1031 debugfs_remove(enable_d);
1032remove_marker_dir:
1033 debugfs_remove(marker_d);
1034out:
1035 mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
1036 return ret;
1037}
1038
1039static int marker_rmdir(struct inode *dir, struct dentry *dentry)
1040{
1041 struct dentry *marker_d, *channel_d;
1042 const char *channel, *name;
1043 int ret, enabled, present;
1044
1045 ret = 0;
1046
1047 channel_d = (struct dentry *)dir->i_private;
1048 channel = channel_d->d_name.name;
1049
1050 marker_d = dir_lookup(channel_d, dentry->d_name.name);
1051
1052 if (!marker_d) {
1053 ret = -ENOENT;
1054 goto out;
1055 }
1056
1057 name = marker_d->d_name.name;
1058
1059 enabled = is_marker_enabled(channel, name);
1060 present = is_marker_present(channel, name);
1061
1062 if (present || (!present && enabled)) {
1063 ret = -EPERM;
1064 goto out;
1065 }
1066
1067 mutex_unlock(&dir->i_mutex);
1068 mutex_unlock(&dentry->d_inode->i_mutex);
1069 debugfs_remove_recursive(marker_d);
1070 mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
1071 mutex_lock(&dentry->d_inode->i_mutex);
1072out:
1073 return ret;
1074}
1075
1076const struct inode_operations channel_dir_opt = {
1077 .lookup = simple_lookup,
1078 .mkdir = marker_mkdir,
1079 .rmdir = marker_rmdir,
1080};
1081
1082static int channel_mkdir(struct inode *dir, struct dentry *dentry, int mode)
1083{
1084 struct dentry *channel_d;
1085 int ret;
1086
1087 ret = 0;
1088 mutex_unlock(&dir->i_mutex);
1089
1090 channel_d = debugfs_create_dir(dentry->d_name.name,
1091 markers_control_dir);
1092 if (IS_ERR(channel_d)) {
1093 ret = PTR_ERR(channel_d);
1094 goto out;
1095 }
1096
1097 channel_d->d_inode->i_private = (void *)channel_d;
1098 init_marker_dir(channel_d, &channel_dir_opt);
1099out:
1100 mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
1101 return ret;
1102}
1103
1104static int channel_rmdir(struct inode *dir, struct dentry *dentry)
1105{
1106 struct dentry *channel_d;
1107 int ret;
1108
1109 ret = 0;
1110
1111 channel_d = dir_lookup(markers_control_dir, dentry->d_name.name);
1112 if (!channel_d) {
1113 ret = -ENOENT;
1114 goto out;
1115 }
1116
1117 if (list_empty(&channel_d->d_subdirs)) {
1118 mutex_unlock(&dir->i_mutex);
1119 mutex_unlock(&dentry->d_inode->i_mutex);
1120 debugfs_remove(channel_d);
1121 mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
1122 mutex_lock(&dentry->d_inode->i_mutex);
1123 } else
1124 ret = -EPERM;
1125
1126out:
1127 return ret;
1128}
1129
1130const struct inode_operations root_dir_opt = {
1131 .lookup = simple_lookup,
1132 .mkdir = channel_mkdir,
1133 .rmdir = channel_rmdir
1134};
1135
1136static int build_marker_file(struct marker *marker)
1137{
1138 struct dentry *channel_d, *marker_d, *enable_d, *info_d;
1139 int err;
1140
1141 channel_d = dir_lookup(markers_control_dir, marker->channel);
1142 if (!channel_d) {
1143 channel_d = debugfs_create_dir(marker->channel,
1144 markers_control_dir);
1145 if (IS_ERR(channel_d) || !channel_d) {
1146 printk(KERN_ERR
1147 "%s: build channel dir of %s failed\n",
1148 __func__, marker->channel);
1149 err = -ENOMEM;
1150 goto err_build_fail;
1151 }
1152 channel_d->d_inode->i_private = (void *)channel_d;
1153 init_marker_dir(channel_d, &channel_dir_opt);
1154 }
1155
1156 marker_d = dir_lookup(channel_d, marker->name);
1157 if (!marker_d) {
1158 marker_d = debugfs_create_dir(marker->name, channel_d);
1159 if (IS_ERR(marker_d) || !marker_d) {
1160 printk(KERN_ERR
1161 "%s: marker dir of %s failed\n",
1162 __func__, marker->name);
1163 err = -ENOMEM;
1164 goto err_build_fail;
1165 }
1166 }
1167
1168 enable_d = dir_lookup(marker_d, "enable");
1169 if (!enable_d) {
1170 enable_d = debugfs_create_file("enable", 0644, marker_d,
1171 NULL, &enable_fops);
1172 if (IS_ERR(enable_d) || !enable_d) {
1173 printk(KERN_ERR
1174 "%s: create file of %s failed\n",
1175 __func__, "enable");
1176 err = -ENOMEM;
1177 goto err_build_fail;
1178 }
1179 }
1180
1181 info_d = dir_lookup(marker_d, "info");
1182 if (!info_d) {
1183 info_d = debugfs_create_file("info", 0444, marker_d,
1184 NULL, &info_fops);
1185 if (IS_ERR(info_d) || !info_d) {
1186 printk(KERN_ERR
1187 "%s: create file of %s failed\n",
1188 __func__, "enable");
1189 err = -ENOMEM;
1190 goto err_build_fail;
1191 }
1192 }
1193
1194 return 0;
1195
1196err_build_fail:
1197 return err;
1198}
1199
1200static int build_marker_control_files(void)
1201{
1202 struct marker_iter iter;
1203 int err;
1204
1205 err = 0;
1206 if (!markers_control_dir)
1207 return -EEXIST;
1208
1209 marker_iter_reset(&iter);
1210 marker_iter_start(&iter);
1211 for (; iter.marker != NULL; marker_iter_next(&iter)) {
1212 err = build_marker_file(iter.marker);
1213 if (err)
1214 goto out;
1215 }
1216 marker_iter_stop(&iter);
1217
1218out:
1219 return err;
1220}
1221
1222#ifdef CONFIG_MODULES
1223static int remove_marker_control_dir(struct module *mod, struct marker *marker)
1224{
1225 struct dentry *channel_d, *marker_d;
1226 const char *channel, *name;
1227 int count;
1228 struct marker_iter iter;
1229
1230 count = 0;
1231
1232 channel_d = dir_lookup(markers_control_dir, marker->channel);
1233 if (!channel_d)
1234 return -ENOENT;
1235 channel = channel_d->d_name.name;
1236
1237 marker_d = dir_lookup(channel_d, marker->name);
1238 if (!marker_d)
1239 return -ENOENT;
1240 name = marker_d->d_name.name;
1241
1242 marker_iter_reset(&iter);
1243 marker_iter_start(&iter);
1244 for (; iter.marker != NULL; marker_iter_next(&iter)) {
1245 if (!strcmp(iter.marker->channel, channel) &&
1246 !strcmp(iter.marker->name, name) && mod != iter.module)
1247 count++;
1248 }
1249
1250 if (count > 0)
1251 goto end;
1252
1253 debugfs_remove_recursive(marker_d);
1254 if (list_empty(&channel_d->d_subdirs))
1255 debugfs_remove(channel_d);
1256
1257end:
1258 marker_iter_stop(&iter);
1259 return 0;
1260}
1261
1262static void cleanup_control_dir(struct module *mod, struct marker *begin,
1263 struct marker *end)
1264{
1265 struct marker *iter;
1266
1267 if (!markers_control_dir)
1268 return;
1269
1270 for (iter = begin; iter < end; iter++)
1271 remove_marker_control_dir(mod, iter);
1272
1273 return;
1274}
1275
1276static void build_control_dir(struct module *mod, struct marker *begin,
1277 struct marker *end)
1278{
1279 struct marker *iter;
1280 int err;
1281
1282 err = 0;
1283 if (!markers_control_dir)
1284 return;
1285
1286 for (iter = begin; iter < end; iter++) {
1287 err = build_marker_file(iter);
1288 if (err)
1289 goto err_build_fail;
1290 }
1291
1292 return;
1293err_build_fail:
1294 cleanup_control_dir(mod, begin, end);
1295}
1296
1297static int module_notify(struct notifier_block *self,
1298 unsigned long val, void *data)
1299{
1300 struct module *mod = data;
1301
1302 switch (val) {
1303 case MODULE_STATE_COMING:
1304 build_control_dir(mod, mod->markers,
1305 mod->markers + mod->num_markers);
1306 break;
1307 case MODULE_STATE_GOING:
1308 cleanup_control_dir(mod, mod->markers,
1309 mod->markers + mod->num_markers);
1310 break;
1311 }
1312 return NOTIFY_DONE;
1313}
1314#else
1315static inline int module_notify(struct notifier_block *self,
1316 unsigned long val, void *data)
1317{
1318 return 0;
1319}
1320#endif
1321
1322static struct notifier_block module_nb = {
1323 .notifier_call = module_notify,
1324};
1325
1326static int __init ltt_trace_control_init(void)
1327{
1328 int err = 0;
1329 struct dentry *ltt_root_dentry;
1330
1331 ltt_root_dentry = get_ltt_root();
1332 if (!ltt_root_dentry) {
1333 err = -ENOENT;
1334 goto err_no_root;
1335 }
1336
1337 ltt_control_dir = debugfs_create_dir(LTT_CONTROL_DIR, ltt_root_dentry);
1338 if (IS_ERR(ltt_control_dir) || !ltt_control_dir) {
1339 printk(KERN_ERR
1340 "ltt_channel_control_init: create dir of %s failed\n",
1341 LTT_CONTROL_DIR);
1342 err = -ENOMEM;
1343 goto err_create_control_dir;
1344 }
1345
1346 ltt_setup_trace_file = debugfs_create_file(LTT_SETUP_TRACE_FILE,
1347 S_IWUSR, ltt_root_dentry,
1348 NULL,
1349 &ltt_setup_trace_operations);
1350 if (IS_ERR(ltt_setup_trace_file) || !ltt_setup_trace_file) {
1351 printk(KERN_ERR
1352 "ltt_channel_control_init: create file of %s failed\n",
1353 LTT_SETUP_TRACE_FILE);
1354 err = -ENOMEM;
1355 goto err_create_setup_trace_file;
1356 }
1357
1358 ltt_destroy_trace_file = debugfs_create_file(LTT_DESTROY_TRACE_FILE,
1359 S_IWUSR, ltt_root_dentry,
1360 NULL,
1361 &ltt_destroy_trace_operations);
1362 if (IS_ERR(ltt_destroy_trace_file) || !ltt_destroy_trace_file) {
1363 printk(KERN_ERR
1364 "ltt_channel_control_init: create file of %s failed\n",
1365 LTT_DESTROY_TRACE_FILE);
1366 err = -ENOMEM;
1367 goto err_create_destroy_trace_file;
1368 }
1369
1370 markers_control_dir = debugfs_create_dir(MARKERS_CONTROL_DIR,
1371 ltt_root_dentry);
1372 if (IS_ERR(markers_control_dir) || !markers_control_dir) {
1373 printk(KERN_ERR
1374 "ltt_channel_control_init: create dir of %s failed\n",
1375 MARKERS_CONTROL_DIR);
1376 err = -ENOMEM;
1377 goto err_create_marker_control_dir;
1378 }
1379
1380 init_marker_dir(markers_control_dir, &root_dir_opt);
1381
1382 if (build_marker_control_files())
1383 goto err_build_fail;
1384
1385 if (!register_module_notifier(&module_nb))
1386 return 0;
1387
1388err_build_fail:
1389 debugfs_remove_recursive(markers_control_dir);
1390 markers_control_dir = NULL;
1391err_create_marker_control_dir:
1392 debugfs_remove(ltt_destroy_trace_file);
1393err_create_destroy_trace_file:
1394 debugfs_remove(ltt_setup_trace_file);
1395err_create_setup_trace_file:
1396 debugfs_remove(ltt_control_dir);
1397err_create_control_dir:
1398err_no_root:
1399 return err;
1400}
1401
1402static void __exit ltt_trace_control_exit(void)
1403{
1404 struct dentry *trace_dir;
1405
1406 /* destory all traces */
1407 list_for_each_entry(trace_dir, &ltt_control_dir->d_subdirs,
1408 d_u.d_child) {
1409 ltt_trace_stop(trace_dir->d_name.name);
1410 ltt_trace_destroy(trace_dir->d_name.name);
1411 }
1412
1413 /* clean dirs in debugfs */
1414 debugfs_remove(ltt_setup_trace_file);
1415 debugfs_remove(ltt_destroy_trace_file);
1416 debugfs_remove_recursive(ltt_control_dir);
1417 debugfs_remove_recursive(markers_control_dir);
1418 unregister_module_notifier(&module_nb);
1419 put_ltt_root();
1420}
1421
1422module_init(ltt_trace_control_init);
1423module_exit(ltt_trace_control_exit);
1424
1425MODULE_LICENSE("GPL and additional rights");
1426MODULE_AUTHOR("Zhao Lei <zhaolei@cn.fujitsu.com>");
1427MODULE_DESCRIPTION("Linux Trace Toolkit Trace Controller");
This page took 0.082697 seconds and 4 git commands to generate.