Fix: Implement RING_BUFFER_GET_NEXT_SUBBUF_METADATA_CHECK
[lttng-modules.git] / src / lttng-abi.c
index 01eb4d55addea3ea41b5def0ed79ca9efd91fcf1..c3721b93e428ce7d48bf94f40ff9ebd0a6585ef4 100644 (file)
@@ -65,6 +65,7 @@ static const struct file_operations lttng_event_fops;
 static struct file_operations lttng_stream_ring_buffer_file_operations;
 
 static int put_u64(uint64_t val, unsigned long arg);
+static int put_u32(uint32_t val, unsigned long arg);
 
 /*
  * Teardown management: opened file descriptors keep a refcount on the module,
@@ -850,6 +851,13 @@ long lttng_metadata_ring_buffer_ioctl(struct file *filp,
        int ret;
        struct lttng_metadata_stream *stream = filp->private_data;
        struct lib_ring_buffer *buf = stream->priv;
+       unsigned int rb_cmd;
+       bool coherent;
+
+       if (cmd == RING_BUFFER_GET_NEXT_SUBBUF_METADATA_CHECK)
+               rb_cmd = RING_BUFFER_GET_NEXT_SUBBUF;
+       else
+               rb_cmd = cmd;
 
        switch (cmd) {
        case RING_BUFFER_GET_NEXT_SUBBUF:
@@ -858,7 +866,7 @@ long lttng_metadata_ring_buffer_ioctl(struct file *filp,
                struct lib_ring_buffer *buf = stream->priv;
                struct channel *chan = buf->backend.chan;
 
-               ret = lttng_metadata_output_channel(stream, chan);
+               ret = lttng_metadata_output_channel(stream, chan, NULL);
                if (ret > 0) {
                        lib_ring_buffer_switch_slow(buf, SWITCH_ACTIVE);
                        ret = 0;
@@ -884,7 +892,7 @@ long lttng_metadata_ring_buffer_ioctl(struct file *filp,
                 * Before doing the actual ring buffer flush, write up to one
                 * packet of metadata in the ring buffer.
                 */
-               ret = lttng_metadata_output_channel(stream, chan);
+               ret = lttng_metadata_output_channel(stream, chan, NULL);
                if (ret < 0)
                        goto err;
                break;
@@ -901,13 +909,28 @@ long lttng_metadata_ring_buffer_ioctl(struct file *filp,
 
                return lttng_metadata_cache_dump(stream);
        }
+       case RING_BUFFER_GET_NEXT_SUBBUF_METADATA_CHECK:
+       {
+               struct lttng_metadata_stream *stream = filp->private_data;
+               struct lib_ring_buffer *buf = stream->priv;
+               struct channel *chan = buf->backend.chan;
+
+               ret = lttng_metadata_output_channel(stream, chan, &coherent);
+               if (ret > 0) {
+                       lib_ring_buffer_switch_slow(buf, SWITCH_ACTIVE);
+                       ret = 0;
+               } else if (ret < 0) {
+                       goto err;
+               }
+               break;
+       }
        default:
                break;
        }
        /* PUT_SUBBUF is the one from lib ring buffer, unmodified. */
 
        /* Performing lib ring buffer ioctl after our own. */
-       ret = lib_ring_buffer_ioctl(filp, cmd, arg, buf);
+       ret = lib_ring_buffer_ioctl(filp, rb_cmd, arg, buf);
        if (ret < 0)
                goto err;
 
@@ -918,6 +941,10 @@ long lttng_metadata_ring_buffer_ioctl(struct file *filp,
                                cmd, arg);
                break;
        }
+       case RING_BUFFER_GET_NEXT_SUBBUF_METADATA_CHECK:
+       {
+               return put_u32(coherent, arg);
+       }
        default:
                break;
        }
@@ -933,6 +960,13 @@ long lttng_metadata_ring_buffer_compat_ioctl(struct file *filp,
        int ret;
        struct lttng_metadata_stream *stream = filp->private_data;
        struct lib_ring_buffer *buf = stream->priv;
+       unsigned int rb_cmd;
+       bool coherent;
+
+       if (cmd == RING_BUFFER_GET_NEXT_SUBBUF_METADATA_CHECK)
+               rb_cmd = RING_BUFFER_GET_NEXT_SUBBUF;
+       else
+               rb_cmd = cmd;
 
        switch (cmd) {
        case RING_BUFFER_GET_NEXT_SUBBUF:
@@ -941,7 +975,7 @@ long lttng_metadata_ring_buffer_compat_ioctl(struct file *filp,
                struct lib_ring_buffer *buf = stream->priv;
                struct channel *chan = buf->backend.chan;
 
-               ret = lttng_metadata_output_channel(stream, chan);
+               ret = lttng_metadata_output_channel(stream, chan, NULL);
                if (ret > 0) {
                        lib_ring_buffer_switch_slow(buf, SWITCH_ACTIVE);
                        ret = 0;
@@ -967,7 +1001,7 @@ long lttng_metadata_ring_buffer_compat_ioctl(struct file *filp,
                 * Before doing the actual ring buffer flush, write up to one
                 * packet of metadata in the ring buffer.
                 */
-               ret = lttng_metadata_output_channel(stream, chan);
+               ret = lttng_metadata_output_channel(stream, chan, NULL);
                if (ret < 0)
                        goto err;
                break;
@@ -984,13 +1018,28 @@ long lttng_metadata_ring_buffer_compat_ioctl(struct file *filp,
 
                return lttng_metadata_cache_dump(stream);
        }
+       case RING_BUFFER_GET_NEXT_SUBBUF_METADATA_CHECK:
+       {
+               struct lttng_metadata_stream *stream = filp->private_data;
+               struct lib_ring_buffer *buf = stream->priv;
+               struct channel *chan = buf->backend.chan;
+
+               ret = lttng_metadata_output_channel(stream, chan, &coherent);
+               if (ret > 0) {
+                       lib_ring_buffer_switch_slow(buf, SWITCH_ACTIVE);
+                       ret = 0;
+               } else if (ret < 0) {
+                       goto err;
+               }
+               break;
+       }
        default:
                break;
        }
        /* PUT_SUBBUF is the one from lib ring buffer, unmodified. */
 
        /* Performing lib ring buffer ioctl after our own. */
-       ret = lib_ring_buffer_compat_ioctl(filp, cmd, arg, buf);
+       ret = lib_ring_buffer_compat_ioctl(filp, rb_cmd, arg, buf);
        if (ret < 0)
                goto err;
 
@@ -1001,6 +1050,10 @@ long lttng_metadata_ring_buffer_compat_ioctl(struct file *filp,
                                cmd, arg);
                break;
        }
+       case RING_BUFFER_GET_NEXT_SUBBUF_METADATA_CHECK:
+       {
+               return put_u32(coherent, arg);
+       }
        default:
                break;
        }
@@ -1167,6 +1220,8 @@ int lttng_abi_open_metadata_stream(struct file *channel_file)
        metadata_stream->priv = buf;
        stream_priv = metadata_stream;
        metadata_stream->transport = channel->transport;
+       /* Initial state is an empty metadata, considered as incoherent. */
+       metadata_stream->coherent = false;
 
        /*
         * Since life-time of metadata cache differs from that of
@@ -1703,6 +1758,11 @@ static int put_u64(uint64_t val, unsigned long arg)
        return put_user(val, (uint64_t __user *) arg);
 }
 
+static int put_u32(uint32_t val, unsigned long arg)
+{
+       return put_user(val, (uint32_t __user *) arg);
+}
+
 static long lttng_stream_ring_buffer_ioctl(struct file *filp,
                unsigned int cmd, unsigned long arg)
 {
This page took 0.026667 seconds and 4 git commands to generate.