[ltt-dev] [PATCH] Separate ltt_trace_create() into ltt_trace_create() and ltt_trace_alloc()
Zhaolei
zhaolei at cn.fujitsu.com
Sun Oct 26 23:47:12 EDT 2008
This is step1 of:
"switch marker list and marker activation (currently in /proc/ltt) to debugfs"
> >> 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.
> >>
> > Yes, this is the goal.
> So, IMHO, we can do it in following steps:
>
> Step1: modify ltt_trace_create(), .etc, separate ltt_trace_create() into
> ltt_trace_setup(), ltt_set_channelsize(), ltt_set_channelnum(),
> ltt_trace_alloc(). But still use old netlink_based ltt_control to make
> it simple.
> Although we modify ltt_set_channelsize() to support setting each channel's
> buffer, we make ltt_control.ko using old UI(only able to set low, med and
> high). So we don't need to modify other program such as user-mode lttctl.
>
Yes. Just make sure a "destroy" deals correctly with a trace that is
"setup" but not "allocated" yet.
> Step2: Write a new module named ltt-channel-control.
> ( I think name of ltt-channel-control will be better than ltt-control,
> because we already have a module named ltt-marker-control. )
> ltt-channel-control is designed on debugfs, as we discussed.
> We can test it by echo XX > /mnt/debugfs/ltt/...
>
Yes, that would be perfect.
> Step3: modify user-mode programs to support ltt-channel-control.
> We also need to modify lttctl's command arguments, to support setup each
> channel's buffer. (Are we take out -Z, -X, -V, -B, -z, -x in lttctl?)
> I haven't read source of lttv, it is necessary to modify?
>
Maybe we could replace lttctl by simple shell scripts ?
Yes, small modification of lttv would be required. There is a GUI module
which executes lttctl to start/stop tracing. It would have to be
modified so it uses the debugfs files instead.
Signed-off-by: Zhao Lei <zhaolei at cn.fujitsu.com>
---
include/linux/ltt-core.h | 3 +-
include/linux/ltt-tracer.h | 40 ++--
ltt/ltt-core.c | 1 +
ltt/ltt-tracer.c | 560 ++++++++++++++++++++++++++++++++++----------
4 files changed, 464 insertions(+), 140 deletions(-)
diff --git a/include/linux/ltt-core.h b/include/linux/ltt-core.h
index 1681e82..db890d8 100644
--- a/include/linux/ltt-core.h
+++ b/include/linux/ltt-core.h
@@ -17,7 +17,8 @@
* list.
*/
struct ltt_traces {
- struct list_head head; /* Traces list */
+ struct list_head prealloc_head; /* Pre-allocated traces list */
+ struct list_head head; /* Allocated Traces list */
unsigned int num_active_traces; /* Number of active traces */
} ____cacheline_aligned;
diff --git a/include/linux/ltt-tracer.h b/include/linux/ltt-tracer.h
index d46bc88..042f518 100644
--- a/include/linux/ltt-tracer.h
+++ b/include/linux/ltt-tracer.h
@@ -197,6 +197,23 @@ struct ltt_transport {
struct ltt_trace_ops ops;
};
+/*
+ * First and last channels in ltt_trace_struct.
+ */
+#define ltt_channel_index_size() sizeof(struct ltt_channel_struct *)
+#define ltt_channel_index_begin() GET_CHANNEL_INDEX(cpu)
+#define ltt_channel_index_end() \
+ (GET_CHANNEL_INDEX(metadata) + ltt_channel_index_size())
+
+enum ltt_channels {
+ LTT_CHANNEL_CPU,
+ LTT_CHANNEL_PROCESSES,
+ LTT_CHANNEL_INTERRUPTS,
+ LTT_CHANNEL_NETWORK,
+ LTT_CHANNEL_MODULES,
+ LTT_CHANNEL_METADATA,
+ NR_LTT_CHANNELS,
+};
enum trace_mode { LTT_TRACE_NORMAL, LTT_TRACE_FLIGHT, LTT_TRACE_HYBRID };
@@ -218,6 +235,12 @@ struct ltt_trace_struct {
struct ltt_channel_struct *modules;
struct ltt_channel_struct *metadata;
} channel;
+ struct {
+ struct {
+ unsigned subbuf_size;
+ unsigned subbuf_cnt;
+ } channels[NR_LTT_CHANNELS];
+ } setting;
u32 freq_scale;
u64 start_freq;
u64 start_tsc;
@@ -236,23 +259,6 @@ struct ltt_trace_struct {
char trace_name[NAME_MAX];
} ____cacheline_aligned;
-/*
- * First and last channels in ltt_trace_struct.
- */
-#define ltt_channel_index_size() sizeof(struct ltt_channel_struct *)
-#define ltt_channel_index_begin() GET_CHANNEL_INDEX(cpu)
-#define ltt_channel_index_end() \
- (GET_CHANNEL_INDEX(metadata) + ltt_channel_index_size())
-
-enum ltt_channels {
- LTT_CHANNEL_CPU,
- LTT_CHANNEL_PROCESSES,
- LTT_CHANNEL_INTERRUPTS,
- LTT_CHANNEL_NETWORK,
- LTT_CHANNEL_MODULES,
- LTT_CHANNEL_METADATA,
-};
-
/* Hardcoded event headers
*
* event header for a trace with active heartbeat : 27 bits timestamps
diff --git a/ltt/ltt-core.c b/ltt/ltt-core.c
index abd3d6d..3d7015e 100644
--- a/ltt/ltt-core.c
+++ b/ltt/ltt-core.c
@@ -12,6 +12,7 @@
/* Traces structures */
struct ltt_traces ltt_traces = {
+ .prealloc_head = LIST_HEAD_INIT(ltt_traces.prealloc_head),
.head = LIST_HEAD_INIT(ltt_traces.head),
};
EXPORT_SYMBOL(ltt_traces);
diff --git a/ltt/ltt-tracer.c b/ltt/ltt-tracer.c
index e4358cf..5eae2b5 100644
--- a/ltt/ltt-tracer.c
+++ b/ltt/ltt-tracer.c
@@ -268,31 +268,20 @@ static struct ltt_trace_struct *_ltt_trace_find(const char *trace_name)
return NULL;
}
-/* This function must be called with traces semaphore held. */
-static int _ltt_trace_create(const char *trace_name, enum trace_mode mode,
- struct ltt_trace_struct *new_trace)
+/* _ltt_trace_find_setup :
+ * find a trace in setup list by given name.
+ *
+ * Returns a pointer to the trace structure, NULL if not found.
+ */
+static struct ltt_trace_struct *_ltt_trace_find_setup(const char *trace_name)
{
- int err = EPERM;
+ struct ltt_trace_struct *trace;
- if (_ltt_trace_find(trace_name) != NULL) {
- printk(KERN_ERR "LTT : Trace %s already exists\n", trace_name);
- err = EEXIST;
- goto traces_error;
- }
- if (list_empty(<t_traces.head)) {
- probe_id_defrag();
- mod_timer(<t_async_wakeup_timer,
- jiffies + LTT_PERCPU_TIMER_INTERVAL);
- set_kernel_trace_flag_all_tasks();
- }
- list_add_rcu(&new_trace->list, <t_traces.head);
- synchronize_sched();
- /* Everything went fine, finish creation */
- return 0;
+ list_for_each_entry(trace, <t_traces.prealloc_head, list)
+ if (!strncmp(trace->trace_name, trace_name, NAME_MAX))
+ return trace;
- /* Error handling */
-traces_error:
- return err;
+ return NULL;
}
/**
@@ -334,170 +323,491 @@ static inline void prepare_chan_size_num(unsigned *subbuf_size,
WARN_ON(hweight32(*n_subbufs) != 1);
}
-static int ltt_trace_create(const char *trace_name, const char *trace_type,
- enum trace_mode mode,
- unsigned subbuf_size_low, unsigned n_subbufs_low,
- unsigned subbuf_size_med, unsigned n_subbufs_med,
- unsigned subbuf_size_high, unsigned n_subbufs_high)
+static int ltt_trace_setup(const char *trace_name)
{
int err = 0;
- struct ltt_trace_struct *new_trace, *trace;
- unsigned long flags;
- struct ltt_transport *tran, *transport = NULL;
+ struct ltt_trace_struct *new_trace = NULL;
- prepare_chan_size_num(&subbuf_size_low, &n_subbufs_low,
- LTT_DEFAULT_SUBBUF_SIZE_LOW, LTT_DEFAULT_N_SUBBUFS_LOW);
+ ltt_lock_traces();
- prepare_chan_size_num(&subbuf_size_med, &n_subbufs_med,
- LTT_DEFAULT_SUBBUF_SIZE_MED, LTT_DEFAULT_N_SUBBUFS_MED);
+ if (_ltt_trace_find_setup(trace_name)) {
+ printk(KERN_ERR "LTT : Trace name %s already used.\n",
+ trace_name);
+ err = -EEXIST;
+ goto traces_error;
+ }
- prepare_chan_size_num(&subbuf_size_high, &n_subbufs_high,
- LTT_DEFAULT_SUBBUF_SIZE_HIGH, LTT_DEFAULT_N_SUBBUFS_HIGH);
+ if (_ltt_trace_find(trace_name)) {
+ printk(KERN_ERR "LTT : Trace name %s already used.\n",
+ trace_name);
+ err = -EEXIST;
+ goto traces_error;
+ }
new_trace = kzalloc(sizeof(struct ltt_trace_struct), GFP_KERNEL);
if (!new_trace) {
printk(KERN_ERR
"LTT : Unable to allocate memory for trace %s\n",
trace_name);
- err = ENOMEM;
- goto traces_error;
+ err = -ENOMEM;
+ goto trace_free;
}
- kref_init(&new_trace->kref);
- kref_init(&new_trace->ltt_transport_kref);
- init_waitqueue_head(&new_trace->kref_wq);
- new_trace->active = 0;
strncpy(new_trace->trace_name, trace_name, NAME_MAX);
- new_trace->mode = mode;
- new_trace->freq_scale = trace_clock_freq_scale();
+ list_add(&new_trace->list, <t_traces.prealloc_head);
+
+ ltt_unlock_traces();
+
+ return 0;
+
+trace_free:
+ kfree(new_trace);
+traces_error:
+ ltt_unlock_traces();
+ return err;
+}
+
+/* must be called from within a traces lock. */
+static void _ltt_trace_free(struct ltt_trace_struct *trace)
+{
+ list_del(&trace->list);
+ kfree(trace);
+}
+
+static int ltt_trace_set_type(const char *trace_name, const char *trace_type)
+{
+ int err = 0;
+ struct ltt_trace_struct *trace;
+ struct ltt_transport *tran_iter, *transport = NULL;
ltt_lock_traces();
- list_for_each_entry(tran, <t_transport_list, node) {
- if (!strcmp(tran->name, trace_type)) {
- transport = tran;
+
+ trace = _ltt_trace_find_setup(trace_name);
+ if (!trace) {
+ printk(KERN_ERR "LTT : Trace not found %s\n", trace_name);
+ err = -ENOENT;
+ goto traces_error;
+ }
+
+ list_for_each_entry(tran_iter, <t_transport_list, node) {
+ if (!strcmp(tran_iter->name, trace_type)) {
+ transport = tran_iter;
break;
}
}
-
if (!transport) {
- err = EINVAL;
printk(KERN_ERR "LTT : Transport %s is not present.\n",
trace_type);
- ltt_unlock_traces();
- goto trace_error;
+ err = -EINVAL;
+ goto traces_error;
}
- if (!try_module_get(transport->owner)) {
- err = ENODEV;
- printk(KERN_ERR "LTT : Can't lock transport module.\n");
- ltt_unlock_traces();
- goto trace_error;
+ trace->transport = transport;
+
+traces_error:
+ ltt_unlock_traces();
+ return err;
+}
+
+static int ltt_trace_set_mode(const char *trace_name, enum trace_mode mode)
+{
+ int err = 0;
+ struct ltt_trace_struct *trace;
+
+ ltt_lock_traces();
+
+ trace = _ltt_trace_find_setup(trace_name);
+ if (!trace) {
+ printk(KERN_ERR "LTT : Trace not found %s\n", trace_name);
+ err = -ENOENT;
+ goto traces_error;
}
- trace = _ltt_trace_find(trace_name);
- if (trace) {
- printk(KERN_ERR "LTT : Trace name %s already used.\n",
- trace_name);
- err = EEXIST;
- goto trace_error;
+ trace->mode = mode;
+
+traces_error:
+ ltt_unlock_traces();
+ return err;
+}
+
+/*
+ * Todo:
+ * Make similar function in channel.c,
+ * so it will be useful for both ltt-tracer.c and ltt-marker-control.c
+ */
+/*
+ * Its order is MUST be same with enum ltt_channels
+ */
+static char *chan_names[] = {
+ LTT_CPU_CHANNEL,
+ LTT_PROCESSES_CHANNEL,
+ LTT_INTERRUPTS_CHANNEL,
+ LTT_NETWORK_CHANNEL,
+ LTT_MODULES_CHANNEL,
+ LTT_METADATA_CHANNEL,
+};
+
+static enum ltt_channels get_channel_type_from_name(const char *name)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(chan_names); i++)
+ if (!strcmp(name, chan_names[i]))
+ return (enum ltt_channels)i;
+
+ return NR_LTT_CHANNELS;
+}
+
+static int ltt_trace_set_channel_subbufsize(const char *trace_name,
+ const char *channel_name, unsigned size)
+{
+ int err = 0;
+ struct ltt_trace_struct *trace;
+ enum ltt_channels channel;
+
+ ltt_lock_traces();
+
+ trace = _ltt_trace_find_setup(trace_name);
+ if (!trace) {
+ printk(KERN_ERR "LTT : Trace not found %s\n", trace_name);
+ err = -ENOENT;
+ goto traces_error;
}
- new_trace->transport = transport;
- new_trace->ops = &transport->ops;
+ channel = get_channel_type_from_name(channel_name);
+ if (channel == NR_LTT_CHANNELS) {
+ printk(KERN_ERR "LTT : Channel %s is not present.\n",
+ channel_name);
+ err = -EINVAL;
+ goto traces_error;
+ }
- err = new_trace->ops->create_dirs(new_trace);
- if (err)
+ trace->setting.channels[channel].subbuf_size = size;
+
+traces_error:
+ ltt_unlock_traces();
+ return err;
+}
+
+static int ltt_trace_set_channel_subbufcount(const char *trace_name,
+ const char *channel_name, unsigned cnt)
+{
+ int err = 0;
+ struct ltt_trace_struct *trace;
+ enum ltt_channels channel;
+
+ ltt_lock_traces();
+
+ trace = _ltt_trace_find_setup(trace_name);
+ if (!trace) {
+ printk(KERN_ERR "LTT : Trace not found %s\n", trace_name);
+ err = -ENOENT;
+ goto traces_error;
+ }
+
+ channel = get_channel_type_from_name(channel_name);
+ if (channel == NR_LTT_CHANNELS) {
+ printk(KERN_ERR "LTT : Channel %s is not present.\n",
+ channel_name);
+ err = -EINVAL;
+ goto traces_error;
+ }
+
+ trace->setting.channels[channel].subbuf_cnt = cnt;
+
+traces_error:
+ ltt_unlock_traces();
+ return err;
+}
+
+static int ltt_trace_alloc(const char *trace_name)
+{
+ int err = 0;
+ struct ltt_trace_struct *trace;
+ int subbuf_size, subbuf_cnt;
+ unsigned long flags;
+
+ ltt_lock_traces();
+
+ trace = _ltt_trace_find_setup(trace_name);
+ if (!trace) {
+ printk(KERN_ERR "LTT : Trace not found %s\n", trace_name);
+ err = -ENOENT;
+ goto traces_error;
+ }
+
+ kref_init(&trace->kref);
+ kref_init(&trace->ltt_transport_kref);
+ init_waitqueue_head(&trace->kref_wq);
+ trace->active = 0;
+ trace->freq_scale = trace_clock_freq_scale();
+
+ if (!trace->transport) {
+ printk(KERN_ERR "LTT : Transport is not set.\n");
+ err = -EINVAL;
+ goto traces_error;
+ }
+ if (!try_module_get(trace->transport->owner)) {
+ printk(KERN_ERR "LTT : Can't lock transport module.\n");
+ err = -ENODEV;
+ goto traces_error;
+ }
+ trace->ops = &trace->transport->ops;
+
+ err = trace->ops->create_dirs(trace);
+ if (err) {
+ printk(KERN_ERR "LTT : Can't create dir for trace %s.\n",
+ trace_name);
goto dirs_error;
+ }
local_irq_save(flags);
- new_trace->start_freq = trace_clock_frequency();
- new_trace->start_tsc = trace_clock_read64();
- do_gettimeofday(&new_trace->start_time);
+ trace->start_freq = trace_clock_frequency();
+ trace->start_tsc = trace_clock_read64();
+ do_gettimeofday(&trace->start_time);
local_irq_restore(flags);
/*
+ * Todo:
+ * Config each channel's default buffersize/cnt, instead of
+ * LTT_DEFAULT_SUBBUF_SIZE_LOW, ...
+ */
+
+ /*
* Always put the metadata channel in non-overwrite mode :
* This is a very low traffic channel and it can't afford to have its
* data overwritten : this data (marker info) is necessary to be
* able to read the trace.
*/
- err = new_trace->ops->create_channel(trace_name, new_trace,
- new_trace->dentry.control_root,
+ subbuf_size = trace->setting.channels[LTT_CHANNEL_METADATA].subbuf_size;
+ subbuf_cnt = trace->setting.channels[LTT_CHANNEL_METADATA].subbuf_cnt;
+ prepare_chan_size_num(&subbuf_size, &subbuf_cnt,
+ LTT_DEFAULT_SUBBUF_SIZE_LOW, LTT_DEFAULT_N_SUBBUFS_LOW);
+ err = trace->ops->create_channel(trace_name, trace,
+ trace->dentry.control_root,
LTT_METADATA_CHANNEL,
- &new_trace->channel.metadata, subbuf_size_low,
- n_subbufs_low,
- is_channel_overwrite(LTT_CHANNEL_METADATA, mode));
- if (err != 0)
+ &trace->channel.metadata,
+ subbuf_size,
+ subbuf_cnt,
+ is_channel_overwrite(LTT_CHANNEL_METADATA,
+ trace->mode));
+ if (err != 0) {
+ printk(KERN_ERR "LTT : Can't create channel %s.\n",
+ chan_names[LTT_CHANNEL_METADATA]);
goto metadata_error;
- err = new_trace->ops->create_channel(trace_name, new_trace,
- new_trace->dentry.control_root,
+ }
+
+ subbuf_size =
+ trace->setting.channels[LTT_CHANNEL_INTERRUPTS].subbuf_size;
+ subbuf_cnt = trace->setting.channels[LTT_CHANNEL_INTERRUPTS].subbuf_cnt;
+ prepare_chan_size_num(&subbuf_size, &subbuf_cnt,
+ LTT_DEFAULT_SUBBUF_SIZE_LOW, LTT_DEFAULT_N_SUBBUFS_LOW);
+ err = trace->ops->create_channel(trace_name, trace,
+ trace->dentry.control_root,
LTT_INTERRUPTS_CHANNEL,
- &new_trace->channel.interrupts, subbuf_size_low,
- n_subbufs_low,
- is_channel_overwrite(LTT_CHANNEL_INTERRUPTS, mode));
- if (err != 0)
+ &trace->channel.interrupts,
+ subbuf_size,
+ subbuf_cnt,
+ is_channel_overwrite(LTT_CHANNEL_INTERRUPTS,
+ trace->mode));
+ if (err != 0) {
+ printk(KERN_ERR "LTT : Can't create channel %s.\n",
+ chan_names[LTT_CHANNEL_INTERRUPTS]);
goto interrupts_error;
- err = new_trace->ops->create_channel(trace_name, new_trace,
- new_trace->dentry.control_root,
+ }
+
+ subbuf_size =
+ trace->setting.channels[LTT_CHANNEL_PROCESSES].subbuf_size;
+ subbuf_cnt = trace->setting.channels[LTT_CHANNEL_PROCESSES].subbuf_cnt;
+ prepare_chan_size_num(&subbuf_size, &subbuf_cnt,
+ LTT_DEFAULT_SUBBUF_SIZE_MED, LTT_DEFAULT_N_SUBBUFS_MED);
+ err = trace->ops->create_channel(trace_name, trace,
+ trace->dentry.control_root,
LTT_PROCESSES_CHANNEL,
- &new_trace->channel.processes, subbuf_size_med,
- n_subbufs_med,
- is_channel_overwrite(LTT_CHANNEL_PROCESSES, mode));
- if (err != 0)
+ &trace->channel.processes,
+ subbuf_size,
+ subbuf_cnt,
+ is_channel_overwrite(LTT_CHANNEL_PROCESSES,
+ trace->mode));
+ if (err != 0) {
+ printk(KERN_ERR "LTT : Can't create channel %s.\n",
+ chan_names[LTT_CHANNEL_PROCESSES]);
goto processes_error;
- err = new_trace->ops->create_channel(trace_name, new_trace,
- new_trace->dentry.control_root,
+ }
+
+ subbuf_size = trace->setting.channels[LTT_CHANNEL_MODULES].subbuf_size;
+ subbuf_cnt = trace->setting.channels[LTT_CHANNEL_MODULES].subbuf_cnt;
+ prepare_chan_size_num(&subbuf_size, &subbuf_cnt,
+ LTT_DEFAULT_SUBBUF_SIZE_LOW, LTT_DEFAULT_N_SUBBUFS_LOW);
+ err = trace->ops->create_channel(trace_name, trace,
+ trace->dentry.control_root,
LTT_MODULES_CHANNEL,
- &new_trace->channel.modules, subbuf_size_low,
- n_subbufs_low,
- is_channel_overwrite(LTT_CHANNEL_MODULES, mode));
- if (err != 0)
+ &trace->channel.modules,
+ subbuf_size,
+ subbuf_cnt,
+ is_channel_overwrite(LTT_CHANNEL_MODULES, trace->mode));
+ if (err != 0) {
+ printk(KERN_ERR "LTT : Can't create channel %s.\n",
+ chan_names[LTT_CHANNEL_MODULES]);
goto modules_error;
- err = new_trace->ops->create_channel(trace_name, new_trace,
- new_trace->dentry.control_root,
+ }
+
+ subbuf_size = trace->setting.channels[LTT_CHANNEL_NETWORK].subbuf_size;
+ subbuf_cnt = trace->setting.channels[LTT_CHANNEL_NETWORK].subbuf_cnt;
+ prepare_chan_size_num(&subbuf_size, &subbuf_cnt,
+ LTT_DEFAULT_SUBBUF_SIZE_LOW, LTT_DEFAULT_N_SUBBUFS_LOW);
+ err = trace->ops->create_channel(trace_name, trace,
+ trace->dentry.control_root,
LTT_NETWORK_CHANNEL,
- &new_trace->channel.network, subbuf_size_low,
- n_subbufs_low,
- is_channel_overwrite(LTT_CHANNEL_NETWORK, mode));
- if (err != 0)
+ &trace->channel.network,
+ subbuf_size,
+ subbuf_cnt,
+ is_channel_overwrite(LTT_CHANNEL_NETWORK, trace->mode));
+ if (err != 0) {
+ printk(KERN_ERR "LTT : Can't create channel %s.\n",
+ chan_names[LTT_CHANNEL_NETWORK]);
goto network_error;
- err = new_trace->ops->create_channel(trace_name, new_trace,
- new_trace->dentry.trace_root,
+ }
+
+ subbuf_size = trace->setting.channels[LTT_CHANNEL_CPU].subbuf_size;
+ subbuf_cnt = trace->setting.channels[LTT_CHANNEL_CPU].subbuf_cnt;
+ prepare_chan_size_num(&subbuf_size, &subbuf_cnt,
+ LTT_DEFAULT_SUBBUF_SIZE_HIGH, LTT_DEFAULT_N_SUBBUFS_HIGH);
+ err = trace->ops->create_channel(trace_name, trace,
+ trace->dentry.trace_root,
LTT_CPU_CHANNEL,
- &new_trace->channel.cpu, subbuf_size_high,
- n_subbufs_high,
- is_channel_overwrite(LTT_CHANNEL_CPU, mode));
- if (err != 0)
+ &trace->channel.cpu,
+ subbuf_size,
+ subbuf_cnt,
+ is_channel_overwrite(LTT_CHANNEL_CPU, trace->mode));
+ if (err != 0) {
+ printk(KERN_ERR "LTT : Can't create channel %s.\n",
+ chan_names[LTT_CHANNEL_CPU]);
goto cpu_error;
+ }
- err = _ltt_trace_create(trace_name, mode, new_trace);
+ list_del(&trace->list);
+ if (list_empty(<t_traces.head)) {
+ probe_id_defrag();
+ mod_timer(<t_async_wakeup_timer,
+ jiffies + LTT_PERCPU_TIMER_INTERVAL);
+ set_kernel_trace_flag_all_tasks();
+ }
+ list_add_rcu(&trace->list, <t_traces.head);
+ synchronize_sched();
- if (err != 0)
- goto lock_create_error;
ltt_unlock_traces();
- return err;
-lock_create_error:
- new_trace->ops->remove_channel(new_trace->channel.cpu);
+ return 0;
+
cpu_error:
- new_trace->ops->remove_channel(new_trace->channel.network);
+ trace->ops->remove_channel(trace->channel.network);
network_error:
- new_trace->ops->remove_channel(new_trace->channel.modules);
+ trace->ops->remove_channel(trace->channel.modules);
modules_error:
- new_trace->ops->remove_channel(new_trace->channel.processes);
+ trace->ops->remove_channel(trace->channel.processes);
processes_error:
- new_trace->ops->remove_channel(new_trace->channel.interrupts);
+ trace->ops->remove_channel(trace->channel.interrupts);
interrupts_error:
- new_trace->ops->remove_channel(new_trace->channel.metadata);
+ trace->ops->remove_channel(trace->channel.metadata);
metadata_error:
- kref_put(&new_trace->ltt_transport_kref, ltt_release_transport);
+ trace->ops->remove_dirs(trace);
dirs_error:
- module_put(transport->owner);
-trace_error:
- kref_put(&new_trace->kref, ltt_release_trace);
- wake_up_interruptible(&new_trace->kref_wq);
- ltt_unlock_traces();
+ module_put(trace->transport->owner);
traces_error:
+ ltt_unlock_traces();
+ return err;
+}
+
+/*
+ * It is worked as a wrapper for current version of ltt_control.ko.
+ * We will make a new ltt_control based on debugfs, and control each channel's
+ * buffer.
+ */
+static int ltt_trace_create(const char *trace_name, const char *trace_type,
+ enum trace_mode mode,
+ unsigned subbuf_size_low, unsigned n_subbufs_low,
+ unsigned subbuf_size_med, unsigned n_subbufs_med,
+ unsigned subbuf_size_high, unsigned n_subbufs_high)
+{
+ int err = 0;
+
+ err = ltt_trace_setup(trace_name);
+ if (IS_ERR_VALUE(err))
+ return err;
+
+ err = ltt_trace_set_type(trace_name, trace_type);
+ if (IS_ERR_VALUE(err))
+ return err;
+
+ err = ltt_trace_set_mode(trace_name, mode);
+ if (IS_ERR_VALUE(err))
+ return err;
+
+ err = ltt_trace_set_channel_subbufsize(trace_name,
+ LTT_METADATA_CHANNEL, subbuf_size_low);
+ if (IS_ERR_VALUE(err))
+ return err;
+
+ err = ltt_trace_set_channel_subbufcount(trace_name,
+ LTT_METADATA_CHANNEL, n_subbufs_low);
+ if (IS_ERR_VALUE(err))
+ return err;
+
+ err = ltt_trace_set_channel_subbufsize(trace_name,
+ LTT_INTERRUPTS_CHANNEL, subbuf_size_low);
+ if (IS_ERR_VALUE(err))
+ return err;
+
+ err = ltt_trace_set_channel_subbufcount(trace_name,
+ LTT_INTERRUPTS_CHANNEL, n_subbufs_low);
+ if (IS_ERR_VALUE(err))
+ return err;
+
+ err = ltt_trace_set_channel_subbufsize(trace_name,
+ LTT_PROCESSES_CHANNEL, subbuf_size_med);
+ if (IS_ERR_VALUE(err))
+ return err;
+
+ err = ltt_trace_set_channel_subbufcount(trace_name,
+ LTT_PROCESSES_CHANNEL, n_subbufs_med);
+ if (IS_ERR_VALUE(err))
+ return err;
+
+ err = ltt_trace_set_channel_subbufsize(trace_name, LTT_MODULES_CHANNEL,
+ subbuf_size_low);
+ if (IS_ERR_VALUE(err))
+ return err;
+
+ err = ltt_trace_set_channel_subbufcount(trace_name, LTT_MODULES_CHANNEL,
+ n_subbufs_low);
+ if (IS_ERR_VALUE(err))
+ return err;
+
+ err = ltt_trace_set_channel_subbufsize(trace_name, LTT_NETWORK_CHANNEL,
+ subbuf_size_low);
+ if (IS_ERR_VALUE(err))
+ return err;
+
+ err = ltt_trace_set_channel_subbufcount(trace_name, LTT_NETWORK_CHANNEL,
+ n_subbufs_low);
+ if (IS_ERR_VALUE(err))
+ return err;
+
+ err = ltt_trace_set_channel_subbufsize(trace_name, LTT_CPU_CHANNEL,
+ subbuf_size_high);
+ if (IS_ERR_VALUE(err))
+ return err;
+
+ err = ltt_trace_set_channel_subbufcount(trace_name, LTT_CPU_CHANNEL,
+ n_subbufs_high);
+ if (IS_ERR_VALUE(err))
+ return err;
+
+ err = ltt_trace_alloc(trace_name);
+ if (IS_ERR_VALUE(err))
+ return err;
+
return err;
}
@@ -817,6 +1127,12 @@ static void __exit ltt_exit(void)
_ltt_trace_destroy(trace);
__ltt_trace_destroy(trace);
}
+ /* free traces in pre-alloc status */
+ list_for_each_safe(pos, n, <t_traces.prealloc_head) {
+ trace = container_of(pos, struct ltt_trace_struct, list);
+ _ltt_trace_free(trace);
+ }
+
ltt_unlock_traces();
}
--
1.5.5.3
More information about the lttng-dev
mailing list