[ltt-dev] [PATCH] LTTng: Make mark-control work in debugfs

Mathieu Desnoyers compudj at krystal.dyndns.org
Wed Feb 4 01:20:51 EST 2009


* Gui Jianfeng (guijianfeng at cn.fujitsu.com) wrote:
> Hi Mathieu,
> 
> This patch makes mark-control work in debugfs
> Control files are organized as following.
> ltt/
> |-- markers
> |   |-- fs
> |   |   |-- buffer_wait_end
> |   |   |   |-- enabled
> |   |   |   `-- info
> |   |   |-- buffer_wait_start
> |   |   |   |-- enabled
> |   |   |   `-- info
> |   |   |-- close
> |   |   |   |-- enabled
> |   |   |   `-- info
> |   |   |-- exec
> |   |   |   |-- enabled
> |   |   |   `-- info
> ...
> 
> One can enable or disable a marker by using the following command
> # echo 1 > ltt/markers/fs/close/enabled
> # echo 0 > ltt/markers/fs/close/enabled
> 
> 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
> 

Thanks a lot Gui, this is a very good patch. I'll make the cosmetic
changes requested by scripts/checkpatch.pl myself and merge it. (please
get used to run it before submission, it's very good at spotting
whitespaces at the end of lines and other coding style errors)

Best regards,

Mathieu

> Signed-off-by: Gui Jianfeng <guijianfeng at cn.fujitsu.com>
> ---
>  ltt/ltt-trace-control.c |  302 ++++++++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 297 insertions(+), 5 deletions(-)
> 
> diff --git a/ltt/ltt-trace-control.c b/ltt/ltt-trace-control.c
> index 16502a2..e4676bf 100644
> --- a/ltt/ltt-trace-control.c
> +++ b/ltt/ltt-trace-control.c
> @@ -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,272 @@ static struct file_operations ltt_destroy_trace_operations = {
>  	.write = destroy_trace_write,
>  };
>  
> +static int marker_enabled_open(struct inode *inode, struct file *filp)
> +{
> +	filp->private_data = inode->i_private;
> +	return 0;
> +}
> +
> +static ssize_t marker_enabled_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_enabled_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 struct file_operations enabled_fops = {
> +	.open = marker_enabled_open,
> +	.read = marker_enabled_read,
> +	.write = marker_enabled_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 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, *enabled_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;
> +		}
> +	}
> +	
> +	enabled_d = dir_lookup(marker_d, "enabled");
> +	if (!enabled_d) {
> +		enabled_d = debugfs_create_file("enabled", 0644, marker_d,
> +						marker, &enabled_fops);
> +		if (IS_ERR(enabled_d) || !enabled_d) {
> +			printk(KERN_ERR
> +			       "%s: create file of %s failed\n",
> +			       __func__, "enabled");
> +			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__, "enabled");
> +			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);
> +	return;
> +}
> +
> +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 +1004,27 @@ static int __init ltt_trace_control_init(void)
>  		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 +1049,8 @@ static void __exit ltt_trace_control_exit(void)
>  	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);
> -- 
> 1.5.4.rc3
> 
> 
> _______________________________________________
> 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




More information about the lttng-dev mailing list