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 jiffies */
368 num
= msecs_to_jiffies(num
);
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
);
738 ltt_trace_destroy(trace_name
);
739 goto err_create_trace_control_dir
;
743 mutex_unlock(&control_lock
);
745 free_page((unsigned long)buf
);
746 free_page((unsigned long)trace_name
);
751 err_create_trace_control_dir
:
752 mutex_unlock(&control_lock
);
755 free_page((unsigned long)buf
);
756 free_page((unsigned long)trace_name
);
760 static const struct file_operations ltt_setup_trace_operations
= {
761 .write
= setup_trace_write
,
765 ssize_t
destroy_trace_write(struct file
*file
, const char __user
*user_buf
,
766 size_t count
, loff_t
*ppos
)
768 struct dentry
*trace_den
;
771 char *buf
= (char *)__get_free_page(GFP_KERNEL
);
772 char *trace_name
= (char *)__get_free_page(GFP_KERNEL
);
774 buf_size
= min_t(size_t, count
, PAGE_SIZE
- 1);
775 err
= copy_from_user(buf
, user_buf
, buf_size
);
777 goto err_copy_from_user
;
780 if (sscanf(buf
, "%s", trace_name
) != 1) {
782 goto err_get_tracename
;
785 mutex_lock(&control_lock
);
787 err
= ltt_trace_destroy(trace_name
);
788 if (IS_ERR_VALUE(err
)) {
790 "destroy_trace_write: ltt_trace_destroy failed: %d\n",
793 goto err_destroy_trace
;
796 trace_den
= dir_lookup(ltt_control_dir
, trace_name
);
799 "destroy_trace_write: lookup for %s's dentry failed\n",
805 debugfs_remove_recursive(trace_den
);
807 mutex_unlock(&control_lock
);
809 free_page((unsigned long)buf
);
810 free_page((unsigned long)trace_name
);
815 mutex_unlock(&control_lock
);
818 free_page((unsigned long)buf
);
819 free_page((unsigned long)trace_name
);
823 static const struct file_operations ltt_destroy_trace_operations
= {
824 .write
= destroy_trace_write
,
827 static void init_marker_dir(struct dentry
*dentry
,
828 const struct inode_operations
*opt
)
830 dentry
->d_inode
->i_op
= opt
;
834 ssize_t
marker_enable_read(struct file
*filp
, char __user
*ubuf
,
835 size_t cnt
, loff_t
*ppos
)
838 const char *channel
, *marker
;
839 int len
, enabled
, present
;
841 marker
= filp
->f_dentry
->d_parent
->d_name
.name
;
842 channel
= filp
->f_dentry
->d_parent
->d_parent
->d_name
.name
;
845 buf
= (char *)__get_free_page(GFP_KERNEL
);
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.
852 enabled
= is_marker_enabled(channel
, marker
);
853 present
= is_marker_present(channel
, marker
);
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);
860 len
= snprintf(buf
, PAGE_SIZE
, "%d\n", 0);
863 if (len
>= PAGE_SIZE
) {
865 buf
[PAGE_SIZE
] = '\0';
867 len
= simple_read_from_buffer(ubuf
, cnt
, ppos
, buf
, len
);
868 free_page((unsigned long)buf
);
874 ssize_t
marker_enable_write(struct file
*filp
, const char __user
*ubuf
,
875 size_t cnt
, loff_t
*ppos
)
877 char *buf
= (char *)__get_free_page(GFP_KERNEL
);
880 const char *channel
, *marker
;
882 marker
= filp
->f_dentry
->d_parent
->d_name
.name
;
883 channel
= filp
->f_dentry
->d_parent
->d_parent
->d_name
.name
;
885 buf_size
= min_t(size_t, cnt
, PAGE_SIZE
- 1);
886 ret
= copy_from_user(buf
, ubuf
, buf_size
);
896 ret
= ltt_marker_connect(channel
, marker
, "default");
903 ret
= ltt_marker_disconnect(channel
, marker
, "default");
913 free_page((unsigned long)buf
);
917 static const struct file_operations enable_fops
= {
918 .read
= marker_enable_read
,
919 .write
= marker_enable_write
,
923 * In practice, the output size should never be larger than 4096 kB. If it
924 * ever happens, the output will simply be truncated.
927 ssize_t
marker_info_read(struct file
*filp
, char __user
*ubuf
,
928 size_t cnt
, loff_t
*ppos
)
931 const char *channel
, *marker
;
933 struct marker_iter iter
;
935 marker
= filp
->f_dentry
->d_parent
->d_name
.name
;
936 channel
= filp
->f_dentry
->d_parent
->d_parent
->d_name
.name
;
939 buf
= (char *)__get_free_page(GFP_KERNEL
);
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");
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
,
955 "format: \"%s\"\nstate: %d\n"
958 "probe %s : 0x%p\n\n",
959 #ifdef CONFIG_MODULES
960 iter
.module
? iter
.module
->name
:
964 _imv_read(iter
.marker
->state
),
965 iter
.marker
->event_id
,
968 "multi" : "single", iter
.marker
->ptype
?
969 (void *)iter
.marker
->multi
:
970 (void *)iter
.marker
->single
.func
);
971 if (len
>= PAGE_SIZE
)
974 marker_iter_stop(&iter
);
977 if (len
>= PAGE_SIZE
) {
979 buf
[PAGE_SIZE
] = '\0';
982 len
= simple_read_from_buffer(ubuf
, cnt
, ppos
, buf
, len
);
983 free_page((unsigned long)buf
);
988 static const struct file_operations info_fops
= {
989 .read
= marker_info_read
,
992 static int marker_mkdir(struct inode
*dir
, struct dentry
*dentry
, int mode
)
994 struct dentry
*marker_d
, *enable_d
, *info_d
, *channel_d
;
998 channel_d
= (struct dentry
*)dir
->i_private
;
999 mutex_unlock(&dir
->i_mutex
);
1001 marker_d
= debugfs_create_dir(dentry
->d_name
.name
,
1003 if (IS_ERR(marker_d
)) {
1004 ret
= PTR_ERR(marker_d
);
1008 enable_d
= debugfs_create_file("enable", 0644, marker_d
,
1009 NULL
, &enable_fops
);
1010 if (IS_ERR(enable_d
) || !enable_d
) {
1012 "%s: create file of %s failed\n",
1013 __func__
, "enable");
1015 goto remove_marker_dir
;
1018 info_d
= debugfs_create_file("info", 0644, marker_d
,
1020 if (IS_ERR(info_d
) || !info_d
) {
1022 "%s: create file of %s failed\n",
1025 goto remove_enable_dir
;
1031 debugfs_remove(enable_d
);
1033 debugfs_remove(marker_d
);
1035 mutex_lock_nested(&dir
->i_mutex
, I_MUTEX_PARENT
);
1039 static int marker_rmdir(struct inode
*dir
, struct dentry
*dentry
)
1041 struct dentry
*marker_d
, *channel_d
;
1042 const char *channel
, *name
;
1043 int ret
, enabled
, present
;
1047 channel_d
= (struct dentry
*)dir
->i_private
;
1048 channel
= channel_d
->d_name
.name
;
1050 marker_d
= dir_lookup(channel_d
, dentry
->d_name
.name
);
1057 name
= marker_d
->d_name
.name
;
1059 enabled
= is_marker_enabled(channel
, name
);
1060 present
= is_marker_present(channel
, name
);
1062 if (present
|| (!present
&& enabled
)) {
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
);
1076 const struct inode_operations channel_dir_opt
= {
1077 .lookup
= simple_lookup
,
1078 .mkdir
= marker_mkdir
,
1079 .rmdir
= marker_rmdir
,
1082 static int channel_mkdir(struct inode
*dir
, struct dentry
*dentry
, int mode
)
1084 struct dentry
*channel_d
;
1088 mutex_unlock(&dir
->i_mutex
);
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
);
1097 channel_d
->d_inode
->i_private
= (void *)channel_d
;
1098 init_marker_dir(channel_d
, &channel_dir_opt
);
1100 mutex_lock_nested(&dir
->i_mutex
, I_MUTEX_PARENT
);
1104 static int channel_rmdir(struct inode
*dir
, struct dentry
*dentry
)
1106 struct dentry
*channel_d
;
1111 channel_d
= dir_lookup(markers_control_dir
, dentry
->d_name
.name
);
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
);
1130 const struct inode_operations root_dir_opt
= {
1131 .lookup
= simple_lookup
,
1132 .mkdir
= channel_mkdir
,
1133 .rmdir
= channel_rmdir
1136 static int build_marker_file(struct marker
*marker
)
1138 struct dentry
*channel_d
, *marker_d
, *enable_d
, *info_d
;
1141 channel_d
= dir_lookup(markers_control_dir
, marker
->channel
);
1143 channel_d
= debugfs_create_dir(marker
->channel
,
1144 markers_control_dir
);
1145 if (IS_ERR(channel_d
) || !channel_d
) {
1147 "%s: build channel dir of %s failed\n",
1148 __func__
, marker
->channel
);
1150 goto err_build_fail
;
1152 channel_d
->d_inode
->i_private
= (void *)channel_d
;
1153 init_marker_dir(channel_d
, &channel_dir_opt
);
1156 marker_d
= dir_lookup(channel_d
, marker
->name
);
1158 marker_d
= debugfs_create_dir(marker
->name
, channel_d
);
1159 if (IS_ERR(marker_d
) || !marker_d
) {
1161 "%s: marker dir of %s failed\n",
1162 __func__
, marker
->name
);
1164 goto err_build_fail
;
1168 enable_d
= dir_lookup(marker_d
, "enable");
1170 enable_d
= debugfs_create_file("enable", 0644, marker_d
,
1171 NULL
, &enable_fops
);
1172 if (IS_ERR(enable_d
) || !enable_d
) {
1174 "%s: create file of %s failed\n",
1175 __func__
, "enable");
1177 goto err_build_fail
;
1181 info_d
= dir_lookup(marker_d
, "info");
1183 info_d
= debugfs_create_file("info", 0444, marker_d
,
1185 if (IS_ERR(info_d
) || !info_d
) {
1187 "%s: create file of %s failed\n",
1188 __func__
, "enable");
1190 goto err_build_fail
;
1200 static int build_marker_control_files(void)
1202 struct marker_iter iter
;
1206 if (!markers_control_dir
)
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
);
1216 marker_iter_stop(&iter
);
1222 #ifdef CONFIG_MODULES
1223 static int remove_marker_control_dir(struct module
*mod
, struct marker
*marker
)
1225 struct dentry
*channel_d
, *marker_d
;
1226 const char *channel
, *name
;
1228 struct marker_iter iter
;
1232 channel_d
= dir_lookup(markers_control_dir
, marker
->channel
);
1235 channel
= channel_d
->d_name
.name
;
1237 marker_d
= dir_lookup(channel_d
, marker
->name
);
1240 name
= marker_d
->d_name
.name
;
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
)
1253 debugfs_remove_recursive(marker_d
);
1254 if (list_empty(&channel_d
->d_subdirs
))
1255 debugfs_remove(channel_d
);
1258 marker_iter_stop(&iter
);
1262 static void cleanup_control_dir(struct module
*mod
, struct marker
*begin
,
1265 struct marker
*iter
;
1267 if (!markers_control_dir
)
1270 for (iter
= begin
; iter
< end
; iter
++)
1271 remove_marker_control_dir(mod
, iter
);
1276 static void build_control_dir(struct module
*mod
, struct marker
*begin
,
1279 struct marker
*iter
;
1283 if (!markers_control_dir
)
1286 for (iter
= begin
; iter
< end
; iter
++) {
1287 err
= build_marker_file(iter
);
1289 goto err_build_fail
;
1294 cleanup_control_dir(mod
, begin
, end
);
1297 static int module_notify(struct notifier_block
*self
,
1298 unsigned long val
, void *data
)
1300 struct module
*mod
= data
;
1303 case MODULE_STATE_COMING
:
1304 build_control_dir(mod
, mod
->markers
,
1305 mod
->markers
+ mod
->num_markers
);
1307 case MODULE_STATE_GOING
:
1308 cleanup_control_dir(mod
, mod
->markers
,
1309 mod
->markers
+ mod
->num_markers
);
1315 static inline int module_notify(struct notifier_block
*self
,
1316 unsigned long val
, void *data
)
1322 static struct notifier_block module_nb
= {
1323 .notifier_call
= module_notify
,
1326 static int __init
ltt_trace_control_init(void)
1329 struct dentry
*ltt_root_dentry
;
1331 ltt_root_dentry
= get_ltt_root();
1332 if (!ltt_root_dentry
) {
1337 ltt_control_dir
= debugfs_create_dir(LTT_CONTROL_DIR
, ltt_root_dentry
);
1338 if (IS_ERR(ltt_control_dir
) || !ltt_control_dir
) {
1340 "ltt_channel_control_init: create dir of %s failed\n",
1343 goto err_create_control_dir
;
1346 ltt_setup_trace_file
= debugfs_create_file(LTT_SETUP_TRACE_FILE
,
1347 S_IWUSR
, ltt_root_dentry
,
1349 <t_setup_trace_operations
);
1350 if (IS_ERR(ltt_setup_trace_file
) || !ltt_setup_trace_file
) {
1352 "ltt_channel_control_init: create file of %s failed\n",
1353 LTT_SETUP_TRACE_FILE
);
1355 goto err_create_setup_trace_file
;
1358 ltt_destroy_trace_file
= debugfs_create_file(LTT_DESTROY_TRACE_FILE
,
1359 S_IWUSR
, ltt_root_dentry
,
1361 <t_destroy_trace_operations
);
1362 if (IS_ERR(ltt_destroy_trace_file
) || !ltt_destroy_trace_file
) {
1364 "ltt_channel_control_init: create file of %s failed\n",
1365 LTT_DESTROY_TRACE_FILE
);
1367 goto err_create_destroy_trace_file
;
1370 markers_control_dir
= debugfs_create_dir(MARKERS_CONTROL_DIR
,
1372 if (IS_ERR(markers_control_dir
) || !markers_control_dir
) {
1374 "ltt_channel_control_init: create dir of %s failed\n",
1375 MARKERS_CONTROL_DIR
);
1377 goto err_create_marker_control_dir
;
1380 init_marker_dir(markers_control_dir
, &root_dir_opt
);
1382 if (build_marker_control_files())
1383 goto err_build_fail
;
1385 if (!register_module_notifier(&module_nb
))
1389 debugfs_remove_recursive(markers_control_dir
);
1390 markers_control_dir
= NULL
;
1391 err_create_marker_control_dir
:
1392 debugfs_remove(ltt_destroy_trace_file
);
1393 err_create_destroy_trace_file
:
1394 debugfs_remove(ltt_setup_trace_file
);
1395 err_create_setup_trace_file
:
1396 debugfs_remove(ltt_control_dir
);
1397 err_create_control_dir
:
1402 static void __exit
ltt_trace_control_exit(void)
1404 struct dentry
*trace_dir
;
1406 /* destory all traces */
1407 list_for_each_entry(trace_dir
, <t_control_dir
->d_subdirs
,
1409 ltt_trace_stop(trace_dir
->d_name
.name
);
1410 ltt_trace_destroy(trace_dir
->d_name
.name
);
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
);
1422 module_init(ltt_trace_control_init
);
1423 module_exit(ltt_trace_control_exit
);
1425 MODULE_LICENSE("GPL and additional rights");
1426 MODULE_AUTHOR("Zhao Lei <zhaolei@cn.fujitsu.com>");
1427 MODULE_DESCRIPTION("Linux Trace Toolkit Trace Controller");