don't close file descriptors twice
[ust.git] / libust / channels.c
CommitLineData
99054cee
PMF
1/*
2 * ltt/ltt-channels.c
3 *
4 * (C) Copyright 2008 - Mathieu Desnoyers (mathieu.desnoyers@polymtl.ca)
5 *
6 * LTTng channel management.
7 *
8 * Author:
9 * Mathieu Desnoyers (mathieu.desnoyers@polymtl.ca)
8fc2d8db
PMF
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
99054cee
PMF
24 */
25
909bc43f 26#include <stdlib.h>
fbca6b62 27#include <ust/kernelcompat.h>
909bc43f 28#include <ust/marker.h>
b6bf28ec 29#include "channels.h"
5f54827b 30#include "usterr.h"
99054cee
PMF
31
32/*
33 * ltt_channel_mutex may be nested inside the LTT trace mutex.
34 * ltt_channel_mutex mutex may be nested inside markers mutex.
35 */
36static DEFINE_MUTEX(ltt_channel_mutex);
37static LIST_HEAD(ltt_channels);
38/*
39 * Index of next channel in array. Makes sure that as long as a trace channel is
40 * allocated, no array index will be re-used when a channel is freed and then
41 * another channel is allocated. This index is cleared and the array indexeds
42 * get reassigned when the index_kref goes back to 0, which indicates that no
43 * more trace channels are allocated.
44 */
45static unsigned int free_index;
46static struct kref index_kref; /* Keeps track of allocated trace channels */
47
48static struct ltt_channel_setting *lookup_channel(const char *name)
49{
50 struct ltt_channel_setting *iter;
51
52 list_for_each_entry(iter, &ltt_channels, list)
53 if (strcmp(name, iter->name) == 0)
54 return iter;
55 return NULL;
56}
57
58/*
59 * Must be called when channel refcount falls to 0 _and_ also when the last
60 * trace is freed. This function is responsible for compacting the channel and
61 * event IDs when no users are active.
62 *
63 * Called with lock_markers() and channels mutex held.
64 */
65static void release_channel_setting(struct kref *kref)
66{
67 struct ltt_channel_setting *setting = container_of(kref,
68 struct ltt_channel_setting, kref);
69 struct ltt_channel_setting *iter;
70
b102c2b0
PMF
71 if (uatomic_read(&index_kref.refcount) == 0
72 && uatomic_read(&setting->kref.refcount) == 0) {
99054cee 73 list_del(&setting->list);
909bc43f 74 free(setting);
99054cee
PMF
75
76 free_index = 0;
77 list_for_each_entry(iter, &ltt_channels, list) {
78 iter->index = free_index++;
79 iter->free_event_id = 0;
80 }
909bc43f 81 /* FIXME: why not run this? */
b6bf28ec 82//ust// markers_compact_event_ids();
99054cee
PMF
83 }
84}
85
86/*
87 * Perform channel index compaction when the last trace channel is freed.
88 *
89 * Called with lock_markers() and channels mutex held.
90 */
91static void release_trace_channel(struct kref *kref)
92{
93 struct ltt_channel_setting *iter, *n;
94
95 list_for_each_entry_safe(iter, n, &ltt_channels, list)
96 release_channel_setting(&iter->kref);
97}
98
99/**
100 * ltt_channels_register - Register a trace channel.
101 * @name: channel name
102 *
103 * Uses refcounting.
104 */
105int ltt_channels_register(const char *name)
106{
107 struct ltt_channel_setting *setting;
108 int ret = 0;
109
110 mutex_lock(&ltt_channel_mutex);
111 setting = lookup_channel(name);
112 if (setting) {
b102c2b0 113 if (uatomic_read(&setting->kref.refcount) == 0)
99054cee
PMF
114 goto init_kref;
115 else {
116 kref_get(&setting->kref);
117 goto end;
118 }
119 }
909bc43f 120 setting = zmalloc(sizeof(*setting));
99054cee
PMF
121 if (!setting) {
122 ret = -ENOMEM;
123 goto end;
124 }
125 list_add(&setting->list, &ltt_channels);
126 strncpy(setting->name, name, PATH_MAX-1);
127 setting->index = free_index++;
128init_kref:
129 kref_init(&setting->kref);
130end:
131 mutex_unlock(&ltt_channel_mutex);
132 return ret;
133}
b6bf28ec 134//ust// EXPORT_SYMBOL_GPL(ltt_channels_register);
99054cee
PMF
135
136/**
137 * ltt_channels_unregister - Unregister a trace channel.
138 * @name: channel name
139 *
140 * Must be called with markers mutex held.
141 */
142int ltt_channels_unregister(const char *name)
143{
144 struct ltt_channel_setting *setting;
145 int ret = 0;
146
147 mutex_lock(&ltt_channel_mutex);
148 setting = lookup_channel(name);
b102c2b0 149 if (!setting || uatomic_read(&setting->kref.refcount) == 0) {
99054cee
PMF
150 ret = -ENOENT;
151 goto end;
152 }
153 kref_put(&setting->kref, release_channel_setting);
154end:
155 mutex_unlock(&ltt_channel_mutex);
156 return ret;
157}
b6bf28ec 158//ust// EXPORT_SYMBOL_GPL(ltt_channels_unregister);
99054cee
PMF
159
160/**
161 * ltt_channels_set_default - Set channel default behavior.
162 * @name: default channel name
163 * @subbuf_size: size of the subbuffers
164 * @subbuf_cnt: number of subbuffers
165 */
166int ltt_channels_set_default(const char *name,
167 unsigned int subbuf_size,
168 unsigned int subbuf_cnt)
169{
170 struct ltt_channel_setting *setting;
171 int ret = 0;
172
173 mutex_lock(&ltt_channel_mutex);
174 setting = lookup_channel(name);
b102c2b0 175 if (!setting || uatomic_read(&setting->kref.refcount) == 0) {
99054cee
PMF
176 ret = -ENOENT;
177 goto end;
178 }
179 setting->subbuf_size = subbuf_size;
180 setting->subbuf_cnt = subbuf_cnt;
181end:
182 mutex_unlock(&ltt_channel_mutex);
183 return ret;
184}
b6bf28ec 185//ust// EXPORT_SYMBOL_GPL(ltt_channels_set_default);
99054cee
PMF
186
187/**
188 * ltt_channels_get_name_from_index - get channel name from channel index
189 * @index: channel index
190 *
191 * Allows to lookup the channel name given its index. Done to keep the name
192 * information outside of each trace channel instance.
193 */
194const char *ltt_channels_get_name_from_index(unsigned int index)
195{
196 struct ltt_channel_setting *iter;
197
198 list_for_each_entry(iter, &ltt_channels, list)
b102c2b0 199 if (iter->index == index && uatomic_read(&iter->kref.refcount))
99054cee
PMF
200 return iter->name;
201 return NULL;
202}
b6bf28ec 203//ust// EXPORT_SYMBOL_GPL(ltt_channels_get_name_from_index);
99054cee
PMF
204
205static struct ltt_channel_setting *
206ltt_channels_get_setting_from_name(const char *name)
207{
208 struct ltt_channel_setting *iter;
209
210 list_for_each_entry(iter, &ltt_channels, list)
211 if (!strcmp(iter->name, name)
b102c2b0 212 && uatomic_read(&iter->kref.refcount))
99054cee
PMF
213 return iter;
214 return NULL;
215}
216
217/**
218 * ltt_channels_get_index_from_name - get channel index from channel name
219 * @name: channel name
220 *
221 * Allows to lookup the channel index given its name. Done to keep the name
222 * information outside of each trace channel instance.
223 * Returns -1 if not found.
224 */
225int ltt_channels_get_index_from_name(const char *name)
226{
227 struct ltt_channel_setting *setting;
228
229 setting = ltt_channels_get_setting_from_name(name);
230 if (setting)
231 return setting->index;
232 else
233 return -1;
234}
b6bf28ec 235//ust// EXPORT_SYMBOL_GPL(ltt_channels_get_index_from_name);
99054cee
PMF
236
237/**
238 * ltt_channels_trace_alloc - Allocate channel structures for a trace
239 * @subbuf_size: subbuffer size. 0 uses default.
240 * @subbuf_cnt: number of subbuffers per per-cpu buffers. 0 uses default.
241 * @flags: Default channel flags
242 *
243 * Use the current channel list to allocate the channels for a trace.
244 * Called with trace lock held. Does not perform the trace buffer allocation,
245 * because we must let the user overwrite specific channel sizes.
246 */
b5b073e2 247struct ust_channel *ltt_channels_trace_alloc(unsigned int *nr_channels,
99054cee
PMF
248 int overwrite,
249 int active)
250{
b5b073e2 251 struct ust_channel *channel = NULL;
99054cee
PMF
252 struct ltt_channel_setting *iter;
253
254 mutex_lock(&ltt_channel_mutex);
5f54827b
PMF
255 if (!free_index) {
256 WARN("ltt_channels_trace_alloc: no free_index; are there any probes connected?");
99054cee 257 goto end;
5f54827b 258 }
b102c2b0 259 if (!uatomic_read(&index_kref.refcount))
99054cee
PMF
260 kref_init(&index_kref);
261 else
262 kref_get(&index_kref);
263 *nr_channels = free_index;
909bc43f 264 channel = zmalloc(sizeof(struct ust_channel) * free_index);
5f54827b
PMF
265 if (!channel) {
266 WARN("ltt_channel_struct: channel null after alloc");
99054cee 267 goto end;
5f54827b 268 }
99054cee 269 list_for_each_entry(iter, &ltt_channels, list) {
b102c2b0 270 if (!uatomic_read(&iter->kref.refcount))
99054cee
PMF
271 continue;
272 channel[iter->index].subbuf_size = iter->subbuf_size;
273 channel[iter->index].subbuf_cnt = iter->subbuf_cnt;
274 channel[iter->index].overwrite = overwrite;
275 channel[iter->index].active = active;
276 channel[iter->index].channel_name = iter->name;
277 }
278end:
279 mutex_unlock(&ltt_channel_mutex);
280 return channel;
281}
b6bf28ec 282//ust// EXPORT_SYMBOL_GPL(ltt_channels_trace_alloc);
99054cee
PMF
283
284/**
285 * ltt_channels_trace_free - Free one trace's channels
286 * @channels: channels to free
287 *
288 * Called with trace lock held. The actual channel buffers must be freed before
289 * this function is called.
290 */
b5b073e2 291void ltt_channels_trace_free(struct ust_channel *channels)
99054cee
PMF
292{
293 lock_markers();
294 mutex_lock(&ltt_channel_mutex);
909bc43f 295 free(channels);
99054cee
PMF
296 kref_put(&index_kref, release_trace_channel);
297 mutex_unlock(&ltt_channel_mutex);
298 unlock_markers();
299}
b6bf28ec 300//ust// EXPORT_SYMBOL_GPL(ltt_channels_trace_free);
99054cee
PMF
301
302/**
303 * _ltt_channels_get_event_id - get next event ID for a marker
304 * @channel: channel name
305 * @name: event name
306 *
307 * Returns a unique event ID (for this channel) or < 0 on error.
308 * Must be called with channels mutex held.
309 */
310int _ltt_channels_get_event_id(const char *channel, const char *name)
311{
312 struct ltt_channel_setting *setting;
313 int ret;
314
315 setting = ltt_channels_get_setting_from_name(channel);
316 if (!setting) {
317 ret = -ENOENT;
318 goto end;
319 }
320 if (strcmp(channel, "metadata") == 0) {
321 if (strcmp(name, "core_marker_id") == 0)
322 ret = 0;
323 else if (strcmp(name, "core_marker_format") == 0)
324 ret = 1;
9c67dc50
PMF
325 else if (strcmp(name, "testev") == 0)
326 ret = 2;
99054cee
PMF
327 else
328 ret = -ENOENT;
329 goto end;
330 }
331 if (setting->free_event_id == EVENTS_PER_CHANNEL - 1) {
332 ret = -ENOSPC;
333 goto end;
334 }
335 ret = setting->free_event_id++;
336end:
337 return ret;
338}
339
340/**
341 * ltt_channels_get_event_id - get next event ID for a marker
342 * @channel: channel name
343 * @name: event name
344 *
345 * Returns a unique event ID (for this channel) or < 0 on error.
346 */
347int ltt_channels_get_event_id(const char *channel, const char *name)
348{
349 int ret;
350
351 mutex_lock(&ltt_channel_mutex);
352 ret = _ltt_channels_get_event_id(channel, name);
353 mutex_unlock(&ltt_channel_mutex);
354 return ret;
355}
356
b6bf28ec
PMF
357//ust// MODULE_LICENSE("GPL");
358//ust// MODULE_AUTHOR("Mathieu Desnoyers");
359//ust// MODULE_DESCRIPTION("Linux Trace Toolkit Next Generation Channel Management");
This page took 0.059846 seconds and 4 git commands to generate.