[ltt-dev] new ltt-trace-control module based on debugfs(v2)

Mathieu Desnoyers compudj at krystal.dyndns.org
Wed Nov 12 00:17:28 EST 2008


* Zhaolei (zhaolei at cn.fujitsu.com) wrote:
> Hi Mathieu,
> 
> I modified ltt-trace-control.ko to support "overwrite" mode of each channel.
> I tested it on x86, lttng 2.6.27.4-lttng-0.52, result seems ok.
> 
> run.sh in attachment can be used to test module's functions.
> 
> B.R.
> Zhaolei

> /*
>  * LTT trace control module over debugfs.
>  *
>  * Copyright 2008 -
>  *	Zhaolei <zhaolei at cn.fujitsu.com>
>  */
> 
> /*
>  * Todo:
>  *   Impl read operations for control file to read attributes
>  *   Create a README file in ltt control dir, for display help info
>  */
> 
> #include <linux/module.h>
> #include <linux/fs.h>
> #include <linux/uaccess.h>
> #include <linux/debugfs.h>
> #include <linux/ltt-tracer.h>
> 
> #define LTT_CONTROL_DIR "control"
> #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;
> 
> static DEFINE_MUTEX(control_lock);
> 
> /*
>  * lookup a file/dir in parent dir.
>  * only designed to work well for debugfs.
>  * (although it maybe ok for other fs)
>  *
>  * return:
>  *	file/dir's dentry on success
>  *	NULL on failure
>  */
> static inline struct dentry *dir_lookup(struct dentry *parent,
> 		const char *name) {
> 	struct qstr q;
> 	struct dentry *d;
> 
> 	q.name = name;
> 	q.len = strlen(name);
> 	q.hash = full_name_hash(q.name, q.len);
> 
> 	d = d_lookup(parent, &q);
> 	if (d)
> 		dput(d);
> 
> 	return d;
> }
> 
> 
> static ssize_t alloc_write(struct file *file, const char __user *user_buf,
> 		size_t count, loff_t *ppos)
> {
> 	int err = 0;
> 	char buf[NAME_MAX];
> 	int buf_size;
> 	char cmd[NAME_MAX];
> 
> 	buf_size = min(count, sizeof(buf) - 1);
> 	err = copy_from_user(buf, user_buf, buf_size);
> 	if (err)
> 		goto err_copy_from_user;
> 	buf[buf_size] = 0;
> 
> 	if (1 != sscanf(buf, "%s", cmd)) {
> 		err = -EPERM;
> 		goto err_get_cmd;
> 	}
> 
> 	if ((cmd[0] != 'Y' && cmd[0] != 'y' && cmd[0] != '1') || cmd[1]) {
> 		err = -EPERM;
> 		goto err_bad_cmd;
> 	}
> 
> 	err = ltt_trace_alloc(file->f_dentry->d_parent->d_name.name);
> 	if (IS_ERR_VALUE(err)) {
> 		printk(KERN_ERR "alloc_write: ltt_trace_alloc failed: %d\n",
> 			err);
> 		goto err_alloc_trace;
> 	}
> 
> 	return count;
> 
> err_alloc_trace:
> err_bad_cmd:
> err_get_cmd:
> err_copy_from_user:
> 	return err;
> }
> 
> static struct file_operations ltt_alloc_operations = {
> 	.write = alloc_write,
> };
> 
> 
> static ssize_t enabled_write(struct file *file, const char __user *user_buf,
> 		size_t count, loff_t *ppos)
> {
> 	int err = 0;
> 	char buf[NAME_MAX];
> 	int buf_size;
> 	char cmd[NAME_MAX];
> 
> 	buf_size = min(count, sizeof(buf) - 1);
> 	err = copy_from_user(buf, user_buf, buf_size);
> 	if (err)
> 		goto err_copy_from_user;
> 	buf[buf_size] = 0;
> 
> 	if (1 != sscanf(buf, "%s", cmd)) {
> 		err = -EPERM;
> 		goto err_get_cmd;
> 	}
> 
> 	if (cmd[1]) {
> 		err = -EPERM;
> 		goto err_bad_cmd;
> 	}
> 
> 	switch (cmd[0]) {
> 	case 'Y':
> 	case 'y':
> 	case '1':
> 		err = ltt_trace_start(
> 			file->f_dentry->d_parent->d_name.name);
> 		/*
> 		 * ltt_trace_start return +ERRNO,
> 		 * so we can't use IS_ERR_VALUE(err)
> 		 */
> 		if (err) {
> 			printk(KERN_ERR "enabled_write: ltt_trace_start failed: %d\n",
> 				err);
> 			err = -EPERM;
> 			goto err_start_trace;
> 		}
> 		break;
> 	case 'N':
> 	case 'n':
> 	case '0':
> 		err = ltt_trace_stop(
> 			file->f_dentry->d_parent->d_name.name);
> 		/*
> 		 * ltt_trace_stop return +ERRNO,
> 		 * so we can't use IS_ERR_VALUE(err)
> 		 */
> 		if (err) {
> 			printk(KERN_ERR "enabled_write: ltt_trace_stop failed: %d\n",
> 				err);
> 			err = -EPERM;
> 			goto err_stop_trace;
> 		}
> 		break;
> 	default:
> 		err = -EPERM;
> 		goto err_bad_cmd;
> 	}
> 
> 	return count;
> 
> err_stop_trace:
> err_start_trace:
> err_bad_cmd:
> err_get_cmd:
> err_copy_from_user:
> 	return err;
> }
> 
> static struct file_operations ltt_enabled_operations = {
> 	.write = enabled_write,
> };
> 
> 
> static ssize_t trans_write(struct file *file, const char __user *user_buf,
> 		size_t count, loff_t *ppos)
> {
> 	int err = 0;
> 	char buf[NAME_MAX];
> 	int buf_size;
> 	char trans_name[NAME_MAX];
> 
> 	buf_size = min(count, sizeof(buf) - 1);
> 	err = copy_from_user(buf, user_buf, buf_size);
> 	if (err)
> 		goto err_copy_from_user;
> 	buf[buf_size] = 0;
> 
> 	if (1 != sscanf(buf, "%s", trans_name)) {
> 		err = -EPERM;
> 		goto err_get_transname;
> 	}
> 
> 	err = ltt_trace_set_type(file->f_dentry->d_parent->d_name.name,
> 		trans_name);
> 	if (IS_ERR_VALUE(err)) {
> 		printk(KERN_ERR "trans_write: ltt_trace_set_type failed: %d\n",
> 			err);
> 		goto err_set_trans;
> 	}
> 
> 	return count;
> 
> err_set_trans:
> err_get_transname:
> err_copy_from_user:
> 	return err;
> }
> 
> static struct file_operations ltt_trans_operations = {
> 	.write = trans_write,
> };
> 
> 
> static ssize_t subbuf_num_write(struct file *file, const char __user *user_buf,
> 		size_t count, loff_t *ppos)
> {
> 	int err = 0;
> 	char buf[NAME_MAX];
> 	int buf_size;
> 	unsigned int num;
> 	const char *channel_name;
> 	const char *trace_name;
> 
> 	buf_size = min(count, sizeof(buf) - 1);
> 	err = copy_from_user(buf, user_buf, buf_size);
> 	if (err)
> 		goto err_copy_from_user;
> 	buf[buf_size] = 0;
> 
> 	if (1 != sscanf(buf, "%u", &num)) {
> 		err = -EPERM;
> 		goto err_get_number;
> 	}
> 
> 	channel_name = file->f_dentry->d_parent->d_name.name;
> 	trace_name = file->f_dentry->d_parent->d_parent->d_parent->d_name.name;
> 
> 	err = ltt_trace_set_channel_subbufcount(trace_name, channel_name, num);
> 	if (IS_ERR_VALUE(err)) {
> 		printk(KERN_ERR "subbuf_num_write: ltt_trace_set_channel_subbufcount failed: %d\n",

This is probably over 80 columns. Maybe you should try
scripts/checkpatch.pl.

> 			err);
> 		goto err_set_subbufcount;
> 	}
> 
> 	return count;
> 
> err_set_subbufcount:
> err_get_number:
> err_copy_from_user:
> 	return err;
> }
> 
> static struct file_operations ltt_subbuf_num_operations = {
> 	.write = subbuf_num_write,
> };
> 
> 
> static ssize_t subbuf_size_write(struct file *file, const char __user *user_buf,
> 		size_t count, loff_t *ppos)
> {
> 	int err = 0;
> 	char buf[NAME_MAX];
> 	int buf_size;
> 	unsigned int num;
> 	const char *channel_name;
> 	const char *trace_name;
> 
> 	buf_size = min(count, sizeof(buf) - 1);
> 	err = copy_from_user(buf, user_buf, buf_size);
> 	if (err)
> 		goto err_copy_from_user;
> 	buf[buf_size] = 0;
> 
> 	if (1 != sscanf(buf, "%u", &num)) {
> 		err = -EPERM;
> 		goto err_get_number;
> 	}
> 
> 	channel_name = file->f_dentry->d_parent->d_name.name;
> 	trace_name = file->f_dentry->d_parent->d_parent->d_parent->d_name.name;
> 
> 	err = ltt_trace_set_channel_subbufsize(trace_name, channel_name, num);
> 	if (IS_ERR_VALUE(err)) {
> 		printk(KERN_ERR "subbuf_size_write: ltt_trace_set_channel_subbufsize failed: %d\n",
> 			err);
> 		goto err_set_subbufsize;
> 	}
> 
> 	return count;
> 
> err_set_subbufsize:
> err_get_number:
> err_copy_from_user:
> 	return err;
> }
> 
> static struct file_operations ltt_subbuf_size_operations = {
> 	.write = subbuf_size_write,
> };
> 
> 
> static ssize_t overwrite_write(struct file *file, const char __user *user_buf,
> 		size_t count, loff_t *ppos)
> {
> 	int err = 0;
> 	char buf[NAME_MAX];
> 	int buf_size;
> 	char cmd[NAME_MAX];
> 	const char *channel_name;
> 	const char *trace_name;
> 
> 	buf_size = min(count, sizeof(buf) - 1);
> 	err = copy_from_user(buf, user_buf, buf_size);
> 	if (err)
> 		goto err_copy_from_user;
> 	buf[buf_size] = 0;
> 
> 	if (1 != sscanf(buf, "%s", cmd)) {

Typically one would write

if (sscanf(buf, "%s", cmd) != 1) {

> 		err = -EPERM;
> 		goto err_get_cmd;
> 	}
> 
> 	if (cmd[1]) {
> 		err = -EPERM;
> 		goto err_bad_cmd;
> 	}
> 
> 	channel_name = file->f_dentry->d_parent->d_name.name;
> 	trace_name = file->f_dentry->d_parent->d_parent->d_parent->d_name.name;
> 
> 	switch (cmd[0]) {
> 	case 'Y':
> 	case 'y':
> 	case '1':
> 		err = ltt_trace_set_channel_overwrite(trace_name, channel_name,
> 			1);
> 		if (IS_ERR_VALUE(err)) {
> 			printk(KERN_ERR
> 				"subbuf_size_write: ltt_trace_set_channel_subbufsize failed: %d\n",
> 				err);
> 			goto err_set_subbufsize;
> 		}
> 		break;
> 	case 'N':
> 	case 'n':
> 	case '0':
> 		err = ltt_trace_set_channel_overwrite(trace_name, channel_name,
> 			0);
> 		if (IS_ERR_VALUE(err)) {
> 			printk(KERN_ERR
> 				"subbuf_size_write: ltt_trace_set_channel_subbufsize failed: %d\n",
> 				err);
> 			goto err_set_subbufsize;
> 		}
> 		break;
> 	default:
> 		err = -EPERM;
> 		goto err_bad_cmd;
> 	}
> 
> 	return count;
> 
> err_set_subbufsize:
> err_bad_cmd:
> err_get_cmd:
> err_copy_from_user:
> 	return err;
> }
> 
> static struct file_operations ltt_overwrite_operations = {
> 	.write = overwrite_write,
> };
> 
> 
> static ssize_t mode_write(struct file *file, const char __user *user_buf,
> 		size_t count, loff_t *ppos)
> {
> 	int err = 0;
> 	char buf[NAME_MAX];
> 	int buf_size;
> 	unsigned int mode_i;
> 	enum trace_mode mode;
> 
> 	buf_size = min(count, sizeof(buf) - 1);
> 	err = copy_from_user(buf, user_buf, buf_size);
> 	if (err)
> 		goto err_copy_from_user;
> 	buf[buf_size] = 0;
> 
> 	if (1 != sscanf(buf, "%u", &mode_i)) {
> 		err = -EPERM;
> 		goto err_get_mode;
> 	}
> 
> 	switch (mode_i) {
> 	case 0:
> 		mode = LTT_TRACE_NORMAL;
> 		break;
> 	case 1:
> 		mode = LTT_TRACE_FLIGHT;
> 		break;
> 	case 2:
> 		mode = LTT_TRACE_HYBRID;
> 		break;
> 	default:
> 		err = -EPERM;
> 		goto err_get_mode;
> 	};
> 
> 	err = ltt_trace_set_mode(
> 		file->f_dentry->d_parent->d_parent->d_parent->d_name.name,
> 		mode);
> 	if (IS_ERR_VALUE(err)) {
> 		printk(KERN_ERR "mode_write: ltt_trace_set_mode failed: %d\n",
> 			err);
> 		goto err_set_mode;
> 	}
> 
> 	return count;
> 
> err_set_mode:
> err_get_mode:
> err_copy_from_user:
> 	return err;
> }
> 
> static struct file_operations ltt_mode_operations = {
> 	.write = mode_write,
> };
> 
> 
> static int _create_trace_control_dir(const char *trace_name)
> {
> 	int err;
> 	struct dentry *trace_root, *channel_root;
> 	struct dentry *tmp_den;
> 	int i;
> 
> 	/*
> 	 * for create channels' dir.
> 	 * Todo:
> 	 *   get channel_names from exported lttng variable.
> 	 */
> 	static const char *channels[] = {
> 		"cpu",
> 		"processes",
> 		"interrupts",
> 		"network",
> 		"modules",
> 		"metadata"
> 	};

Declaring this outside of the scope of the function would be preferred.

> 
> 	/* debugfs/control/trace_name */
> 	trace_root = debugfs_create_dir(trace_name, ltt_control_dir);
> 	if (IS_ERR(trace_root) || !trace_root) {
> 		printk(KERN_ERR "_create_trace_control_dir: create control root dir of %s failed\n",
> 			trace_name);
> 		err = -ENOMEM;
> 		goto err_create_trace_root;
> 	}
> 
> 	/* debugfs/control/trace_name/alloc */
> 	tmp_den = debugfs_create_file("alloc", 0200, trace_root, NULL,

0200 -> maybe we should use the standard macros for this.

Thanks,

MAthieu

> 		&ltt_alloc_operations);
> 	if (IS_ERR(tmp_den) || !tmp_den) {
> 		printk(KERN_ERR "_create_trace_control_dir: create file of alloc failed\n");
> 		err = -ENOMEM;
> 		goto err_create_subdir;
> 	}
> 
> 	/* debugfs/control/trace_name/trans */
> 	tmp_den = debugfs_create_file("trans", 0200, trace_root, NULL,
> 		&ltt_trans_operations);
> 	if (IS_ERR(tmp_den) || !tmp_den) {
> 		printk(KERN_ERR "_create_trace_control_dir: create file of trans failed\n");
> 		err = -ENOMEM;
> 		goto err_create_subdir;
> 	}
> 
> 	/* debugfs/control/trace_name/enabled */
> 	tmp_den = debugfs_create_file("enabled", 0200, trace_root, NULL,
> 		&ltt_enabled_operations);
> 	if (IS_ERR(tmp_den) || !tmp_den) {
> 		printk(KERN_ERR "_create_trace_control_dir: create file of enabled failed\n");
> 		err = -ENOMEM;
> 		goto err_create_subdir;
> 	}
> 
> 	/* debugfs/control/trace_name/channel/ */
> 	channel_root = debugfs_create_dir("channel", trace_root);
> 	if (IS_ERR(channel_root) || !channel_root) {
> 		printk(KERN_ERR "_create_trace_control_dir: create dir of channel failed\n");
> 		err = -ENOMEM;
> 		goto err_create_subdir;
> 	}
> 
> 	/*
> 	 * Create dir and files in debugfs/ltt/control/trace_name/channel/
> 	 * Following things(without <>) will be created:
> 	 * `-- <control>
> 	 *     `-- <trace_name>
> 	 *         `-- <channel>
> 	 *             |-- interrupts
> 	 *             |   |-- subbuf_num
> 	 *             |   `-- subbuf_size
> 	 *             |-- metadata
> 	 *             |   |-- subbuf_num
> 	 *             |   `-- subbuf_size
> 	 *             |-- modules
> 	 *             |   |-- subbuf_num
> 	 *             |   `-- subbuf_size
> 	 *             |-- network
> 	 *             |   |-- subbuf_num
> 	 *             |   `-- subbuf_size
> 	 *             |-- processes
> 	 *             |   |-- subbuf_num
> 	 *             |   `-- subbuf_size
> 	 *             `-- cpu
> 	 *                 |-- mode
> 	 *                 |-- subbuf_num
> 	 *                 `-- subbuf_size
> 	 */
> 
> 	for (i = 0; i < sizeof(channels)/sizeof(channels[0]); i++) {
> 		struct dentry *channel_den;
> 
> 		channel_den = debugfs_create_dir(channels[i], channel_root);
> 		if (IS_ERR(channel_den) || !channel_den) {
> 			printk(KERN_ERR "_create_trace_control_dir: create channel dir of %s failed\n",
> 				channels[i]);
> 			err = -ENOMEM;
> 			goto err_create_subdir;
> 		}
> 
> 		tmp_den = debugfs_create_file("subbuf_num", 0200, channel_den,
> 			NULL, &ltt_subbuf_num_operations);
> 		if (IS_ERR(tmp_den) || !tmp_den) {
> 			printk(KERN_ERR "_create_trace_control_dir: create subbuf_num in %s failed\n",
> 				channels[i]);
> 			err = -ENOMEM;
> 			goto err_create_subdir;
> 		}
> 
> 		tmp_den = debugfs_create_file("subbuf_size", 0200, channel_den,
> 			NULL, &ltt_subbuf_size_operations);
> 		if (IS_ERR(tmp_den) || !tmp_den) {
> 			printk(KERN_ERR "_create_trace_control_dir: create subbuf_size in %s failed\n",
> 				channels[i]);
> 			err = -ENOMEM;
> 			goto err_create_subdir;
> 		}
> 
> 		tmp_den = debugfs_create_file("overwrite", 0200, channel_den,
> 			NULL, &ltt_overwrite_operations);
> 		if (IS_ERR(tmp_den) || !tmp_den) {
> 			printk(KERN_ERR "_create_trace_control_dir: create overwrite in %s failed\n",
> 				channels[i]);
> 			err = -ENOMEM;
> 			goto err_create_subdir;
> 		}
> 
> 		if (!i) {
> 			/* debugfs/control/trace_name/channel/cpu/mode */
> 			tmp_den = debugfs_create_file("mode", 0200,
> 				channel_den, NULL, &ltt_mode_operations);
> 			if (IS_ERR(tmp_den) || !tmp_den) {
> 				printk(KERN_ERR "_create_trace_control_dir: create mode in %s failed\n",
> 					channels[i]);
> 				err = -ENOMEM;
> 				goto err_create_subdir;
> 			}
> 		}
> 	}
> 
> 	return 0;
> 
> err_create_subdir:
> 	debugfs_remove_recursive(trace_root);
> err_create_trace_root:
> 	return err;
> }
> 
> static ssize_t setup_trace_write(struct file *file, const char __user *user_buf,
> 		size_t count, loff_t *ppos)
> {
> 	int err = 0;
> 	char buf[NAME_MAX];
> 	int buf_size;
> 	char trace_name[NAME_MAX];
> 
> 	buf_size = min(count, sizeof(buf) - 1);
> 	err = copy_from_user(buf, user_buf, buf_size);
> 	if (err)
> 		goto err_copy_from_user;
> 	buf[buf_size] = 0;
> 
> 	if (1 != sscanf(buf, "%s", trace_name)) {
> 		err = -EPERM;
> 		goto err_get_tracename;
> 	}
> 
> 	mutex_lock(&control_lock);
> 
> 	err = ltt_trace_setup(trace_name);
> 	if (IS_ERR_VALUE(err)) {
> 		printk(KERN_ERR "setup_trace_write: ltt_trace_setup failed: %d\n",
> 			err);
> 		goto err_setup_trace;
> 	}
> 
> 	err = _create_trace_control_dir(trace_name);
> 	if (IS_ERR_VALUE(err)) {
> 		printk(KERN_ERR "setup_trace_write: _create_trace_control_dir failed: %d\n",
> 			err);
> 		goto err_create_trace_control_dir;
> 	}
> 
> 	mutex_unlock(&control_lock);
> 
> 	return count;
> 
> err_create_trace_control_dir:
> 	ltt_trace_destroy(trace_name);
> err_setup_trace:
> 	mutex_unlock(&control_lock);
> err_get_tracename:
> err_copy_from_user:
> 	return err;
> }
> 
> static struct file_operations ltt_setup_trace_operations = {
> 	.write = setup_trace_write,
> };
> 
> 
> static ssize_t destroy_trace_write(struct file *file,
> 		const char __user *user_buf, size_t count, loff_t *ppos)
> {
> 	int err = 0;
> 	char buf[NAME_MAX];
> 	int buf_size;
> 	char trace_name[NAME_MAX];
> 	struct dentry *trace_den;
> 
> 
> 	buf_size = min(count, sizeof(buf) - 1);
> 	err = copy_from_user(buf, user_buf, buf_size);
> 	if (err)
> 		goto err_copy_from_user;
> 	buf[buf_size] = 0;
> 
> 	if (1 != sscanf(buf, "%s", trace_name)) {
> 		err = -EPERM;
> 		goto err_get_tracename;
> 	}
> 
> 	mutex_lock(&control_lock);
> 
> 	err = ltt_trace_destroy(trace_name);
> 	/*
> 	 * ltt_trace_destroy return +ERRNO,
> 	 * so we can't use IS_ERR_VALUE(err)
> 	 */
> 	if (err) {
> 		printk(KERN_ERR "destroy_trace_write: ltt_trace_destroy failed: %d\n",
> 			err);
> 		err = -EPERM;
> 		goto err_destroy_trace;
> 	}
> 
> 	trace_den = dir_lookup(ltt_control_dir, trace_name);
> 	if (!trace_den) {
> 		printk(KERN_ERR "destroy_trace_write: lookup for %s's dentry failed\n",
> 			trace_name);
> 		err = -ENOENT;
> 		goto err_get_dentry;
> 	}
> 
> 	debugfs_remove_recursive(trace_den);
> 
> 	mutex_unlock(&control_lock);
> 
> 	return count;
> 
> err_get_dentry:
> err_destroy_trace:
> 	mutex_unlock(&control_lock);
> err_get_tracename:
> err_copy_from_user:
> 	return err;
> }
> 
> static struct file_operations ltt_destroy_trace_operations = {
> 	.write = destroy_trace_write,
> };
> 
> 
> static int __init ltt_trace_control_init(void)
> {
> 	int err = 0;
> 
> 	if (!ltt_root_dentry) {
> 		err = -ENOENT;
> 		goto err_no_root;
> 	}
> 
> 	ltt_control_dir = debugfs_create_dir(LTT_CONTROL_DIR, ltt_root_dentry);
> 	if (IS_ERR(ltt_control_dir) || !ltt_control_dir) {
> 		printk(KERN_ERR "ltt_channel_control_init: create dir of %s failed\n",
> 			LTT_CONTROL_DIR);
> 		err = -ENOMEM;
> 		goto err_create_control_dir;
> 	}
> 
> 	ltt_setup_trace_file = debugfs_create_file(LTT_SETUP_TRACE_FILE, 0200,
> 		ltt_root_dentry, NULL, &ltt_setup_trace_operations);
> 	if (IS_ERR(ltt_setup_trace_file) || !ltt_setup_trace_file) {
> 		printk(KERN_ERR "ltt_channel_control_init: create file of %s failed\n",
> 			LTT_SETUP_TRACE_FILE);
> 		err = -ENOMEM;
> 		goto err_create_setup_trace_file;
> 	}
> 
> 	ltt_destroy_trace_file = debugfs_create_file(LTT_DESTROY_TRACE_FILE,
> 		0200, ltt_root_dentry, NULL, &ltt_destroy_trace_operations);
> 	if (IS_ERR(ltt_destroy_trace_file) || !ltt_destroy_trace_file) {
> 		printk(KERN_ERR "ltt_channel_control_init: create file of %s failed\n",
> 			LTT_DESTROY_TRACE_FILE);
> 		err = -ENOMEM;
> 		goto err_create_destroy_trace_file;
> 	}
> 
> 	return 0;
> 
> err_create_destroy_trace_file:
> 	debugfs_remove(ltt_setup_trace_file);
> err_create_setup_trace_file:
> 	debugfs_remove(ltt_control_dir);
> err_create_control_dir:
> err_no_root:
> 	return err;
> }
> 
> static void __exit ltt_trace_control_exit(void)
> {
> 	struct dentry *trace_dir;
> 
> 	/* destory all traces */
> 	list_for_each_entry(trace_dir, &ltt_control_dir->d_subdirs,
> 		d_u.d_child) {
> 		ltt_trace_stop(trace_dir->d_name.name);
> 		ltt_trace_destroy(trace_dir->d_name.name);
> 	}
> 
> 	/* clean dirs in debugfs */
> 	debugfs_remove(ltt_setup_trace_file);
> 	debugfs_remove(ltt_destroy_trace_file);
> 	debugfs_remove_recursive(ltt_control_dir);
> }
> 
> module_init(ltt_trace_control_init);
> module_exit(ltt_trace_control_exit);
> 
> MODULE_LICENSE("GPL");

> obj-m := ltt_trace_control.o
> KDIR := /lib/modules/$(shell uname -r)/build
> PWD := $(shell pwd)
> 
> default:
> 	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
> clean:
> 	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) clean
> 	rm -rf Module.markers modules.order Module.symvers

> #!/bin/bash
> make
> insmod ltt_trace_control.ko
> 
> echo BEFORE CREATE CHANNEL
> tree /mnt/debugfs/ltt
> echo;echo
> 
> echo CREATE CHANNEL
> echo zltest > /mnt/debugfs/ltt/setup_trace
> tree /mnt/debugfs/ltt
> echo;echo
> 
> echo SETUP TRANS
> echo relay > /mnt/debugfs/ltt/control/zltest/trans
> echo;echo
> 
> 
> echo SETUP BUFNUMBER
> echo 4 > /mnt/debugfs/ltt/control/zltest/channel/network/subbuf_num
> echo;echo
> 
> 
> echo SETUP BUFSIZE
> echo 65536 > /mnt/debugfs/ltt/control/zltest/channel/network/subbuf_size
> echo;echo
> 
> echo SETUP OVERWRITE
> echo 1 > /mnt/debugfs/ltt/control/zltest/channel/network/overwrite
> echo 0 > /mnt/debugfs/ltt/control/zltest/channel/cpu/overwrite
> echo;echo
> 
> echo SETUP WRONG OVERWRITE
> echo 1 > /mnt/debugfs/ltt/control/zltest/channel/metadata/overwrite
> echo;echo
> 
> 
> echo ALLOC CHANNEL
> echo 1 > /mnt/debugfs/ltt/control/zltest/alloc
> echo;echo
> 
> 
> echo RUN CHANNEL
> echo 1 > /mnt/debugfs/ltt/control/zltest/enabled
> echo;echo
> 
> echo STOP CHANNEL
> echo 0 > /mnt/debugfs/ltt/control/zltest/enabled
> echo;echo
> 
> echo DESTROY CHANNEL
> echo zltest > /mnt/debugfs/ltt/destroy_trace
> echo;echo
> 
> echo RM MOD
> rmmod ltt_trace_control.ko
> 

> _______________________________________________
> ltt-dev mailing list
> ltt-dev at lists.casi.polymtl.ca
> http://lists.casi.polymtl.ca/cgi-bin/mailman/listinfo/ltt-dev


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




More information about the lttng-dev mailing list