X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=lttng-abi.c;h=d4c5ea0fc8938d1d31b6639357546b24a5d19ffa;hb=f127e61ee231d002fb9a7803643a157e06f6d2e2;hp=261a0ad3f8a1bf0ae4af6e76c9a2a246115589b4;hpb=dd5a0db3ea07c46bee3c1814ef7326736f38a06e;p=lttng-modules.git diff --git a/lttng-abi.c b/lttng-abi.c index 261a0ad3..d4c5ea0f 100644 --- a/lttng-abi.c +++ b/lttng-abi.c @@ -49,6 +49,7 @@ #include "wrapper/ringbuffer/backend.h" #include "wrapper/ringbuffer/frontend.h" #include "wrapper/poll.h" +#include "wrapper/file.h" #include "lttng-abi.h" #include "lttng-abi-old.h" #include "lttng-events.h" @@ -83,7 +84,7 @@ int lttng_abi_create_session(void) session = lttng_session_create(); if (!session) return -ENOMEM; - session_fd = get_unused_fd(); + session_fd = lttng_get_unused_fd(); if (session_fd < 0) { ret = session_fd; goto fd_error; @@ -112,13 +113,13 @@ int lttng_abi_tracepoint_list(void) struct file *tracepoint_list_file; int file_fd, ret; - file_fd = get_unused_fd(); + file_fd = lttng_get_unused_fd(); if (file_fd < 0) { ret = file_fd; goto fd_error; } - tracepoint_list_file = anon_inode_getfile("[lttng_session]", + tracepoint_list_file = anon_inode_getfile("[lttng_tracepoint_list]", <tng_tracepoint_list_fops, NULL, O_RDWR); if (IS_ERR(tracepoint_list_file)) { @@ -143,6 +144,51 @@ fd_error: return ret; } +#ifndef CONFIG_HAVE_SYSCALL_TRACEPOINTS +static inline +int lttng_abi_syscall_list(void) +{ + return -ENOSYS; +} +#else +static +int lttng_abi_syscall_list(void) +{ + struct file *syscall_list_file; + int file_fd, ret; + + file_fd = lttng_get_unused_fd(); + if (file_fd < 0) { + ret = file_fd; + goto fd_error; + } + + syscall_list_file = anon_inode_getfile("[lttng_syscall_list]", + <tng_syscall_list_fops, + NULL, O_RDWR); + if (IS_ERR(syscall_list_file)) { + ret = PTR_ERR(syscall_list_file); + goto file_error; + } + ret = lttng_syscall_list_fops.open(NULL, syscall_list_file); + if (ret < 0) + goto open_error; + fd_install(file_fd, syscall_list_file); + if (file_fd < 0) { + ret = file_fd; + goto fd_error; + } + return file_fd; + +open_error: + fput(syscall_list_file); +file_error: + put_unused_fd(file_fd); +fd_error: + return ret; +} +#endif + static void lttng_abi_tracer_version(struct lttng_kernel_tracer_version *v) { @@ -151,6 +197,13 @@ void lttng_abi_tracer_version(struct lttng_kernel_tracer_version *v) v->patchlevel = LTTNG_MODULES_PATCHLEVEL_VERSION; } +static +void lttng_abi_tracer_abi_version(struct lttng_kernel_tracer_abi_version *v) +{ + v->major = LTTNG_MODULES_ABI_MAJOR_VERSION; + v->minor = LTTNG_MODULES_ABI_MINOR_VERSION; +} + static long lttng_abi_add_context(struct file *file, struct lttng_kernel_context *context_param, @@ -208,6 +261,8 @@ long lttng_abi_add_context(struct file *file, * Returns a file descriptor listing available tracepoints * LTTNG_KERNEL_WAIT_QUIESCENT * Returns after all previously running probes have completed + * LTTNG_KERNEL_TRACER_ABI_VERSION + * Returns the LTTng kernel tracer ABI version * * The returned session will be deleted when its file descriptor is closed. */ @@ -241,7 +296,19 @@ long lttng_ioctl(struct file *file, unsigned int cmd, unsigned long arg) (struct lttng_kernel_tracer_version __user *) arg; lttng_abi_tracer_version(&version); - + + if (copy_to_user(uversion, &version, sizeof(version))) + return -EFAULT; + return 0; + } + case LTTNG_KERNEL_TRACER_ABI_VERSION: + { + struct lttng_kernel_tracer_abi_version version; + struct lttng_kernel_tracer_abi_version *uversion = + (struct lttng_kernel_tracer_abi_version __user *) arg; + + lttng_abi_tracer_abi_version(&version); + if (copy_to_user(uversion, &version, sizeof(version))) return -EFAULT; return 0; @@ -249,6 +316,8 @@ long lttng_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case LTTNG_KERNEL_OLD_TRACEPOINT_LIST: case LTTNG_KERNEL_TRACEPOINT_LIST: return lttng_abi_tracepoint_list(); + case LTTNG_KERNEL_SYSCALL_LIST: + return lttng_abi_syscall_list(); case LTTNG_KERNEL_OLD_WAIT_QUIESCENT: case LTTNG_KERNEL_WAIT_QUIESCENT: synchronize_trace(); @@ -309,7 +378,7 @@ int lttng_abi_create_channel(struct file *session_file, int chan_fd; int ret = 0; - chan_fd = get_unused_fd(); + chan_fd = lttng_get_unused_fd(); if (chan_fd < 0) { ret = chan_fd; goto fd_error; @@ -399,6 +468,10 @@ fd_error: * Disables tracing for a session (strong disable) * LTTNG_KERNEL_METADATA * Returns a LTTng metadata file descriptor + * LTTNG_KERNEL_SESSION_TRACK_PID + * Add PID to session tracker + * LTTNG_KERNEL_SESSION_UNTRACK_PID + * Remove PID from session tracker * * The returned channel will be deleted when its file descriptor is closed. */ @@ -478,6 +551,12 @@ long lttng_session_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return lttng_abi_create_channel(file, &chan_param, METADATA_CHANNEL); } + case LTTNG_KERNEL_SESSION_TRACK_PID: + return lttng_session_track_pid(session, (int) arg); + case LTTNG_KERNEL_SESSION_UNTRACK_PID: + return lttng_session_untrack_pid(session, (int) arg); + case LTTNG_KERNEL_SESSION_LIST_TRACKER_PIDS: + return lttng_session_list_tracker_pids(session); default: return -ENOIOCTLCMD; } @@ -760,7 +839,7 @@ int lttng_abi_create_stream_fd(struct file *channel_file, void *stream_priv, int stream_fd, ret; struct file *stream_file; - stream_fd = get_unused_fd(); + stream_fd = lttng_get_unused_fd(); if (stream_fd < 0) { ret = stream_fd; goto fd_error; @@ -841,6 +920,7 @@ int lttng_abi_open_metadata_stream(struct file *channel_file) metadata_stream->priv = buf; stream_priv = metadata_stream; metadata_stream->transport = channel->transport; + mutex_init(&metadata_stream->lock); /* * Since life-time of metadata cache differs from that of @@ -876,9 +956,9 @@ int lttng_abi_create_event(struct file *channel_file, struct lttng_kernel_event *event_param) { struct lttng_channel *channel = channel_file->private_data; - struct lttng_event *event; int event_fd, ret; struct file *event_file; + void *priv; event_param->name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; switch (event_param->instrumentation) { @@ -894,47 +974,51 @@ int lttng_abi_create_event(struct file *channel_file, default: break; } - switch (event_param->instrumentation) { - default: - event_fd = get_unused_fd(); - if (event_fd < 0) { - ret = event_fd; - goto fd_error; - } - event_file = anon_inode_getfile("[lttng_event]", - <tng_event_fops, - NULL, O_RDWR); - if (IS_ERR(event_file)) { - ret = PTR_ERR(event_file); - goto file_error; + event_fd = lttng_get_unused_fd(); + if (event_fd < 0) { + ret = event_fd; + goto fd_error; + } + event_file = anon_inode_getfile("[lttng_event]", + <tng_event_fops, + NULL, O_RDWR); + if (IS_ERR(event_file)) { + ret = PTR_ERR(event_file); + goto file_error; + } + if (event_param->instrumentation == LTTNG_KERNEL_TRACEPOINT + || event_param->instrumentation == LTTNG_KERNEL_SYSCALL) { + struct lttng_enabler *enabler; + + if (event_param->name[strlen(event_param->name) - 1] == '*') { + enabler = lttng_enabler_create(LTTNG_ENABLER_WILDCARD, + event_param, channel); + } else { + enabler = lttng_enabler_create(LTTNG_ENABLER_NAME, + event_param, channel); } + priv = enabler; + } else { + struct lttng_event *event; + /* * We tolerate no failure path after event creation. It * will stay invariant for the rest of the session. */ - event = lttng_event_create(channel, event_param, NULL, NULL); + event = lttng_event_create(channel, event_param, + NULL, NULL, + event_param->instrumentation); WARN_ON_ONCE(!event); if (IS_ERR(event)) { ret = PTR_ERR(event); goto event_error; } - event_file->private_data = event; - fd_install(event_fd, event_file); - /* The event holds a reference on the channel */ - atomic_long_inc(&channel_file->f_count); - break; - case LTTNG_KERNEL_SYSCALL: - /* - * Only all-syscall tracing supported for now. - */ - if (event_param->name[0] != '\0') - return -EINVAL; - ret = lttng_syscalls_register(channel, NULL); - if (ret) - goto fd_error; - event_fd = 0; - break; + priv = event; } + event_file->private_data = priv; + fd_install(event_fd, event_file); + /* The event holds a reference on the channel */ + atomic_long_inc(&channel_file->f_count); return event_fd; event_error: @@ -1121,6 +1205,9 @@ old_ctx_end: case LTTNG_KERNEL_OLD_DISABLE: case LTTNG_KERNEL_DISABLE: return lttng_channel_disable(channel); + case LTTNG_KERNEL_SYSCALL_MASK: + return lttng_channel_syscall_mask(channel, + (struct lttng_kernel_syscall_mask __user *) arg); default: return -ENOIOCTLCMD; } @@ -1240,77 +1327,59 @@ static const struct file_operations lttng_metadata_fops = { static long lttng_event_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct lttng_event *event = file->private_data; + struct lttng_event *event; + struct lttng_enabler *enabler; + enum lttng_event_type *evtype = file->private_data; switch (cmd) { case LTTNG_KERNEL_OLD_CONTEXT: { - struct lttng_kernel_context *ucontext_param; - struct lttng_kernel_old_context *old_ucontext_param; - int ret; - - ucontext_param = kmalloc(sizeof(struct lttng_kernel_context), - GFP_KERNEL); - if (!ucontext_param) { - ret = -ENOMEM; - goto old_ctx_end; - } - old_ucontext_param = kmalloc(sizeof(struct lttng_kernel_old_context), - GFP_KERNEL); - if (!old_ucontext_param) { - ret = -ENOMEM; - goto old_ctx_error_free_param; - } - - if (copy_from_user(old_ucontext_param, - (struct lttng_kernel_old_context __user *) arg, - sizeof(struct lttng_kernel_old_context))) { - ret = -EFAULT; - goto old_ctx_error_free_old_param; - } - ucontext_param->ctx = old_ucontext_param->ctx; - memcpy(ucontext_param->padding, old_ucontext_param->padding, - sizeof(ucontext_param->padding)); - /* only type that uses the union */ - if (old_ucontext_param->ctx == LTTNG_KERNEL_CONTEXT_PERF_COUNTER) { - ucontext_param->u.perf_counter.type = - old_ucontext_param->u.perf_counter.type; - ucontext_param->u.perf_counter.config = - old_ucontext_param->u.perf_counter.config; - memcpy(ucontext_param->u.perf_counter.name, - old_ucontext_param->u.perf_counter.name, - sizeof(ucontext_param->u.perf_counter.name)); - } - - ret = lttng_abi_add_context(file, - ucontext_param, - &event->ctx, event->chan->session); - -old_ctx_error_free_old_param: - kfree(old_ucontext_param); -old_ctx_error_free_param: - kfree(ucontext_param); -old_ctx_end: - return ret; + /* Not implemented */ + return -ENOSYS; } case LTTNG_KERNEL_CONTEXT: { - struct lttng_kernel_context ucontext_param; - - if (copy_from_user(&ucontext_param, - (struct lttng_kernel_context __user *) arg, - sizeof(ucontext_param))) - return -EFAULT; - return lttng_abi_add_context(file, - &ucontext_param, - &event->ctx, event->chan->session); + /* Not implemented */ + return -ENOSYS; } case LTTNG_KERNEL_OLD_ENABLE: case LTTNG_KERNEL_ENABLE: - return lttng_event_enable(event); + switch (*evtype) { + case LTTNG_TYPE_EVENT: + event = file->private_data; + return lttng_event_enable(event); + case LTTNG_TYPE_ENABLER: + enabler = file->private_data; + return lttng_enabler_enable(enabler); + default: + WARN_ON_ONCE(1); + return -ENOSYS; + } case LTTNG_KERNEL_OLD_DISABLE: case LTTNG_KERNEL_DISABLE: - return lttng_event_disable(event); + switch (*evtype) { + case LTTNG_TYPE_EVENT: + event = file->private_data; + return lttng_event_disable(event); + case LTTNG_TYPE_ENABLER: + enabler = file->private_data; + return lttng_enabler_disable(enabler); + default: + WARN_ON_ONCE(1); + return -ENOSYS; + } + case LTTNG_KERNEL_FILTER: + switch (*evtype) { + case LTTNG_TYPE_EVENT: + return -EINVAL; + case LTTNG_TYPE_ENABLER: + { + enabler = file->private_data; + return lttng_enabler_attach_bytecode(enabler, + (struct lttng_kernel_filter_bytecode __user *) arg); + } + + } default: return -ENOIOCTLCMD; } @@ -1319,10 +1388,29 @@ old_ctx_end: static int lttng_event_release(struct inode *inode, struct file *file) { - struct lttng_event *event = file->private_data; + struct lttng_event *event; + struct lttng_enabler *enabler; + enum lttng_event_type *evtype = file->private_data; + + if (!evtype) + return 0; + + switch (*evtype) { + case LTTNG_TYPE_EVENT: + event = file->private_data; + if (event) + fput(event->chan->file); + break; + case LTTNG_TYPE_ENABLER: + enabler = file->private_data; + if (enabler) + fput(enabler->chan->file); + break; + default: + WARN_ON_ONCE(1); + break; + } - if (event) - fput(event->chan->file); return 0; } @@ -1555,7 +1643,8 @@ error: return ret; } -void __exit lttng_abi_exit(void) +/* No __exit annotation because used by init error path too. */ +void lttng_abi_exit(void) { if (lttng_proc_dentry) remove_proc_entry("lttng", NULL);