[ltt-dev] [PATCH] LTTng: Make mark-control work in debugfs
Gui Jianfeng
guijianfeng at cn.fujitsu.com
Wed Feb 11 04:27:27 EST 2009
Mathieu Desnoyers wrote:
> I think I have an idea we could implement to support arming markers
> which are not loaded in the kernel yet. The use-case is :
>
> We have a marker in a given module, which is not loaded. We are
> interested in tracing events in this module happening soon after module
> load. Therefore, we cannot use the /mnt/debugfs/ltt/markers/**/* files,
> because the marker is not present yet.
>
> We could implement mkdir operations to support this. This is out of
> ltt-armall scope, and people would have to use it manually and *know*
> what channel and marker names they want to enable, but I think it's ok.
>
> So basically, we would have :
>
> cd /mnt/debugfs/ltt
> mkdir channel_name
> cd channel_name
> mkdir marker_name
>
> The marker_name subdirectory would be populated with standard
> information and enable files.
Do you mean if we do "mkdir channel_name" and "mkdir marker_name"
kernel will automatically insert the probe module, but in debugfs,
it doesn't show all of the markers this module have, but just the
requested one?
>
> Do you think it could be added easily to ltt-trace-control ?
>
> Mathieu
>
>
>> Thanks,
>>
>> Mathieu
>>
>>>> I'm providing the patch modified to fit with checkpatch below.
>>>>
>>>> Thanks,
>>>>
>>>> Mathieu
>>>>
>>>>
>>>> lttng-make-mark-control-work-in-debugfs
>>>>
>>>> This patch makes mark-control work in debugfs
>>>> Control files are organized as following.
>>>> ltt/
>>>> |-- markers
>>>> | |-- fs
>>>> | | |-- buffer_wait_end
>>>> | | | |-- enable
>>>> | | | `-- info
>>>> | | |-- buffer_wait_start
>>>> | | | |-- enable
>>>> | | | `-- info
>>>> | | |-- close
>>>> | | | |-- enable
>>>> | | | `-- info
>>>> | | |-- exec
>>>> | | | |-- enable
>>>> | | | `-- info
>>>> ...
>>>>
>>>> One can enable or disable a marker by using the following command
>>>> # echo 1 > ltt/markers/fs/close/enable
>>>> # echo 0 > ltt/markers/fs/close/enable
>>>>
>>>> Show the marker information as following
>>>> # cat ltt/markers/fs/close/info
>>>> format: "fd %u"
>>>> state: 1
>>>> event_id: 2
>>>> call: 0xc0459118
>>>> probe single : 0xc04f7b08
>>>>
>>>> Mathieu :
>>>>
>>>> enabled -> enable to follow the semantic of the rest of the debugfs API.
>>>> checkpatch.pl cleanup.
>>>>
>>>> Signed-off-by: Gui Jianfeng <guijianfeng at cn.fujitsu.com>
>>>> Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers at polymtl.ca>
>>>> ---
>>>> ltt/ltt-trace-control.c | 298 +++++++++++++++++++++++++++++++++++++++++++++++-
>>>> 1 file changed, 294 insertions(+), 4 deletions(-)
>>>>
>>>> Index: linux-2.6-lttng/ltt/ltt-trace-control.c
>>>> ===================================================================
>>>> --- linux-2.6-lttng.orig/ltt/ltt-trace-control.c 2009-02-04 00:56:05.000000000 -0500
>>>> +++ linux-2.6-lttng/ltt/ltt-trace-control.c 2009-02-04 01:01:46.000000000 -0500
>>>> @@ -1,8 +1,10 @@
>>>> /*
>>>> * LTT trace control module over debugfs.
>>>> *
>>>> - * Copyright 2008 -
>>>> - * Zhaolei <zhaolei at cn.fujitsu.com>
>>>> + * Copyright 2008 - Zhaolei <zhaolei at cn.fujitsu.com>
>>>> + *
>>>> + * Copyright 2009 - Gui Jianfeng <guijianfeng at cn.fujitsu.com>
>>>> + * Make mark-control work in debugfs
>>>> */
>>>>
>>>> /*
>>>> @@ -16,14 +18,17 @@
>>>> #include <linux/uaccess.h>
>>>> #include <linux/debugfs.h>
>>>> #include <linux/ltt-tracer.h>
>>>> +#include <linux/notifier.h>
>>>>
>>>> #define LTT_CONTROL_DIR "control"
>>>> +#define MARKERS_CONTROL_DIR "markers"
>>>> #define LTT_SETUP_TRACE_FILE "setup_trace"
>>>> #define LTT_DESTROY_TRACE_FILE "destroy_trace"
>>>>
>>>> #define LTT_WRITE_MAXLEN (128)
>>>>
>>>> -struct dentry *ltt_control_dir, *ltt_setup_trace_file, *ltt_destroy_trace_file;
>>>> +struct dentry *ltt_control_dir, *ltt_setup_trace_file, *ltt_destroy_trace_file,
>>>> + *markers_control_dir;
>>>>
>>>> /*
>>>> * the traces_lock nests inside control_lock.
>>>> @@ -692,6 +697,270 @@ static struct file_operations ltt_destro
>>>> .write = destroy_trace_write,
>>>> };
>>>>
>>>> +static int marker_enable_open(struct inode *inode, struct file *filp)
>>>> +{
>>>> + filp->private_data = inode->i_private;
>>>> + return 0;
>>>> +}
>>>> +
>>>> +static ssize_t marker_enable_read(struct file *filp, char __user *ubuf,
>>>> + size_t cnt, loff_t *ppos)
>>>> +{
>>>> + struct marker *marker;
>>>> + char *buf;
>>>> + int len;
>>>> +
>>>> + marker = (struct marker *)filp->private_data;
>>>> + buf = kmalloc(1024, GFP_KERNEL);
>>>> +
>>>> + len = sprintf(buf, "%d\n", _imv_read(marker->state));
>>>> +
>>>> + len = simple_read_from_buffer(ubuf, cnt, ppos, buf, len);
>>>> + kfree(buf);
>>>> +
>>>> + return len;
>>>> +}
>>>> +
>>>> +static ssize_t marker_enable_write(struct file *filp, const char __user *ubuf,
>>>> + size_t cnt, loff_t *ppos)
>>>> +{
>>>> + char buf[NAME_MAX];
>>>> + int buf_size;
>>>> + int err = 0;
>>>> + struct marker *marker;
>>>> +
>>>> + marker = (struct marker *)filp->private_data;
>>>> + buf_size = min(cnt, sizeof(buf) - 1);
>>>> + err = copy_from_user(buf, ubuf, buf_size);
>>>> + if (err)
>>>> + return err;
>>>> +
>>>> + buf[buf_size] = 0;
>>>> +
>>>> + switch (buf[0]) {
>>>> + case 'Y':
>>>> + case 'y':
>>>> + case '1':
>>>> + err = ltt_marker_connect(marker->channel, marker->name,
>>>> + "default");
>>>> + if (err)
>>>> + return err;
>>>> + break;
>>>> + case 'N':
>>>> + case 'n':
>>>> + case '0':
>>>> + err = ltt_marker_disconnect(marker->channel, marker->name,
>>>> + "default");
>>>> + if (err)
>>>> + return err;
>>>> + break;
>>>> + default:
>>>> + return -EPERM;
>>>> + }
>>>> +
>>>> + return cnt;
>>>> +}
>>>> +
>>>> +static const struct file_operations enable_fops = {
>>>> + .open = marker_enable_open,
>>>> + .read = marker_enable_read,
>>>> + .write = marker_enable_write,
>>>> +};
>>>> +
>>>> +static int marker_info_open(struct inode *inode, struct file *filp)
>>>> +{
>>>> + filp->private_data = inode->i_private;
>>>> + return 0;
>>>> +}
>>>> +
>>>> +static ssize_t marker_info_read(struct file *filp, char __user *ubuf,
>>>> + size_t cnt, loff_t *ppos)
>>>> +{
>>>> + struct marker *marker;
>>>> + char *buf;
>>>> + int len;
>>>> +
>>>> + marker = (struct marker *)filp->private_data;
>>>> + buf = kmalloc(1024, GFP_KERNEL);
>>>> +
>>>> + len = sprintf(buf, "format: \"%s\"\nstate: %d\n"
>>>> + "event_id: %hu\n"
>>>> + "call: 0x%p\n"
>>>> + "probe %s : 0x%p\n",
>>>> + marker->format, _imv_read(marker->state),
>>>> + marker->event_id, marker->call, marker->ptype ?
>>>> + "multi" : "single", marker->ptype ?
>>>> + (void *)marker->multi : (void *)marker->single.func);
>>>> +
>>>> + len = simple_read_from_buffer(ubuf, cnt, ppos, buf, len);
>>>> + kfree(buf);
>>>> +
>>>> + return len;
>>>> +}
>>>> +
>>>> +static const struct file_operations info_fops = {
>>>> + .open = marker_info_open,
>>>> + .read = marker_info_read,
>>>> +};
>>>> +
>>>> +static int build_marker_file(struct marker *marker)
>>>> +{
>>>> + struct dentry *channel_d, *marker_d, *enable_d, *info_d;
>>>> + int err;
>>>> +
>>>> + channel_d = dir_lookup(markers_control_dir, marker->channel);
>>>> + if (!channel_d) {
>>>> + channel_d = debugfs_create_dir(marker->channel,
>>>> + markers_control_dir);
>>>> + if (IS_ERR(channel_d) || !channel_d) {
>>>> + printk(KERN_ERR
>>>> + "%s: build channel dir of %s failed\n",
>>>> + __func__, marker->channel);
>>>> + err = -ENOMEM;
>>>> + goto err_build_fail;
>>>> + }
>>>> + }
>>>> +
>>>> + marker_d = dir_lookup(channel_d, marker->name);
>>>> + if (!marker_d) {
>>>> + marker_d = debugfs_create_dir(marker->name, channel_d);
>>>> + if (IS_ERR(marker_d) || !marker_d) {
>>>> + printk(KERN_ERR
>>>> + "%s: marker dir of %s failed\n",
>>>> + __func__, marker->name);
>>>> + err = -ENOMEM;
>>>> + goto err_build_fail;
>>>> + }
>>>> + }
>>>> +
>>>> + enable_d = dir_lookup(marker_d, "enable");
>>>> + if (!enable_d) {
>>>> + enable_d = debugfs_create_file("enable", 0644, marker_d,
>>>> + marker, &enable_fops);
>>>> + if (IS_ERR(enable_d) || !enable_d) {
>>>> + printk(KERN_ERR
>>>> + "%s: create file of %s failed\n",
>>>> + __func__, "enable");
>>>> + err = -ENOMEM;
>>>> + goto err_build_fail;
>>>> + }
>>>> + }
>>>> +
>>>> + info_d = dir_lookup(marker_d, "info");
>>>> + if (!info_d) {
>>>> + info_d = debugfs_create_file("info", 0444, marker_d,
>>>> + marker, &info_fops);
>>>> + if (IS_ERR(info_d) || !info_d) {
>>>> + printk(KERN_ERR
>>>> + "%s: create file of %s failed\n",
>>>> + __func__, "enable");
>>>> + err = -ENOMEM;
>>>> + goto err_build_fail;
>>>> + }
>>>> + }
>>>> +
>>>> + return 0;
>>>> +
>>>> +err_build_fail:
>>>> + return err;
>>>> +}
>>>> +
>>>> +static int build_marker_control_files(void)
>>>> +{
>>>> + struct marker_iter iter;
>>>> + int err;
>>>> +
>>>> + err = 0;
>>>> + if (!markers_control_dir)
>>>> + return -EEXIST;
>>>> +
>>>> + marker_iter_reset(&iter);
>>>> + marker_iter_start(&iter);
>>>> + for (; iter.marker != NULL; marker_iter_next(&iter)) {
>>>> + err = build_marker_file(iter.marker);
>>>> + if (err)
>>>> + goto err_build_fail;
>>>> + }
>>>> + marker_iter_stop(&iter);
>>>> + return 0;
>>>> +
>>>> +err_build_fail:
>>>> + return err;
>>>> +}
>>>> +
>>>> +static int remove_marker_control_dir(struct marker *marker)
>>>> +{
>>>> + struct dentry *channel_d, *marker_d;
>>>> +
>>>> + channel_d = dir_lookup(markers_control_dir, marker->channel);
>>>> + if (!channel_d)
>>>> + return -ENOENT;
>>>> +
>>>> + marker_d = dir_lookup(channel_d, marker->name);
>>>> + if (!marker_d)
>>>> + return -ENOENT;
>>>> +
>>>> + debugfs_remove_recursive(marker_d);
>>>> + if (list_empty(&channel_d->d_subdirs))
>>>> + debugfs_remove(channel_d);
>>>> +
>>>> + return 0;
>>>> +}
>>>> +
>>>> +static void cleanup_control_dir(struct marker *begin, struct marker *end)
>>>> +{
>>>> + struct marker *iter;
>>>> +
>>>> + if (!markers_control_dir)
>>>> + return;
>>>> +
>>>> + for (iter = begin; iter < end; iter++)
>>>> + remove_marker_control_dir(iter);
>>>> +
>>>> + return;
>>>> +}
>>>> +
>>>> +static void build_control_dir(struct marker *begin, struct marker *end)
>>>> +{
>>>> + struct marker *iter;
>>>> + int err;
>>>> +
>>>> + err = 0;
>>>> + if (!markers_control_dir)
>>>> + return;
>>>> +
>>>> + for (iter = begin; iter < end; iter++) {
>>>> + err = build_marker_file(iter);
>>>> + if (err)
>>>> + goto err_build_fail;
>>>> + }
>>>> +
>>>> + return;
>>>> +err_build_fail:
>>>> + cleanup_control_dir(begin, end);
>>>> +}
>>>> +
>>>> +static int module_notify(struct notifier_block *self,
>>>> + unsigned long val, void *data)
>>>> +{
>>>> + struct module *mod = data;
>>>> +
>>>> + switch (val) {
>>>> + case MODULE_STATE_COMING:
>>>> + build_control_dir(mod->markers,
>>>> + mod->markers + mod->num_markers);
>>>> + break;
>>>> + case MODULE_STATE_GOING:
>>>> + cleanup_control_dir(mod->markers,
>>>> + mod->markers + mod->num_markers);
>>>> + break;
>>>> + }
>>>> + return NOTIFY_DONE;
>>>> +}
>>>> +
>>>> +static struct notifier_block module_nb = {
>>>> + .notifier_call = module_notify,
>>>> +};
>>>>
>>>> static int __init ltt_trace_control_init(void)
>>>> {
>>>> @@ -733,8 +1002,27 @@ static int __init ltt_trace_control_init
>>>> goto err_create_destroy_trace_file;
>>>> }
>>>>
>>>> - return 0;
>>>> + markers_control_dir = debugfs_create_dir(MARKERS_CONTROL_DIR,
>>>> + ltt_root_dentry);
>>>> + if (IS_ERR(markers_control_dir) || !markers_control_dir) {
>>>> + printk(KERN_ERR
>>>> + "ltt_channel_control_init: create dir of %s failed\n",
>>>> + MARKERS_CONTROL_DIR);
>>>> + err = -ENOMEM;
>>>> + goto err_create_marker_control_dir;
>>>> + }
>>>>
>>>> + if (build_marker_control_files())
>>>> + goto err_build_fail;
>>>> +
>>>> + if (!register_module_notifier(&module_nb))
>>>> + return 0;
>>>> +
>>>> +err_build_fail:
>>>> + debugfs_remove_recursive(markers_control_dir);
>>>> + markers_control_dir = NULL;
>>>> +err_create_marker_control_dir:
>>>> + debugfs_remove(ltt_destroy_trace_file);
>>>> err_create_destroy_trace_file:
>>>> debugfs_remove(ltt_setup_trace_file);
>>>> err_create_setup_trace_file:
>>>> @@ -759,6 +1047,8 @@ static void __exit ltt_trace_control_exi
>>>> debugfs_remove(ltt_setup_trace_file);
>>>> debugfs_remove(ltt_destroy_trace_file);
>>>> debugfs_remove_recursive(ltt_control_dir);
>>>> + debugfs_remove_recursive(markers_control_dir);
>>>> + unregister_module_notifier(&module_nb);
>>>> }
>>>>
>>>> module_init(ltt_trace_control_init);
>>>>
>>>>
>>> --
>>> Regards
>>> Gui Jianfeng
>>>
>>>
>>>
>>> _______________________________________________
>>> ltt-dev mailing list
>>> ltt-dev at lists.casi.polymtl.ca
>>> http://lists.casi.polymtl.ca/cgi-bin/mailman/listinfo/ltt-dev
>>>
>> --
>> Mathieu Desnoyers
>> OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
>
--
Regards
Gui Jianfeng
More information about the lttng-dev
mailing list