From: David Goulet Date: Thu, 19 May 2011 21:59:14 +0000 (-0400) Subject: Add kernel sesison and channel creation support X-Git-Tag: v2.0-pre1~132 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=20fe210416ef1cc0e9b85e5a40c58344e3185fd6;p=lttng-tools.git Add kernel sesison and channel creation support New kernel-ctl.c/.h files used to interact with the libkernelctl for the session daemon. All kernel trace actions are made in this C file. Signed-off-by: David Goulet --- diff --git a/include/lttng/lttng.h b/include/lttng/lttng.h index 6f4ce130f..98d632c76 100644 --- a/include/lttng/lttng.h +++ b/include/lttng/lttng.h @@ -81,9 +81,6 @@ extern int lttng_kernel_disable_event(char *event_name); extern int lttng_kernel_create_session(void); extern int lttng_kernel_start_tracing(void); extern int lttng_kernel_stop_tracing(void); -extern int lttng_kernel_create_channel(int overwrite, - uint64_t subbuf_size, uint64_t num_subbuf, - unsigned int switch_timer_interval, - unsigned int read_timer_interval); +extern int lttng_kernel_create_channel(void); #endif /* _LIBLTTNGCTL_H */ diff --git a/liblttngctl/liblttngctl.c b/liblttngctl/liblttngctl.c index 230a19d7e..2cf79f4ed 100644 --- a/liblttngctl/liblttngctl.c +++ b/liblttngctl/liblttngctl.c @@ -198,18 +198,8 @@ int lttng_kernel_create_session(void) * * Create a channel in the kernel tracer. */ -int lttng_kernel_create_channel(int overwrite, - u64 subbuf_size, u64 num_subbuf, - unsigned int switch_timer_interval, - unsigned int read_timer_interval) +int lttng_kernel_create_channel(void) { - /* Write setting to the session message */ - lsm.u.create_channel.overwrite = overwrite; - lsm.u.create_channel.subbuf_size = subbuf_size; - lsm.u.create_channel.num_subbuf = num_subbuf; - lsm.u.create_channel.switch_timer_interval = switch_timer_interval; - lsm.u.create_channel.read_timer_interval = read_timer_interval; - return ask_sessiond(KERNEL_CREATE_CHANNEL, NULL); } diff --git a/liblttsessiondcomm/liblttsessiondcomm.c b/liblttsessiondcomm/liblttsessiondcomm.c index a5b3818c4..d754f59da 100644 --- a/liblttsessiondcomm/liblttsessiondcomm.c +++ b/liblttsessiondcomm/liblttsessiondcomm.c @@ -48,6 +48,9 @@ static const char *lttcomm_readable_code[] = { [ LTTCOMM_ERR_INDEX(LTTCOMM_NO_TRACEABLE) ] = "App is not traceable", [ LTTCOMM_ERR_INDEX(LTTCOMM_SELECT_SESS) ] = "A session MUST be selected", [ LTTCOMM_ERR_INDEX(LTTCOMM_EXIST_SESS) ] = "Session name already exist", + [ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_NA) ] = "Kernel tracer not available", + [ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_SESS_FAIL) ] = "Kernel create session failed", + [ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_CHAN_FAIL) ] = "Kernel create channel failed", [ LTTCOMM_ERR_INDEX(KCONSUMERD_COMMAND_SOCK_READY) ] = "Kconsumerd command socket ready", [ LTTCOMM_ERR_INDEX(KCONSUMERD_SUCCESS_RECV_FD) ] = "Kconsumerd success on receiving fds", [ LTTCOMM_ERR_INDEX(KCONSUMERD_ERROR_RECV_FD) ] = "Kconsumerd error on receiving fds", diff --git a/liblttsessiondcomm/liblttsessiondcomm.h b/liblttsessiondcomm/liblttsessiondcomm.h index abcca2509..8e6a862ef 100644 --- a/liblttsessiondcomm/liblttsessiondcomm.h +++ b/liblttsessiondcomm/liblttsessiondcomm.h @@ -82,34 +82,38 @@ enum lttcomm_sessiond_command { * lttcomm error code. */ enum lttcomm_return_code { - LTTCOMM_OK = 1000, /* Ok */ - LTTCOMM_ERR, /* Unknown Error */ - LTTCOMM_UND, /* Undefine command */ - LTTCOMM_ALLOC_FAIL, /* Trace allocation fail */ - LTTCOMM_NO_SESSION, /* No session found */ - LTTCOMM_CREATE_FAIL, /* Create trace fail */ - LTTCOMM_SESSION_FAIL, /* Create session fail */ - LTTCOMM_START_FAIL, /* Start tracing fail */ - LTTCOMM_STOP_FAIL, /* Stop tracing fail */ - LTTCOMM_LIST_FAIL, /* Listing apps fail */ - LTTCOMM_NO_APPS, /* No traceable application */ - LTTCOMM_NO_SESS, /* No sessions available */ - LTTCOMM_NO_TRACE, /* No trace exist */ - LTTCOMM_FATAL, /* Session daemon had a fatal error */ - LTTCOMM_NO_TRACEABLE, /* Error for non traceable app */ - LTTCOMM_SELECT_SESS, /* Must select a session */ - LTTCOMM_EXIST_SESS, /* Session name already exist */ - LTTCOMM_NO_EVENT, /* No event found */ - LTTCOMM_NR, /* Last element */ + LTTCOMM_OK = 1000, /* Ok */ + LTTCOMM_ERR, /* Unknown Error */ + LTTCOMM_UND, /* Undefine command */ + LTTCOMM_ALLOC_FAIL, /* Trace allocation fail */ + LTTCOMM_NO_SESSION, /* No session found */ + LTTCOMM_CREATE_FAIL, /* Create trace fail */ + LTTCOMM_SESSION_FAIL, /* Create session fail */ + LTTCOMM_START_FAIL, /* Start tracing fail */ + LTTCOMM_STOP_FAIL, /* Stop tracing fail */ + LTTCOMM_LIST_FAIL, /* Listing apps fail */ + LTTCOMM_NO_APPS, /* No traceable application */ + LTTCOMM_NO_SESS, /* No sessions available */ + LTTCOMM_NO_TRACE, /* No trace exist */ + LTTCOMM_FATAL, /* Session daemon had a fatal error */ + LTTCOMM_NO_TRACEABLE, /* Error for non traceable app */ + LTTCOMM_SELECT_SESS, /* Must select a session */ + LTTCOMM_EXIST_SESS, /* Session name already exist */ + LTTCOMM_NO_EVENT, /* No event found */ + LTTCOMM_KERN_NA, /* Kernel tracer unavalable */ + LTTCOMM_KERN_SESS_FAIL, /* Kernel create session failed */ + LTTCOMM_KERN_CHAN_FAIL, /* Kernel create channel failed */ KCONSUMERD_COMMAND_SOCK_READY, /* when kconsumerd command socket ready */ - KCONSUMERD_SUCCESS_RECV_FD, /* success on receiving fds */ - KCONSUMERD_ERROR_RECV_FD, /* error on receiving fds */ - KCONSUMERD_POLL_ERROR, /* Error in polling thread in kconsumerd */ - KCONSUMERD_POLL_NVAL, /* Poll on closed fd */ - KCONSUMERD_POLL_HUP, /* All fds have hungup */ - KCONSUMERD_EXIT_SUCCESS, /* kconsumerd exiting normally */ - KCONSUMERD_EXIT_FAILURE, /* kconsumerd exiting on error */ - KCONSUMERD_OUTFD_ERROR, /* error opening the tracefile */ + KCONSUMERD_SUCCESS_RECV_FD, /* success on receiving fds */ + KCONSUMERD_ERROR_RECV_FD, /* error on receiving fds */ + KCONSUMERD_POLL_ERROR, /* Error in polling thread in kconsumerd */ + KCONSUMERD_POLL_NVAL, /* Poll on closed fd */ + KCONSUMERD_POLL_HUP, /* All fds have hungup */ + KCONSUMERD_EXIT_SUCCESS, /* kconsumerd exiting normally */ + KCONSUMERD_EXIT_FAILURE, /* kconsumerd exiting on error */ + KCONSUMERD_OUTFD_ERROR, /* error opening the tracefile */ + /* MUST be last element */ + LTTCOMM_NR, /* Last element */ }; /* commands for kconsumerd */ @@ -143,14 +147,6 @@ struct lttcomm_session_msg { struct { char event_name[NAME_MAX]; } event; - /* Create channel kernel */ - struct { - int overwrite; - u64 subbuf_size; - u64 num_subbuf; - unsigned int switch_timer_interval; - unsigned int read_timer_interval; - } create_channel; } u; }; diff --git a/ltt-sessiond/Makefile.am b/ltt-sessiond/Makefile.am index d24a23aec..525851b42 100644 --- a/ltt-sessiond/Makefile.am +++ b/ltt-sessiond/Makefile.am @@ -1,9 +1,10 @@ -AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/liblttsessiondcomm +AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/liblttsessiondcomm -I$(top_srcdir)/libkernelctl AM_CFLAGS = -fno-strict-aliasing bin_PROGRAMS = ltt-sessiond -ltt_sessiond_SOURCES = session.c trace.c traceable-app.c main.c +ltt_sessiond_SOURCES = session.c trace.c traceable-app.c kernel-ctl.c main.c ltt_sessiond_LDADD = \ - $(top_builddir)/liblttsessiondcomm/liblttsessiondcomm.la + $(top_builddir)/liblttsessiondcomm/liblttsessiondcomm.la \ + $(top_builddir)/libkernelctl/libkernelctl.la diff --git a/ltt-sessiond/kernel-ctl.c b/ltt-sessiond/kernel-ctl.c new file mode 100644 index 000000000..12a00eb1f --- /dev/null +++ b/ltt-sessiond/kernel-ctl.c @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2011 - David Goulet + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#include "ltt-sessiond.h" +#include "libkernelctl.h" +#include "kernel-ctl.h" +#include "trace.h" + +/* + * kernel_create_session + * + * Create a new kernel session using the command context session. + */ +int kernel_create_session(struct command_ctx *cmd_ctx, int tracer_fd) +{ + int ret; + struct ltt_kernel_session *lks; + + /* Allocate a new kernel session */ + lks = malloc(sizeof(struct ltt_kernel_session)); + if (lks == NULL) { + perror("kernel session malloc"); + ret = -errno; + goto error; + } + + ret = kernctl_create_session(tracer_fd); + if (ret < 0) { + goto error; + } + + /* Assigning session fd and to the command context */ + lks->fd = ret; + cmd_ctx->session->kernel_session = lks; + cmd_ctx->session->kern_session_count++; + + return 0; + +error: + return ret; +} + +/* + * kernel_create_channel + * + * Create a kernel channel within the kernel session. + */ +int kernel_create_channel(struct command_ctx *cmd_ctx) +{ + int ret; + struct ltt_kernel_channel *lkc; + struct lttng_channel *chan; + + lkc = malloc(sizeof(struct ltt_kernel_channel)); + chan = malloc(sizeof(struct lttng_channel)); + + if (lkc == NULL || chan == NULL) { + perror("kernel channel malloc"); + ret = -errno; + goto error; + } + + chan->overwrite = DEFAULT_KERNEL_OVERWRITE; + chan->subbuf_size = DEFAULT_KERNEL_SUBBUF_SIZE; + chan->num_subbuf = DEFAULT_KERNEL_SUBBUF_NUM; + chan->switch_timer_interval = DEFAULT_KERNEL_SWITCH_TIMER; + chan->read_timer_interval = DEFAULT_KERNEL_READ_TIMER; + + ret = kernctl_create_channel(cmd_ctx->session->kernel_session->fd, chan); + if (ret < 0) { + goto error; + } + + lkc->fd = ret; + lkc->channel = chan; + CDS_INIT_LIST_HEAD(&lkc->events_list.head); + + cmd_ctx->session->kernel_session->channel = lkc; + + return 0; + +error: + return ret; +} diff --git a/ltt-sessiond/kernel-ctl.h b/ltt-sessiond/kernel-ctl.h new file mode 100644 index 000000000..35057be08 --- /dev/null +++ b/ltt-sessiond/kernel-ctl.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2011 - David Goulet + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _LTT_KERNEL_CTL_H +#define _LTT_KERNEL_CTL_H + +int kernel_create_session(struct command_ctx *cmd_ctx, int tracer_fd); +int kernel_create_channel(struct command_ctx *cmd_ctx); + +#endif /* _LTT_KERNEL_CTL_H */ diff --git a/ltt-sessiond/ltt-sessiond.h b/ltt-sessiond/ltt-sessiond.h index 7133d061f..d563d1016 100644 --- a/ltt-sessiond/ltt-sessiond.h +++ b/ltt-sessiond/ltt-sessiond.h @@ -22,6 +22,16 @@ #define DEFAULT_UST_SOCK_DIR "/tmp/ust-app-socks" #define DEFAULT_GLOBAL_APPS_PIPE "/tmp/ust-app-socks/global" +/* + * Kernel tracer defines + */ +#define DEFAULT_KERNEL_TRACER_PATH "/mnt/debugfs/lttng" +#define DEFAULT_KERNEL_OVERWRITE 0 +#define DEFAULT_KERNEL_SUBBUF_SIZE 512 /* bytes */ +#define DEFAULT_KERNEL_SUBBUF_NUM 2 /* Must always be a power of 2 */ +#define DEFAULT_KERNEL_SWITCH_TIMER 0 /* usec */ +#define DEFAULT_KERNEL_READ_TIMER 10000 /* usec */ + extern const char default_home_dir[], default_tracing_group[], default_ust_sock_dir[], diff --git a/ltt-sessiond/main.c b/ltt-sessiond/main.c index 76e927e43..5b7fb0c21 100644 --- a/ltt-sessiond/main.c +++ b/ltt-sessiond/main.c @@ -40,6 +40,7 @@ #include "liblttsessiondcomm.h" #include "ltt-sessiond.h" #include "lttngerr.h" +#include "kernel-ctl.h" #include "session.h" #include "trace.h" #include "traceable-app.h" @@ -95,6 +96,7 @@ static char kconsumerd_cmd_unix_sock_path[PATH_MAX]; /* kconsumerd command Unix static int client_sock; static int apps_sock; static int kconsumerd_err_sock; +static int kernel_tracer_fd; /* * thread_manage_kconsumerd @@ -455,6 +457,17 @@ static int process_client_msg(struct command_ctx *cmd_ctx) break; } + /* Check command for kernel tracing */ + switch (cmd_ctx->lsm->cmd_type) { + case KERNEL_CREATE_SESSION: + case KERNEL_CREATE_CHANNEL: + if (kernel_tracer_fd == 0) { + ret = LTTCOMM_KERN_NA; + goto error; + } + break; + } + /* Connect to ust apps if available pid */ if (cmd_ctx->lsm->pid > 0) { /* Connect to app using ustctl API */ @@ -467,6 +480,42 @@ static int process_client_msg(struct command_ctx *cmd_ctx) /* Process by command type */ switch (cmd_ctx->lsm->cmd_type) { + case KERNEL_CREATE_SESSION: + { + ret = setup_lttng_msg(cmd_ctx, 0); + if (ret < 0) { + goto setup_error; + } + + DBG("Creating kernel session"); + + ret = kernel_create_session(cmd_ctx, kernel_tracer_fd); + if (ret < 0) { + ret = LTTCOMM_KERN_SESS_FAIL; + goto error; + } + + ret = LTTCOMM_OK; + break; + } + case KERNEL_CREATE_CHANNEL: + { + ret = setup_lttng_msg(cmd_ctx, 0); + if (ret < 0) { + goto setup_error; + } + + DBG("Creating kernel session"); + + ret = kernel_create_channel(cmd_ctx); + if (ret < 0) { + ret = LTTCOMM_KERN_CHAN_FAIL; + goto error; + } + + ret = LTTCOMM_OK; + break; + } case KERNEL_ENABLE_EVENT: { /* Setup lttng message with no payload */ @@ -909,6 +958,21 @@ error: return ret; } +/* + * init_kernel_tracer + * + * Setup necessary data for kernel tracer action. + */ +static void init_kernel_tracer(void) +{ + /* Set the global kernel tracer fd */ + kernel_tracer_fd = open(DEFAULT_KERNEL_TRACER_PATH, O_RDWR); + if (kernel_tracer_fd < 0) { + WARN("No kernel tracer available"); + kernel_tracer_fd = 0; + } +} + /* * set_kconsumerd_sockets * @@ -1101,6 +1165,9 @@ int main(int argc, char **argv) if (ret < 0) { goto error; } + + /* Setup kernel tracer */ + init_kernel_tracer(); } else { if (strlen(apps_unix_sock_path) == 0) { snprintf(apps_unix_sock_path, PATH_MAX, diff --git a/ltt-sessiond/session.c b/ltt-sessiond/session.c index 069213655..9fef73cf7 100644 --- a/ltt-sessiond/session.c +++ b/ltt-sessiond/session.c @@ -200,11 +200,9 @@ int create_session(char *name, uuid_t *session_id) /* Init list */ CDS_INIT_LIST_HEAD(&new_session->ust_traces); - CDS_INIT_LIST_HEAD(&new_session->kernel_traces); /* Set trace list counter */ new_session->ust_trace_count = 0; - new_session->kern_trace_count = 0; /* Add new session to the global session list */ add_session_list(new_session); diff --git a/ltt-sessiond/session.h b/ltt-sessiond/session.h index 586c55a24..7567d9867 100644 --- a/ltt-sessiond/session.h +++ b/ltt-sessiond/session.h @@ -20,6 +20,7 @@ #define _LTT_SESSION_H #include +#include #include /* Global session list */ @@ -31,13 +32,13 @@ struct ltt_session_list { * to identify a tracing session for both LTTng and UST. */ struct ltt_session { - char *name; struct cds_list_head list; + char *name; uuid_t uuid; struct cds_list_head ust_traces; - struct cds_list_head kernel_traces; + struct ltt_kernel_session *kernel_session; unsigned int ust_trace_count; - unsigned int kern_trace_count; + unsigned int kern_session_count; pid_t ust_consumer; pid_t kernel_consumer; }; diff --git a/ltt-sessiond/trace.c b/ltt-sessiond/trace.c index 9a3c95956..1cddb31fa 100644 --- a/ltt-sessiond/trace.c +++ b/ltt-sessiond/trace.c @@ -63,7 +63,7 @@ static struct ltt_ust_trace *find_session_ust_trace_by_pid( */ int get_trace_count_per_session(struct ltt_session *session) { - return session->ust_trace_count + session->kern_trace_count; + return session->ust_trace_count + session->kern_session_count; } /* @@ -76,7 +76,6 @@ void get_traces_per_session(struct ltt_session *session, struct lttng_trace *tra { int i = 0; struct ltt_ust_trace *ust_iter; - struct ltt_kernel_trace *kern_iter; struct lttng_trace trace; DBG("Getting userspace traces for session %s", session->name); @@ -95,13 +94,10 @@ void get_traces_per_session(struct ltt_session *session, struct lttng_trace *tra DBG("Getting kernel traces for session %s", session->name); /* Getting kernel traces */ - cds_list_for_each_entry(kern_iter, &session->kernel_traces, list) { + if (session->kern_session_count > 0) { trace.type = KERNEL; - strncpy(trace.name, kern_iter->name, sizeof(trace.name)); - trace.name[sizeof(trace.name) - 1] = '\0'; + strncpy(trace.name, "kernel", 6); memcpy(&traces[i], &trace, sizeof(trace)); - memset(&trace, 0, sizeof(trace)); - i++; } } diff --git a/ltt-sessiond/trace.h b/ltt-sessiond/trace.h index 5114272d8..6e86915b6 100644 --- a/ltt-sessiond/trace.h +++ b/ltt-sessiond/trace.h @@ -21,12 +21,31 @@ #include "ltt-sessiond.h" #include "session.h" +#include "lttng-kernel.h" -/* LTTng trace representation */ -struct ltt_kernel_trace { - struct cds_list_head list; +/* Kernel event list */ +struct ltt_kernel_event_list { + struct cds_list_head head; +}; + +/* Kernel event */ +struct ltt_kernel_event { char name[NAME_MAX]; - struct cds_list_head marker_list; + int fd; + struct cds_list_head list; +}; + +/* Kernel channel */ +struct ltt_kernel_channel { + int fd; + struct lttng_channel *channel; + struct ltt_kernel_event_list events_list; +}; + +/* Kernel session */ +struct ltt_kernel_session { + int fd; + struct ltt_kernel_channel *channel; }; /* UST trace representation */ diff --git a/lttng/lttng.c b/lttng/lttng.c index 10ce2ddfc..beb67ffb4 100644 --- a/lttng/lttng.c +++ b/lttng/lttng.c @@ -181,7 +181,24 @@ error: /* fall through */ */ static int process_kernel_create_trace(void) { + int ret; + + /* Setup kernel session */ + ret = lttng_kernel_create_session(); + if (ret < 0) { + goto error; + } + + /* Create an empty channel (with no event) */ + ret = lttng_kernel_create_channel(); + if (ret < 0) { + goto error; + } + return 0; + +error: + return ret; } /* diff --git a/lttng/lttng.h b/lttng/lttng.h index 412eba355..efaed09b5 100644 --- a/lttng/lttng.h +++ b/lttng/lttng.h @@ -37,7 +37,7 @@ extern int opt_enable_event; extern int opt_disable_event; extern int opt_destroy_session; extern int opt_create_session; -extern int opt_create_channel; +extern int opt_kern_create_channel; extern int opt_list_apps; extern int opt_no_sessiond; extern int opt_list_session; diff --git a/lttng/options.c b/lttng/options.c index bb0233e7e..bb3ecbb0c 100644 --- a/lttng/options.c +++ b/lttng/options.c @@ -42,7 +42,7 @@ int opt_start_trace = 0; int opt_stop_trace = 0; int opt_enable_event; int opt_disable_event; -int opt_create_channel; +int opt_kern_create_channel; pid_t opt_trace_pid = 0; enum { @@ -68,6 +68,7 @@ static struct poptOption long_options[] = { {"group", 0, POPT_ARG_STRING, &opt_tracing_group, 0, 0, 0}, {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0}, {"kernel", 'k', POPT_ARG_VAL, &opt_trace_kernel, 1, 0, 0}, + {"kern-create-channel",0, POPT_ARG_VAL, &opt_kern_create_channel, 1, 0, 0}, {"list-apps", 'L', POPT_ARG_VAL, &opt_list_apps, 1, 0, 0}, {"list-sessions", 'l', POPT_ARG_VAL, &opt_list_session, 1, 0, 0}, {"list-traces", 't', POPT_ARG_VAL, &opt_list_traces, 1, 0, 0}, @@ -119,7 +120,7 @@ static void usage(FILE *ofp) fprintf(ofp, " --stop [NAME] Stop tracing. Use NAME to identify user-space trace\n"); fprintf(ofp, "\n"); fprintf(ofp, "Kernel tracing options:\n"); - fprintf(ofp, " --create-channel Create kernel channel\n"); + fprintf(ofp, " --kern-create-channel Create a kernel channel\n"); fprintf(ofp, "\n"); fprintf(ofp, "User-space tracing options:\n"); fprintf(ofp, "\n");