Fix: add "flush empty" ioctl for stream intersection
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 11 May 2017 20:50:50 +0000 (16:50 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 11 May 2017 21:49:49 +0000 (17:49 -0400)
Changing the behavior of the "snapshot" lttng command to implicitly do a
buffer "flush" (even when current packet is empty) had unwanted
side-effects: for instance, the snapshot ABI is used by the live timer
to grab the buffer positions, and we don't want to generate useless
empty packets in that scenario.

Therefore, add the "flush empty" behavior as a new ioctl to the ring
buffer. This allows lttng-tools to perform buffer flush (even for empty
packets) when it needs to. Given that this new ioctl is added within
stable branches as well, lttng-tools always need to handle "-ENOSYS"
gracefully.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
lib/ringbuffer/frontend_internal.h
lib/ringbuffer/ring_buffer_frontend.c
lib/ringbuffer/ring_buffer_vfs.c
lib/ringbuffer/vfs.h
lttng-abi.c

index b13edd10b7e80c2803d07343b1edcc1dbe0c0883..4b367aea351d0589f1942d2768cd1064c56f5ca2 100644 (file)
@@ -158,6 +158,8 @@ void lib_ring_buffer_switch_slow(struct lib_ring_buffer *buf,
 
 extern
 void lib_ring_buffer_switch_remote(struct lib_ring_buffer *buf);
 
 extern
 void lib_ring_buffer_switch_remote(struct lib_ring_buffer *buf);
+extern
+void lib_ring_buffer_switch_remote_empty(struct lib_ring_buffer *buf);
 
 /* Buffer write helpers */
 
 
 /* Buffer write helpers */
 
index 922940d14a9825d672339d6ba9a6932484001110..97c963c81a7c41b1b71d2d62a08f87a123a68a71 100644 (file)
@@ -1784,12 +1784,20 @@ static void _lib_ring_buffer_switch_remote(struct lib_ring_buffer *buf,
        put_online_cpus();
 }
 
        put_online_cpus();
 }
 
+/* Switch sub-buffer if current sub-buffer is non-empty. */
 void lib_ring_buffer_switch_remote(struct lib_ring_buffer *buf)
 {
        _lib_ring_buffer_switch_remote(buf, SWITCH_ACTIVE);
 }
 EXPORT_SYMBOL_GPL(lib_ring_buffer_switch_remote);
 
 void lib_ring_buffer_switch_remote(struct lib_ring_buffer *buf)
 {
        _lib_ring_buffer_switch_remote(buf, SWITCH_ACTIVE);
 }
 EXPORT_SYMBOL_GPL(lib_ring_buffer_switch_remote);
 
+/* Switch sub-buffer even if current sub-buffer is empty. */
+void lib_ring_buffer_switch_remote_empty(struct lib_ring_buffer *buf)
+{
+       _lib_ring_buffer_switch_remote(buf, SWITCH_FLUSH);
+}
+EXPORT_SYMBOL_GPL(lib_ring_buffer_switch_remote_empty);
+
 /*
  * Returns :
  * 0 if ok
 /*
  * Returns :
  * 0 if ok
index f1a8bab781cd2f5829c552067eefdb2365c1f2e7..4b1aa38ea674f18184aa4a684a0a6c9bc4051fed 100644 (file)
@@ -270,6 +270,9 @@ long lib_ring_buffer_ioctl(struct file *filp, unsigned int cmd,
        case RING_BUFFER_FLUSH:
                lib_ring_buffer_switch_remote(buf);
                return 0;
        case RING_BUFFER_FLUSH:
                lib_ring_buffer_switch_remote(buf);
                return 0;
+       case RING_BUFFER_FLUSH_EMPTY:
+               lib_ring_buffer_switch_remote_empty(buf);
+               return 0;
        default:
                return -ENOIOCTLCMD;
        }
        default:
                return -ENOIOCTLCMD;
        }
@@ -415,6 +418,9 @@ long lib_ring_buffer_compat_ioctl(struct file *filp, unsigned int cmd,
        case RING_BUFFER_COMPAT_FLUSH:
                lib_ring_buffer_switch_remote(buf);
                return 0;
        case RING_BUFFER_COMPAT_FLUSH:
                lib_ring_buffer_switch_remote(buf);
                return 0;
+       case RING_BUFFER_COMPAT_FLUSH_EMPTY:
+               lib_ring_buffer_switch_remote_empty(buf);
+               return 0;
        default:
                return -ENOIOCTLCMD;
        }
        default:
                return -ENOIOCTLCMD;
        }
index 5444a4b2bb6404a68ffc675f9badf5ec7cd1c808..2387afc23dcc90e4c83c442268b85b89d1dc8310 100644 (file)
@@ -111,10 +111,13 @@ ssize_t vfs_lib_ring_buffer_splice_read(struct file *in, loff_t *ppos,
 #define RING_BUFFER_GET_MMAP_LEN               _IOR(0xF6, 0x0A, unsigned long)
 /* returns the offset of the subbuffer belonging to the mmap reader. */
 #define RING_BUFFER_GET_MMAP_READ_OFFSET       _IOR(0xF6, 0x0B, unsigned long)
 #define RING_BUFFER_GET_MMAP_LEN               _IOR(0xF6, 0x0A, unsigned long)
 /* returns the offset of the subbuffer belonging to the mmap reader. */
 #define RING_BUFFER_GET_MMAP_READ_OFFSET       _IOR(0xF6, 0x0B, unsigned long)
-/* flush the current sub-buffer */
+/* Flush the current sub-buffer, if non-empty. */
 #define RING_BUFFER_FLUSH                      _IO(0xF6, 0x0C)
 /* Get the current version of the metadata cache (after a get_next). */
 #define RING_BUFFER_GET_METADATA_VERSION       _IOR(0xF6, 0x0D, uint64_t)
 #define RING_BUFFER_FLUSH                      _IO(0xF6, 0x0C)
 /* Get the current version of the metadata cache (after a get_next). */
 #define RING_BUFFER_GET_METADATA_VERSION       _IOR(0xF6, 0x0D, uint64_t)
+/* Reserved: (0xF6, 0x0E). */
+/* Flush the current sub-buffer, even if empty. */
+#define RING_BUFFER_FLUSH_EMPTY                        _IO(0xF6, 0x0F)
 
 #ifdef CONFIG_COMPAT
 /* Get a snapshot of the current ring buffer producer and consumer positions */
 
 #ifdef CONFIG_COMPAT
 /* Get a snapshot of the current ring buffer producer and consumer positions */
@@ -145,10 +148,13 @@ ssize_t vfs_lib_ring_buffer_splice_read(struct file *in, loff_t *ppos,
 #define RING_BUFFER_COMPAT_GET_MMAP_LEN                _IOR(0xF6, 0x0A, compat_ulong_t)
 /* returns the offset of the subbuffer belonging to the mmap reader. */
 #define RING_BUFFER_COMPAT_GET_MMAP_READ_OFFSET        _IOR(0xF6, 0x0B, compat_ulong_t)
 #define RING_BUFFER_COMPAT_GET_MMAP_LEN                _IOR(0xF6, 0x0A, compat_ulong_t)
 /* returns the offset of the subbuffer belonging to the mmap reader. */
 #define RING_BUFFER_COMPAT_GET_MMAP_READ_OFFSET        _IOR(0xF6, 0x0B, compat_ulong_t)
-/* flush the current sub-buffer */
+/* Flush the current sub-buffer, if non-empty. */
 #define RING_BUFFER_COMPAT_FLUSH               RING_BUFFER_FLUSH
 /* Get the current version of the metadata cache (after a get_next). */
 #define RING_BUFFER_COMPAT_GET_METADATA_VERSION        RING_BUFFER_GET_METADATA_VERSION
 #define RING_BUFFER_COMPAT_FLUSH               RING_BUFFER_FLUSH
 /* Get the current version of the metadata cache (after a get_next). */
 #define RING_BUFFER_COMPAT_GET_METADATA_VERSION        RING_BUFFER_GET_METADATA_VERSION
+/* Flush the current sub-buffer, even if empty. */
+#define RING_BUFFER_COMPAT_FLUSH_EMPTY                 \
+       RING_BUFFER_FLUSH_EMPTY
 #endif /* CONFIG_COMPAT */
 
 #endif /* _LIB_RING_BUFFER_VFS_H */
 #endif /* CONFIG_COMPAT */
 
 #endif /* _LIB_RING_BUFFER_VFS_H */
index fc72e29bb0096f34756852f4beead6b02a051dbc..6a255ae55a95f7177fe9c5e0873c4fbf7f1b8f7f 100644 (file)
@@ -681,6 +681,7 @@ long lttng_metadata_ring_buffer_ioctl(struct file *filp,
                 */
                return -ENOSYS;
        }
                 */
                return -ENOSYS;
        }
+       case RING_BUFFER_FLUSH_EMPTY:   /* Fall-through. */
        case RING_BUFFER_FLUSH:
        {
                struct lttng_metadata_stream *stream = filp->private_data;
        case RING_BUFFER_FLUSH:
        {
                struct lttng_metadata_stream *stream = filp->private_data;
@@ -757,6 +758,7 @@ long lttng_metadata_ring_buffer_compat_ioctl(struct file *filp,
                 */
                return -ENOSYS;
        }
                 */
                return -ENOSYS;
        }
+       case RING_BUFFER_FLUSH_EMPTY:   /* Fall-through. */
        case RING_BUFFER_FLUSH:
        {
                struct lttng_metadata_stream *stream = filp->private_data;
        case RING_BUFFER_FLUSH:
        {
                struct lttng_metadata_stream *stream = filp->private_data;
This page took 0.030096 seconds and 4 git commands to generate.