*/
#define _GNU_SOURCE
+#include <inttypes.h>
#include <string.h>
#include <unistd.h>
#include <common/sessiond-comm/sessiond-comm.h>
#include "channel.h"
+#include "lttng-sessiond.h"
#include "kernel.h"
#include "ust-ctl.h"
#include "utils.h"
/*
* Return allocated channel attributes.
*/
-struct lttng_channel *channel_new_default_attr(int dom)
+struct lttng_channel *channel_new_default_attr(int dom,
+ enum lttng_buffer_type type)
{
struct lttng_channel *chan;
goto error;
}
+ /* Same for all domains. */
chan->attr.overwrite = DEFAULT_CHANNEL_OVERWRITE;
+ chan->attr.tracefile_size = DEFAULT_CHANNEL_TRACEFILE_SIZE;
+ chan->attr.tracefile_count = DEFAULT_CHANNEL_TRACEFILE_COUNT;
switch (dom) {
case LTTNG_DOMAIN_KERNEL:
+ assert(type == LTTNG_BUFFER_GLOBAL);
chan->attr.subbuf_size =
default_get_kernel_channel_subbuf_size();
chan->attr.num_subbuf = DEFAULT_KERNEL_CHANNEL_SUBBUF_NUM;
chan->attr.read_timer_interval = DEFAULT_KERNEL_CHANNEL_READ_TIMER;
break;
case LTTNG_DOMAIN_UST:
-#if 0
- case LTTNG_DOMAIN_UST_PID:
- case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
- case LTTNG_DOMAIN_UST_EXEC_NAME:
-#endif
- chan->attr.subbuf_size = default_get_ust_channel_subbuf_size();
- chan->attr.num_subbuf = DEFAULT_UST_CHANNEL_SUBBUF_NUM;
- chan->attr.output = DEFAULT_UST_CHANNEL_OUTPUT;
- chan->attr.switch_timer_interval = DEFAULT_UST_CHANNEL_SWITCH_TIMER;
- chan->attr.read_timer_interval = DEFAULT_UST_CHANNEL_READ_TIMER;
+ switch (type) {
+ case LTTNG_BUFFER_PER_UID:
+ chan->attr.subbuf_size = default_get_ust_uid_channel_subbuf_size();
+ chan->attr.num_subbuf = DEFAULT_UST_UID_CHANNEL_SUBBUF_NUM;
+ chan->attr.output = DEFAULT_UST_UID_CHANNEL_OUTPUT;
+ chan->attr.switch_timer_interval =
+ DEFAULT_UST_UID_CHANNEL_SWITCH_TIMER;
+ chan->attr.read_timer_interval =
+ DEFAULT_UST_UID_CHANNEL_READ_TIMER;
+ break;
+ case LTTNG_BUFFER_PER_PID:
+ default:
+ chan->attr.subbuf_size = default_get_ust_pid_channel_subbuf_size();
+ chan->attr.num_subbuf = DEFAULT_UST_PID_CHANNEL_SUBBUF_NUM;
+ chan->attr.output = DEFAULT_UST_PID_CHANNEL_OUTPUT;
+ chan->attr.switch_timer_interval =
+ DEFAULT_UST_PID_CHANNEL_SWITCH_TIMER;
+ chan->attr.read_timer_interval =
+ DEFAULT_UST_PID_CHANNEL_READ_TIMER;
+ break;
+ }
break;
default:
goto error; /* Not implemented */
/* Creating channel attributes if needed */
if (attr == NULL) {
- defattr = channel_new_default_attr(LTTNG_DOMAIN_KERNEL);
+ defattr = channel_new_default_attr(LTTNG_DOMAIN_KERNEL,
+ LTTNG_BUFFER_GLOBAL);
if (defattr == NULL) {
ret = LTTNG_ERR_FATAL;
goto error;
/*
* Enable UST channel for session and domain.
*/
-int channel_ust_enable(struct ltt_ust_session *usess, int domain,
+int channel_ust_enable(struct ltt_ust_session *usess,
struct ltt_ust_channel *uchan)
{
int ret = LTTNG_OK;
goto end;
}
- switch (domain) {
- case LTTNG_DOMAIN_UST:
- DBG2("Channel %s being enabled in UST global domain", uchan->name);
-
- /*
- * Enable channel for UST global domain on all applications. Ignore
- * return value here since whatever error we got, it means that the
- * channel was not created on one or many registered applications and
- * we can not report this to the user yet. However, at this stage, the
- * channel was successfully created on the session daemon side so the
- * enable-channel command is a success.
- */
- (void) ust_app_create_channel_glb(usess, uchan);
- break;
-#if 0
- case LTTNG_DOMAIN_UST_PID:
- case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
- case LTTNG_DOMAIN_UST_EXEC_NAME:
-#endif
- default:
- ret = LTTNG_ERR_UND;
- goto error;
- }
+ DBG2("Channel %s being enabled in UST domain", uchan->name);
+
+ /*
+ * Enable channel for UST global domain on all applications. Ignore return
+ * value here since whatever error we got, it means that the channel was
+ * not created on one or many registered applications and we can not report
+ * this to the user yet. However, at this stage, the channel was
+ * successfully created on the session daemon side so the enable-channel
+ * command is a success.
+ */
+ (void) ust_app_enable_channel_glb(usess, uchan);
uchan->enabled = 1;
DBG2("Channel %s enabled successfully", uchan->name);
end:
-error:
return ret;
}
/*
* Create UST channel for session and domain.
*/
-int channel_ust_create(struct ltt_ust_session *usess, int domain,
- struct lttng_channel *attr)
+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;
/* Creating channel attributes if needed */
if (attr == NULL) {
- defattr = channel_new_default_attr(domain);
+ defattr = channel_new_default_attr(LTTNG_DOMAIN_UST, type);
if (defattr == NULL) {
ret = LTTNG_ERR_FATAL;
goto error;
attr = defattr;
}
- if (attr->attr.subbuf_size < DEFAULT_UST_CHANNEL_SUBBUF_SIZE) {
- 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
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;
}
+ /*
+ * 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, usess->pathname);
+ uchan = trace_ust_create_channel(attr);
if (uchan == NULL) {
ret = LTTNG_ERR_FATAL;
goto error;
}
uchan->enabled = 1;
-
- switch (domain) {
- case LTTNG_DOMAIN_UST:
- DBG2("Channel %s being created in UST global domain", uchan->name);
-
- /* Enable channel for global domain */
- ret = ust_app_create_channel_glb(usess, uchan);
- break;
-#if 0
- case LTTNG_DOMAIN_UST_PID:
- case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
- case LTTNG_DOMAIN_UST_EXEC_NAME:
-#endif
- default:
- ret = LTTNG_ERR_UND;
+ 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;
/*
* Disable UST channel for session and domain.
*/
-int channel_ust_disable(struct ltt_ust_session *usess, int domain,
+int channel_ust_disable(struct ltt_ust_session *usess,
struct ltt_ust_channel *uchan)
{
int ret = LTTNG_OK;
goto end;
}
- /* Get the right channel's hashtable */
- switch (domain) {
- case LTTNG_DOMAIN_UST:
- DBG2("Channel %s being disabled in UST global domain", uchan->name);
- /* Disable channel for global domain */
- ret = ust_app_disable_channel_glb(usess, uchan);
- break;
-#if 0
- case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
- case LTTNG_DOMAIN_UST_EXEC_NAME:
- case LTTNG_DOMAIN_UST_PID:
-#endif
- default:
- ret = LTTNG_ERR_UND;
- goto error;
- }
-
+ DBG2("Channel %s being disabled in UST global domain", uchan->name);
+ /* Disable channel for global domain */
+ ret = ust_app_disable_channel_glb(usess, uchan);
if (ret < 0 && ret != -LTTNG_UST_ERR_EXIST) {
ret = LTTNG_ERR_UST_CHAN_DISABLE_FAIL;
goto error;