static void test_create_ust_channel(void) { struct ltt_ust_channel *uchan; struct lttng_channel attr; memset(&attr, 0, sizeof(attr)); strncpy(attr.name, "channel0", 8); uchan = trace_ust_create_channel(&attr); ok(uchan != NULL, "Create UST channel"); ok(uchan->enabled == 0 && strncmp(uchan->name, "channel0", 8) == 0 && uchan->name[LTTNG_UST_SYM_NAME_LEN - 1] == '\0' && uchan->ctx != NULL && uchan->events != NULL && uchan->attr.overwrite == attr.attr.overwrite, "Validate UST channel"); trace_ust_destroy_channel(uchan); }
/* * Create UST channel for session and domain. */ int channel_ust_create(struct ltt_ust_session *usess, struct lttng_channel *attr, enum lttng_buffer_type type) { int ret = LTTNG_OK; struct ltt_ust_channel *uchan = NULL; struct lttng_channel *defattr = NULL; enum lttng_domain_type domain = LTTNG_DOMAIN_UST; assert(usess); /* Creating channel attributes if needed */ if (attr == NULL) { defattr = channel_new_default_attr(LTTNG_DOMAIN_UST, type); if (defattr == NULL) { ret = LTTNG_ERR_FATAL; goto error; } attr = defattr; } else { /* * HACK: Set the channel's subdomain (JUL, Log4j, Python, etc.) * based on the default name. */ if (!strcmp(attr->name, DEFAULT_JUL_CHANNEL_NAME)) { domain = LTTNG_DOMAIN_JUL; } else if (!strcmp(attr->name, DEFAULT_LOG4J_CHANNEL_NAME)) { domain = LTTNG_DOMAIN_LOG4J; } else if (!strcmp(attr->name, DEFAULT_PYTHON_CHANNEL_NAME)) { domain = LTTNG_DOMAIN_PYTHON; } } /* * Set the overwrite mode for this channel based on the session * type unless the client explicitly overrides the channel mode. */ if (attr->attr.overwrite == DEFAULT_CHANNEL_OVERWRITE) { attr->attr.overwrite = !!usess->snapshot_mode; } /* Enforce mmap output for snapshot sessions. */ if (usess->snapshot_mode) { attr->attr.output = LTTNG_EVENT_MMAP; } /* Validate common channel properties. */ if (channel_validate(attr) < 0) { ret = LTTNG_ERR_INVALID; goto error; } /* * Validate UST buffer size and number of buffers: must both be power of 2 * and nonzero. We validate right here for UST, because applications will * not report the error to the user (unlike kernel tracing). */ if (!attr->attr.subbuf_size || (attr->attr.subbuf_size & (attr->attr.subbuf_size - 1))) { ret = LTTNG_ERR_INVALID; goto error; } /* * Invalid subbuffer size if it's lower then the page size. */ if (attr->attr.subbuf_size < page_size) { ret = LTTNG_ERR_INVALID; goto error; } if (!attr->attr.num_subbuf || (attr->attr.num_subbuf & (attr->attr.num_subbuf - 1))) { ret = LTTNG_ERR_INVALID; goto error; } if (attr->attr.output != LTTNG_EVENT_MMAP) { ret = LTTNG_ERR_NOT_SUPPORTED; goto error; } /* * The tracefile_size should not be < to the subbuf_size, otherwise * we won't be able to write the packets on disk */ if ((attr->attr.tracefile_size > 0) && (attr->attr.tracefile_size < attr->attr.subbuf_size)) { ret = LTTNG_ERR_INVALID; goto error; } /* Validate buffer type. */ switch (type) { case LTTNG_BUFFER_PER_PID: break; case LTTNG_BUFFER_PER_UID: break; default: ret = LTTNG_ERR_BUFFER_NOT_SUPPORTED; goto error; } /* Create UST channel */ uchan = trace_ust_create_channel(attr, domain); if (uchan == NULL) { ret = LTTNG_ERR_FATAL; goto error; } uchan->enabled = 1; if (trace_ust_is_max_id(usess->used_channel_id)) { ret = LTTNG_ERR_UST_CHAN_FAIL; goto error; } uchan->id = trace_ust_get_next_chan_id(usess); DBG2("Channel %s is being created for UST with buffer %d and id %" PRIu64, uchan->name, type, uchan->id); /* Flag session buffer type. */ if (!usess->buffer_type_changed) { usess->buffer_type = type; usess->buffer_type_changed = 1; } else if (usess->buffer_type != type) { /* Buffer type was already set. Refuse to create channel. */ ret = LTTNG_ERR_BUFFER_TYPE_MISMATCH; goto error_free_chan; } /* Enable channel for global domain */ ret = ust_app_create_channel_glb(usess, uchan); if (ret < 0 && ret != -LTTNG_UST_ERR_EXIST) { ret = LTTNG_ERR_UST_CHAN_FAIL; goto error_free_chan; } /* Adding the channel to the channel hash table. */ rcu_read_lock(); if (strncmp(uchan->name, DEFAULT_METADATA_NAME, sizeof(uchan->name))) { lttng_ht_add_unique_str(usess->domain_global.channels, &uchan->node); } else { /* * Copy channel attribute to session if this is metadata so if NO * application exists we can access that data in the shadow copy during * the global update of newly registered application. */ memcpy(&usess->metadata_attr, &uchan->attr, sizeof(usess->metadata_attr)); } rcu_read_unlock(); DBG2("Channel %s created successfully", uchan->name); if (domain != LTTNG_DOMAIN_UST) { struct agent *agt = trace_ust_find_agent(usess, domain); if (!agt) { agt = agent_create(domain); if (!agt) { ret = LTTNG_ERR_NOMEM; goto error_free_chan; } agent_add(agt, usess->agents); } } channel_attr_destroy(defattr); return LTTNG_OK; error_free_chan: /* * No need to remove the channel from the hash table because at this point * it was not added hence the direct call and no call_rcu(). */ trace_ust_destroy_channel(uchan); error: channel_attr_destroy(defattr); return ret; }