2 * LTT trace control module over debugfs.
4 * Copyright 2008 - Zhaolei <zhaolei@cn.fujitsu.com>
6 * Copyright 2009 - Gui Jianfeng <guijianfeng@cn.fujitsu.com>
7 * Make mark-control work in debugfs
9 * Dual LGPL v2.1/GPL v2 license.
14 * Impl read operations for control file to read attributes
15 * Create a README file in ltt control dir, for display help info
18 #include <linux/module.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>
26 #include "ltt-tracer.h"
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"
33 #define LTT_WRITE_MAXLEN (128)
35 struct dentry
*ltt_control_dir
, *ltt_setup_trace_file
, *ltt_destroy_trace_file
,
39 * the traces_lock nests inside control_lock.
40 * control_lock protects the consistency of directories presented in ltt
43 static DEFINE_MUTEX(control_lock
);
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.
57 * lookup a file/dir in parent dir.
58 * only designed to work well for debugfs.
59 * (although it maybe ok for other fs)
62 * file/dir's dentry on success
65 static struct dentry
*dir_lookup(struct dentry
*parent
, const char *name
)
72 q
.hash
= full_name_hash(q
.name
, q
.len
);
74 d
= d_lookup(parent
, &q
);
82 static ssize_t
alloc_write(struct file
*file
, const char __user
*user_buf
,
83 size_t count
, loff_t
*ppos
)
87 char *buf
= (char *)__get_free_page(GFP_KERNEL
);
88 char *cmd
= (char *)__get_free_page(GFP_KERNEL
);
90 buf_size
= min_t(size_t, count
, PAGE_SIZE
- 1);
91 err
= copy_from_user(buf
, user_buf
, buf_size
);
93 goto err_copy_from_user
;
96 if (sscanf(buf
, "%s", cmd
) != 1) {
101 if ((cmd
[0] != 'Y' && cmd
[0] != 'y' && cmd
[0] != '1') || cmd
[1]) {
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",
110 goto err_alloc_trace
;
113 free_page((unsigned long)buf
);
114 free_page((unsigned long)cmd
);
121 free_page((unsigned long)buf
);
122 free_page((unsigned long)cmd
);
126 static const struct file_operations ltt_alloc_operations
= {
127 .write
= alloc_write
,
131 static ssize_t
enabled_write(struct file
*file
, const char __user
*user_buf
,
132 size_t count
, loff_t
*ppos
)
136 char *buf
= (char *)__get_free_page(GFP_KERNEL
);
137 char *cmd
= (char *)__get_free_page(GFP_KERNEL
);
139 buf_size
= min_t(size_t, count
, PAGE_SIZE
- 1);
140 err
= copy_from_user(buf
, user_buf
, buf_size
);
142 goto err_copy_from_user
;
145 if (sscanf(buf
, "%s", cmd
) != 1) {
159 err
= ltt_trace_start(file
->f_dentry
->d_parent
->d_name
.name
);
160 if (IS_ERR_VALUE(err
)) {
162 "enabled_write: ltt_trace_start failed: %d\n",
165 goto err_start_trace
;
171 err
= ltt_trace_stop(file
->f_dentry
->d_parent
->d_name
.name
);
172 if (IS_ERR_VALUE(err
)) {
174 "enabled_write: ltt_trace_stop failed: %d\n",
185 free_page((unsigned long)buf
);
186 free_page((unsigned long)cmd
);
194 free_page((unsigned long)buf
);
195 free_page((unsigned long)cmd
);
199 static const struct file_operations ltt_enabled_operations
= {
200 .write
= enabled_write
,
204 static ssize_t
trans_write(struct file
*file
, const char __user
*user_buf
,
205 size_t count
, loff_t
*ppos
)
207 char *buf
= (char *)__get_free_page(GFP_KERNEL
);
208 char *trans_name
= (char *)__get_free_page(GFP_KERNEL
);
212 buf_size
= min_t(size_t, count
, PAGE_SIZE
- 1);
213 err
= copy_from_user(buf
, user_buf
, buf_size
);
215 goto err_copy_from_user
;
218 if (sscanf(buf
, "%s", trans_name
) != 1) {
220 goto err_get_transname
;
223 err
= ltt_trace_set_type(file
->f_dentry
->d_parent
->d_name
.name
,
225 if (IS_ERR_VALUE(err
)) {
226 printk(KERN_ERR
"trans_write: ltt_trace_set_type failed: %d\n",
231 free_page((unsigned long)buf
);
232 free_page((unsigned long)trans_name
);
238 free_page((unsigned long)buf
);
239 free_page((unsigned long)trans_name
);
243 static const struct file_operations ltt_trans_operations
= {
244 .write
= trans_write
,
248 static ssize_t
channel_subbuf_num_write(struct file
*file
,
249 const char __user
*user_buf
, size_t count
, loff_t
*ppos
)
254 const char *channel_name
;
255 const char *trace_name
;
256 char *buf
= (char *)__get_free_page(GFP_KERNEL
);
258 buf_size
= min_t(size_t, count
, PAGE_SIZE
- 1);
259 err
= copy_from_user(buf
, user_buf
, buf_size
);
261 goto err_copy_from_user
;
264 if (sscanf(buf
, "%u", &num
) != 1) {
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
;
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
;
279 free_page((unsigned long)buf
);
285 free_page((unsigned long)buf
);
289 static const struct file_operations ltt_channel_subbuf_num_operations
= {
290 .write
= channel_subbuf_num_write
,
295 ssize_t
channel_subbuf_size_write(struct file
*file
,
296 const char __user
*user_buf
,
297 size_t count
, loff_t
*ppos
)
302 const char *channel_name
;
303 const char *trace_name
;
304 char *buf
= (char *)__get_free_page(GFP_KERNEL
);
306 buf_size
= min_t(size_t, count
, PAGE_SIZE
- 1);
307 err
= copy_from_user(buf
, user_buf
, buf_size
);
309 goto err_copy_from_user
;
312 if (sscanf(buf
, "%u", &num
) != 1) {
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
;
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
;
327 free_page((unsigned long)buf
);
333 free_page((unsigned long)buf
);
337 static const struct file_operations ltt_channel_subbuf_size_operations
= {
338 .write
= channel_subbuf_size_write
,
342 ssize_t
channel_switch_timer_write(struct file
*file
,
343 const char __user
*user_buf
,
344 size_t count
, loff_t
*ppos
)
349 const char *channel_name
;
350 const char *trace_name
;
351 char *buf
= (char *)__get_free_page(GFP_KERNEL
);
353 buf_size
= min_t(size_t, count
, PAGE_SIZE
- 1);
354 err
= copy_from_user(buf
, user_buf
, buf_size
);
356 goto err_copy_from_user
;
359 if (sscanf(buf
, "%lu", &num
) != 1) {
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
;
367 /* Convert from ms to us */
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
;
377 free_page((unsigned long)buf
);
380 err_set_switch_timer
:
383 free_page((unsigned long)buf
);
387 static struct file_operations ltt_channel_switch_timer_operations
= {
388 .write
= channel_switch_timer_write
,
392 ssize_t
channel_overwrite_write(struct file
*file
,
393 const char __user
*user_buf
, size_t count
,
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
);
403 buf_size
= min_t(size_t, count
, PAGE_SIZE
- 1);
404 err
= copy_from_user(buf
, user_buf
, buf_size
);
406 goto err_copy_from_user
;
409 if (sscanf(buf
, "%s", cmd
) != 1) {
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
;
426 err
= ltt_trace_set_channel_overwrite(trace_name
, channel_name
,
428 if (IS_ERR_VALUE(err
)) {
429 printk(KERN_ERR
"channel_overwrite_write: "
430 "ltt_trace_set_channel_overwrite failed: %d\n",
432 goto err_set_subbufsize
;
438 err
= ltt_trace_set_channel_overwrite(trace_name
, channel_name
,
440 if (IS_ERR_VALUE(err
)) {
441 printk(KERN_ERR
"channel_overwrite_write: "
442 "ltt_trace_set_channel_overwrite failed: %d\n",
444 goto err_set_subbufsize
;
452 free_page((unsigned long)buf
);
453 free_page((unsigned long)cmd
);
460 free_page((unsigned long)buf
);
461 free_page((unsigned long)cmd
);
465 static const struct file_operations ltt_channel_overwrite_operations
= {
466 .write
= channel_overwrite_write
,
471 ssize_t
channel_enable_write(struct file
*file
,
472 const char __user
*user_buf
, size_t count
,
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
);
482 buf_size
= min_t(size_t, count
, PAGE_SIZE
- 1);
483 err
= copy_from_user(buf
, user_buf
, buf_size
);
485 goto err_copy_from_user
;
488 if (sscanf(buf
, "%s", cmd
) != 1) {
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
;
505 err
= ltt_trace_set_channel_enable(trace_name
, channel_name
,
507 if (IS_ERR_VALUE(err
)) {
508 printk(KERN_ERR
"channel_enable_write: "
509 "ltt_trace_set_channel_enable failed: %d\n",
511 goto err_set_subbufsize
;
517 err
= ltt_trace_set_channel_enable(trace_name
, channel_name
,
519 if (IS_ERR_VALUE(err
)) {
520 printk(KERN_ERR
"channel_enable_write: "
521 "ltt_trace_set_channel_enable failed: %d\n",
523 goto err_set_subbufsize
;
531 free_page((unsigned long)buf
);
532 free_page((unsigned long)cmd
);
539 free_page((unsigned long)buf
);
540 free_page((unsigned long)cmd
);
544 static const struct file_operations ltt_channel_enable_operations
= {
545 .write
= channel_enable_write
,
549 static int _create_trace_control_dir(const char *trace_name
,
550 struct ltt_trace
*trace
)
553 struct dentry
*trace_root
, *channel_root
;
554 struct dentry
*tmp_den
;
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
);
563 goto err_create_trace_root
;
566 /* debugfs/control/trace_name/alloc */
567 tmp_den
= debugfs_create_file("alloc", S_IWUSR
, trace_root
, NULL
,
568 <t_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");
573 goto err_create_subdir
;
576 /* debugfs/control/trace_name/trans */
577 tmp_den
= debugfs_create_file("trans", S_IWUSR
, trace_root
, NULL
,
578 <t_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");
583 goto err_create_subdir
;
586 /* debugfs/control/trace_name/enabled */
587 tmp_den
= debugfs_create_file("enabled", S_IWUSR
, trace_root
, NULL
,
588 <t_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");
593 goto err_create_subdir
;
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");
602 goto err_create_subdir
;
606 * Create dir and files in debugfs/ltt/control/trace_name/channel/
607 * Following things(without <>) will be created:
620 for (i
= 0; i
< trace
->nr_channels
; i
++) {
621 struct dentry
*channel_den
;
622 struct ltt_chan
*chan
;
624 chan
= &trace
->channels
[i
];
627 channel_den
= debugfs_create_dir(chan
->a
.filename
,
629 if (IS_ERR(channel_den
) || !channel_den
) {
630 printk(KERN_ERR
"_create_trace_control_dir: "
631 "create channel dir of %s failed\n",
634 goto err_create_subdir
;
637 tmp_den
= debugfs_create_file("subbuf_num", S_IWUSR
,
639 <t_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",
645 goto err_create_subdir
;
648 tmp_den
= debugfs_create_file("subbuf_size", S_IWUSR
,
650 <t_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",
656 goto err_create_subdir
;
659 tmp_den
= debugfs_create_file("enable", S_IWUSR
, channel_den
,
661 <t_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",
667 goto err_create_subdir
;
670 tmp_den
= debugfs_create_file("overwrite", S_IWUSR
, channel_den
,
672 <t_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",
678 goto err_create_subdir
;
681 tmp_den
= debugfs_create_file("switch_timer", S_IWUSR
,
683 <t_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",
689 goto err_create_subdir
;
696 debugfs_remove_recursive(trace_root
);
697 err_create_trace_root
:
702 ssize_t
setup_trace_write(struct file
*file
, const char __user
*user_buf
,
703 size_t count
, loff_t
*ppos
)
707 struct ltt_trace
*trace
;
708 char *buf
= (char *)__get_free_page(GFP_KERNEL
);
709 char *trace_name
= (char *)__get_free_page(GFP_KERNEL
);
711 buf_size
= min_t(size_t, count
, PAGE_SIZE
- 1);
712 err
= copy_from_user(buf
, user_buf
, buf_size
);
714 goto err_copy_from_user
;
717 if (sscanf(buf
, "%s", trace_name
) != 1) {
719 goto err_get_tracename
;
722 mutex_lock(&control_lock
);
725 err
= _ltt_trace_setup(trace_name
);
726 if (IS_ERR_VALUE(err
)) {
728 "setup_trace_write: ltt_trace_setup failed: %d\n", err
);
729 goto err_setup_trace
;
731 trace
= _ltt_trace_find_setup(trace_name
);
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
;
741 mutex_unlock(&control_lock
);
743 free_page((unsigned long)buf
);
744 free_page((unsigned long)trace_name
);
747 err_create_trace_control_dir
:
748 ltt_trace_destroy(trace_name
);
751 mutex_unlock(&control_lock
);
754 free_page((unsigned long)buf
);
755 free_page((unsigned long)trace_name
);
759 static const struct file_operations ltt_setup_trace_operations
= {
760 .write
= setup_trace_write
,
764 ssize_t
destroy_trace_write(struct file
*file
, const char __user
*user_buf
,
765 size_t count
, loff_t
*ppos
)
767 struct dentry
*trace_den
;
770 char *buf
= (char *)__get_free_page(GFP_KERNEL
);
771 char *trace_name
= (char *)__get_free_page(GFP_KERNEL
);
773 buf_size
= min_t(size_t, count
, PAGE_SIZE
- 1);
774 err
= copy_from_user(buf
, user_buf
, buf_size
);
776 goto err_copy_from_user
;
779 if (sscanf(buf
, "%s", trace_name
) != 1) {
781 goto err_get_tracename
;
784 mutex_lock(&control_lock
);
786 err
= ltt_trace_destroy(trace_name
);
787 if (IS_ERR_VALUE(err
)) {
789 "destroy_trace_write: ltt_trace_destroy failed: %d\n",
792 goto err_destroy_trace
;
795 trace_den
= dir_lookup(ltt_control_dir
, trace_name
);
798 "destroy_trace_write: lookup for %s's dentry failed\n",
804 debugfs_remove_recursive(trace_den
);
806 mutex_unlock(&control_lock
);
808 free_page((unsigned long)buf
);
809 free_page((unsigned long)trace_name
);
814 mutex_unlock(&control_lock
);
817 free_page((unsigned long)buf
);
818 free_page((unsigned long)trace_name
);
822 static const struct file_operations ltt_destroy_trace_operations
= {
823 .write
= destroy_trace_write
,
826 static void init_marker_dir(struct dentry
*dentry
,
827 const struct inode_operations
*opt
)
829 dentry
->d_inode
->i_op
= opt
;
833 ssize_t
marker_enable_read(struct file
*filp
, char __user
*ubuf
,
834 size_t cnt
, loff_t
*ppos
)
837 const char *channel
, *marker
;
838 int len
, enabled
, present
;
840 marker
= filp
->f_dentry
->d_parent
->d_name
.name
;
841 channel
= filp
->f_dentry
->d_parent
->d_parent
->d_name
.name
;
844 buf
= (char *)__get_free_page(GFP_KERNEL
);
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.
851 enabled
= is_marker_enabled(channel
, marker
);
852 present
= is_marker_present(channel
, marker
);
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);
859 len
= snprintf(buf
, PAGE_SIZE
, "%d\n", 0);
862 if (len
>= PAGE_SIZE
) {
864 buf
[PAGE_SIZE
] = '\0';
866 len
= simple_read_from_buffer(ubuf
, cnt
, ppos
, buf
, len
);
867 free_page((unsigned long)buf
);
873 ssize_t
marker_enable_write(struct file
*filp
, const char __user
*ubuf
,
874 size_t cnt
, loff_t
*ppos
)
876 char *buf
= (char *)__get_free_page(GFP_KERNEL
);
879 const char *channel
, *marker
;
881 marker
= filp
->f_dentry
->d_parent
->d_name
.name
;
882 channel
= filp
->f_dentry
->d_parent
->d_parent
->d_name
.name
;
884 buf_size
= min_t(size_t, cnt
, PAGE_SIZE
- 1);
885 ret
= copy_from_user(buf
, ubuf
, buf_size
);
895 ret
= ltt_marker_connect(channel
, marker
, "default");
902 ret
= ltt_marker_disconnect(channel
, marker
, "default");
912 free_page((unsigned long)buf
);
916 static const struct file_operations enable_fops
= {
917 .read
= marker_enable_read
,
918 .write
= marker_enable_write
,
922 * In practice, the output size should never be larger than 4096 kB. If it
923 * ever happens, the output will simply be truncated.
926 ssize_t
marker_info_read(struct file
*filp
, char __user
*ubuf
,
927 size_t cnt
, loff_t
*ppos
)
930 const char *channel
, *marker
;
932 struct marker_iter iter
;
934 marker
= filp
->f_dentry
->d_parent
->d_name
.name
;
935 channel
= filp
->f_dentry
->d_parent
->d_parent
->d_name
.name
;
938 buf
= (char *)__get_free_page(GFP_KERNEL
);
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");
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
,
954 "format: \"%s\"\nstate: %d\n"
957 "probe %s : 0x%p\n\n",
958 #ifdef CONFIG_MODULES
959 iter
.module
? iter
.module
->name
:
963 _imv_read(iter
.marker
->state
),
964 iter
.marker
->event_id
,
967 "multi" : "single", iter
.marker
->ptype
?
968 (void *)iter
.marker
->multi
:
969 (void *)iter
.marker
->single
.func
);
970 if (len
>= PAGE_SIZE
)
973 marker_iter_stop(&iter
);
976 if (len
>= PAGE_SIZE
) {
978 buf
[PAGE_SIZE
] = '\0';
981 len
= simple_read_from_buffer(ubuf
, cnt
, ppos
, buf
, len
);
982 free_page((unsigned long)buf
);
987 static const struct file_operations info_fops
= {
988 .read
= marker_info_read
,
991 static int marker_mkdir(struct inode
*dir
, struct dentry
*dentry
, int mode
)
993 struct dentry
*marker_d
, *enable_d
, *info_d
, *channel_d
;
997 channel_d
= (struct dentry
*)dir
->i_private
;
998 mutex_unlock(&dir
->i_mutex
);
1000 marker_d
= debugfs_create_dir(dentry
->d_name
.name
,
1002 if (IS_ERR(marker_d
)) {
1003 ret
= PTR_ERR(marker_d
);
1007 enable_d
= debugfs_create_file("enable", 0644, marker_d
,
1008 NULL
, &enable_fops
);
1009 if (IS_ERR(enable_d
) || !enable_d
) {
1011 "%s: create file of %s failed\n",
1012 __func__
, "enable");
1014 goto remove_marker_dir
;
1017 info_d
= debugfs_create_file("info", 0644, marker_d
,
1019 if (IS_ERR(info_d
) || !info_d
) {
1021 "%s: create file of %s failed\n",
1024 goto remove_enable_dir
;
1030 debugfs_remove(enable_d
);
1032 debugfs_remove(marker_d
);
1034 mutex_lock_nested(&dir
->i_mutex
, I_MUTEX_PARENT
);
1038 static int marker_rmdir(struct inode
*dir
, struct dentry
*dentry
)
1040 struct dentry
*marker_d
, *channel_d
;
1041 const char *channel
, *name
;
1042 int ret
, enabled
, present
;
1046 channel_d
= (struct dentry
*)dir
->i_private
;
1047 channel
= channel_d
->d_name
.name
;
1049 marker_d
= dir_lookup(channel_d
, dentry
->d_name
.name
);
1056 name
= marker_d
->d_name
.name
;
1058 enabled
= is_marker_enabled(channel
, name
);
1059 present
= is_marker_present(channel
, name
);
1061 if (present
|| (!present
&& enabled
)) {
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
);
1075 const struct inode_operations channel_dir_opt
= {
1076 .lookup
= simple_lookup
,
1077 .mkdir
= marker_mkdir
,
1078 .rmdir
= marker_rmdir
,
1081 static int channel_mkdir(struct inode
*dir
, struct dentry
*dentry
, int mode
)
1083 struct dentry
*channel_d
;
1087 mutex_unlock(&dir
->i_mutex
);
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
);
1096 channel_d
->d_inode
->i_private
= (void *)channel_d
;
1097 init_marker_dir(channel_d
, &channel_dir_opt
);
1099 mutex_lock_nested(&dir
->i_mutex
, I_MUTEX_PARENT
);
1103 static int channel_rmdir(struct inode
*dir
, struct dentry
*dentry
)
1105 struct dentry
*channel_d
;
1110 channel_d
= dir_lookup(markers_control_dir
, dentry
->d_name
.name
);
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
);
1129 const struct inode_operations root_dir_opt
= {
1130 .lookup
= simple_lookup
,
1131 .mkdir
= channel_mkdir
,
1132 .rmdir
= channel_rmdir
1135 static int build_marker_file(struct marker
*marker
)
1137 struct dentry
*channel_d
, *marker_d
, *enable_d
, *info_d
;
1140 channel_d
= dir_lookup(markers_control_dir
, marker
->channel
);
1142 channel_d
= debugfs_create_dir(marker
->channel
,
1143 markers_control_dir
);
1144 if (IS_ERR(channel_d
) || !channel_d
) {
1146 "%s: build channel dir of %s failed\n",
1147 __func__
, marker
->channel
);
1149 goto err_build_fail
;
1151 channel_d
->d_inode
->i_private
= (void *)channel_d
;
1152 init_marker_dir(channel_d
, &channel_dir_opt
);
1155 marker_d
= dir_lookup(channel_d
, marker
->name
);
1157 marker_d
= debugfs_create_dir(marker
->name
, channel_d
);
1158 if (IS_ERR(marker_d
) || !marker_d
) {
1160 "%s: marker dir of %s failed\n",
1161 __func__
, marker
->name
);
1163 goto err_build_fail
;
1167 enable_d
= dir_lookup(marker_d
, "enable");
1169 enable_d
= debugfs_create_file("enable", 0644, marker_d
,
1170 NULL
, &enable_fops
);
1171 if (IS_ERR(enable_d
) || !enable_d
) {
1173 "%s: create file of %s failed\n",
1174 __func__
, "enable");
1176 goto err_build_fail
;
1180 info_d
= dir_lookup(marker_d
, "info");
1182 info_d
= debugfs_create_file("info", 0444, marker_d
,
1184 if (IS_ERR(info_d
) || !info_d
) {
1186 "%s: create file of %s failed\n",
1187 __func__
, "enable");
1189 goto err_build_fail
;
1199 static int build_marker_control_files(void)
1201 struct marker_iter iter
;
1205 if (!markers_control_dir
)
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
);
1215 marker_iter_stop(&iter
);
1221 #ifdef CONFIG_MODULES
1222 static int remove_marker_control_dir(struct module
*mod
, struct marker
*marker
)
1224 struct dentry
*channel_d
, *marker_d
;
1225 const char *channel
, *name
;
1227 struct marker_iter iter
;
1231 channel_d
= dir_lookup(markers_control_dir
, marker
->channel
);
1234 channel
= channel_d
->d_name
.name
;
1236 marker_d
= dir_lookup(channel_d
, marker
->name
);
1239 name
= marker_d
->d_name
.name
;
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
)
1252 debugfs_remove_recursive(marker_d
);
1253 if (list_empty(&channel_d
->d_subdirs
))
1254 debugfs_remove(channel_d
);
1257 marker_iter_stop(&iter
);
1261 static void cleanup_control_dir(struct module
*mod
, struct marker
*begin
,
1264 struct marker
*iter
;
1266 if (!markers_control_dir
)
1269 for (iter
= begin
; iter
< end
; iter
++)
1270 remove_marker_control_dir(mod
, iter
);
1275 static void build_control_dir(struct module
*mod
, struct marker
*begin
,
1278 struct marker
*iter
;
1282 if (!markers_control_dir
)
1285 for (iter
= begin
; iter
< end
; iter
++) {
1286 err
= build_marker_file(iter
);
1288 goto err_build_fail
;
1293 cleanup_control_dir(mod
, begin
, end
);
1296 static int module_notify(struct notifier_block
*self
,
1297 unsigned long val
, void *data
)
1299 struct module
*mod
= data
;
1302 case MODULE_STATE_COMING
:
1303 build_control_dir(mod
, mod
->markers
,
1304 mod
->markers
+ mod
->num_markers
);
1306 case MODULE_STATE_GOING
:
1307 cleanup_control_dir(mod
, mod
->markers
,
1308 mod
->markers
+ mod
->num_markers
);
1314 static inline int module_notify(struct notifier_block
*self
,
1315 unsigned long val
, void *data
)
1321 static struct notifier_block module_nb
= {
1322 .notifier_call
= module_notify
,
1325 static int __init
ltt_trace_control_init(void)
1328 struct dentry
*ltt_root_dentry
;
1330 ltt_root_dentry
= get_ltt_root();
1331 if (!ltt_root_dentry
) {
1336 ltt_control_dir
= debugfs_create_dir(LTT_CONTROL_DIR
, ltt_root_dentry
);
1337 if (IS_ERR(ltt_control_dir
) || !ltt_control_dir
) {
1339 "ltt_channel_control_init: create dir of %s failed\n",
1342 goto err_create_control_dir
;
1345 ltt_setup_trace_file
= debugfs_create_file(LTT_SETUP_TRACE_FILE
,
1346 S_IWUSR
, ltt_root_dentry
,
1348 <t_setup_trace_operations
);
1349 if (IS_ERR(ltt_setup_trace_file
) || !ltt_setup_trace_file
) {
1351 "ltt_channel_control_init: create file of %s failed\n",
1352 LTT_SETUP_TRACE_FILE
);
1354 goto err_create_setup_trace_file
;
1357 ltt_destroy_trace_file
= debugfs_create_file(LTT_DESTROY_TRACE_FILE
,
1358 S_IWUSR
, ltt_root_dentry
,
1360 <t_destroy_trace_operations
);
1361 if (IS_ERR(ltt_destroy_trace_file
) || !ltt_destroy_trace_file
) {
1363 "ltt_channel_control_init: create file of %s failed\n",
1364 LTT_DESTROY_TRACE_FILE
);
1366 goto err_create_destroy_trace_file
;
1369 markers_control_dir
= debugfs_create_dir(MARKERS_CONTROL_DIR
,
1371 if (IS_ERR(markers_control_dir
) || !markers_control_dir
) {
1373 "ltt_channel_control_init: create dir of %s failed\n",
1374 MARKERS_CONTROL_DIR
);
1376 goto err_create_marker_control_dir
;
1379 init_marker_dir(markers_control_dir
, &root_dir_opt
);
1381 if (build_marker_control_files())
1382 goto err_build_fail
;
1384 if (!register_module_notifier(&module_nb
))
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
:
1401 static void __exit
ltt_trace_control_exit(void)
1403 struct dentry
*trace_dir
;
1405 /* destory all traces */
1406 list_for_each_entry(trace_dir
, <t_control_dir
->d_subdirs
,
1408 ltt_trace_stop(trace_dir
->d_name
.name
);
1409 ltt_trace_destroy(trace_dir
->d_name
.name
);
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
);
1421 module_init(ltt_trace_control_init
);
1422 module_exit(ltt_trace_control_exit
);
1424 MODULE_LICENSE("GPL and additional rights");
1425 MODULE_AUTHOR("Zhao Lei <zhaolei@cn.fujitsu.com>");
1426 MODULE_DESCRIPTION("Linux Trace Toolkit Trace Controller");