Implement filtering infrastructure
[lttng-modules.git] / lttng-abi.c
index ab0a11286c7ba75f423e430085b616c0df4e76b0..beaad907d072ca5db410d8fc2a23e1feb0d17a25 100644 (file)
@@ -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,7 +113,7 @@ 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;
@@ -143,43 +144,6 @@ fd_error:
        return ret;
 }
 
-static
-int lttng_abi_syscall_list(void)
-{
-       struct file *syscall_list_file;
-       int file_fd, ret;
-
-       file_fd = get_unused_fd();
-       if (file_fd < 0) {
-               ret = file_fd;
-               goto fd_error;
-       }
-
-       syscall_list_file = anon_inode_getfile("[lttng_syscall_list]",
-                                         &lttng_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;
-}
-
 static
 void lttng_abi_tracer_version(struct lttng_kernel_tracer_version *v)
 {
@@ -188,6 +152,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,
@@ -245,6 +216,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.
  */
@@ -278,7 +251,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;
@@ -348,7 +333,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;
@@ -438,6 +423,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.
  */
@@ -517,6 +506,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;
        }
@@ -799,7 +794,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;
@@ -916,9 +911,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) {
@@ -934,55 +929,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]",
-                                               &lttng_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]",
+                                       &lttng_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:
-               ret = lttng_syscalls_register(channel, NULL);
-               if (ret)
-                       goto fd_error;
-               event_fd = 0;
-               if (event_param->u.syscall.disable) {
-                       ret = lttng_syscall_filter_disable(channel,
-                               event_param->name[0] == '\0' ?
-                                       NULL : event_param->name);
-                       if (ret)
-                               goto fd_error;
-               } else {
-                       ret = lttng_syscall_filter_enable(channel,
-                               event_param->name[0] == '\0' ?
-                                       NULL : event_param->name);
-                       if (ret)
-                               goto fd_error;
-               }
-               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:
@@ -1169,6 +1160,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;
        }
@@ -1288,77 +1282,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;
        }
@@ -1367,10 +1343,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;
 }
 
This page took 0.02664 seconds and 4 git commands to generate.