[ltt-dev] [PATCH v4] LTTNG: Make marker enabled in advance

Mathieu Desnoyers compudj at krystal.dyndns.org
Mon Apr 6 13:35:44 EDT 2009


* Gui Jianfeng (guijianfeng at cn.fujitsu.com) wrote:
> Hi Mathieu,
> 
> Sorry for the later, i'm a little busy these days.
> 

Sounds good, I'll pull it. Thanks !

Mathieu

> v3 -> v4 changes:
> - export _is_marker_present and _is_marker_enabled
> - hold markers_mutex around _is_marker_present and _is_marker_enabled
> - fix a typo
> 
> This patch makes marker enabled in advance.
> IOW, even if the marker isn't present for the moment,
> you can still enable it for future use.
> As soon as the marker is inserted into kernel, tracing 
> work can be started immediately.
> 
> Here is an example for using the user interface:
> This patch assumes the marker control patch is applied.
> [root at localhost markers]# cd /mnt/debugfs/ltt/markers
> [root at localhost markers]# mkdir fs
> [root at localhost markers]# cd fs/
> [root at localhost fs]# mkdir close
> [root at localhost fs]# cd close/
> [root at localhost close]# echo 1 > enable
> [root at localhost close]# cat enable
> 2
> [root at localhost close]# cat info
> Marker Pre-enabled
> [root at localhost close]# modprobe fs-trace
> [root at localhost close]# cat enable
> 1
> [root at localhost close]# cat info
> Location: fs_trace
> format: "fd %u"
> state: 1
> event_id: 0
> call: 0xc0468192
> probe single : 0xc0520ed8
> 
> You can also remove a marker directory by "rmdir" if there
> is no actual marker backed and isn't enabled in advance. 
> A channel directory can be remove if there are not any marker
> directories in it.
> 
> Signed-off-by: Gui Jianfeng <guijianfeng at cn.fujitsu.com>
> ---
>  include/linux/marker.h  |    3
>  kernel/marker.c         |   75 ++++++++++++++++++-
>  ltt/ltt-trace-control.c |  189 +++++++++++++++++++++++++++++++++++++++++++++---
>  3 files changed, 255 insertions(+), 12 deletions(-)
> 
> diff --git a/include/linux/marker.h b/include/linux/marker.h
> index 2d78113..d185235 100644
> --- a/include/linux/marker.h
> +++ b/include/linux/marker.h
> @@ -260,6 +260,9 @@ extern void marker_iter_stop(struct marker_iter *iter);
>  extern void marker_iter_reset(struct marker_iter *iter);
>  extern int marker_get_iter_range(struct marker **marker, struct marker *begin,
>  	struct marker *end);
> +extern int _is_marker_enabled(const char *channel, const char *name);
>  extern int is_marker_enabled(const char *channel, const char *name);
> +extern int _is_marker_present(const char *channel, const char *name);
> +extern int is_marker_present(const char *channel, const char *name);
>  
>  #endif
> diff --git a/kernel/marker.c b/kernel/marker.c
> index 93ffa8e..bb35db2 100644
> --- a/kernel/marker.c
> +++ b/kernel/marker.c
> @@ -653,22 +653,89 @@ static void disable_marker(struct marker *elem)
>  }
>  
>  /*
> - * is_marker_enabled - Check if a marker is enabled
> + * _is_marker_present - Check if a marker is present in kernel must be called
> + *                      with markers_mutex held.
> + * @channel: channel name
> + * @name: marker name
> + *
> + * Returns 1 if the marker is present, 0 if not.
> + */
> +int _is_marker_present(const char *channel, const char *name)
> +{
> +	int ret;
> +	struct marker_iter iter;
> +
> +	ret = 0;
> +
> +	marker_iter_reset(&iter);
> +	marker_iter_start(&iter);
> +	for (; iter.marker != NULL; marker_iter_next(&iter)) {
> +		if (!strcmp(iter.marker->channel, channel) &&
> +		    !strcmp(iter.marker->name, name)) {
> +			ret = 1;
> +			goto end;
> +		}
> +	}
> +end:
> +	marker_iter_stop(&iter);
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(_is_marker_present);
> +
> +/*
> + * is_marker_present - the wrapper of _is_marker_present
> + * @channel: channel name
> + * @name: marker name
> + *
> + * Returns 1 if the marker is present, 0 if not.
> + */
> +int is_marker_present(const char *channel, const char *name)
> +{
> +	int ret;
> +
> +	lock_markers();
> +	ret = _is_marker_present(channel, name);
> +	unlock_markers();
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(is_marker_present);
> +
> +/*
> + * _is_marker_enabled - Check if a marker is enabled, must be called with
> + *                      markers_mutex held.
>   * @channel: channel name
>   * @name: marker name
>   *
>   * Returns 1 if the marker is enabled, 0 if disabled.
>   */
> -int is_marker_enabled(const char *channel, const char *name)
> +int _is_marker_enabled(const char *channel, const char *name)
>  {
>  	struct marker_entry *entry;
>  
> -	mutex_lock(&markers_mutex);
>  	entry = get_marker(channel, name);
> -	mutex_unlock(&markers_mutex);
>  
>  	return entry && !!entry->refcount;
>  }
> +EXPORT_SYMBOL_GPL(_is_marker_enabled);
> +
> +/*
> + * is_marker_enabled - the wrapper of _is_marker_enabled
> + * @channel: channel name
> + * @name: marker name
> + *
> + * Returns 1 if the marker is enabled, 0 if disabled.
> + */
> +int is_marker_enabled(const char *channel, const char *name)
> +{
> +	int ret;
> +
> +	lock_markers();
> +	ret = _is_marker_enabled(channel, name);
> +	unlock_markers();
> +
> +	return ret;
> +}
>  EXPORT_SYMBOL_GPL(is_marker_enabled);
>  
>  /**
> diff --git a/ltt/ltt-trace-control.c b/ltt/ltt-trace-control.c
> index 63cbb29..35ef759 100644
> --- a/ltt/ltt-trace-control.c
> +++ b/ltt/ltt-trace-control.c
> @@ -756,12 +756,18 @@ static const struct file_operations ltt_destroy_trace_operations = {
>  	.write = destroy_trace_write,
>  };
>  
> +static void init_marker_dir(struct dentry *dentry,
> +			    const struct inode_operations *opt)
> +{
> +	dentry->d_inode->i_op = opt;
> +}
> +
>  static ssize_t marker_enable_read(struct file *filp, char __user *ubuf,
>  			    size_t cnt, loff_t *ppos)
>  {
>  	char *buf;
>  	const char *channel, *marker;
> -	int len;
> +	int len, enabled, present;
>  
>  	marker = filp->f_dentry->d_parent->d_name.name;
>  	channel = filp->f_dentry->d_parent->d_parent->d_name.name;
> @@ -769,10 +775,21 @@ static ssize_t marker_enable_read(struct file *filp, char __user *ubuf,
>  	len = 0;
>  	buf = (char *)__get_free_page(GFP_KERNEL);
>  
> -	if (is_marker_enabled(channel, marker))
> +	lock_markers();
> +
> +	enabled = _is_marker_enabled(channel, marker);
> +	present = _is_marker_present(channel, marker);
> +
> +	unlock_markers();
> +
> +	if (enabled && present)
>  		len = snprintf(buf, PAGE_SIZE, "%d\n", 1);
> +	else if (enabled && !present)
> +		len = snprintf(buf, PAGE_SIZE, "%d\n", 2);
>  	else
>  		len = snprintf(buf, PAGE_SIZE, "%d\n", 0);
> +
> +
>  	if (len >= PAGE_SIZE) {
>  		len = PAGE_SIZE;
>  		buf[PAGE_SIZE] = '\0';
> @@ -848,6 +865,13 @@ static ssize_t marker_info_read(struct file *filp, char __user *ubuf,
>  
>  	lock_markers();
>  
> +	if (_is_marker_enabled(channel, marker) &&
> +	    !_is_marker_present(channel, marker)) {
> +		len += snprintf(buf + len, PAGE_SIZE - len,
> +				"Marker Pre-enabled\n");
> +		goto out;
> +	}
> +
>  	marker_iter_reset(&iter);
>  	marker_iter_start(&iter);
>  	for (; iter.marker != NULL; marker_iter_next(&iter)) {
> @@ -874,8 +898,8 @@ static ssize_t marker_info_read(struct file *filp, char __user *ubuf,
>  	}
>  	marker_iter_stop(&iter);
>  
> +out:
>  	unlock_markers();
> -
>  	if (len >= PAGE_SIZE) {
>  		len = PAGE_SIZE;
>  		buf[PAGE_SIZE] = '\0';
> @@ -891,6 +915,154 @@ static const struct file_operations info_fops = {
>  	.read = marker_info_read,
>  };
>  
> +static int marker_mkdir(struct inode *dir, struct dentry *dentry, int mode)
> +{
> +	struct dentry *marker_d, *enable_d, *info_d, *channel_d;
> +	int ret;
> +
> +	ret = 0;
> +	channel_d = (struct dentry *)dir->i_private;
> +	mutex_unlock(&dir->i_mutex);
> +
> +	marker_d = debugfs_create_dir(dentry->d_name.name,
> +				      channel_d);
> +	if (IS_ERR(marker_d)) {
> +		ret = PTR_ERR(marker_d);
> +		goto out;
> +	}
> +
> +	enable_d = debugfs_create_file("enable", 0644, marker_d,
> +				       NULL, &enable_fops);
> +	if (IS_ERR(enable_d) || !enable_d) {
> +		printk(KERN_ERR
> +		       "%s: create file of %s failed\n",
> +		       __func__, "enable");
> +		ret = -ENOMEM;
> +		goto remove_marker_dir;
> +	}
> +
> +	info_d = debugfs_create_file("info", 0644, marker_d,
> +				     NULL, &info_fops);
> +	if (IS_ERR(info_d) || !info_d) {
> +		printk(KERN_ERR
> +		       "%s: create file of %s failed\n",
> +		       __func__, "info");
> +		ret = -ENOMEM;
> +		goto remove_enable_dir;
> +	}
> +
> +	goto out;
> +
> +remove_enable_dir:
> +	debugfs_remove(enable_d);
> +remove_marker_dir:
> +	debugfs_remove(marker_d);
> +out:
> +	mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
> +	return ret;
> +}
> +
> +static int marker_rmdir(struct inode *dir, struct dentry *dentry)
> +{
> +	struct dentry *marker_d, *channel_d;
> +	const char *channel, *name;
> +	int ret, enabled, present;
> +
> +	ret = 0;
> +
> +	channel_d = (struct dentry *)dir->i_private;
> +	channel = channel_d->d_name.name;
> +
> +	marker_d = dir_lookup(channel_d, dentry->d_name.name);
> +
> +	if (!marker_d) {
> +		ret = -ENOENT;
> +		goto out;
> +	}
> +
> +	name = marker_d->d_name.name;
> +
> +	lock_markers();
> +
> +	enabled = _is_marker_enabled(channel, name);
> +	present = _is_marker_present(channel, name);
> +
> +	unlock_markers();
> +
> +	if (present || (!present && enabled)) {
> +		ret = -EPERM;
> +		goto out;
> +	}
> +
> +	mutex_unlock(&dir->i_mutex);
> +	mutex_unlock(&dentry->d_inode->i_mutex);
> +	debugfs_remove_recursive(marker_d);
> +	mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
> +	mutex_lock(&dentry->d_inode->i_mutex);
> +out:
> +	return ret;
> +}
> +
> +const struct inode_operations channel_dir_opt = {
> +	.lookup = simple_lookup,
> +	.mkdir = marker_mkdir,
> +	.rmdir = marker_rmdir,
> +};
> +
> +static int channel_mkdir(struct inode *dir, struct dentry *dentry, int mode)
> +{
> +	struct dentry *channel_d;
> +	int ret;
> +
> +	ret = 0;
> +	mutex_unlock(&dir->i_mutex);
> +
> +	channel_d = debugfs_create_dir(dentry->d_name.name,
> +				       markers_control_dir);
> +	if (IS_ERR(channel_d)) {
> +		ret = PTR_ERR(channel_d);
> +		goto out;
> +	}
> +
> +	channel_d->d_inode->i_private = (void *)channel_d;
> +	init_marker_dir(channel_d, &channel_dir_opt);
> +out:
> +	mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
> +	return ret;
> +}
> +
> +static int channel_rmdir(struct inode *dir, struct dentry *dentry)
> +{
> +	struct dentry *channel_d;
> +	int ret;
> +
> +	ret = 0;
> +
> +	channel_d = dir_lookup(markers_control_dir, dentry->d_name.name);
> +	if (!channel_d) {
> +		ret = -ENOENT;
> +		goto out;
> +	}
> +
> +	if (list_empty(&channel_d->d_subdirs)) {
> +		mutex_unlock(&dir->i_mutex);
> +		mutex_unlock(&dentry->d_inode->i_mutex);
> +		debugfs_remove(channel_d);
> +		mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
> +		mutex_lock(&dentry->d_inode->i_mutex);
> +	} else
> +		ret = -EPERM;
> +
> +out:
> +	return ret;
> +}
> +
> +const struct inode_operations root_dir_opt = {
> +	.lookup = simple_lookup,
> +	.mkdir = channel_mkdir,
> +	.rmdir = channel_rmdir
> +};
> +
>  static int build_marker_file(struct marker *marker)
>  {
>  	struct dentry *channel_d, *marker_d, *enable_d, *info_d;
> @@ -907,6 +1079,8 @@ static int build_marker_file(struct marker *marker)
>  			err = -ENOMEM;
>  			goto err_build_fail;
>  		}
> +		channel_d->d_inode->i_private = (void *)channel_d;
> +		init_marker_dir(channel_d, &channel_dir_opt);
>  	}
>  
>  	marker_d  = dir_lookup(channel_d, marker->name);
> @@ -969,15 +1143,12 @@ static int build_marker_control_files(void)
>  	for (; iter.marker != NULL; marker_iter_next(&iter)) {
>  		err = build_marker_file(iter.marker);
>  		if (err)
> -			goto err_build_fail;
> +			goto out;
>  	}
>  	marker_iter_stop(&iter);
>  
> +out:
>  	unlock_markers();
> -
> -	return 0;
> -
> -err_build_fail:
>  	return err;
>  }
>  
> @@ -1130,6 +1301,8 @@ static int __init ltt_trace_control_init(void)
>  		goto err_create_marker_control_dir;
>  	}
>  
> +	init_marker_dir(markers_control_dir, &root_dir_opt);
> +
>  	if (build_marker_control_files())
>  		goto err_build_fail;
>  
> 
> 
> _______________________________________________
> 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