[ltt-dev] TODO list before releasing LTTng-buffering to LKML]

Zhaolei zhaolei at cn.fujitsu.com
Fri Oct 17 02:31:40 EDT 2008


>* Zhaolei (zhaolei at cn.fujitsu.com) wrote:
>> >> - switch ltt-control.ko (currently over netlink) to debugfs
>> >> - switch marker list (and marker activation (currently in /proc/ltt) to debugfs
>> >>   Marker directory. One file per marker.
>> >> - Create a ltt-ascii.ko kernel module which merge-sorts the buffers and exports
>> >>   them to userspace through a debugfs file.
>> >>
>> > 
>> > Hi, Mathieu,
>> > 
>> > We are interested with the above TODOs, and we are planning to implement them.
>> > 
>> Hi Mathieu,
>> 
>> I finished a simple ltt-control.ko based on debugfs.
>> 
>> With this module, we can control ltt by following command now:
>> Start trace1 channel:
>> echo "0 trace1" > /sys/kernel/debug/ltt_control/control
>> Stop trace1 channel:
>> echo "1 trace1" > /sys/kernel/debug/ltt_control/control
>> Create trace1 channel:
>> echo "2 trace1 relay 0 0 0 0 0 0 0" > /sys/kernel/debug/ltt_control/control
>> Destroy trace1 channel:
>> echo "3 trace1" > /sys/kernel/debug/ltt_control/control
>> 
>> I tested it on i386 linux 2.6.27 with lttng.
>> 
>> User-mode lttctl also needs some modification to support this kind of control,
>> but at first, I'd like to hear some advice on this module.
>> 
> 
> Hrm, let me see.. can we have a directory hierarchy like this ?
> 
Hello, Mathieu,

Thanks for your advice!

Are you means make debugfs like this?
(let us assume er have a channel named trace1)

`-- debugfs
    `-- ltt
        |-- buffers
        |   `-- trace1
        |       |-- control
        |       |   |-- interrupts_0
        |       |   |-- metadata_0
        |       |   |-- modules_0
        |       |   |-- network_0
        |       |   `-- processes_0
        |       `-- cpu_0
        |-- control
        |   `-- trace1
        |       |-- alloc
        |       |-- channel
        |       |   |-- control
        |       |   |   |-- 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
        |       `-- enabled
        |-- setup_trace
        `-- trace?

> (/sys/kernel/debug seems to be the same as /mnt/debugfs)
> 
> #define LTT_ROOT_DENTRY "/mnt/debugfs/ltt"
> 
> All the following are subdirectories of LTT_ROOT_DENTRY
> 
> #define LTT_BUFFERS_DENTRY LTT_ROOT_DENTRY "/buffers"
> #define LTT_CONTROL_DENTRY LTT_ROOT_DENTRY "/control"
> 
> #define LTT_TRACE_DENTRY LTT_ROOT_DENTRY "/trace"
> file -> read() : shows how to use it
Could you teach me detail about LTT_TRACE_DENTRY?
It it used to export trace status?
and what is hierarchy in LTT_TRACE_DENTRY?

> Create a new trace :
> echo trace_name > /mnt/debugfs/ltt/setup_trace
> 
> Note that a "setup" trace will be _different_ from the current
> "creation" notion in LTTng. I would like to have a state where a trace
> is created in the sense that its data structures are there, but the
> buffers are not allocated and it's not ready for tracing. A second
> "alloc" operation will have to be performed after the buffer sizes have
> been entered to perform the actual buffer allocation. After that, a
> trace start can be issued.
Are you means we need following steps to start a trace:
1: setup trace
2: alloc trace
3: start trace

I understood differece between "setup" and "alloc", but why we need a "setup" status?
(used for what? or what is the merit?)

> 
> Under LTT_BUFFERS_DENTRY, we create a new directory to contain each trace
> buffers.
> 
> e.g. :
> LTT_BUFFERS_DENTRY "/trace_name/cpu_0"
> LTT_BUFFERS_DENTRY "/trace_name/control/metadata_0"
> ...
> 
> Under LTT_CONTROL_DENTRY, we create a new directory to contain each
> trace control files.
> 
> (in parenthesis, this is probably a tiny description of what the files
> do and of what should be returned on read())
> 
> e.g. :
> LTT_CONTROL_DENTRY "/trace_name/alloc" (just writing to the file should
>  be enough) (allocate the buffers)
> LTT_CONTROL_DENTRY "/trace_name/enabled" (echo 0 et 1) (tracing enabled)
> LTT_CONTROL_DENTRY "/trace_name/channel/cpu/subbuf_size" (subbuffer size)
> LTT_CONTROL_DENTRY "/trace_name/channel/cpu/subbuf_num" (number of
>   subbuffers)
> LTT_CONTROL_DENTRY "/trace_name/channel/cpu/mode" (normal, flight)
> LTT_CONTROL_DENTRY "/trace_name/channel/control/metadata/subbuf_size"
>  (subbuffer size)
> LTT_CONTROL_DENTRY "/trace_name/channel/control/metadata/subbuf_num"
>  (number of subbuffers)
Are you means we can control each channel's (interrupt, process, ...) subbuf in future version?
(I think current version can only control low, med and high)
If this is true, maybe we need modify ltt_trace_create() before impl ltt_control.

> 
> Does it make sense ?
Thanks for your advice.
I think maybe we need to decide some detail action of this implement.
For example, for user,
correct operation is
  echo "trace1" > debugfs/ltt/setup_trace
  echo 65536 > debugfs/ltt/control/trace1/channel/interrupts/subbuf_num
  echo 2 > debugfs/ltt/control/trace1/channel/interrupts/subbuf_size
  echo 262144 > debugfs/ltt/control/trace1/channel/process/subbuf_num
  echo 2 > debugfs/ltt/control/trace1/channel/process/subbuf_size
  ...
  echo 1 > debugfs/ltt/control/trace1/alloc
  echo 1 > debugfs/ltt/control/trace1/enable
but if user:
  echo 4 > debugfs/ltt/control/trace1/channel/process/subbuf_size
  after echo 1 > debugfs/ltt/control/trace1/alloc
  maybe we need return a error, because it is already allocated.

> 
> Mathieu
> 
>> Thanks!
>> Zhaolei
>> > Thanks, Lai
>> > 
>> 
>> >> If some of you are interested to work on any of these, you are welcome.
>> >> I'll be glad to post more details about these items upon request.
>> >>
>> >> Mathieu
>> >>
>> > 
> 
>> obj-m := ltt_control.o
>> KDIR := /lib/modules/$(shell uname -r)/build
>> PWD := $(shell pwd)
>> 
>> default:
>> $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
>> clean:
>> rm -rf *.mod.c *.ko *.o .*.cmd .tmp_versions Module.symvers Module.markers modules.order
> 
>> /*
>>  * LTT control module over debugfs.
>>  *
>>  * Copyright 2008 -
>>  * Zhaolei <zhaolei at cn.fujitsu.com>
>>  */
>> 
>> #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 "ltt_control"
>> #define LTT_CONTROL_RECV "control"
>> 
>> #define LTT_CONTROL_RECVMAXLINE (128)
>> 
>> struct dentry *lttctrl_dir, *lttctrl_file;
>> 
>> static ssize_t read_control(struct file *file, char __user *user_buf,
>> size_t count, loff_t *ppos)
>> {
>> char info[] = "ltt_control informations\nTodo: impl it\n";
>> 
>> return simple_read_from_buffer(user_buf, count, ppos, info,
>> sizeof(info));
>> }
>> 
>> /*
>>  * line format:
>>  * Start:
>>  * control_msg(0)
>>  * name
>>  * Stop:
>>  * control_msg(1)
>>  * name
>>  * Create:
>>  * control_msg(2)
>>  * name
>>  * type
>>  * trace_mode
>>  * subbuf_size_low
>>  * n_subbufs_low
>>  * subbuf_size_med
>>  * n_subbufs_med
>>  * subbuf_size_high
>>  * n_subbufs_high
>>  * Destroy:
>>  * control_msg(3)
>>  * name
>>  *
>>  * control_msg:
>>  * 0: LTT_CONTROL_START
>>  * 1: LTT_CONTROL_STOP
>>  * 2: LTT_CONTROL_CREATE_TRACE
>>  * 3: LTT_CONTROL_DESTROY_TRACE
>>  *
>>  * trace_mode:
>>  * 0: LTT_TRACE_NORMAL
>>  * 1: LTT_TRACE_FLIGHT
>>  * 2: LTT_TRACE_HYBRID
>>  *
>>  * Ex:
>>  * Create a normal trace named trace1:
>>  * echo "2 trace1 relay 0 0 0 0 0 0 0" > \
>>  * /sys/kernel/debug/ltt_control/control
>>  * Start trace1 channel:
>>  * echo "0 trace1" > /sys/kernel/debug/ltt_control/control
>>  * Stop trace1 channel:
>>  * echo "1 trace1" > /sys/kernel/debug/ltt_control/control
>>  * Destroy trace1 channel:
>>  * echo "3 trace1" > /sys/kernel/debug/ltt_control/control
>>  */
>> static ssize_t write_control(struct file *file, const char __user *user_buf,
>> size_t count, loff_t *ppos)
>> {
>> char buf[LTT_CONTROL_RECVMAXLINE];
>> int buf_size;
>> 
>> enum ltt_control_msg msg;
>> char trace_name[NAME_MAX];
>> char trace_type[NAME_MAX];
>> union ltt_control_args args;
>> unsigned int op_n, mode_n;
>> 
>> int err = 0;
>> 
>> buf_size = min(count, sizeof(buf) - 1);
>> err = copy_from_user(buf, user_buf, buf_size);
>> if (err)
>> return err;
>> buf[buf_size] = 0;
>> 
>> if (1 != sscanf(buf, "%u", &op_n))
>> return -EPERM;
>> 
>> /*
>> * Not necessary to clear memory, only for safe, maybe I will
>> * remove it
>> */
>> msg = 0;
>> trace_name[0] = 0;
>> trace_type[0] = 0;
>> memset(&args, 0, sizeof(args));
>> 
>> switch (op_n) {
>> case 0:
>> msg = LTT_CONTROL_START;
>> if (1 != sscanf(buf, "%*u %s", trace_name))
>> return -EPERM;
>> break;
>> case 1:
>> msg = LTT_CONTROL_STOP;
>> if (1 != sscanf(buf, "%*u %s", trace_name))
>> return -EPERM;
>> break;
>> case 2:
>> msg = LTT_CONTROL_CREATE_TRACE;
>> if (9 != sscanf(buf, "%*u %s %s %u %u %u %u %u %u %u",
>> trace_name,
>> trace_type,
>> &mode_n,
>> &args.new_trace.subbuf_size_low,
>> &args.new_trace.n_subbufs_low,
>> &args.new_trace.subbuf_size_med,
>> &args.new_trace.n_subbufs_med,
>> &args.new_trace.subbuf_size_high,
>> &args.new_trace.n_subbufs_high
>> ))
>> return -EPERM;
>> switch (mode_n) {
>> case 0:
>> args.new_trace.mode = LTT_TRACE_NORMAL;
>> break;
>> case 1:
>> args.new_trace.mode = LTT_TRACE_FLIGHT;
>> break;
>> case 2:
>> args.new_trace.mode = LTT_TRACE_HYBRID;
>> break;
>> default:
>> return -EPERM;
>> }
>> break;
>> case 3:
>> msg = LTT_CONTROL_DESTROY_TRACE;
>> if (1 != sscanf(buf, "%*u %s", trace_name))
>> return -EPERM;
>> break;
>> default:
>> return -EPERM;
>> }
>> 
>> err = ltt_control(msg, trace_name, trace_type, args);
>> if (IS_ERR(err))
>> return err;
>> 
>> return count;
>> }
>> 
>> static struct file_operations ltt_control_operations = {
>> .read = read_control,
>> .write = write_control,
>> };
>> 
>> static int __init init_ltt_control(void)
>> {
>> lttctrl_dir = debugfs_create_dir(LTT_CONTROL_DIR, NULL);
>> if (IS_ERR(lttctrl_dir) || !lttctrl_dir)
>> return -ENOMEM;
>> 
>> lttctrl_file = debugfs_create_file(LTT_CONTROL_RECV, 0600, lttctrl_dir,
>> NULL, &ltt_control_operations);
>> if (IS_ERR(lttctrl_file) || !lttctrl_file) {
>> debugfs_remove(lttctrl_dir);
>> return -ENOMEM;
>> }
>> 
>> return 0;
>> }
>> 
>> static void __exit exit_ltt_control(void)
>> {
>> debugfs_remove(lttctrl_file);
>> debugfs_remove(lttctrl_dir);
>> }
>> 
>> module_init(init_ltt_control);
>> module_exit(exit_ltt_control);
>> 
>> MODULE_LICENSE("GPL");
> 
> 
> -- 
> Mathieu Desnoyers
> OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68
> 
>


More information about the lttng-dev mailing list