[ltt-dev] [PATCH] LTTng: Make mark-control work in debugfs
Gui Jianfeng
guijianfeng at cn.fujitsu.com
Sun Feb 15 21:43:02 EST 2009
Mathieu Desnoyers wrote:
> * Gui Jianfeng (guijianfeng at cn.fujitsu.com) wrote:
>> Mathieu Desnoyers wrote:
>>> * Gui Jianfeng (guijianfeng at cn.fujitsu.com) wrote:
>>>> 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?
>>>>
>>> No. I mean that doing :
>>> mkdir channel_name
>>> mkdir channel_name/marker_name
>>> echo 1 > channel_name/marker_name
>>>
>>> Should be the same as the
>>> echo "connect channel_name marker_name" > /proc/ltt
>>>
>>> This worked even if the channel/marker pair were not listed in
>>> /proc/ltt.
>>>
>>> This would create the directories locally even if they do not exist in
>>> the marker table, and call ltt_marker_connect() when echo 1 >
>>> channel_name/marker_name is done.
>> Well, I got your point now.
>> /proc/ltt shows the markers which are located in a specific ELF section "__markers".
>> echo "connect channel_name marker_name" > /proc/ltt just creates a marker_entry. Since
>> a marker with "channel_name marker_name" doesn't exist in any where. IOW, it can never
>> be triggered. Hence, does this feature really make sense?
>>
>
> Yes, because it could eventually exist when a module is loaded. We have
> this situation :
>
> ltt-armall list markers (marker X unavailable)
> modprobe module Z (contains marker X)
> would like to probe marker X...
>
> So we have to allow enabling a unexisting marker.
Hi Mathieu,
I guess it's not easy to implement the *mkdir* for marker control.
But I have an alternative solution that we can add a control file
*new_channel* at the same level of channel directories, and add a
control file *new_marker* in each channel directory.
Making use of the following, we can create a marker even if it
doesn't exist by now.
cd /mnt/ltt/markers
echo "channel_name" > new_channel
echo "marker_name" > channel_name/new_marker
>
> Mathieu
>
>>> Mathieu
>>>
>>>>> 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
>>>>
>>>> _______________________________________________
>>>> ltt-dev mailing list
>>>> ltt-dev at lists.casi.polymtl.ca
>>>> http://lists.casi.polymtl.ca/cgi-bin/mailman/listinfo/ltt-dev
>>>>
>> --
>> 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
>>
>
--
Regards
Gui Jianfeng
More information about the lttng-dev
mailing list