From mboxrd@z Thu Jan 1 00:00:00 1970 From: compudj@krystal.dyndns.org (Mathieu Desnoyers) Date: Wed, 4 Mar 2009 12:10:22 -0500 Subject: [ltt-dev] [PATCH] LTTNG: Make marker enabled in advance In-Reply-To: <49AC9C77.5050206@cn.fujitsu.com> References: <49AC9C77.5050206@cn.fujitsu.com> Message-ID: <20090304171022.GA2554@Krystal> * Gui Jianfeng (guijianfeng at cn.fujitsu.com) wrote: > Hi Mathieu, > > 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]# ls > enable info > [root at localhost close]# echo 1 > enable > [root at localhost close]# cat enable > 2 > [root at localhost close]# cat info > marker is not present now! > [root at localhost close]# modprobe fs_trace > [root at localhost close]# cat enable > 1 > [root at localhost close]# cat info > format: "fd %u" > state: 1 > event_id: 1 > call: 0xc0468167 > probe single : 0xc0520cdc > > Signed-off-by: Gui Jianfeng > --- > ltt/ltt-trace-control.c | 357 ++++++++++++++++++++++++++++++++--------------- > 1 files changed, 247 insertions(+), 110 deletions(-) > > diff --git a/ltt/ltt-trace-control.c b/ltt/ltt-trace-control.c > index 128db4e..7e1c32e 100644 > --- a/ltt/ltt-trace-control.c > +++ b/ltt/ltt-trace-control.c > @@ -19,6 +19,7 @@ > #include > #include > #include > +#include > > #define LTT_CONTROL_DIR "control" > #define MARKERS_CONTROL_DIR "markers" > @@ -27,9 +28,240 @@ > > #define LTT_WRITE_MAXLEN (128) > > +#define MARKER_ENABLE_MASK 0x7UL What is this doing ? > + > +static DEFINE_MUTEX(unload_mutex); Can you tell me exactly what this protects, where it is nested ? Mathieu > + > struct dentry *ltt_control_dir, *ltt_setup_trace_file, *ltt_destroy_trace_file, > *markers_control_dir; > > +#define get_marker_addr(p) \ > + ((struct marker *)((unsigned long)p & ~MARKER_ENABLE_MASK)) > +#define is_pre_enabled(p) ((unsigned long)p & MARKER_ENABLE_MASK) > + > +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 = get_marker_addr(filp->private_data); > + buf = kmalloc(1024, GFP_KERNEL); > + > + if (marker) > + len = sprintf(buf, "%d\n", _imv_read(marker->state)); > + else { > + if (is_pre_enabled(filp->private_data)) > + len = sprintf(buf, "%d\n", 2); > + else > + len = sprintf(buf, "%d\n", 0); > + } > + 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; > + const char *channel_name, *marker_name; > + > + marker = get_marker_addr(filp->private_data); > + if (marker) { > + marker_name = marker->name; > + channel_name = marker->channel; > + } else { > + marker_name = filp->f_dentry->d_parent->d_name.name; > + channel_name = filp->f_dentry->d_parent->d_parent->d_name.name; > + filp->f_dentry->d_inode->i_private = (void *)1; > + } > + > + 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(channel_name, marker_name, > + "default"); > + if (err) > + return err; > + break; > + case 'N': > + case 'n': > + case '0': > + err = ltt_marker_disconnect(channel_name, > + 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 = get_marker_addr(filp->private_data); > + buf = kmalloc(1024, GFP_KERNEL); > + > + if (marker) > + 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); > + else > + len = sprintf(buf, "marker is not present now!\n"); > + > + 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, > +}; > + > +void init_marker_dir(struct dentry *dentry, const struct inode_operations *opt) > +{ > + dentry->d_inode->i_op = opt; > +} > + > +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); > + > + /* > + * Prevent from removing files > + */ > + mutex_lock(&unload_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_unlock(&unload_mutex); > + mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); > + return ret; > +} > + > +const struct inode_operations channel_dir_opt = { > + .lookup = simple_lookup, > + .mkdir = marker_mkdir, > +}; > + > +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); > + > + /* > + * Prevent from removing files > + */ > + mutex_lock(&unload_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_unlock(&unload_mutex); > + mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); > + return ret; > +} > + > +const struct inode_operations marker_control_root_dir_opt = { > + .lookup = simple_lookup, > + .mkdir = channel_mkdir, > +}; > + > /* > * the traces_lock nests inside control_lock. > */ > @@ -697,112 +929,6 @@ static struct file_operations ltt_destroy_trace_operations = { > .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; > @@ -820,8 +946,10 @@ static int build_marker_file(struct marker *marker) > 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); > + 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) { > @@ -832,6 +960,7 @@ static int build_marker_file(struct marker *marker) > goto err_build_fail; > } > } > + marker_d->d_inode->i_private = (void *)marker_d; > > enable_d = dir_lookup(marker_d, "enable"); > if (!enable_d) { > @@ -844,7 +973,8 @@ static int build_marker_file(struct marker *marker) > err = -ENOMEM; > goto err_build_fail; > } > - } > + } else > + enable_d->d_inode->i_private = (void *)marker; > > info_d = dir_lookup(marker_d, "info"); > if (!info_d) { > @@ -857,7 +987,8 @@ static int build_marker_file(struct marker *marker) > err = -ENOMEM; > goto err_build_fail; > } > - } > + } else > + info_d->d_inode->i_private = (void *)marker; > > return 0; > > @@ -892,6 +1023,7 @@ static int remove_marker_control_dir(struct marker *marker) > { > struct dentry *channel_d, *marker_d; > > + mutex_lock(&unload_mutex); > channel_d = dir_lookup(markers_control_dir, marker->channel); > if (!channel_d) > return -ENOENT; > @@ -904,6 +1036,7 @@ static int remove_marker_control_dir(struct marker *marker) > if (list_empty(&channel_d->d_subdirs)) > debugfs_remove(channel_d); > > + mutex_unlock(&unload_mutex); > return 0; > } > > @@ -1012,6 +1145,8 @@ static int __init ltt_trace_control_init(void) > goto err_create_marker_control_dir; > } > > + init_marker_dir(markers_control_dir, &marker_control_root_dir_opt); > + > if (build_marker_control_files()) > goto err_build_fail; > > @@ -1036,6 +1171,7 @@ static void __exit ltt_trace_control_exit(void) > { > struct dentry *trace_dir; > > + mutex_lock(&unload_mutex); > /* destory all traces */ > list_for_each_entry(trace_dir, <t_control_dir->d_subdirs, > d_u.d_child) { > @@ -1046,9 +1182,10 @@ static void __exit ltt_trace_control_exit(void) > /* clean dirs in debugfs */ > debugfs_remove(ltt_setup_trace_file); > debugfs_remove(ltt_destroy_trace_file); > - debugfs_remove_recursive(ltt_control_dir); > debugfs_remove_recursive(markers_control_dir); > + debugfs_remove_recursive(ltt_control_dir); > unregister_module_notifier(&module_nb); > + mutex_unlock(&unload_mutex); > } > > 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