2 * ltt/probes/jbd2-trace.c
4 * JBD2 tracepoint probes.
6 * (C) Copyright 2009 - Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
7 * Dual LGPL v2.1/GPL v2 license.
10 #include <linux/module.h>
11 #include <linux/debugfs.h>
12 #include <linux/mutex.h>
13 #include <linux/rcupdate.h>
14 #include <trace/events/jbd2.h>
16 #include "../ltt-tracer.h"
18 static struct dentry
*jbd2_filter_dentry
, *jbd2_filter_dev_dentry
;
19 static DEFINE_MUTEX(jbd2_filter_mutex
);
20 /* Make sure we don't race between module exit and file write */
21 static int module_exits
;
23 struct rcu_dev_filter
{
25 char devname
[NAME_MAX
];
28 static struct rcu_dev_filter
*dev_filter
;
31 * Probes are executed in rcu_sched read-side critical section.
33 static int do_filter(const char *dev
)
35 struct rcu_dev_filter
*ldev_filter
= rcu_dereference(dev_filter
);
37 if (unlikely(ldev_filter
))
38 if (unlikely(strcmp(ldev_filter
->devname
, dev
)))
43 void probe_jbd2_checkpoint(void *data
, journal_t
*journal
, int result
)
45 if (unlikely(!do_filter(journal
->j_devname
)))
47 trace_mark_tp(jbd2
, checkpoint
, jbd2_checkpoint
,
48 probe_jbd2_checkpoint
, "dev %s need_checkpoint %d",
49 journal
->j_devname
, result
);
52 void probe_jbd2_start_commit(void *data
, journal_t
*journal
,
53 transaction_t
*commit_transaction
)
55 if (unlikely(!do_filter(journal
->j_devname
)))
57 trace_mark_tp(jbd2
, start_commit
, jbd2_start_commit
,
58 probe_jbd2_start_commit
, "dev %s transaction %d",
59 journal
->j_devname
, commit_transaction
->t_tid
);
62 void probe_jbd2_end_commit(void *data
, journal_t
*journal
,
63 transaction_t
*commit_transaction
)
65 if (unlikely(!do_filter(journal
->j_devname
)))
67 trace_mark_tp(jbd2
, end_commit
, jbd2_end_commit
,
68 probe_jbd2_end_commit
, "dev %s transaction %d head %d",
69 journal
->j_devname
, commit_transaction
->t_tid
,
70 journal
->j_tail_sequence
);
73 static void free_dev_filter(struct rcu_head
*head
)
75 kfree(container_of(head
, struct rcu_dev_filter
, rcu
));
78 static ssize_t
filter_op_write(struct file
*file
,
79 const char __user
*user_buf
, size_t count
, loff_t
*ppos
)
85 struct rcu_dev_filter
*new, *old
;
87 mutex_lock(&jbd2_filter_mutex
);
92 buf_size
= min(count
, sizeof(buf
) - 1);
93 err
= copy_from_user(buf
, user_buf
, buf_size
);
98 if (sscanf(buf
, "%s", name
) != 1) {
105 /* Empty string or * means all active */
106 if (name
[0] == '\0' || (name
[0] == '*' && name
[1] == '\0')) {
109 new = kmalloc(sizeof(*new), GFP_KERNEL
);
110 strcpy(new->devname
, name
);
113 rcu_assign_pointer(dev_filter
, new);
115 call_rcu_sched(&old
->rcu
, free_dev_filter
);
117 mutex_unlock(&jbd2_filter_mutex
);
121 mutex_unlock(&jbd2_filter_mutex
);
125 static ssize_t
filter_op_read(struct file
*filp
, char __user
*buffer
,
126 size_t count
, loff_t
*ppos
)
131 mutex_lock(&jbd2_filter_mutex
);
135 devname
= dev_filter
->devname
;
136 bcount
= simple_read_from_buffer(buffer
, count
, ppos
,
137 devname
, strlen(devname
));
138 mutex_unlock(&jbd2_filter_mutex
);
142 static struct file_operations jbd2_file_operations
= {
143 .write
= filter_op_write
,
144 .read
= filter_op_read
,
147 static void release_filter_dev(void)
149 struct rcu_dev_filter
*old
;
151 mutex_lock(&jbd2_filter_mutex
);
154 rcu_assign_pointer(dev_filter
, NULL
);
156 call_rcu_sched(&old
->rcu
, free_dev_filter
);
157 mutex_unlock(&jbd2_filter_mutex
);
160 static int __init
filter_init(void)
162 struct dentry
*filter_root_dentry
;
165 filter_root_dentry
= get_filter_root();
166 if (!filter_root_dentry
) {
171 jbd2_filter_dentry
= debugfs_create_dir("jbd2", filter_root_dentry
);
173 if (IS_ERR(jbd2_filter_dentry
) || !jbd2_filter_dentry
) {
174 printk(KERN_ERR
"Failed to create jbd2 filter file\n");
179 jbd2_filter_dev_dentry
= debugfs_create_file("dev", S_IWUSR
,
180 jbd2_filter_dentry
, NULL
, &jbd2_file_operations
);
181 if (IS_ERR(jbd2_filter_dentry
) || !jbd2_filter_dentry
) {
182 printk(KERN_ERR
"Failed to create jbd2 filter file\n");
184 goto release_filter_dentry
;
189 release_filter_dentry
:
190 debugfs_remove(jbd2_filter_dentry
);
191 release_filter_dev();
196 static void __exit
filter_exit(void)
198 debugfs_remove(jbd2_filter_dev_dentry
);
199 debugfs_remove(jbd2_filter_dentry
);
200 release_filter_dev();
203 module_init(filter_init
);
204 module_exit(filter_exit
);
206 MODULE_LICENSE("GPL and additional rights");
207 MODULE_AUTHOR("Mathieu Desnoyers");
208 MODULE_DESCRIPTION("JBD2 Tracepoint Probes");