Mirror of the lttng-dev mailing list
 help / color / mirror / Atom feed
* [ltt-dev] [PATCH] LTTng: Make mark-control work in debugfs
@ 2009-02-04  1:46 Gui Jianfeng
  2009-02-04  6:20 ` Mathieu Desnoyers
  0 siblings, 1 reply; 17+ messages in thread
From: Gui Jianfeng @ 2009-02-04  1:46 UTC (permalink / raw)


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

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





^ permalink raw reply	[flat|nested] 17+ messages in thread

* [ltt-dev] [PATCH] LTTng: Make mark-control work in debugfs
  2009-02-04  1:46 [ltt-dev] [PATCH] LTTng: Make mark-control work in debugfs Gui Jianfeng
@ 2009-02-04  6:20 ` Mathieu Desnoyers
  2009-02-04  6:30   ` Mathieu Desnoyers
  2009-02-04  6:44   ` Gui Jianfeng
  0 siblings, 2 replies; 17+ messages in thread
From: Mathieu Desnoyers @ 2009-02-04  6:20 UTC (permalink / raw)


* 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




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [ltt-dev] [PATCH] LTTng: Make mark-control work in debugfs
  2009-02-04  6:20 ` Mathieu Desnoyers
@ 2009-02-04  6:30   ` Mathieu Desnoyers
  2009-02-04  6:44   ` Gui Jianfeng
  1 sibling, 0 replies; 17+ messages in thread
From: Mathieu Desnoyers @ 2009-02-04  6:30 UTC (permalink / raw)


* Mathieu Desnoyers (compudj at krystal.dyndns.org) wrote:
> * 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

I'll also change enabled -> enable

to follow the same semantic as debugfs/ltt/ per-channel control files.

Mathieu

> > |   |   |   `-- 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
> 
> _______________________________________________
> 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




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [ltt-dev] [PATCH] LTTng: Make mark-control work in debugfs
  2009-02-04  6:20 ` Mathieu Desnoyers
  2009-02-04  6:30   ` Mathieu Desnoyers
@ 2009-02-04  6:44   ` Gui Jianfeng
  2009-02-04  7:12     ` Mathieu Desnoyers
  1 sibling, 1 reply; 17+ messages in thread
From: Gui Jianfeng @ 2009-02-04  6:44 UTC (permalink / raw)


Mathieu Desnoyers wrote:
> * 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

  I see, thanks for pointing this out. :)

  BTW, I'll post a patch to modify user tools accordingly as soon as this patch
  has been merged into the new version of LTTng.

> 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
>>
> 

-- 
Regards
Gui Jianfeng





^ permalink raw reply	[flat|nested] 17+ messages in thread

* [ltt-dev] [PATCH] LTTng: Make mark-control work in debugfs
  2009-02-04  6:44   ` Gui Jianfeng
@ 2009-02-04  7:12     ` Mathieu Desnoyers
  2009-02-05  1:20       ` Gui Jianfeng
  0 siblings, 1 reply; 17+ messages in thread
From: Mathieu Desnoyers @ 2009-02-04  7:12 UTC (permalink / raw)


* Gui Jianfeng (guijianfeng at cn.fujitsu.com) wrote:
> Mathieu Desnoyers wrote:
> > * 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
> 
>   I see, thanks for pointing this out. :)
> 
>   BTW, I'll post a patch to modify user tools accordingly as soon as this patch
>   has been merged into the new version of LTTng.
> 

Hrm, I'm playing a bit with the interface, and I think I should wait
before I merge it. There are a few things to fix.

First, when enabling a marker with the old ltt-marker-control.ko, if we
rmmod the module containing this marker and after modprobe the module
again, the marker stays enabled. With this debugfs interface, it seems
to become disabled.

Also, when I connect to a marker, there is some module refcounting
involved to make sure the marked modules stays loaded. For some reason
I've been able to unload a module with armed markers.. this should
probably be looked at.

Thirdly, when I do

cd /mnt/debugfs/ltt/markers
for a in */*/enable; do echo $a; echo 1 > $a; done

I get :
metadata/core_marker_format
-su: echo: write error: File exists
metadata/core_marker_id
-su: echo: write error: File exists

Which is expected, because those marker are activated within the kernel
and should not have their state modified by the user-visible API.

Then I do :
for a in */*/enable; do echo $a; echo 0 > $a; done

And do the first command again :
for a in */*/enable; do echo $a; echo 1 > $a; done

This shows that userspace is able to alter the state of builtin "core"
markers, which I disallow in ltt-marker-control.ko. The same would be
good in the debugfs interface.

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);


-- 
Mathieu Desnoyers
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [ltt-dev] [PATCH] LTTng: Make mark-control work in debugfs
  2009-02-04  7:12     ` Mathieu Desnoyers
@ 2009-02-05  1:20       ` Gui Jianfeng
  2009-02-11  5:32         ` Mathieu Desnoyers
  0 siblings, 1 reply; 17+ messages in thread
From: Gui Jianfeng @ 2009-02-05  1:20 UTC (permalink / raw)


Mathieu Desnoyers wrote:
> 
> Hrm, I'm playing a bit with the interface, and I think I should wait
> before I merge it. There are a few things to fix.
> 
> First, when enabling a marker with the old ltt-marker-control.ko, if we
> rmmod the module containing this marker and after modprobe the module
> again, the marker stays enabled. With this debugfs interface, it seems
> to become disabled.

  Hi Mathieu,

  When enabling a marker with either way(old proc or debugfs), if this marker
  belongs a module, I'm afraid this module can't be unloaded any more.
  For example:
  #modprobe fs_trace
  #echo "connect fs close default" > /proc/ltt
  #rmmod fs_trace
  We'll get:
  ERROR: Module fs_trace is in use

  I tested under lttng-0.91, do i miss something?

> 
> Also, when I connect to a marker, there is some module refcounting
> involved to make sure the marked modules stays loaded. For some reason
> I've been able to unload a module with armed markers.. this should
> probably be looked at.

  Do you mean even if the marker is enabled(by using debugfs or proc interface),
  the module which includes this marker are still able to be unloaded?

> 
> Thirdly, when I do
> 
> cd /mnt/debugfs/ltt/markers
> for a in */*/enable; do echo $a; echo 1 > $a; done
> 
> I get :
> metadata/core_marker_format
> -su: echo: write error: File exists
> metadata/core_marker_id
> -su: echo: write error: File exists
> 
> Which is expected, because those marker are activated within the kernel
> and should not have their state modified by the user-visible API.
> 
> Then I do :
> for a in */*/enable; do echo $a; echo 0 > $a; done
> 
> And do the first command again :
> for a in */*/enable; do echo $a; echo 1 > $a; done
> 
> This shows that userspace is able to alter the state of builtin "core"
> markers, which I disallow in ltt-marker-control.ko. The same would be
> good in the debugfs interface.

  I tried on lttng-0.91
  #echo "disconnect metadata core_marker_format" > /proc/ltt
  #cat /proc/ltt | grep core_marker_format
  i got the following:
    channel: metadata marker: core_marker_format format: "channel %s name %s format %s" state: 0 event_id: 1 call: 0xc0460b7c probe single : 0xc045f904
  
  It seems core_marker_format has been disabled by old interface. Do i miss something again?

  ltt-armall do the restriction, consider the follwing piece of code 
  MARKERS=`cat /proc/ltt|grep -v %k|awk '{print $2 " " $4}'|sort -u|grep -v ^metadata
|          grep -v ^locking|grep -v ^lockdep`
  Actually, this block of code do the restriction from userspace.

> 
> 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






^ permalink raw reply	[flat|nested] 17+ messages in thread

* [ltt-dev] [PATCH] LTTng: Make mark-control work in debugfs
  2009-02-05  1:20       ` Gui Jianfeng
@ 2009-02-11  5:32         ` Mathieu Desnoyers
  2009-02-11  8:43           ` Mathieu Desnoyers
  0 siblings, 1 reply; 17+ messages in thread
From: Mathieu Desnoyers @ 2009-02-11  5:32 UTC (permalink / raw)


* Gui Jianfeng (guijianfeng at cn.fujitsu.com) wrote:
> Mathieu Desnoyers wrote:
> > 
> > Hrm, I'm playing a bit with the interface, and I think I should wait
> > before I merge it. There are a few things to fix.
> > 
> > First, when enabling a marker with the old ltt-marker-control.ko, if we
> > rmmod the module containing this marker and after modprobe the module
> > again, the marker stays enabled. With this debugfs interface, it seems
> > to become disabled.
> 
>   Hi Mathieu,
> 
>   When enabling a marker with either way(old proc or debugfs), if this marker
>   belongs a module, I'm afraid this module can't be unloaded any more.
>   For example:
>   #modprobe fs_trace
>   #echo "connect fs close default" > /proc/ltt
>   #rmmod fs_trace
>   We'll get:
>   ERROR: Module fs_trace is in use
> 
>   I tested under lttng-0.91, do i miss something?
> 

That's expected when a marker is a trace_mark_tp. That's the simplest
way I found to deal with references. As I recall, a trace_mark() (not
_tp) should not have this side-effect. So basically, it's mostly the
lttng probes which have this refcounting.

> > 
> > Also, when I connect to a marker, there is some module refcounting
> > involved to make sure the marked modules stays loaded. For some reason
> > I've been able to unload a module with armed markers.. this should
> > probably be looked at.
> 
>   Do you mean even if the marker is enabled(by using debugfs or proc interface),
>   the module which includes this marker are still able to be unloaded?
> 

See the above paragraph about explanation around trace_mark_tp(). So
basically, I expect that lttng module containing trace_mark_tp() should
not be unloadable when armed.

> > 
> > Thirdly, when I do
> > 
> > cd /mnt/debugfs/ltt/markers
> > for a in */*/enable; do echo $a; echo 1 > $a; done
> > 
> > I get :
> > metadata/core_marker_format
> > -su: echo: write error: File exists
> > metadata/core_marker_id
> > -su: echo: write error: File exists
> > 
> > Which is expected, because those marker are activated within the kernel
> > and should not have their state modified by the user-visible API.
> > 
> > Then I do :
> > for a in */*/enable; do echo $a; echo 0 > $a; done
> > 
> > And do the first command again :
> > for a in */*/enable; do echo $a; echo 1 > $a; done
> > 
> > This shows that userspace is able to alter the state of builtin "core"
> > markers, which I disallow in ltt-marker-control.ko. The same would be
> > good in the debugfs interface.
> 
>   I tried on lttng-0.91
>   #echo "disconnect metadata core_marker_format" > /proc/ltt
>   #cat /proc/ltt | grep core_marker_format
>   i got the following:
>     channel: metadata marker: core_marker_format format: "channel %s name %s format %s" state: 0 event_id: 1 call: 0xc0460b7c probe single : 0xc045f904
>   
>   It seems core_marker_format has been disabled by old interface. Do i miss something again?
> 
>   ltt-armall do the restriction, consider the follwing piece of code 
>   MARKERS=`cat /proc/ltt|grep -v %k|awk '{print $2 " " $4}'|sort -u|grep -v ^metadata
> |          grep -v ^locking|grep -v ^lockdep`
>   Actually, this block of code do the restriction from userspace.
> 

Ah, this is possible. Then we have to make sure the core event IDs are
never allocated dynamically.

I am pulling your new interface for 2.6.29-rc4, we'll start from there.
As you say, it provides the same functionnality as the old interface. We
might want to test the cases I spotted. They might well be problems that
were there in the previous interface as well.

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




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [ltt-dev] [PATCH] LTTng: Make mark-control work in debugfs
  2009-02-11  5:32         ` Mathieu Desnoyers
@ 2009-02-11  8:43           ` Mathieu Desnoyers
  2009-02-11  9:27             ` Gui Jianfeng
  0 siblings, 1 reply; 17+ messages in thread
From: Mathieu Desnoyers @ 2009-02-11  8:43 UTC (permalink / raw)


* Mathieu Desnoyers (compudj at krystal.dyndns.org) wrote:
> * Gui Jianfeng (guijianfeng at cn.fujitsu.com) wrote:
> > Mathieu Desnoyers wrote:
> > > 
> > > Hrm, I'm playing a bit with the interface, and I think I should wait
> > > before I merge it. There are a few things to fix.
> > > 
> > > First, when enabling a marker with the old ltt-marker-control.ko, if we
> > > rmmod the module containing this marker and after modprobe the module
> > > again, the marker stays enabled. With this debugfs interface, it seems
> > > to become disabled.
> > 
> >   Hi Mathieu,
> > 
> >   When enabling a marker with either way(old proc or debugfs), if this marker
> >   belongs a module, I'm afraid this module can't be unloaded any more.
> >   For example:
> >   #modprobe fs_trace
> >   #echo "connect fs close default" > /proc/ltt
> >   #rmmod fs_trace
> >   We'll get:
> >   ERROR: Module fs_trace is in use
> > 
> >   I tested under lttng-0.91, do i miss something?
> > 
> 
> That's expected when a marker is a trace_mark_tp. That's the simplest
> way I found to deal with references. As I recall, a trace_mark() (not
> _tp) should not have this side-effect. So basically, it's mostly the
> lttng probes which have this refcounting.
> 
> > > 
> > > Also, when I connect to a marker, there is some module refcounting
> > > involved to make sure the marked modules stays loaded. For some reason
> > > I've been able to unload a module with armed markers.. this should
> > > probably be looked at.
> > 
> >   Do you mean even if the marker is enabled(by using debugfs or proc interface),
> >   the module which includes this marker are still able to be unloaded?
> > 
> 
> See the above paragraph about explanation around trace_mark_tp(). So
> basically, I expect that lttng module containing trace_mark_tp() should
> not be unloadable when armed.
> 
> > > 
> > > Thirdly, when I do
> > > 
> > > cd /mnt/debugfs/ltt/markers
> > > for a in */*/enable; do echo $a; echo 1 > $a; done
> > > 
> > > I get :
> > > metadata/core_marker_format
> > > -su: echo: write error: File exists
> > > metadata/core_marker_id
> > > -su: echo: write error: File exists
> > > 
> > > Which is expected, because those marker are activated within the kernel
> > > and should not have their state modified by the user-visible API.
> > > 
> > > Then I do :
> > > for a in */*/enable; do echo $a; echo 0 > $a; done
> > > 
> > > And do the first command again :
> > > for a in */*/enable; do echo $a; echo 1 > $a; done
> > > 
> > > This shows that userspace is able to alter the state of builtin "core"
> > > markers, which I disallow in ltt-marker-control.ko. The same would be
> > > good in the debugfs interface.
> > 
> >   I tried on lttng-0.91
> >   #echo "disconnect metadata core_marker_format" > /proc/ltt
> >   #cat /proc/ltt | grep core_marker_format
> >   i got the following:
> >     channel: metadata marker: core_marker_format format: "channel %s name %s format %s" state: 0 event_id: 1 call: 0xc0460b7c probe single : 0xc045f904
> >   
> >   It seems core_marker_format has been disabled by old interface. Do i miss something again?
> > 
> >   ltt-armall do the restriction, consider the follwing piece of code 
> >   MARKERS=`cat /proc/ltt|grep -v %k|awk '{print $2 " " $4}'|sort -u|grep -v ^metadata
> > |          grep -v ^locking|grep -v ^lockdep`
> >   Actually, this block of code do the restriction from userspace.
> > 
> 
> Ah, this is possible. Then we have to make sure the core event IDs are
> never allocated dynamically.
> 
> I am pulling your new interface for 2.6.29-rc4, we'll start from there.
> As you say, it provides the same functionnality as the old interface. We
> might want to test the cases I spotted. They might well be problems that
> were there in the previous interface as well.
> 

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 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

-- 
Mathieu Desnoyers
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [ltt-dev] [PATCH] LTTng: Make mark-control work in debugfs
  2009-02-11  8:43           ` Mathieu Desnoyers
@ 2009-02-11  9:27             ` Gui Jianfeng
  2009-02-11 16:56               ` Mathieu Desnoyers
  0 siblings, 1 reply; 17+ messages in thread
From: Gui Jianfeng @ 2009-02-11  9:27 UTC (permalink / raw)


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




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [ltt-dev] [PATCH] LTTng: Make mark-control work in debugfs
  2009-02-11  9:27             ` Gui Jianfeng
@ 2009-02-11 16:56               ` Mathieu Desnoyers
  2009-02-13  6:24                 ` Gui Jianfeng
  0 siblings, 1 reply; 17+ messages in thread
From: Mathieu Desnoyers @ 2009-02-11 16:56 UTC (permalink / raw)


* 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.

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
> 

-- 
Mathieu Desnoyers
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [ltt-dev] [PATCH] LTTng: Make mark-control work in debugfs
  2009-02-11 16:56               ` Mathieu Desnoyers
@ 2009-02-13  6:24                 ` Gui Jianfeng
  2009-02-13  6:54                   ` Mathieu Desnoyers
  0 siblings, 1 reply; 17+ messages in thread
From: Gui Jianfeng @ 2009-02-13  6:24 UTC (permalink / raw)


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?

> 
> 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




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [ltt-dev] [PATCH] LTTng: Make mark-control work in debugfs
  2009-02-13  6:24                 ` Gui Jianfeng
@ 2009-02-13  6:54                   ` Mathieu Desnoyers
  2009-02-16  2:43                     ` Gui Jianfeng
  0 siblings, 1 reply; 17+ messages in thread
From: Mathieu Desnoyers @ 2009-02-13  6:54 UTC (permalink / raw)


* 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.

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
> 

-- 
Mathieu Desnoyers
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [ltt-dev] [PATCH] LTTng: Make mark-control work in debugfs
  2009-02-13  6:54                   ` Mathieu Desnoyers
@ 2009-02-16  2:43                     ` Gui Jianfeng
  2009-02-16  3:16                       ` KOSAKI Motohiro
  0 siblings, 1 reply; 17+ messages in thread
From: Gui Jianfeng @ 2009-02-16  2:43 UTC (permalink / raw)


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





^ permalink raw reply	[flat|nested] 17+ messages in thread

* [ltt-dev] [PATCH] LTTng: Make mark-control work in debugfs
  2009-02-16  2:43                     ` Gui Jianfeng
@ 2009-02-16  3:16                       ` KOSAKI Motohiro
  2009-02-16  3:48                         ` Gui Jianfeng
  0 siblings, 1 reply; 17+ messages in thread
From: KOSAKI Motohiro @ 2009-02-16  3:16 UTC (permalink / raw)


>   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

No.
good user interface is important than easy implementation.

this UI is really ugly.







^ permalink raw reply	[flat|nested] 17+ messages in thread

* [ltt-dev] [PATCH] LTTng: Make mark-control work in debugfs
  2009-02-16  3:16                       ` KOSAKI Motohiro
@ 2009-02-16  3:48                         ` Gui Jianfeng
  2009-02-16  4:37                           ` Mathieu Desnoyers
  0 siblings, 1 reply; 17+ messages in thread
From: Gui Jianfeng @ 2009-02-16  3:48 UTC (permalink / raw)


KOSAKI Motohiro wrote:
>>   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
> 
> No.
> good user interface is important than easy implementation.
> 
> this UI is really ugly.

  Hi Kosaki-san,

  Thank you for your kind comments.
  I say *not easy* becasue debugfs itself doesn't support *mkdir* completely.
  If we are going to implement mkdir in marker control, we have to modify debugfs
  itself. IMHO, it's not reasonable and i guess most of the debugfs subsystems don't 
  like to see this change.
  On the other hand, it's very natual to use a control file to do something in debugfs.
  So, I choose this solution. I hope that what I say will clarify the situation.:)
  Mathieu, What do you say?


> 
> 
> 
> 
> 
> 

-- 
Regards
Gui Jianfeng





^ permalink raw reply	[flat|nested] 17+ messages in thread

* [ltt-dev] [PATCH] LTTng: Make mark-control work in debugfs
  2009-02-16  3:48                         ` Gui Jianfeng
@ 2009-02-16  4:37                           ` Mathieu Desnoyers
  2009-02-16  5:16                             ` Gui Jianfeng
  0 siblings, 1 reply; 17+ messages in thread
From: Mathieu Desnoyers @ 2009-02-16  4:37 UTC (permalink / raw)


* Gui Jianfeng (guijianfeng at cn.fujitsu.com) wrote:
> KOSAKI Motohiro wrote:
> >>   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
> > 
> > No.
> > good user interface is important than easy implementation.
> > 
> > this UI is really ugly.
> 
>   Hi Kosaki-san,
> 
>   Thank you for your kind comments.
>   I say *not easy* becasue debugfs itself doesn't support *mkdir* completely.
>   If we are going to implement mkdir in marker control, we have to modify debugfs
>   itself. IMHO, it's not reasonable and i guess most of the debugfs subsystems don't 
>   like to see this change.
>   On the other hand, it's very natual to use a control file to do something in debugfs.
>   So, I choose this solution. I hope that what I say will clarify the situation.:)
>   Mathieu, What do you say?
> 

Hi Gui,

I would recommend adding mkdir support in our own directories. That
means we have to override debugfs use of "simple" libfs basic
operations. We want to use the same operations, but also define a mkdir
callback. See

fs/debugfs/inode.c:
debugfs_get_inode :
it sets inode->i_op = &simple_dir_inode_operations;

We will need to override this with our own. See
fs/libfs.c: simple_dir_inode_operations

I fully agree with Kosaki : the quality of the user interface is what
matters and is much more important than implementation difficulty.

Thanks,

Mathieu

> 
> > 
> > 
> > 
> > 
> > 
> > 
> 
> -- 
> 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




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [ltt-dev] [PATCH] LTTng: Make mark-control work in debugfs
  2009-02-16  4:37                           ` Mathieu Desnoyers
@ 2009-02-16  5:16                             ` Gui Jianfeng
  0 siblings, 0 replies; 17+ messages in thread
From: Gui Jianfeng @ 2009-02-16  5:16 UTC (permalink / raw)


Mathieu Desnoyers wrote:
> * Gui Jianfeng (guijianfeng at cn.fujitsu.com) wrote:
>> KOSAKI Motohiro wrote:
>>>>   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
>>> No.
>>> good user interface is important than easy implementation.
>>>
>>> this UI is really ugly.
>>   Hi Kosaki-san,
>>
>>   Thank you for your kind comments.
>>   I say *not easy* becasue debugfs itself doesn't support *mkdir* completely.
>>   If we are going to implement mkdir in marker control, we have to modify debugfs
>>   itself. IMHO, it's not reasonable and i guess most of the debugfs subsystems don't 
>>   like to see this change.
>>   On the other hand, it's very natual to use a control file to do something in debugfs.
>>   So, I choose this solution. I hope that what I say will clarify the situation.:)
>>   Mathieu, What do you say?
>>
> 
> Hi Gui,
> 
> I would recommend adding mkdir support in our own directories. That
> means we have to override debugfs use of "simple" libfs basic
> operations. We want to use the same operations, but also define a mkdir
> callback. See
> 
> fs/debugfs/inode.c:
> debugfs_get_inode :
> it sets inode->i_op = &simple_dir_inode_operations;
> 
> We will need to override this with our own. See
> fs/libfs.c: simple_dir_inode_operations
> 
  Ah, I see now, thanks for the suggestion, 

> I fully agree with Kosaki : the quality of the user interface is what
> matters and is much more important than implementation difficulty.

  Me too :)

> 
> Thanks,
> 
> Mathieu
> 
>>>
>>>
>>>
>>>
>>>
>> -- 
>> 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





^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2009-02-16  5:16 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-02-04  1:46 [ltt-dev] [PATCH] LTTng: Make mark-control work in debugfs Gui Jianfeng
2009-02-04  6:20 ` Mathieu Desnoyers
2009-02-04  6:30   ` Mathieu Desnoyers
2009-02-04  6:44   ` Gui Jianfeng
2009-02-04  7:12     ` Mathieu Desnoyers
2009-02-05  1:20       ` Gui Jianfeng
2009-02-11  5:32         ` Mathieu Desnoyers
2009-02-11  8:43           ` Mathieu Desnoyers
2009-02-11  9:27             ` Gui Jianfeng
2009-02-11 16:56               ` Mathieu Desnoyers
2009-02-13  6:24                 ` Gui Jianfeng
2009-02-13  6:54                   ` Mathieu Desnoyers
2009-02-16  2:43                     ` Gui Jianfeng
2009-02-16  3:16                       ` KOSAKI Motohiro
2009-02-16  3:48                         ` Gui Jianfeng
2009-02-16  4:37                           ` Mathieu Desnoyers
2009-02-16  5:16                             ` Gui Jianfeng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox