#include <lttng/lttng.h>
#include <common/lttng-kernel.h>
+#include <common/lttng-kernel-old.h>
#include "consumer.h"
#define __USE_LINUX_IOCTL_DEFS
#include <sys/ioctl.h>
+#include <string.h>
#include "kernel-ctl.h"
#include "kernel-ioctl.h"
+/*
+ * This flag indicates which version of the kernel ABI to use. The old
+ * ABI (namespace _old) does not support a 32-bit user-space when the
+ * kernel is 64-bit. The old ABI is kept here for compatibility but is
+ * deprecated and will be removed eventually.
+ */
+static int lttng_kernel_use_old_abi = -1;
+
+/*
+ * Execute the new or old ioctl depending on the ABI version.
+ * If the ABI version is not determined yet (lttng_kernel_use_old_abi = -1),
+ * this function tests if the new ABI is available and otherwise fallbacks
+ * on the old one.
+ * This function takes the fd on which the ioctl must be executed and the old
+ * and new request codes.
+ * It returns the return value of the ioctl executed.
+ */
+static inline int compat_ioctl_no_arg(int fd, unsigned long oldname,
+ unsigned long newname)
+{
+ int ret;
+
+ if (lttng_kernel_use_old_abi == -1) {
+ ret = ioctl(fd, newname);
+ if (!ret) {
+ lttng_kernel_use_old_abi = 0;
+ goto end;
+ }
+ lttng_kernel_use_old_abi = 1;
+ }
+ if (lttng_kernel_use_old_abi) {
+ ret = ioctl(fd, oldname);
+ } else {
+ ret = ioctl(fd, newname);
+ }
+
+end:
+ return ret;
+}
+
int kernctl_create_session(int fd)
{
- return ioctl(fd, LTTNG_KERNEL_SESSION);
+ return compat_ioctl_no_arg(fd, LTTNG_KERNEL_OLD_SESSION,
+ LTTNG_KERNEL_SESSION);
}
/* open the metadata global channel */
int kernctl_open_metadata(int fd, struct lttng_channel_attr *chops)
{
- return ioctl(fd, LTTNG_KERNEL_METADATA, chops);
+ struct lttng_kernel_old_channel old_channel;
+ struct lttng_kernel_channel channel;
+
+ if (lttng_kernel_use_old_abi) {
+ old_channel.overwrite = chops->overwrite;
+ old_channel.subbuf_size = chops->subbuf_size;
+ old_channel.num_subbuf = chops->num_subbuf;
+ old_channel.switch_timer_interval = chops->switch_timer_interval;
+ old_channel.read_timer_interval = chops->read_timer_interval;
+ old_channel.output = chops->output;
+ memcpy(old_channel.padding, chops->padding, sizeof(old_channel.padding));
+
+ return ioctl(fd, LTTNG_KERNEL_OLD_METADATA, &old_channel);
+ }
+
+ channel.overwrite = chops->overwrite;
+ channel.subbuf_size = chops->subbuf_size;
+ channel.num_subbuf = chops->num_subbuf;
+ channel.switch_timer_interval = chops->switch_timer_interval;
+ channel.read_timer_interval = chops->read_timer_interval;
+ channel.output = chops->output;
+ memcpy(channel.padding, chops->padding, sizeof(channel.padding));
+
+ return ioctl(fd, LTTNG_KERNEL_METADATA, &channel);
}
int kernctl_create_channel(int fd, struct lttng_channel_attr *chops)
{
- return ioctl(fd, LTTNG_KERNEL_CHANNEL, chops);
+ struct lttng_kernel_channel channel;
+
+ if (lttng_kernel_use_old_abi) {
+ struct lttng_kernel_old_channel old_channel;
+
+ old_channel.overwrite = chops->overwrite;
+ old_channel.subbuf_size = chops->subbuf_size;
+ old_channel.num_subbuf = chops->num_subbuf;
+ old_channel.switch_timer_interval = chops->switch_timer_interval;
+ old_channel.read_timer_interval = chops->read_timer_interval;
+ old_channel.output = chops->output;
+ memcpy(old_channel.padding, chops->padding, sizeof(old_channel.padding));
+
+ return ioctl(fd, LTTNG_KERNEL_OLD_CHANNEL, &old_channel);
+ }
+
+ channel.overwrite = chops->overwrite;
+ channel.subbuf_size = chops->subbuf_size;
+ channel.num_subbuf = chops->num_subbuf;
+ channel.switch_timer_interval = chops->switch_timer_interval;
+ channel.read_timer_interval = chops->read_timer_interval;
+ channel.output = chops->output;
+ memcpy(channel.padding, chops->padding, sizeof(channel.padding));
+
+ return ioctl(fd, LTTNG_KERNEL_CHANNEL, &channel);
}
int kernctl_create_stream(int fd)
{
- return ioctl(fd, LTTNG_KERNEL_STREAM);
+ return compat_ioctl_no_arg(fd, LTTNG_KERNEL_OLD_STREAM,
+ LTTNG_KERNEL_STREAM);
}
int kernctl_create_event(int fd, struct lttng_kernel_event *ev)
{
+ if (lttng_kernel_use_old_abi) {
+ struct lttng_kernel_old_event old_event;
+
+ memcpy(old_event.name, ev->name, sizeof(old_event.name));
+ old_event.instrumentation = ev->instrumentation;
+ switch (ev->instrumentation) {
+ case LTTNG_KERNEL_KPROBE:
+ old_event.u.kprobe.addr = ev->u.kprobe.addr;
+ old_event.u.kprobe.offset = ev->u.kprobe.offset;
+ memcpy(old_event.u.kprobe.symbol_name,
+ ev->u.kprobe.symbol_name,
+ sizeof(old_event.u.kprobe.symbol_name));
+ break;
+ case LTTNG_KERNEL_KRETPROBE:
+ old_event.u.kretprobe.addr = ev->u.kretprobe.addr;
+ old_event.u.kretprobe.offset = ev->u.kretprobe.offset;
+ memcpy(old_event.u.kretprobe.symbol_name,
+ ev->u.kretprobe.symbol_name,
+ sizeof(old_event.u.kretprobe.symbol_name));
+ break;
+ case LTTNG_KERNEL_FUNCTION:
+ memcpy(old_event.u.ftrace.symbol_name,
+ ev->u.ftrace.symbol_name,
+ sizeof(old_event.u.ftrace.symbol_name));
+ break;
+ default:
+ break;
+ }
+
+ return ioctl(fd, LTTNG_KERNEL_OLD_EVENT, &old_event);
+ }
return ioctl(fd, LTTNG_KERNEL_EVENT, ev);
}
int kernctl_add_context(int fd, struct lttng_kernel_context *ctx)
{
+ if (lttng_kernel_use_old_abi) {
+ struct lttng_kernel_old_context old_ctx;
+
+ old_ctx.ctx = ctx->ctx;
+ /* only type that uses the union */
+ if (ctx->ctx == LTTNG_KERNEL_CONTEXT_PERF_COUNTER) {
+ old_ctx.u.perf_counter.type =
+ ctx->u.perf_counter.type;
+ old_ctx.u.perf_counter.config =
+ ctx->u.perf_counter.config;
+ memcpy(old_ctx.u.perf_counter.name,
+ ctx->u.perf_counter.name,
+ sizeof(old_ctx.u.perf_counter.name));
+ }
+ return ioctl(fd, LTTNG_KERNEL_OLD_CONTEXT, &old_ctx);
+ }
return ioctl(fd, LTTNG_KERNEL_CONTEXT, ctx);
}
/* Enable event, channel and session ioctl */
int kernctl_enable(int fd)
{
- return ioctl(fd, LTTNG_KERNEL_ENABLE);
+ return compat_ioctl_no_arg(fd, LTTNG_KERNEL_OLD_ENABLE,
+ LTTNG_KERNEL_ENABLE);
}
/* Disable event, channel and session ioctl */
int kernctl_disable(int fd)
{
- return ioctl(fd, LTTNG_KERNEL_DISABLE);
+ return compat_ioctl_no_arg(fd, LTTNG_KERNEL_OLD_DISABLE,
+ LTTNG_KERNEL_DISABLE);
}
int kernctl_start_session(int fd)
{
- return ioctl(fd, LTTNG_KERNEL_SESSION_START);
+ return compat_ioctl_no_arg(fd, LTTNG_KERNEL_OLD_SESSION_START,
+ LTTNG_KERNEL_SESSION_START);
}
int kernctl_stop_session(int fd)
{
- return ioctl(fd, LTTNG_KERNEL_SESSION_STOP);
+ return compat_ioctl_no_arg(fd, LTTNG_KERNEL_OLD_SESSION_STOP,
+ LTTNG_KERNEL_SESSION_STOP);
}
-
int kernctl_tracepoint_list(int fd)
{
- return ioctl(fd, LTTNG_KERNEL_TRACEPOINT_LIST);
+ return compat_ioctl_no_arg(fd, LTTNG_KERNEL_OLD_TRACEPOINT_LIST,
+ LTTNG_KERNEL_TRACEPOINT_LIST);
}
int kernctl_tracer_version(int fd, struct lttng_kernel_tracer_version *v)
{
- return ioctl(fd, LTTNG_KERNEL_TRACER_VERSION, v);
+ int ret;
+
+ if (lttng_kernel_use_old_abi == -1) {
+ ret = ioctl(fd, LTTNG_KERNEL_TRACER_VERSION, v);
+ if (!ret) {
+ lttng_kernel_use_old_abi = 0;
+ goto end;
+ }
+ lttng_kernel_use_old_abi = 1;
+ }
+ if (lttng_kernel_use_old_abi) {
+ struct lttng_kernel_old_tracer_version old_v;
+
+ ret = ioctl(fd, LTTNG_KERNEL_OLD_TRACER_VERSION, &old_v);
+ if (ret) {
+ goto end;
+ }
+ v->major = old_v.major;
+ v->minor = old_v.minor;
+ v->patchlevel = old_v.patchlevel;
+ } else {
+ ret = ioctl(fd, LTTNG_KERNEL_TRACER_VERSION, v);
+ }
+
+end:
+ return ret;
}
int kernctl_wait_quiescent(int fd)
{
- return ioctl(fd, LTTNG_KERNEL_WAIT_QUIESCENT);
+ return compat_ioctl_no_arg(fd, LTTNG_KERNEL_OLD_WAIT_QUIESCENT,
+ LTTNG_KERNEL_WAIT_QUIESCENT);
}
int kernctl_calibrate(int fd, struct lttng_kernel_calibrate *calibrate)
{
- return ioctl(fd, LTTNG_KERNEL_CALIBRATE, calibrate);
+ int ret;
+
+ if (lttng_kernel_use_old_abi == -1) {
+ ret = ioctl(fd, LTTNG_KERNEL_CALIBRATE, calibrate);
+ if (!ret) {
+ lttng_kernel_use_old_abi = 0;
+ goto end;
+ }
+ lttng_kernel_use_old_abi = 1;
+ }
+ if (lttng_kernel_use_old_abi) {
+ struct lttng_kernel_old_calibrate old_calibrate;
+
+ old_calibrate.type = calibrate->type;
+ ret = ioctl(fd, LTTNG_KERNEL_OLD_CALIBRATE, &old_calibrate);
+ if (ret) {
+ goto end;
+ }
+ calibrate->type = old_calibrate.type;
+ } else {
+ ret = ioctl(fd, LTTNG_KERNEL_CALIBRATE, calibrate);
+ }
+
+end:
+ return ret;
}
{
return ioctl(fd, RING_BUFFER_SET_STREAM_ID, stream_id);
}
-
-/* Get the offset of the stream_id in the packet header */
-int kernctl_get_net_stream_id_offset(int fd, unsigned long *offset)
-{
- return ioctl(fd, LTTNG_KERNEL_STREAM_ID_OFFSET, offset);
-
-}
#include <lttng/lttng.h>
#include <common/lttng-kernel.h>
+#include <common/lttng-kernel-old.h>
int kernctl_create_session(int fd);
int kernctl_open_metadata(int fd, struct lttng_channel_attr *chops);
/* map stream to stream id for network streaming */
#define RING_BUFFER_SET_STREAM_ID _IOW(0xF6, 0x0D, unsigned long)
+/* Old ABI (without support for 32/64 bits compat) */
+/* LTTng file descriptor ioctl */
+#define LTTNG_KERNEL_OLD_SESSION _IO(0xF6, 0x40)
+#define LTTNG_KERNEL_OLD_TRACER_VERSION \
+ _IOR(0xF6, 0x41, struct lttng_kernel_old_tracer_version)
+#define LTTNG_KERNEL_OLD_TRACEPOINT_LIST _IO(0xF6, 0x42)
+#define LTTNG_KERNEL_OLD_WAIT_QUIESCENT _IO(0xF6, 0x43)
+#define LTTNG_KERNEL_OLD_CALIBRATE \
+ _IOWR(0xF6, 0x44, struct lttng_kernel_old_calibrate)
+
+/* Session FD ioctl */
+#define LTTNG_KERNEL_OLD_METADATA \
+ _IOW(0xF6, 0x50, struct lttng_kernel_old_channel)
+#define LTTNG_KERNEL_OLD_CHANNEL \
+ _IOW(0xF6, 0x51, struct lttng_kernel_old_channel)
+#define LTTNG_KERNEL_OLD_SESSION_START _IO(0xF6, 0x52)
+#define LTTNG_KERNEL_OLD_SESSION_STOP _IO(0xF6, 0x53)
+
+/* Channel FD ioctl */
+#define LTTNG_KERNEL_OLD_STREAM _IO(0xF6, 0x60)
+#define LTTNG_KERNEL_OLD_EVENT \
+ _IOW(0xF6, 0x61, struct lttng_kernel_old_event)
+#define LTTNG_KERNEL_OLD_STREAM_ID_OFFSET \
+ _IOR(0xF6, 0x62, unsigned long)
+/* Event and Channel FD ioctl */
+#define LTTNG_KERNEL_OLD_CONTEXT \
+ _IOW(0xF6, 0x70, struct lttng_kernel_old_context)
+
+/* Event, Channel and Session ioctl */
+#define LTTNG_KERNEL_OLD_ENABLE _IO(0xF6, 0x80)
+#define LTTNG_KERNEL_OLD_DISABLE _IO(0xF6, 0x81)
+
+
+/* Current ABI (with suport for 32/64 bits compat) */
/* LTTng file descriptor ioctl */
-#define LTTNG_KERNEL_SESSION _IO(0xF6, 0x40)
-#define LTTNG_KERNEL_TRACER_VERSION \
- _IOR(0xF6, 0x41, struct lttng_kernel_tracer_version)
-#define LTTNG_KERNEL_TRACEPOINT_LIST _IO(0xF6, 0x42)
-#define LTTNG_KERNEL_WAIT_QUIESCENT _IO(0xF6, 0x43)
+#define LTTNG_KERNEL_SESSION _IO(0xF6, 0x45)
+#define LTTNG_KERNEL_TRACER_VERSION \
+ _IOR(0xF6, 0x46, struct lttng_kernel_tracer_version)
+#define LTTNG_KERNEL_TRACEPOINT_LIST _IO(0xF6, 0x47)
+#define LTTNG_KERNEL_WAIT_QUIESCENT _IO(0xF6, 0x48)
#define LTTNG_KERNEL_CALIBRATE \
- _IOWR(0xF6, 0x44, struct lttng_kernel_calibrate)
+ _IOWR(0xF6, 0x49, struct lttng_kernel_calibrate)
/* Session FD ioctl */
-#define LTTNG_KERNEL_METADATA \
- _IOW(0xF6, 0x50, struct lttng_channel_attr)
-#define LTTNG_KERNEL_CHANNEL \
- _IOW(0xF6, 0x51, struct lttng_channel_attr)
-#define LTTNG_KERNEL_SESSION_START _IO(0xF6, 0x52)
-#define LTTNG_KERNEL_SESSION_STOP _IO(0xF6, 0x53)
+#define LTTNG_KERNEL_METADATA \
+ _IOW(0xF6, 0x54, struct lttng_kernel_channel)
+#define LTTNG_KERNEL_CHANNEL \
+ _IOW(0xF6, 0x55, struct lttng_kernel_channel)
+#define LTTNG_KERNEL_SESSION_START _IO(0xF6, 0x56)
+#define LTTNG_KERNEL_SESSION_STOP _IO(0xF6, 0x57)
/* Channel FD ioctl */
-#define LTTNG_KERNEL_STREAM _IO(0xF6, 0x60)
-#define LTTNG_KERNEL_EVENT \
- _IOW(0xF6, 0x61, struct lttng_kernel_event)
-#define LTTNG_KERNEL_STREAM_ID_OFFSET \
- _IOR(0xF6, 0x62, unsigned long)
+#define LTTNG_KERNEL_STREAM _IO(0xF6, 0x62)
+#define LTTNG_KERNEL_EVENT \
+ _IOW(0xF6, 0x63, struct lttng_kernel_event)
/* Event and Channel FD ioctl */
-#define LTTNG_KERNEL_CONTEXT \
- _IOW(0xF6, 0x70, struct lttng_kernel_context)
+#define LTTNG_KERNEL_CONTEXT \
+ _IOW(0xF6, 0x71, struct lttng_kernel_context)
/* Event, Channel and Session ioctl */
-#define LTTNG_KERNEL_ENABLE _IO(0xF6, 0x80)
-#define LTTNG_KERNEL_DISABLE _IO(0xF6, 0x81)
+#define LTTNG_KERNEL_ENABLE _IO(0xF6, 0x82)
+#define LTTNG_KERNEL_DISABLE _IO(0xF6, 0x83)
#endif /* _LTT_KERNEL_IOCTL_H */
--- /dev/null
+/*
+ * Copyright (C) 2011 - Julien Desfossez <julien.desfossez@polymtl.ca>
+ * Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * David Goulet <david.goulet@polymtl.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _LTTNG_KERNEL_OLD_H
+#define _LTTNG_KERNEL_OLD_H
+
+#include <stdint.h>
+#include <common/lttng-kernel.h>
+
+/*
+ * LTTng DebugFS ABI structures.
+ *
+ * This is the kernel ABI copied from lttng-modules tree.
+ */
+
+/* Perf counter attributes */
+struct lttng_kernel_old_perf_counter_ctx {
+ uint32_t type;
+ uint64_t config;
+ char name[LTTNG_KERNEL_SYM_NAME_LEN];
+};
+
+/* Event/Channel context */
+#define LTTNG_KERNEL_OLD_CONTEXT_PADDING1 16
+#define LTTNG_KERNEL_OLD_CONTEXT_PADDING2 LTTNG_KERNEL_SYM_NAME_LEN + 32
+struct lttng_kernel_old_context {
+ enum lttng_kernel_context_type ctx;
+ char padding[LTTNG_KERNEL_OLD_CONTEXT_PADDING1];
+
+ union {
+ struct lttng_kernel_old_perf_counter_ctx perf_counter;
+ char padding[LTTNG_KERNEL_OLD_CONTEXT_PADDING2];
+ } u;
+};
+
+struct lttng_kernel_old_kretprobe {
+ uint64_t addr;
+
+ uint64_t offset;
+ char symbol_name[LTTNG_KERNEL_SYM_NAME_LEN];
+};
+
+/*
+ * Either addr is used, or symbol_name and offset.
+ */
+struct lttng_kernel_old_kprobe {
+ uint64_t addr;
+
+ uint64_t offset;
+ char symbol_name[LTTNG_KERNEL_SYM_NAME_LEN];
+};
+
+/* Function tracer */
+struct lttng_kernel_old_function {
+ char symbol_name[LTTNG_KERNEL_SYM_NAME_LEN];
+};
+
+#define LTTNG_KERNEL_OLD_EVENT_PADDING1 16
+#define LTTNG_KERNEL_OLD_EVENT_PADDING2 LTTNG_KERNEL_SYM_NAME_LEN + 32
+struct lttng_kernel_old_event {
+ char name[LTTNG_KERNEL_SYM_NAME_LEN];
+ enum lttng_kernel_instrumentation instrumentation;
+ char padding[LTTNG_KERNEL_OLD_EVENT_PADDING1];
+
+ /* Per instrumentation type configuration */
+ union {
+ struct lttng_kernel_old_kretprobe kretprobe;
+ struct lttng_kernel_old_kprobe kprobe;
+ struct lttng_kernel_old_function ftrace;
+ char padding[LTTNG_KERNEL_OLD_EVENT_PADDING2];
+ } u;
+};
+
+struct lttng_kernel_old_tracer_version {
+ uint32_t major;
+ uint32_t minor;
+ uint32_t patchlevel;
+};
+
+struct lttng_kernel_old_calibrate {
+ enum lttng_kernel_calibrate_type type; /* type (input) */
+};
+
+/*
+ * kernel channel
+ */
+#define LTTNG_KERNEL_OLD_CHANNEL_PADDING1 LTTNG_SYMBOL_NAME_LEN + 32
+struct lttng_kernel_old_channel {
+ int overwrite; /* 1: overwrite, 0: discard */
+ uint64_t subbuf_size; /* bytes */
+ uint64_t num_subbuf; /* power of 2 */
+ unsigned int switch_timer_interval; /* usec */
+ unsigned int read_timer_interval; /* usec */
+ enum lttng_event_output output; /* splice, mmap */
+
+ char padding[LTTNG_KERNEL_OLD_CHANNEL_PADDING1];
+};
+
+#endif /* _LTTNG_KERNEL_OLD_H */
uint32_t type;
uint64_t config;
char name[LTTNG_KERNEL_SYM_NAME_LEN];
-};
+}__attribute__((packed));
/* Event/Channel context */
#define LTTNG_KERNEL_CONTEXT_PADDING1 16
struct lttng_kernel_perf_counter_ctx perf_counter;
char padding[LTTNG_KERNEL_CONTEXT_PADDING2];
} u;
-};
+}__attribute__((packed));
struct lttng_kernel_kretprobe {
uint64_t addr;
uint64_t offset;
char symbol_name[LTTNG_KERNEL_SYM_NAME_LEN];
-};
+}__attribute__((packed));
/*
* Either addr is used, or symbol_name and offset.
uint64_t offset;
char symbol_name[LTTNG_KERNEL_SYM_NAME_LEN];
-};
+}__attribute__((packed));
/* Function tracer */
struct lttng_kernel_function {
char symbol_name[LTTNG_KERNEL_SYM_NAME_LEN];
-};
+}__attribute__((packed));
#define LTTNG_KERNEL_EVENT_PADDING1 16
#define LTTNG_KERNEL_EVENT_PADDING2 LTTNG_KERNEL_SYM_NAME_LEN + 32
struct lttng_kernel_function ftrace;
char padding[LTTNG_KERNEL_EVENT_PADDING2];
} u;
-};
+}__attribute__((packed));
struct lttng_kernel_tracer_version {
uint32_t major;
uint32_t minor;
uint32_t patchlevel;
-};
+}__attribute__((packed));
enum lttng_kernel_calibrate_type {
LTTNG_KERNEL_CALIBRATE_KRETPROBE,
struct lttng_kernel_calibrate {
enum lttng_kernel_calibrate_type type; /* type (input) */
-};
+}__attribute__((packed));
+
+/*
+ * kernel channel
+ */
+#define LTTNG_KERNEL_CHANNEL_PADDING1 LTTNG_SYMBOL_NAME_LEN + 32
+struct lttng_kernel_channel {
+ uint64_t subbuf_size; /* bytes */
+ uint64_t num_subbuf; /* power of 2 */
+ unsigned int switch_timer_interval; /* usec */
+ unsigned int read_timer_interval; /* usec */
+ enum lttng_event_output output; /* splice, mmap */
+
+ int overwrite; /* 1: overwrite, 0: discard */
+ char padding[LTTNG_KERNEL_CHANNEL_PADDING1];
+}__attribute__((packed));
#endif /* _LTTNG_KERNEL_H */