Rename the "discard" directory to "deprecated"
[lttng-modules.git] / deprecated / ltt-trace-control.c
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
35 struct 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 */
43 static 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 */
65 static 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
82 static 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
117 err_alloc_trace:
118 err_bad_cmd:
119 err_get_cmd:
120 err_copy_from_user:
121 free_page((unsigned long)buf);
122 free_page((unsigned long)cmd);
123 return err;
124 }
125
126 static const struct file_operations ltt_alloc_operations = {
127 .write = alloc_write,
128 };
129
130
131 static 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
189 err_stop_trace:
190 err_start_trace:
191 err_bad_cmd:
192 err_get_cmd:
193 err_copy_from_user:
194 free_page((unsigned long)buf);
195 free_page((unsigned long)cmd);
196 return err;
197 }
198
199 static const struct file_operations ltt_enabled_operations = {
200 .write = enabled_write,
201 };
202
203
204 static 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
235 err_set_trans:
236 err_get_transname:
237 err_copy_from_user:
238 free_page((unsigned long)buf);
239 free_page((unsigned long)trans_name);
240 return err;
241 }
242
243 static const struct file_operations ltt_trans_operations = {
244 .write = trans_write,
245 };
246
247
248 static 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
282 err_set_subbufcount:
283 err_get_number:
284 err_copy_from_user:
285 free_page((unsigned long)buf);
286 return err;
287 }
288
289 static const struct file_operations ltt_channel_subbuf_num_operations = {
290 .write = channel_subbuf_num_write,
291 };
292
293
294 static
295 ssize_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
330 err_set_subbufsize:
331 err_get_number:
332 err_copy_from_user:
333 free_page((unsigned long)buf);
334 return err;
335 }
336
337 static const struct file_operations ltt_channel_subbuf_size_operations = {
338 .write = channel_subbuf_size_write,
339 };
340
341 static
342 ssize_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 us */
368 num *= 1000;
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
380 err_set_switch_timer:
381 err_get_number:
382 err_copy_from_user:
383 free_page((unsigned long)buf);
384 return err;
385 }
386
387 static struct file_operations ltt_channel_switch_timer_operations = {
388 .write = channel_switch_timer_write,
389 };
390
391 static
392 ssize_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
456 err_set_subbufsize:
457 err_bad_cmd:
458 err_get_cmd:
459 err_copy_from_user:
460 free_page((unsigned long)buf);
461 free_page((unsigned long)cmd);
462 return err;
463 }
464
465 static const struct file_operations ltt_channel_overwrite_operations = {
466 .write = channel_overwrite_write,
467 };
468
469
470 static
471 ssize_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
535 err_set_subbufsize:
536 err_bad_cmd:
537 err_get_cmd:
538 err_copy_from_user:
539 free_page((unsigned long)buf);
540 free_page((unsigned long)cmd);
541 return err;
542 }
543
544 static const struct file_operations ltt_channel_enable_operations = {
545 .write = channel_enable_write,
546 };
547
548
549 static 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
695 err_create_subdir:
696 debugfs_remove_recursive(trace_root);
697 err_create_trace_root:
698 return err;
699 }
700
701 static
702 ssize_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);
737 goto err_create_trace_control_dir;
738 }
739
740 ltt_unlock_traces();
741 mutex_unlock(&control_lock);
742
743 free_page((unsigned long)buf);
744 free_page((unsigned long)trace_name);
745 return count;
746
747 err_create_trace_control_dir:
748 ltt_trace_destroy(trace_name);
749 err_setup_trace:
750 ltt_unlock_traces();
751 mutex_unlock(&control_lock);
752 err_get_tracename:
753 err_copy_from_user:
754 free_page((unsigned long)buf);
755 free_page((unsigned long)trace_name);
756 return err;
757 }
758
759 static const struct file_operations ltt_setup_trace_operations = {
760 .write = setup_trace_write,
761 };
762
763 static
764 ssize_t destroy_trace_write(struct file *file, const char __user *user_buf,
765 size_t count, loff_t *ppos)
766 {
767 struct dentry *trace_den;
768 int buf_size;
769 int err = 0;
770 char *buf = (char *)__get_free_page(GFP_KERNEL);
771 char *trace_name = (char *)__get_free_page(GFP_KERNEL);
772
773 buf_size = min_t(size_t, count, PAGE_SIZE - 1);
774 err = copy_from_user(buf, user_buf, buf_size);
775 if (err)
776 goto err_copy_from_user;
777 buf[buf_size] = 0;
778
779 if (sscanf(buf, "%s", trace_name) != 1) {
780 err = -EPERM;
781 goto err_get_tracename;
782 }
783
784 mutex_lock(&control_lock);
785
786 err = ltt_trace_destroy(trace_name);
787 if (IS_ERR_VALUE(err)) {
788 printk(KERN_ERR
789 "destroy_trace_write: ltt_trace_destroy failed: %d\n",
790 err);
791 err = -EPERM;
792 goto err_destroy_trace;
793 }
794
795 trace_den = dir_lookup(ltt_control_dir, trace_name);
796 if (!trace_den) {
797 printk(KERN_ERR
798 "destroy_trace_write: lookup for %s's dentry failed\n",
799 trace_name);
800 err = -ENOENT;
801 goto err_get_dentry;
802 }
803
804 debugfs_remove_recursive(trace_den);
805
806 mutex_unlock(&control_lock);
807
808 free_page((unsigned long)buf);
809 free_page((unsigned long)trace_name);
810 return count;
811
812 err_get_dentry:
813 err_destroy_trace:
814 mutex_unlock(&control_lock);
815 err_get_tracename:
816 err_copy_from_user:
817 free_page((unsigned long)buf);
818 free_page((unsigned long)trace_name);
819 return err;
820 }
821
822 static const struct file_operations ltt_destroy_trace_operations = {
823 .write = destroy_trace_write,
824 };
825
826 static void init_marker_dir(struct dentry *dentry,
827 const struct inode_operations *opt)
828 {
829 dentry->d_inode->i_op = opt;
830 }
831
832 static
833 ssize_t marker_enable_read(struct file *filp, char __user *ubuf,
834 size_t cnt, loff_t *ppos)
835 {
836 char *buf;
837 const char *channel, *marker;
838 int len, enabled, present;
839
840 marker = filp->f_dentry->d_parent->d_name.name;
841 channel = filp->f_dentry->d_parent->d_parent->d_name.name;
842
843 len = 0;
844 buf = (char *)__get_free_page(GFP_KERNEL);
845
846 /*
847 * Note: we cannot take the marker lock to make these two checks
848 * atomic, because the marker mutex nests inside the module mutex, taken
849 * inside the marker present check.
850 */
851 enabled = is_marker_enabled(channel, marker);
852 present = is_marker_present(channel, marker);
853
854 if (enabled && present)
855 len = snprintf(buf, PAGE_SIZE, "%d\n", 1);
856 else if (enabled && !present)
857 len = snprintf(buf, PAGE_SIZE, "%d\n", 2);
858 else
859 len = snprintf(buf, PAGE_SIZE, "%d\n", 0);
860
861
862 if (len >= PAGE_SIZE) {
863 len = PAGE_SIZE;
864 buf[PAGE_SIZE] = '\0';
865 }
866 len = simple_read_from_buffer(ubuf, cnt, ppos, buf, len);
867 free_page((unsigned long)buf);
868
869 return len;
870 }
871
872 static
873 ssize_t marker_enable_write(struct file *filp, const char __user *ubuf,
874 size_t cnt, loff_t *ppos)
875 {
876 char *buf = (char *)__get_free_page(GFP_KERNEL);
877 int buf_size;
878 ssize_t ret = 0;
879 const char *channel, *marker;
880
881 marker = filp->f_dentry->d_parent->d_name.name;
882 channel = filp->f_dentry->d_parent->d_parent->d_name.name;
883
884 buf_size = min_t(size_t, cnt, PAGE_SIZE - 1);
885 ret = copy_from_user(buf, ubuf, buf_size);
886 if (ret)
887 goto end;
888
889 buf[buf_size] = 0;
890
891 switch (buf[0]) {
892 case 'Y':
893 case 'y':
894 case '1':
895 ret = ltt_marker_connect(channel, marker, "default");
896 if (ret)
897 goto end;
898 break;
899 case 'N':
900 case 'n':
901 case '0':
902 ret = ltt_marker_disconnect(channel, marker, "default");
903 if (ret)
904 goto end;
905 break;
906 default:
907 ret = -EPERM;
908 goto end;
909 }
910 ret = cnt;
911 end:
912 free_page((unsigned long)buf);
913 return ret;
914 }
915
916 static const struct file_operations enable_fops = {
917 .read = marker_enable_read,
918 .write = marker_enable_write,
919 };
920
921 /*
922 * In practice, the output size should never be larger than 4096 kB. If it
923 * ever happens, the output will simply be truncated.
924 */
925 static
926 ssize_t marker_info_read(struct file *filp, char __user *ubuf,
927 size_t cnt, loff_t *ppos)
928 {
929 char *buf;
930 const char *channel, *marker;
931 int len;
932 struct marker_iter iter;
933
934 marker = filp->f_dentry->d_parent->d_name.name;
935 channel = filp->f_dentry->d_parent->d_parent->d_name.name;
936
937 len = 0;
938 buf = (char *)__get_free_page(GFP_KERNEL);
939
940 if (is_marker_enabled(channel, marker) &&
941 !is_marker_present(channel, marker)) {
942 len += snprintf(buf + len, PAGE_SIZE - len,
943 "Marker Pre-enabled\n");
944 goto out;
945 }
946
947 marker_iter_reset(&iter);
948 marker_iter_start(&iter);
949 for (; iter.marker != NULL; marker_iter_next(&iter)) {
950 if (!strcmp(iter.marker->channel, channel) &&
951 !strcmp(iter.marker->name, marker))
952 len += snprintf(buf + len, PAGE_SIZE - len,
953 "Location: %s\n"
954 "format: \"%s\"\nstate: %d\n"
955 "event_id: %hu\n"
956 "call: 0x%p\n"
957 "probe %s : 0x%p\n\n",
958 #ifdef CONFIG_MODULES
959 iter.module ? iter.module->name :
960 #endif
961 "Core Kernel",
962 iter.marker->format,
963 _imv_read(iter.marker->state),
964 iter.marker->event_id,
965 iter.marker->call,
966 iter.marker->ptype ?
967 "multi" : "single", iter.marker->ptype ?
968 (void *)iter.marker->multi :
969 (void *)iter.marker->single.func);
970 if (len >= PAGE_SIZE)
971 break;
972 }
973 marker_iter_stop(&iter);
974
975 out:
976 if (len >= PAGE_SIZE) {
977 len = PAGE_SIZE;
978 buf[PAGE_SIZE] = '\0';
979 }
980
981 len = simple_read_from_buffer(ubuf, cnt, ppos, buf, len);
982 free_page((unsigned long)buf);
983
984 return len;
985 }
986
987 static const struct file_operations info_fops = {
988 .read = marker_info_read,
989 };
990
991 static int marker_mkdir(struct inode *dir, struct dentry *dentry, int mode)
992 {
993 struct dentry *marker_d, *enable_d, *info_d, *channel_d;
994 int ret;
995
996 ret = 0;
997 channel_d = (struct dentry *)dir->i_private;
998 mutex_unlock(&dir->i_mutex);
999
1000 marker_d = debugfs_create_dir(dentry->d_name.name,
1001 channel_d);
1002 if (IS_ERR(marker_d)) {
1003 ret = PTR_ERR(marker_d);
1004 goto out;
1005 }
1006
1007 enable_d = debugfs_create_file("enable", 0644, marker_d,
1008 NULL, &enable_fops);
1009 if (IS_ERR(enable_d) || !enable_d) {
1010 printk(KERN_ERR
1011 "%s: create file of %s failed\n",
1012 __func__, "enable");
1013 ret = -ENOMEM;
1014 goto remove_marker_dir;
1015 }
1016
1017 info_d = debugfs_create_file("info", 0644, marker_d,
1018 NULL, &info_fops);
1019 if (IS_ERR(info_d) || !info_d) {
1020 printk(KERN_ERR
1021 "%s: create file of %s failed\n",
1022 __func__, "info");
1023 ret = -ENOMEM;
1024 goto remove_enable_dir;
1025 }
1026
1027 goto out;
1028
1029 remove_enable_dir:
1030 debugfs_remove(enable_d);
1031 remove_marker_dir:
1032 debugfs_remove(marker_d);
1033 out:
1034 mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
1035 return ret;
1036 }
1037
1038 static int marker_rmdir(struct inode *dir, struct dentry *dentry)
1039 {
1040 struct dentry *marker_d, *channel_d;
1041 const char *channel, *name;
1042 int ret, enabled, present;
1043
1044 ret = 0;
1045
1046 channel_d = (struct dentry *)dir->i_private;
1047 channel = channel_d->d_name.name;
1048
1049 marker_d = dir_lookup(channel_d, dentry->d_name.name);
1050
1051 if (!marker_d) {
1052 ret = -ENOENT;
1053 goto out;
1054 }
1055
1056 name = marker_d->d_name.name;
1057
1058 enabled = is_marker_enabled(channel, name);
1059 present = is_marker_present(channel, name);
1060
1061 if (present || (!present && enabled)) {
1062 ret = -EPERM;
1063 goto out;
1064 }
1065
1066 mutex_unlock(&dir->i_mutex);
1067 mutex_unlock(&dentry->d_inode->i_mutex);
1068 debugfs_remove_recursive(marker_d);
1069 mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
1070 mutex_lock(&dentry->d_inode->i_mutex);
1071 out:
1072 return ret;
1073 }
1074
1075 const struct inode_operations channel_dir_opt = {
1076 .lookup = simple_lookup,
1077 .mkdir = marker_mkdir,
1078 .rmdir = marker_rmdir,
1079 };
1080
1081 static int channel_mkdir(struct inode *dir, struct dentry *dentry, int mode)
1082 {
1083 struct dentry *channel_d;
1084 int ret;
1085
1086 ret = 0;
1087 mutex_unlock(&dir->i_mutex);
1088
1089 channel_d = debugfs_create_dir(dentry->d_name.name,
1090 markers_control_dir);
1091 if (IS_ERR(channel_d)) {
1092 ret = PTR_ERR(channel_d);
1093 goto out;
1094 }
1095
1096 channel_d->d_inode->i_private = (void *)channel_d;
1097 init_marker_dir(channel_d, &channel_dir_opt);
1098 out:
1099 mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
1100 return ret;
1101 }
1102
1103 static int channel_rmdir(struct inode *dir, struct dentry *dentry)
1104 {
1105 struct dentry *channel_d;
1106 int ret;
1107
1108 ret = 0;
1109
1110 channel_d = dir_lookup(markers_control_dir, dentry->d_name.name);
1111 if (!channel_d) {
1112 ret = -ENOENT;
1113 goto out;
1114 }
1115
1116 if (list_empty(&channel_d->d_subdirs)) {
1117 mutex_unlock(&dir->i_mutex);
1118 mutex_unlock(&dentry->d_inode->i_mutex);
1119 debugfs_remove(channel_d);
1120 mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
1121 mutex_lock(&dentry->d_inode->i_mutex);
1122 } else
1123 ret = -EPERM;
1124
1125 out:
1126 return ret;
1127 }
1128
1129 const struct inode_operations root_dir_opt = {
1130 .lookup = simple_lookup,
1131 .mkdir = channel_mkdir,
1132 .rmdir = channel_rmdir
1133 };
1134
1135 static int build_marker_file(struct marker *marker)
1136 {
1137 struct dentry *channel_d, *marker_d, *enable_d, *info_d;
1138 int err;
1139
1140 channel_d = dir_lookup(markers_control_dir, marker->channel);
1141 if (!channel_d) {
1142 channel_d = debugfs_create_dir(marker->channel,
1143 markers_control_dir);
1144 if (IS_ERR(channel_d) || !channel_d) {
1145 printk(KERN_ERR
1146 "%s: build channel dir of %s failed\n",
1147 __func__, marker->channel);
1148 err = -ENOMEM;
1149 goto err_build_fail;
1150 }
1151 channel_d->d_inode->i_private = (void *)channel_d;
1152 init_marker_dir(channel_d, &channel_dir_opt);
1153 }
1154
1155 marker_d = dir_lookup(channel_d, marker->name);
1156 if (!marker_d) {
1157 marker_d = debugfs_create_dir(marker->name, channel_d);
1158 if (IS_ERR(marker_d) || !marker_d) {
1159 printk(KERN_ERR
1160 "%s: marker dir of %s failed\n",
1161 __func__, marker->name);
1162 err = -ENOMEM;
1163 goto err_build_fail;
1164 }
1165 }
1166
1167 enable_d = dir_lookup(marker_d, "enable");
1168 if (!enable_d) {
1169 enable_d = debugfs_create_file("enable", 0644, marker_d,
1170 NULL, &enable_fops);
1171 if (IS_ERR(enable_d) || !enable_d) {
1172 printk(KERN_ERR
1173 "%s: create file of %s failed\n",
1174 __func__, "enable");
1175 err = -ENOMEM;
1176 goto err_build_fail;
1177 }
1178 }
1179
1180 info_d = dir_lookup(marker_d, "info");
1181 if (!info_d) {
1182 info_d = debugfs_create_file("info", 0444, marker_d,
1183 NULL, &info_fops);
1184 if (IS_ERR(info_d) || !info_d) {
1185 printk(KERN_ERR
1186 "%s: create file of %s failed\n",
1187 __func__, "enable");
1188 err = -ENOMEM;
1189 goto err_build_fail;
1190 }
1191 }
1192
1193 return 0;
1194
1195 err_build_fail:
1196 return err;
1197 }
1198
1199 static int build_marker_control_files(void)
1200 {
1201 struct marker_iter iter;
1202 int err;
1203
1204 err = 0;
1205 if (!markers_control_dir)
1206 return -EEXIST;
1207
1208 marker_iter_reset(&iter);
1209 marker_iter_start(&iter);
1210 for (; iter.marker != NULL; marker_iter_next(&iter)) {
1211 err = build_marker_file(iter.marker);
1212 if (err)
1213 goto out;
1214 }
1215 marker_iter_stop(&iter);
1216
1217 out:
1218 return err;
1219 }
1220
1221 #ifdef CONFIG_MODULES
1222 static int remove_marker_control_dir(struct module *mod, struct marker *marker)
1223 {
1224 struct dentry *channel_d, *marker_d;
1225 const char *channel, *name;
1226 int count;
1227 struct marker_iter iter;
1228
1229 count = 0;
1230
1231 channel_d = dir_lookup(markers_control_dir, marker->channel);
1232 if (!channel_d)
1233 return -ENOENT;
1234 channel = channel_d->d_name.name;
1235
1236 marker_d = dir_lookup(channel_d, marker->name);
1237 if (!marker_d)
1238 return -ENOENT;
1239 name = marker_d->d_name.name;
1240
1241 marker_iter_reset(&iter);
1242 marker_iter_start(&iter);
1243 for (; iter.marker != NULL; marker_iter_next(&iter)) {
1244 if (!strcmp(iter.marker->channel, channel) &&
1245 !strcmp(iter.marker->name, name) && mod != iter.module)
1246 count++;
1247 }
1248
1249 if (count > 0)
1250 goto end;
1251
1252 debugfs_remove_recursive(marker_d);
1253 if (list_empty(&channel_d->d_subdirs))
1254 debugfs_remove(channel_d);
1255
1256 end:
1257 marker_iter_stop(&iter);
1258 return 0;
1259 }
1260
1261 static void cleanup_control_dir(struct module *mod, struct marker *begin,
1262 struct marker *end)
1263 {
1264 struct marker *iter;
1265
1266 if (!markers_control_dir)
1267 return;
1268
1269 for (iter = begin; iter < end; iter++)
1270 remove_marker_control_dir(mod, iter);
1271
1272 return;
1273 }
1274
1275 static void build_control_dir(struct module *mod, struct marker *begin,
1276 struct marker *end)
1277 {
1278 struct marker *iter;
1279 int err;
1280
1281 err = 0;
1282 if (!markers_control_dir)
1283 return;
1284
1285 for (iter = begin; iter < end; iter++) {
1286 err = build_marker_file(iter);
1287 if (err)
1288 goto err_build_fail;
1289 }
1290
1291 return;
1292 err_build_fail:
1293 cleanup_control_dir(mod, begin, end);
1294 }
1295
1296 static int module_notify(struct notifier_block *self,
1297 unsigned long val, void *data)
1298 {
1299 struct module *mod = data;
1300
1301 switch (val) {
1302 case MODULE_STATE_COMING:
1303 build_control_dir(mod, mod->markers,
1304 mod->markers + mod->num_markers);
1305 break;
1306 case MODULE_STATE_GOING:
1307 cleanup_control_dir(mod, mod->markers,
1308 mod->markers + mod->num_markers);
1309 break;
1310 }
1311 return NOTIFY_DONE;
1312 }
1313 #else
1314 static inline int module_notify(struct notifier_block *self,
1315 unsigned long val, void *data)
1316 {
1317 return 0;
1318 }
1319 #endif
1320
1321 static struct notifier_block module_nb = {
1322 .notifier_call = module_notify,
1323 };
1324
1325 static int __init ltt_trace_control_init(void)
1326 {
1327 int err = 0;
1328 struct dentry *ltt_root_dentry;
1329
1330 ltt_root_dentry = get_ltt_root();
1331 if (!ltt_root_dentry) {
1332 err = -ENOENT;
1333 goto err_no_root;
1334 }
1335
1336 ltt_control_dir = debugfs_create_dir(LTT_CONTROL_DIR, ltt_root_dentry);
1337 if (IS_ERR(ltt_control_dir) || !ltt_control_dir) {
1338 printk(KERN_ERR
1339 "ltt_channel_control_init: create dir of %s failed\n",
1340 LTT_CONTROL_DIR);
1341 err = -ENOMEM;
1342 goto err_create_control_dir;
1343 }
1344
1345 ltt_setup_trace_file = debugfs_create_file(LTT_SETUP_TRACE_FILE,
1346 S_IWUSR, ltt_root_dentry,
1347 NULL,
1348 &ltt_setup_trace_operations);
1349 if (IS_ERR(ltt_setup_trace_file) || !ltt_setup_trace_file) {
1350 printk(KERN_ERR
1351 "ltt_channel_control_init: create file of %s failed\n",
1352 LTT_SETUP_TRACE_FILE);
1353 err = -ENOMEM;
1354 goto err_create_setup_trace_file;
1355 }
1356
1357 ltt_destroy_trace_file = debugfs_create_file(LTT_DESTROY_TRACE_FILE,
1358 S_IWUSR, ltt_root_dentry,
1359 NULL,
1360 &ltt_destroy_trace_operations);
1361 if (IS_ERR(ltt_destroy_trace_file) || !ltt_destroy_trace_file) {
1362 printk(KERN_ERR
1363 "ltt_channel_control_init: create file of %s failed\n",
1364 LTT_DESTROY_TRACE_FILE);
1365 err = -ENOMEM;
1366 goto err_create_destroy_trace_file;
1367 }
1368
1369 markers_control_dir = debugfs_create_dir(MARKERS_CONTROL_DIR,
1370 ltt_root_dentry);
1371 if (IS_ERR(markers_control_dir) || !markers_control_dir) {
1372 printk(KERN_ERR
1373 "ltt_channel_control_init: create dir of %s failed\n",
1374 MARKERS_CONTROL_DIR);
1375 err = -ENOMEM;
1376 goto err_create_marker_control_dir;
1377 }
1378
1379 init_marker_dir(markers_control_dir, &root_dir_opt);
1380
1381 if (build_marker_control_files())
1382 goto err_build_fail;
1383
1384 if (!register_module_notifier(&module_nb))
1385 return 0;
1386
1387 err_build_fail:
1388 debugfs_remove_recursive(markers_control_dir);
1389 markers_control_dir = NULL;
1390 err_create_marker_control_dir:
1391 debugfs_remove(ltt_destroy_trace_file);
1392 err_create_destroy_trace_file:
1393 debugfs_remove(ltt_setup_trace_file);
1394 err_create_setup_trace_file:
1395 debugfs_remove(ltt_control_dir);
1396 err_create_control_dir:
1397 err_no_root:
1398 return err;
1399 }
1400
1401 static void __exit ltt_trace_control_exit(void)
1402 {
1403 struct dentry *trace_dir;
1404
1405 /* destory all traces */
1406 list_for_each_entry(trace_dir, &ltt_control_dir->d_subdirs,
1407 d_u.d_child) {
1408 ltt_trace_stop(trace_dir->d_name.name);
1409 ltt_trace_destroy(trace_dir->d_name.name);
1410 }
1411
1412 /* clean dirs in debugfs */
1413 debugfs_remove(ltt_setup_trace_file);
1414 debugfs_remove(ltt_destroy_trace_file);
1415 debugfs_remove_recursive(ltt_control_dir);
1416 debugfs_remove_recursive(markers_control_dir);
1417 unregister_module_notifier(&module_nb);
1418 put_ltt_root();
1419 }
1420
1421 module_init(ltt_trace_control_init);
1422 module_exit(ltt_trace_control_exit);
1423
1424 MODULE_LICENSE("GPL and additional rights");
1425 MODULE_AUTHOR("Zhao Lei <zhaolei@cn.fujitsu.com>");
1426 MODULE_DESCRIPTION("Linux Trace Toolkit Trace Controller");
This page took 0.061073 seconds and 5 git commands to generate.