Пример #1
0
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);
}
Пример #2
0
/*
 * 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;
}