Fix: don't fail on push metadata if no channel
[lttng-tools.git] / src / common / ust-consumer / ust-consumer.c
index 9b1675e8be94b89b560dcd77db1e36e5fedb8775..e315c4681c94def1d2d36305637f6218a7ff3a20 100644 (file)
@@ -399,7 +399,7 @@ static int send_sessiond_channel(int sock,
                struct lttng_consumer_channel *channel,
                struct lttng_consumer_local_data *ctx, int *relayd_error)
 {
-       int ret, ret_code = LTTNG_OK;
+       int ret, ret_code = LTTCOMM_CONSUMERD_SUCCESS;
        struct lttng_consumer_stream *stream;
 
        assert(channel);
@@ -427,7 +427,7 @@ static int send_sessiond_channel(int sock,
 
        /* Inform sessiond that we are about to send channel and streams. */
        ret = consumer_send_status_msg(sock, ret_code);
-       if (ret < 0 || ret_code != LTTNG_OK) {
+       if (ret < 0 || ret_code != LTTCOMM_CONSUMERD_SUCCESS) {
                /*
                 * Either the session daemon is not responding or the relayd died so we
                 * stop now.
@@ -466,7 +466,7 @@ static int send_sessiond_channel(int sock,
        return 0;
 
 error:
-       if (ret_code != LTTNG_OK) {
+       if (ret_code != LTTCOMM_CONSUMERD_SUCCESS) {
                ret = -1;
        }
        return ret;
@@ -605,6 +605,45 @@ error:
        rcu_read_unlock();
        return ret;
 }
+/*
+ * Close metadata stream wakeup_fd using the given key to retrieve the channel.
+ * RCU read side lock MUST be acquired before calling this function.
+ *
+ * NOTE: This function does NOT take any channel nor stream lock.
+ *
+ * Return 0 on success else LTTng error code.
+ */
+static int _close_metadata(struct lttng_consumer_channel *channel)
+{
+       int ret = LTTCOMM_CONSUMERD_SUCCESS;
+
+       assert(channel);
+       assert(channel->type == CONSUMER_CHANNEL_TYPE_METADATA);
+
+       if (channel->switch_timer_enabled == 1) {
+               DBG("Deleting timer on metadata channel");
+               consumer_timer_switch_stop(channel);
+       }
+
+       if (channel->metadata_stream) {
+               ret = ustctl_stream_close_wakeup_fd(channel->metadata_stream->ustream);
+               if (ret < 0) {
+                       ERR("UST consumer unable to close fd of metadata (ret: %d)", ret);
+                       ret = LTTCOMM_CONSUMERD_ERROR_METADATA;
+               }
+
+               if (channel->monitor) {
+                       /* Close the read-side in consumer_del_metadata_stream */
+                       ret = close(channel->metadata_stream->ust_metadata_poll_pipe[1]);
+                       if (ret < 0) {
+                               PERROR("Close UST metadata write-side poll pipe");
+                               ret = LTTCOMM_CONSUMERD_ERROR_METADATA;
+                       }
+               }
+       }
+
+       return ret;
+}
 
 /*
  * Close metadata stream wakeup_fd using the given key to retrieve the channel.
@@ -639,26 +678,7 @@ static int close_metadata(uint64_t chan_key)
                goto error_unlock;
        }
 
-       if (channel->switch_timer_enabled == 1) {
-               DBG("Deleting timer on metadata channel");
-               consumer_timer_switch_stop(channel);
-       }
-
-       if (channel->metadata_stream) {
-               ret = ustctl_stream_close_wakeup_fd(channel->metadata_stream->ustream);
-               if (ret < 0) {
-                       ERR("UST consumer unable to close fd of metadata (ret: %d)", ret);
-                       ret = LTTCOMM_CONSUMERD_ERROR_METADATA;
-                       goto error_unlock;
-               }
-               if (channel->monitor) {
-                       /* close the read-side in consumer_del_metadata_stream */
-                       ret = close(channel->metadata_stream->ust_metadata_poll_pipe[1]);
-                       if (ret < 0) {
-                               PERROR("Close UST metadata write-side poll pipe");
-                       }
-               }
-       }
+       ret = _close_metadata(channel);
 
 error_unlock:
        pthread_mutex_unlock(&channel->lock);
@@ -1004,7 +1024,7 @@ int lttng_ustconsumer_recv_metadata(int sock, uint64_t key, uint64_t offset,
                uint64_t len, struct lttng_consumer_channel *channel,
                int timer)
 {
-       int ret, ret_code = LTTNG_OK;
+       int ret, ret_code = LTTCOMM_CONSUMERD_SUCCESS;
        char *metadata_str;
 
        DBG("UST consumer push metadata key %" PRIu64 " of len %" PRIu64, key, len);
@@ -1059,7 +1079,7 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                int sock, struct pollfd *consumer_sockpoll)
 {
        ssize_t ret;
-       enum lttng_error_code ret_code = LTTNG_OK;
+       enum lttcomm_return_code ret_code = LTTCOMM_CONSUMERD_SUCCESS;
        struct lttcomm_consumer_msg msg;
        struct lttng_consumer_channel *channel = NULL;
 
@@ -1192,9 +1212,16 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                attr.switch_timer_interval = msg.u.ask_channel.switch_timer_interval;
                attr.read_timer_interval = msg.u.ask_channel.read_timer_interval;
                attr.chan_id = msg.u.ask_channel.chan_id;
-               attr.output = msg.u.ask_channel.output;
                memcpy(attr.uuid, msg.u.ask_channel.uuid, sizeof(attr.uuid));
 
+               /* Match channel buffer type to the UST abi. */
+               switch (msg.u.ask_channel.output) {
+               case LTTNG_EVENT_MMAP:
+               default:
+                       attr.output = LTTNG_UST_MMAP;
+                       break;
+               }
+
                /* Translate and save channel type. */
                switch (msg.u.ask_channel.type) {
                case LTTNG_UST_CHAN_PER_CPU:
@@ -1363,13 +1390,20 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
 
                channel = consumer_find_channel(key);
                if (!channel) {
-                       ERR("UST consumer push metadata %" PRIu64 " not found", key);
-                       ret_code = LTTNG_ERR_UST_CHAN_NOT_FOUND;
+                       /*
+                        * This is possible if the metadata creation on the consumer side
+                        * is in flight vis-a-vis a concurrent push metadata from the
+                        * session daemon.  Simply return that the channel failed and the
+                        * session daemon will handle that message correctly considering
+                        * that this race is acceptable thus the DBG() statement here.
+                        */
+                       DBG("UST consumer push metadata %" PRIu64 " not found", key);
+                       ret_code = LTTCOMM_CONSUMERD_CHANNEL_FAIL;
                        goto end_msg_sessiond;
                }
 
                /* Tell session daemon we are ready to receive the metadata. */
-               ret = consumer_send_status_msg(sock, LTTNG_OK);
+               ret = consumer_send_status_msg(sock, LTTCOMM_CONSUMERD_SUCCESS);
                if (ret < 0) {
                        /* Somehow, the session daemon is not responding anymore. */
                        goto error_fatal;
@@ -1746,6 +1780,12 @@ int lttng_ustconsumer_data_pending(struct lttng_consumer_stream *stream)
        }
 
        if (stream->chan->type == CONSUMER_CHANNEL_TYPE_METADATA) {
+               uint64_t contiguous, pushed;
+
+               /* Ease our life a bit. */
+               contiguous = stream->chan->metadata_cache->contiguous;
+               pushed = stream->ust_metadata_pushed;
+
                /*
                 * We can simply check whether all contiguously available data
                 * has been pushed to the ring buffer, since the push operation
@@ -1757,10 +1797,10 @@ int lttng_ustconsumer_data_pending(struct lttng_consumer_stream *stream)
                 * metadata has been consumed from the metadata stream.
                 */
                DBG("UST consumer metadata pending check: contiguous %" PRIu64 " vs pushed %" PRIu64,
-                       stream->chan->metadata_cache->contiguous,
-                       stream->ust_metadata_pushed);
-               if (stream->chan->metadata_cache->contiguous
-                               != stream->ust_metadata_pushed) {
+                               contiguous, pushed);
+               assert(((int64_t) contiguous - pushed) >= 0);
+               if ((contiguous != pushed) ||
+                               (((int64_t) contiguous - pushed) > 0 || contiguous == 0)) {
                        ret = 1;        /* Data is pending */
                        goto end;
                }
@@ -1796,7 +1836,6 @@ end:
  */
 void lttng_ustconsumer_close_metadata(struct lttng_ht *metadata_ht)
 {
-       int ret;
        struct lttng_ht_iter iter;
        struct lttng_consumer_stream *stream;
 
@@ -1808,17 +1847,16 @@ void lttng_ustconsumer_close_metadata(struct lttng_ht *metadata_ht)
        rcu_read_lock();
        cds_lfht_for_each_entry(metadata_ht->ht, &iter.iter, stream,
                        node.node) {
-               int fd = stream->wait_fd;
-
+               pthread_mutex_lock(&stream->chan->lock);
                /*
-                * Whatever happens here we have to continue to try to close every
-                * streams. Let's report at least the error on failure.
+                * Whatever returned value, we must continue to try to close everything
+                * so ignore it.
                 */
-               ret = ustctl_stream_close_wakeup_fd(stream->ustream);
-               if (ret) {
-                       ERR("Unable to close metadata stream fd %d ret %d", fd, ret);
-               }
-               DBG("Metadata wait fd %d closed", fd);
+               (void) _close_metadata(stream->chan);
+               DBG("Metadata wait fd %d and poll pipe fd %d closed", stream->wait_fd,
+                               stream->ust_metadata_poll_pipe[1]);
+               pthread_mutex_unlock(&stream->chan->lock);
+
        }
        rcu_read_unlock();
 }
@@ -1844,7 +1882,7 @@ int lttng_ustconsumer_request_metadata(struct lttng_consumer_local_data *ctx,
 {
        struct lttcomm_metadata_request_msg request;
        struct lttcomm_consumer_msg msg;
-       enum lttng_error_code ret_code = LTTNG_OK;
+       enum lttcomm_return_code ret_code = LTTCOMM_CONSUMERD_SUCCESS;
        uint64_t len, key, offset;
        int ret;
 
@@ -1924,7 +1962,7 @@ int lttng_ustconsumer_request_metadata(struct lttng_consumer_local_data *ctx,
 
        /* Tell session daemon we are ready to receive the metadata. */
        ret = consumer_send_status_msg(ctx->consumer_metadata_socket,
-                       LTTNG_OK);
+                       LTTCOMM_CONSUMERD_SUCCESS);
        if (ret < 0 || len == 0) {
                /*
                 * Somehow, the session daemon is not responding anymore or there is
@@ -1933,14 +1971,14 @@ int lttng_ustconsumer_request_metadata(struct lttng_consumer_local_data *ctx,
                goto end;
        }
 
-       ret_code = lttng_ustconsumer_recv_metadata(ctx->consumer_metadata_socket,
+       ret = lttng_ustconsumer_recv_metadata(ctx->consumer_metadata_socket,
                        key, offset, len, channel, timer);
-       if (ret_code >= 0) {
+       if (ret >= 0) {
                /*
                 * Only send the status msg if the sessiond is alive meaning a positive
                 * ret code.
                 */
-               (void) consumer_send_status_msg(ctx->consumer_metadata_socket, ret_code);
+               (void) consumer_send_status_msg(ctx->consumer_metadata_socket, ret);
        }
        ret = 0;
 
This page took 0.026882 seconds and 4 git commands to generate.