fix: Add a 1MB limit to lttng_strlen_user_inatomic
[lttng-modules.git] / src / lttng-events.c
index 6bef77c934ccc765418a5ed9d9d2a6be4bfe4082..5023d450b1bd77f50969776c32b8e2735a192317 100644 (file)
@@ -205,6 +205,10 @@ void lttng_session_destroy(struct lttng_session *session)
                WARN_ON(ret);
        }
        synchronize_trace();    /* Wait for in-flight events to complete */
+       list_for_each_entry(chan, &session->chan, list) {
+               ret = lttng_syscalls_destroy(chan);
+               WARN_ON(ret);
+       }
        list_for_each_entry_safe(enabler, tmpenabler,
                        &session->enablers_head, node)
                lttng_enabler_destroy(enabler);
@@ -214,8 +218,10 @@ void lttng_session_destroy(struct lttng_session *session)
                BUG_ON(chan->channel_type == METADATA_CHANNEL);
                _lttng_channel_destroy(chan);
        }
+       mutex_lock(&session->metadata_cache->lock);
        list_for_each_entry(metadata_stream, &session->metadata_cache->metadata_stream, list)
                _lttng_metadata_channel_hangup(metadata_stream);
+       mutex_unlock(&session->metadata_cache->lock);
        lttng_id_tracker_destroy(&session->pid_tracker, false);
        lttng_id_tracker_destroy(&session->vpid_tracker, false);
        lttng_id_tracker_destroy(&session->uid_tracker, false);
@@ -500,12 +506,12 @@ struct lttng_channel *lttng_channel_create(struct lttng_session *session,
                goto active;    /* Refuse to add channel to active session */
        transport = lttng_transport_find(transport_name);
        if (!transport) {
-               printk(KERN_WARNING "LTTng transport %s not found\n",
+               printk(KERN_WARNING "LTTng: transport %s not found\n",
                       transport_name);
                goto notransport;
        }
        if (!try_module_get(transport->owner)) {
-               printk(KERN_WARNING "LTT : Can't lock transport module.\n");
+               printk(KERN_WARNING "LTTng: Can't lock transport module.\n");
                goto notransport;
        }
        chan = kzalloc(sizeof(struct lttng_channel), GFP_KERNEL);
@@ -742,6 +748,28 @@ struct lttng_event *_lttng_event_create(struct lttng_channel *chan,
                event->enabled = 0;
                event->registered = 0;
                event->desc = event_desc;
+               switch (event_param->u.syscall.entryexit) {
+               case LTTNG_KERNEL_SYSCALL_ENTRYEXIT:
+                       ret = -EINVAL;
+                       goto register_error;
+               case LTTNG_KERNEL_SYSCALL_ENTRY:
+                       event->u.syscall.entryexit = LTTNG_SYSCALL_ENTRY;
+                       break;
+               case LTTNG_KERNEL_SYSCALL_EXIT:
+                       event->u.syscall.entryexit = LTTNG_SYSCALL_EXIT;
+                       break;
+               }
+               switch (event_param->u.syscall.abi) {
+               case LTTNG_KERNEL_SYSCALL_ABI_ALL:
+                       ret = -EINVAL;
+                       goto register_error;
+               case LTTNG_KERNEL_SYSCALL_ABI_NATIVE:
+                       event->u.syscall.abi = LTTNG_SYSCALL_ABI_NATIVE;
+                       break;
+               case LTTNG_KERNEL_SYSCALL_ABI_COMPAT:
+                       event->u.syscall.abi = LTTNG_SYSCALL_ABI_COMPAT;
+                       break;
+               }
                if (!event->desc) {
                        ret = -EINVAL;
                        goto register_error;
@@ -828,8 +856,7 @@ void register_event(struct lttng_event *event)
                                                  event);
                break;
        case LTTNG_KERNEL_SYSCALL:
-               ret = lttng_syscall_filter_enable(event->chan,
-                       desc->name);
+               ret = lttng_syscall_filter_enable(event->chan, event);
                break;
        case LTTNG_KERNEL_KPROBE:
        case LTTNG_KERNEL_UPROBE:
@@ -872,8 +899,7 @@ int _lttng_event_unregister(struct lttng_event *event)
                ret = 0;
                break;
        case LTTNG_KERNEL_SYSCALL:
-               ret = lttng_syscall_filter_disable(event->chan,
-                       desc->name);
+               ret = lttng_syscall_filter_disable(event->chan, event);
                break;
        case LTTNG_KERNEL_NOOP:
                ret = 0;
@@ -1205,39 +1231,87 @@ int lttng_desc_match_enabler(const struct lttng_event_desc *desc,
                struct lttng_enabler *enabler)
 {
        const char *desc_name, *enabler_name;
+       bool compat = false, entry = false;
 
        enabler_name = enabler->event_param.name;
        switch (enabler->event_param.instrumentation) {
        case LTTNG_KERNEL_TRACEPOINT:
                desc_name = desc->name;
+               switch (enabler->type) {
+               case LTTNG_ENABLER_STAR_GLOB:
+                       return lttng_match_enabler_star_glob(desc_name, enabler_name);
+               case LTTNG_ENABLER_NAME:
+                       return lttng_match_enabler_name(desc_name, enabler_name);
+               default:
+                       return -EINVAL;
+               }
                break;
        case LTTNG_KERNEL_SYSCALL:
                desc_name = desc->name;
-               if (!strncmp(desc_name, "compat_", strlen("compat_")))
+               if (!strncmp(desc_name, "compat_", strlen("compat_"))) {
                        desc_name += strlen("compat_");
+                       compat = true;
+               }
                if (!strncmp(desc_name, "syscall_exit_",
                                strlen("syscall_exit_"))) {
                        desc_name += strlen("syscall_exit_");
                } else if (!strncmp(desc_name, "syscall_entry_",
                                strlen("syscall_entry_"))) {
                        desc_name += strlen("syscall_entry_");
+                       entry = true;
                } else {
                        WARN_ON_ONCE(1);
                        return -EINVAL;
                }
+               switch (enabler->event_param.u.syscall.entryexit) {
+               case LTTNG_KERNEL_SYSCALL_ENTRYEXIT:
+                       break;
+               case LTTNG_KERNEL_SYSCALL_ENTRY:
+                       if (!entry)
+                               return 0;
+                       break;
+               case LTTNG_KERNEL_SYSCALL_EXIT:
+                       if (entry)
+                               return 0;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               switch (enabler->event_param.u.syscall.abi) {
+               case LTTNG_KERNEL_SYSCALL_ABI_ALL:
+                       break;
+               case LTTNG_KERNEL_SYSCALL_ABI_NATIVE:
+                       if (compat)
+                               return 0;
+                       break;
+               case LTTNG_KERNEL_SYSCALL_ABI_COMPAT:
+                       if (!compat)
+                               return 0;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               switch (enabler->event_param.u.syscall.match) {
+               case LTTNG_SYSCALL_MATCH_NAME:
+                       switch (enabler->type) {
+                       case LTTNG_ENABLER_STAR_GLOB:
+                               return lttng_match_enabler_star_glob(desc_name, enabler_name);
+                       case LTTNG_ENABLER_NAME:
+                               return lttng_match_enabler_name(desc_name, enabler_name);
+                       default:
+                               return -EINVAL;
+                       }
+                       break;
+               case LTTNG_SYSCALL_MATCH_NR:
+                       return -EINVAL; /* Not implemented. */
+               default:
+                       return -EINVAL;
+               }
                break;
        default:
                WARN_ON_ONCE(1);
                return -EINVAL;
        }
-       switch (enabler->type) {
-       case LTTNG_ENABLER_STAR_GLOB:
-               return lttng_match_enabler_star_glob(desc_name, enabler_name);
-       case LTTNG_ENABLER_NAME:
-               return lttng_match_enabler_name(desc_name, enabler_name);
-       default:
-               return -EINVAL;
-       }
 }
 
 static
@@ -1318,7 +1392,7 @@ void lttng_create_tracepoint_if_missing(struct lttng_enabler *enabler)
                                        NULL, NULL, desc,
                                        LTTNG_KERNEL_TRACEPOINT);
                        if (!event) {
-                               printk(KERN_INFO "Unable to create event %s\n",
+                               printk(KERN_INFO "LTTng: Unable to create event %s\n",
                                        probe_desc->event_desc[i]->name);
                        }
                }
@@ -1363,9 +1437,21 @@ void lttng_create_event_if_missing(struct lttng_enabler *enabler)
 static
 int lttng_enabler_ref_events(struct lttng_enabler *enabler)
 {
-       struct lttng_session *session = enabler->chan->session;
+       struct lttng_channel *chan = enabler->chan;
+       struct lttng_session *session = chan->session;
        struct lttng_event *event;
 
+       if (enabler->event_param.instrumentation == LTTNG_KERNEL_SYSCALL &&
+                       enabler->event_param.u.syscall.entryexit == LTTNG_KERNEL_SYSCALL_ENTRYEXIT &&
+                       enabler->event_param.u.syscall.abi == LTTNG_KERNEL_SYSCALL_ABI_ALL &&
+                       enabler->event_param.u.syscall.match == LTTNG_SYSCALL_MATCH_NAME &&
+                       !strcmp(enabler->event_param.name, "*")) {
+               if (enabler->enabled)
+                       WRITE_ONCE(chan->syscall_all, 1);
+               else
+                       WRITE_ONCE(chan->syscall_all, 0);
+       }
+
        /* First ensure that probe events are created for this enabler. */
        lttng_create_event_if_missing(enabler);
 
@@ -1626,7 +1712,7 @@ void lttng_session_lazy_sync_enablers(struct lttng_session *session)
  * was written and a negative value on error.
  */
 int lttng_metadata_output_channel(struct lttng_metadata_stream *stream,
-               struct channel *chan)
+               struct channel *chan, bool *coherent)
 {
        struct lib_ring_buffer_ctx ctx;
        int ret = 0;
@@ -1665,6 +1751,7 @@ int lttng_metadata_output_channel(struct lttng_metadata_stream *stream,
        ret = stream->transport->ops.event_reserve(&ctx, 0);
        if (ret != 0) {
                printk(KERN_WARNING "LTTng: Metadata event reservation failed\n");
+               stream->coherent = false;
                goto end;
        }
        stream->transport->ops.event_write(&ctx,
@@ -1672,18 +1759,46 @@ int lttng_metadata_output_channel(struct lttng_metadata_stream *stream,
                        reserve_len);
        stream->transport->ops.event_commit(&ctx);
        stream->metadata_in += reserve_len;
+       if (reserve_len < len)
+               stream->coherent = false;
+       else
+               stream->coherent = true;
        ret = reserve_len;
 
 end:
+       if (coherent)
+               *coherent = stream->coherent;
        mutex_unlock(&stream->metadata_cache->lock);
        return ret;
 }
 
+static
+void lttng_metadata_begin(struct lttng_session *session)
+{
+       if (atomic_inc_return(&session->metadata_cache->producing) == 1)
+               mutex_lock(&session->metadata_cache->lock);
+}
+
+static
+void lttng_metadata_end(struct lttng_session *session)
+{
+       WARN_ON_ONCE(!atomic_read(&session->metadata_cache->producing));
+       if (atomic_dec_return(&session->metadata_cache->producing) == 0) {
+               struct lttng_metadata_stream *stream;
+
+               list_for_each_entry(stream, &session->metadata_cache->metadata_stream, list)
+                       wake_up_interruptible(&stream->read_wait);
+               mutex_unlock(&session->metadata_cache->lock);
+       }
+}
+
 /*
  * Write the metadata to the metadata cache.
  * Must be called with sessions_mutex held.
  * The metadata cache lock protects us from concurrent read access from
  * thread outputting metadata content to ring buffer.
+ * The content of the printf is printed as a single atomic metadata
+ * transaction.
  */
 int lttng_metadata_printf(struct lttng_session *session,
                          const char *fmt, ...)
@@ -1691,9 +1806,8 @@ int lttng_metadata_printf(struct lttng_session *session,
        char *str;
        size_t len;
        va_list ap;
-       struct lttng_metadata_stream *stream;
 
-       WARN_ON_ONCE(!READ_ONCE(session->active));
+       WARN_ON_ONCE(!LTTNG_READ_ONCE(session->active));
 
        va_start(ap, fmt);
        str = kvasprintf(GFP_KERNEL, fmt, ap);
@@ -1702,7 +1816,7 @@ int lttng_metadata_printf(struct lttng_session *session,
                return -ENOMEM;
 
        len = strlen(str);
-       mutex_lock(&session->metadata_cache->lock);
+       WARN_ON_ONCE(!atomic_read(&session->metadata_cache->producing));
        if (session->metadata_cache->metadata_written + len >
                        session->metadata_cache->cache_alloc) {
                char *tmp_cache_realloc;
@@ -1728,16 +1842,11 @@ int lttng_metadata_printf(struct lttng_session *session,
                        session->metadata_cache->metadata_written,
                        str, len);
        session->metadata_cache->metadata_written += len;
-       mutex_unlock(&session->metadata_cache->lock);
        kfree(str);
 
-       list_for_each_entry(stream, &session->metadata_cache->metadata_stream, list)
-               wake_up_interruptible(&stream->read_wait);
-
        return 0;
 
 err:
-       mutex_unlock(&session->metadata_cache->lock);
        kfree(str);
        return -ENOMEM;
 }
@@ -2312,6 +2421,8 @@ int _lttng_fields_metadata_statedump(struct lttng_session *session,
 
 /*
  * Must be called with sessions_mutex held.
+ * The entire event metadata is printed as a single atomic metadata
+ * transaction.
  */
 static
 int _lttng_event_metadata_statedump(struct lttng_session *session,
@@ -2320,11 +2431,13 @@ int _lttng_event_metadata_statedump(struct lttng_session *session,
 {
        int ret = 0;
 
-       if (event->metadata_dumped || !READ_ONCE(session->active))
+       if (event->metadata_dumped || !LTTNG_READ_ONCE(session->active))
                return 0;
        if (chan->channel_type == METADATA_CHANNEL)
                return 0;
 
+       lttng_metadata_begin(session);
+
        ret = lttng_metadata_printf(session,
                "event {\n"
                "       name = \"%s\";\n"
@@ -2374,12 +2487,15 @@ int _lttng_event_metadata_statedump(struct lttng_session *session,
 
        event->metadata_dumped = 1;
 end:
+       lttng_metadata_end(session);
        return ret;
 
 }
 
 /*
  * Must be called with sessions_mutex held.
+ * The entire channel metadata is printed as a single atomic metadata
+ * transaction.
  */
 static
 int _lttng_channel_metadata_statedump(struct lttng_session *session,
@@ -2387,12 +2503,14 @@ int _lttng_channel_metadata_statedump(struct lttng_session *session,
 {
        int ret = 0;
 
-       if (chan->metadata_dumped || !READ_ONCE(session->active))
+       if (chan->metadata_dumped || !LTTNG_READ_ONCE(session->active))
                return 0;
 
        if (chan->channel_type == METADATA_CHANNEL)
                return 0;
 
+       lttng_metadata_begin(session);
+
        WARN_ON_ONCE(!chan->header_type);
        ret = lttng_metadata_printf(session,
                "stream {\n"
@@ -2426,6 +2544,7 @@ int _lttng_channel_metadata_statedump(struct lttng_session *session,
 
        chan->metadata_dumped = 1;
 end:
+       lttng_metadata_end(session);
        return ret;
 }
 
@@ -2611,8 +2730,11 @@ int _lttng_session_metadata_statedump(struct lttng_session *session)
        struct lttng_event *event;
        int ret = 0;
 
-       if (!READ_ONCE(session->active))
+       if (!LTTNG_READ_ONCE(session->active))
                return 0;
+
+       lttng_metadata_begin(session);
+
        if (session->metadata_dumped)
                goto skip_session;
 
@@ -2785,6 +2907,7 @@ skip_session:
        }
        session->metadata_dumped = 1;
 end:
+       lttng_metadata_end(session);
        return ret;
 }
 
This page took 0.027633 seconds and 4 git commands to generate.