update version
[ltt-control.git] / trunk / ltt-control / liblttctl / liblttctl.c
CommitLineData
2727692a 1/* libltt
2 *
3 * Linux Trace Toolkit Netlink Control Library
4 *
c928825d 5 * Controls the ltt-control kernel module through debugfs.
2727692a 6 *
7 * Copyright 2005 -
8 * Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
9 *
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10e8a188 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2727692a 19 * GNU General Public License for more details.
c928825d 20 *
2727692a 21 */
22
23#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
26
27#include <liblttctl/lttctl.h>
28#include <errno.h>
29#include <stdio.h>
2727692a 30#include <string.h>
c928825d 31#include <dirent.h>
32#include <limits.h>
33#include <fcntl.h>
34#include <stdlib.h>
2727692a 35
c928825d 36#define MAX_CHANNEL (256)
2727692a 37
c928825d 38static char debugfsmntdir[PATH_MAX];
2727692a 39
c928825d 40static int initdebugfsmntdir(void)
2727692a 41{
c928825d 42 char mnt_dir[PATH_MAX];
43 char mnt_type[PATH_MAX];
2727692a 44
c928825d 45 FILE *fp = fopen("/proc/mounts", "r");
46 if (!fp) {
47 fprintf(stderr, "%s: Can't open /proc/mounts\n", __func__);
48 return 1;
49 }
2727692a 50
c928825d 51 while (1) {
52 if (fscanf(fp, "%*s %s %s %*s %*s %*s", mnt_dir, mnt_type)
53 <= 0) {
54 fprintf(stderr, "%s: debugfs mountpoint not found\n",
55 __func__);
56 return 1;
2727692a 57 }
c928825d 58 if (!strcmp(mnt_type, "debugfs")) {
59 strcpy(debugfsmntdir, mnt_dir);
2727692a 60 return 0;
61 }
62 }
c928825d 63}
64
65int lttctl_init(void)
66{
67 int ret;
68 DIR *dir;
69 char controldirname[PATH_MAX];
70
71 ret = initdebugfsmntdir();
72 if (ret) {
73 fprintf(stderr, "Debugfs mount point not found\n");
74 return 1;
2727692a 75 }
2727692a 76
c928825d 77 /* check ltt control's debugfs dir */
78 sprintf(controldirname, "%s/ltt/control/", debugfsmntdir);
2727692a 79
c928825d 80 dir = opendir(controldirname);
81 if (!dir) {
82 fprintf(stderr, "ltt-trace-control's debugfs dir not found\n");
83 closedir(dir);
84 return -errno;
85 }
2727692a 86
c928825d 87 closedir(dir);
2727692a 88
c928825d 89 return 0;
90}
2727692a 91
c928825d 92int lttctl_destroy(void)
2727692a 93{
c928825d 94 return 0;
2727692a 95}
96
c928825d 97static int lttctl_sendop(const char *fname, const char *op)
2727692a 98{
c928825d 99 int fd;
100
101 if (!fname) {
102 fprintf(stderr, "%s: args invalid\n", __func__);
103 return 1;
104 }
105
106 fd = open(fname, O_WRONLY);
107 if (fd == -1) {
108 fprintf(stderr, "%s: open %s failed: %s\n", __func__, fname,
109 strerror(errno));
110 return errno;
111 }
112
113 if (write(fd, op, strlen(op)) == -1) {
114 fprintf(stderr, "%s: write %s to %s failed: %s\n", __func__, op,
115 fname, strerror(errno));
116 close(fd);
117 return 1;
118 }
2727692a 119
c928825d 120 close(fd);
121
122 return 0;
123}
2727692a 124
125/*
c928825d 126 * check is trace exist(check debugfsmntdir too)
127 * expect:
128 * 0: expect that trace not exist
129 * !0: expect that trace exist
130 *
131 * ret:
132 * 0: check pass
133 * 1: check failed
134 * -ERRNO: error happened (no check)
2727692a 135 */
c928825d 136static int lttctl_check_trace(const char *name, int expect)
2727692a 137{
c928825d 138 char tracedirname[PATH_MAX];
139 DIR *dir;
140 int exist;
2727692a 141
c928825d 142 if (!name) {
143 fprintf(stderr, "%s: args invalid\n", __func__);
144 return -EINVAL;
2727692a 145 }
c928825d 146
147 if (!debugfsmntdir[0]) {
148 fprintf(stderr, "%s: debugfsmntdir not valid\n", __func__);
149 return -EINVAL;
150 }
151
152 sprintf(tracedirname, "%s/ltt/control/%s", debugfsmntdir, name);
153
154 dir = opendir(tracedirname);
155 if (dir) {
156 exist = 1;
157 } else {
158 if (errno != ENOENT) {
159 fprintf(stderr, "%s: %s\n", __func__, strerror(errno));
160 return -EINVAL;
161 }
162 exist = 0;
163 }
164
165 closedir(dir);
166
167 if (!expect != !exist) {
168 if (exist)
169 fprintf(stderr, "Trace %s already exist\n", name);
170 else
171 fprintf(stderr, "Trace %s not exist\n", name);
172 return 1;
173 }
174
175 return 0;
2727692a 176}
177
178/*
c928825d 179 * get channel list of a trace
180 * don't include metadata channel when metadata is 0
181 *
182 * return number of channel on success
183 * return negative number on fail
184 * Caller must free channellist.
2727692a 185 */
c928825d 186static int lttctl_get_channellist(const char *tracename,
187 char ***channellist, int metadata)
2727692a 188{
c928825d 189 char tracedirname[PATH_MAX];
190 struct dirent *dirent;
191 DIR *dir;
192 char **list = NULL, **old_list;
193 int nr_chan = 0;
194
195 sprintf(tracedirname, "%s/ltt/control/%s/channel", debugfsmntdir,
196 tracename);
197
198 dir = opendir(tracedirname);
199 if (!dir) {
200 nr_chan = -ENOENT;
201 goto error;
202 }
203
204 for (;;) {
205 dirent = readdir(dir);
206 if (!dirent)
207 break;
208 if (!strcmp(dirent->d_name, ".")
209 || !strcmp(dirent->d_name, ".."))
210 continue;
211 if (!metadata && !strcmp(dirent->d_name, "metadata"))
212 continue;
213 old_list = list;
214 list = malloc(sizeof(char *) * ++nr_chan);
215 memcpy(list, old_list, sizeof(*list) * (nr_chan - 1));
216 free(old_list);
217 list[nr_chan - 1] = strdup(dirent->d_name);
218 }
219
220 closedir(dir);
221
222 *channellist = list;
223 return nr_chan;
224error:
225 free(list);
226 *channellist = NULL;
227 return nr_chan;
228}
229
230int lttctl_setup_trace(const char *name)
231{
232 int ret;
233 char ctlfname[PATH_MAX];
234
235 if (!name) {
236 fprintf(stderr, "%s: args invalid\n", __func__);
237 ret = -EINVAL;
238 goto arg_error;
239 }
240
241 ret = lttctl_check_trace(name, 0);
242 if (ret)
243 goto arg_error;
244
245 sprintf(ctlfname, "%s/ltt/setup_trace", debugfsmntdir);
246
247 ret = lttctl_sendop(ctlfname, name);
248 if (ret) {
249 fprintf(stderr, "Setup trace failed\n");
250 goto op_err;
2727692a 251 }
c928825d 252
2727692a 253 return 0;
c928825d 254
255op_err:
256arg_error:
257 return ret;
2727692a 258}
259
c928825d 260int lttctl_destroy_trace(const char *name)
261{
262 int ret;
263 char ctlfname[PATH_MAX];
264
265 if (!name) {
266 fprintf(stderr, "%s: args invalid\n", __func__);
267 ret = -EINVAL;
268 goto arg_error;
269 }
270
271 ret = lttctl_check_trace(name, 1);
272 if (ret)
273 goto arg_error;
274
275 sprintf(ctlfname, "%s/ltt/destroy_trace", debugfsmntdir);
276
277 ret = lttctl_sendop(ctlfname, name);
278 if (ret) {
279 fprintf(stderr, "Destroy trace failed\n");
280 goto op_err;
281 }
282
283 return 0;
284
285op_err:
286arg_error:
287 return ret;
288}
2727692a 289
c928825d 290int lttctl_alloc_trace(const char *name)
2727692a 291{
c928825d 292 int ret;
293 char ctlfname[PATH_MAX];
294
295 if (!name) {
296 fprintf(stderr, "%s: args invalid\n", __func__);
297 ret = -EINVAL;
298 goto arg_error;
299 }
300
301 ret = lttctl_check_trace(name, 1);
302 if (ret)
303 goto arg_error;
304
305 sprintf(ctlfname, "%s/ltt/control/%s/alloc", debugfsmntdir, name);
306
307 ret = lttctl_sendop(ctlfname, "1");
308 if (ret) {
309 fprintf(stderr, "Allocate trace failed\n");
310 goto op_err;
311 }
312
313 return 0;
314
315op_err:
316arg_error:
317 return ret;
318}
319
320int lttctl_start(const char *name)
321{
322 int ret;
323 char ctlfname[PATH_MAX];
324
325 if (!name) {
326 fprintf(stderr, "%s: args invalid\n", __func__);
327 ret = -EINVAL;
328 goto arg_error;
329 }
330
331 ret = lttctl_check_trace(name, 1);
332 if (ret)
333 goto arg_error;
334
335 sprintf(ctlfname, "%s/ltt/control/%s/enabled", debugfsmntdir, name);
336
337 ret = lttctl_sendop(ctlfname, "1");
338 if (ret) {
339 fprintf(stderr, "Start trace failed\n");
340 goto op_err;
2727692a 341 }
342
343 return 0;
344
c928825d 345op_err:
346arg_error:
347 return ret;
2727692a 348}
349
c928825d 350int lttctl_pause(const char *name)
2727692a 351{
c928825d 352 int ret;
353 char ctlfname[PATH_MAX];
354
355 if (!name) {
356 fprintf(stderr, "%s: args invalid\n", __func__);
357 ret = -EINVAL;
358 goto arg_error;
359 }
360
361 ret = lttctl_check_trace(name, 1);
362 if (ret)
363 goto arg_error;
364
365 sprintf(ctlfname, "%s/ltt/control/%s/enabled", debugfsmntdir, name);
366
367 ret = lttctl_sendop(ctlfname, "0");
368 if (ret) {
369 fprintf(stderr, "Pause trace failed\n");
370 goto op_err;
2727692a 371 }
372
373 return 0;
374
c928825d 375op_err:
376arg_error:
377 return ret;
378}
379
380int lttctl_set_trans(const char *name, const char *trans)
381{
382 int ret;
383 char ctlfname[PATH_MAX];
384
385 if (!name) {
386 fprintf(stderr, "%s: args invalid\n", __func__);
387 ret = -EINVAL;
388 goto arg_error;
389 }
390
391 ret = lttctl_check_trace(name, 1);
392 if (ret)
393 goto arg_error;
394
395 sprintf(ctlfname, "%s/ltt/control/%s/trans", debugfsmntdir, name);
2727692a 396
c928825d 397 ret = lttctl_sendop(ctlfname, trans);
398 if (ret) {
399 fprintf(stderr, "Set transport failed\n");
400 goto op_err;
401 }
402
403 return 0;
404
405op_err:
406arg_error:
407 return ret;
2727692a 408}
409
c928825d 410static int __lttctl_set_channel_enable(const char *name, const char *channel,
411 int enable)
2727692a 412{
c928825d 413 int ret;
414 char ctlfname[PATH_MAX];
2727692a 415
c928825d 416 sprintf(ctlfname, "%s/ltt/control/%s/channel/%s/enable", debugfsmntdir,
417 name, channel);
2727692a 418
c928825d 419 ret = lttctl_sendop(ctlfname, enable ? "1" : "0");
420 if (ret)
421 fprintf(stderr, "Set channel's enable mode failed\n");
2727692a 422
c928825d 423 return ret;
424}
425int lttctl_set_channel_enable(const char *name, const char *channel,
426 int enable)
427{
428 int ret;
2727692a 429
c928825d 430 if (!name || !channel) {
431 fprintf(stderr, "%s: args invalid\n", __func__);
432 ret = -EINVAL;
433 goto arg_error;
434 }
2727692a 435
c928825d 436 ret = lttctl_check_trace(name, 1);
437 if (ret)
438 goto arg_error;
439
440 if (strcmp(channel, "all")) {
441 ret = __lttctl_set_channel_enable(name, channel, enable);
442 if (ret)
443 goto op_err;
444 } else {
445 char **channellist;
446 int n_channel;
447
448 /* Don't allow set enable state for metadata channel */
449 n_channel = lttctl_get_channellist(name, &channellist, 0);
450 if (n_channel < 0) {
451 fprintf(stderr, "%s: lttctl_get_channellist failed\n",
452 __func__);
453 ret = -ENOENT;
454 goto op_err;
455 }
2727692a 456
c928825d 457 for (; n_channel > 0; n_channel--) {
458 ret = __lttctl_set_channel_enable(name,
459 channellist[n_channel - 1], enable);
460 if (ret)
461 goto op_err;
462 }
463 free(channellist);
2727692a 464 }
465
466 return 0;
467
c928825d 468op_err:
469arg_error:
470 return ret;
471}
472
473static int __lttctl_set_channel_overwrite(const char *name, const char *channel,
474 int overwrite)
475{
476 int ret;
477 char ctlfname[PATH_MAX];
478
479 sprintf(ctlfname, "%s/ltt/control/%s/channel/%s/overwrite",
480 debugfsmntdir, name, channel);
481
482 ret = lttctl_sendop(ctlfname, overwrite ? "1" : "0");
483 if (ret)
484 fprintf(stderr, "Set channel's overwrite mode failed\n");
485
486 return ret;
487}
488int lttctl_set_channel_overwrite(const char *name, const char *channel,
489 int overwrite)
490{
491 int ret;
492
493 if (!name || !channel) {
494 fprintf(stderr, "%s: args invalid\n", __func__);
495 ret = -EINVAL;
496 goto arg_error;
497 }
498
499 ret = lttctl_check_trace(name, 1);
500 if (ret)
501 goto arg_error;
502
503 if (strcmp(channel, "all")) {
504 ret = __lttctl_set_channel_overwrite(name, channel, overwrite);
505 if (ret)
506 goto op_err;
507 } else {
508 char **channellist;
509 int n_channel;
510
511 /* Don't allow set overwrite for metadata channel */
512 n_channel = lttctl_get_channellist(name, &channellist, 0);
513 if (n_channel < 0) {
514 fprintf(stderr, "%s: lttctl_get_channellist failed\n",
515 __func__);
516 ret = -ENOENT;
517 goto op_err;
518 }
519
520 for (; n_channel > 0; n_channel--) {
521 ret = __lttctl_set_channel_overwrite(name,
522 channellist[n_channel - 1], overwrite);
523 if (ret)
524 goto op_err;
525 }
526 free(channellist);
527 }
528
529 return 0;
2727692a 530
c928825d 531op_err:
532arg_error:
533 return ret;
2727692a 534}
535
c928825d 536static int __lttctl_set_channel_subbuf_num(const char *name,
537 const char *channel, unsigned subbuf_num)
538{
539 int ret;
540 char ctlfname[PATH_MAX];
541 char opstr[32];
542
543 sprintf(ctlfname, "%s/ltt/control/%s/channel/%s/subbuf_num",
544 debugfsmntdir, name, channel);
545
546 sprintf(opstr, "%u", subbuf_num);
547
548 ret = lttctl_sendop(ctlfname, opstr);
549 if (ret)
550 fprintf(stderr, "Set channel's subbuf number failed\n");
551
552 return ret;
553}
554int lttctl_set_channel_subbuf_num(const char *name, const char *channel,
555 unsigned subbuf_num)
2727692a 556{
c928825d 557 int ret;
558
559 if (!name || !channel) {
560 fprintf(stderr, "%s: args invalid\n", __func__);
561 ret = -EINVAL;
562 goto arg_error;
563 }
564
565 ret = lttctl_check_trace(name, 1);
566 if (ret)
567 goto arg_error;
568
569 if (strcmp(channel, "all")) {
570 ret = __lttctl_set_channel_subbuf_num(name, channel,
571 subbuf_num);
572 if (ret)
573 goto op_err;
574 } else {
575 char **channellist;
576 int n_channel;
577
578 /* allow set subbuf_num for metadata channel */
579 n_channel = lttctl_get_channellist(name, &channellist, 1);
580 if (n_channel < 0) {
581 fprintf(stderr, "%s: lttctl_get_channellist failed\n",
582 __func__);
583 ret = -ENOENT;
584 goto op_err;
585 }
586
587 for (; n_channel > 0; n_channel--) {
588 ret = __lttctl_set_channel_subbuf_num(name,
589 channellist[n_channel - 1], subbuf_num);
590 if (ret)
591 goto op_err;
592 }
593 free(channellist);
2727692a 594 }
595
596 return 0;
597
c928825d 598op_err:
599arg_error:
600 return ret;
601}
602
603static int __lttctl_set_channel_subbuf_size(const char *name,
604 const char *channel, unsigned subbuf_size)
605{
606 int ret;
607 char ctlfname[PATH_MAX];
608 char opstr[32];
609
610 sprintf(ctlfname, "%s/ltt/control/%s/channel/%s/subbuf_size",
611 debugfsmntdir, name, channel);
612
613 sprintf(opstr, "%u", subbuf_size);
614
615 ret = lttctl_sendop(ctlfname, opstr);
616 if (ret)
617 fprintf(stderr, "Set channel's subbuf size failed\n");
2727692a 618}
c928825d 619int lttctl_set_channel_subbuf_size(const char *name, const char *channel,
620 unsigned subbuf_size)
621{
622 int ret;
2727692a 623
c928825d 624 if (!name || !channel) {
625 fprintf(stderr, "%s: args invalid\n", __func__);
626 ret = -EINVAL;
627 goto arg_error;
628 }
629
630 ret = lttctl_check_trace(name, 1);
631 if (ret)
632 goto arg_error;
633
634 if (strcmp(channel, "all")) {
635 ret = __lttctl_set_channel_subbuf_size(name, channel,
636 subbuf_size);
637 if (ret)
638 goto op_err;
639 } else {
640 char **channellist;
641 int n_channel;
642
643 /* allow set subbuf_size for metadata channel */
644 n_channel = lttctl_get_channellist(name, &channellist, 1);
645 if (n_channel < 0) {
646 fprintf(stderr, "%s: lttctl_get_channellist failed\n",
647 __func__);
648 ret = -ENOENT;
649 goto op_err;
650 }
651
652 for (; n_channel > 0; n_channel--) {
653 ret = __lttctl_set_channel_subbuf_size(name,
654 channellist[n_channel - 1], subbuf_size);
655 if (ret)
656 goto op_err;
657 }
658 free(channellist);
659 }
660
661 return 0;
662
663op_err:
664arg_error:
665 return ret;
666}
This page took 0.049024 seconds and 4 git commands to generate.