From e49273dcf0cc67623cea694916c753ebb4272193 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 11 May 2017 17:53:58 -0400 Subject: [PATCH] Fix: use "flush empty" ioctl for snapshots MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit When the flush empty ioctl is available, use it to produce an empty packet at the end of the snapshot, which ensures the stream intersection feature works. If this specific ioctl is not available, fallback on the "flush" ioctl, which does not produce empty packets. In that situation, there were two prior behaviors possible for lttng-modules: earlier versions implement a "snapshot" command which does not perform an implicit "flush_empty". In that case, the stream intersection feature may not be reliable. In more recent lttng-modules versions (included stable branch) which did not implement the flush_empty ioctl, the snapshot ioctl implicitly performed a flush_empty, which makes the stream intersection feature work, but has side-effects on the snapshot ioctl performed by the live timer (produces a stream of empty packets in live mode). [ Please apply to master, 2.10, 2.9, 2.8 branches. ] Signed-off-by: Mathieu Desnoyers Signed-off-by: Jérémie Galarneau --- src/common/kernel-consumer/kernel-consumer.c | 17 +++++++++++++---- src/common/kernel-ctl/kernel-ctl.c | 5 +++++ src/common/kernel-ctl/kernel-ctl.h | 1 + src/common/kernel-ctl/kernel-ioctl.h | 4 +++- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/common/kernel-consumer/kernel-consumer.c b/src/common/kernel-consumer/kernel-consumer.c index d9c4d2685..57656dcc8 100644 --- a/src/common/kernel-consumer/kernel-consumer.c +++ b/src/common/kernel-consumer/kernel-consumer.c @@ -188,11 +188,20 @@ int lttng_kconsumer_snapshot_channel(uint64_t key, char *path, channel->streams_sent_to_relayd = true; } - ret = kernctl_buffer_flush(stream->wait_fd); + ret = kernctl_buffer_flush_empty(stream->wait_fd); if (ret < 0) { - ERR("Failed to flush kernel stream"); - ret = -errno; - goto end_unlock; + /* + * Doing a buffer flush which does not take into + * account empty packets. This is not perfect + * for stream intersection, but required as a + * fall-back when "flush_empty" is not + * implemented by lttng-modules. + */ + ret = kernctl_buffer_flush(stream->wait_fd); + if (ret < 0) { + ERR("Failed to flush kernel stream"); + goto end_unlock; + } } ret = lttng_kconsumer_take_snapshot(stream); diff --git a/src/common/kernel-ctl/kernel-ctl.c b/src/common/kernel-ctl/kernel-ctl.c index 610a3c53b..144dbf04d 100644 --- a/src/common/kernel-ctl/kernel-ctl.c +++ b/src/common/kernel-ctl/kernel-ctl.c @@ -426,6 +426,11 @@ int kernctl_buffer_flush(int fd) return LTTNG_IOCTL(fd, RING_BUFFER_FLUSH); } +int kernctl_buffer_flush_empty(int fd) +{ + return LTTNG_IOCTL(fd, RING_BUFFER_FLUSH_EMPTY); +} + /* returns the version of the metadata. */ int kernctl_get_metadata_version(int fd, uint64_t *version) { diff --git a/src/common/kernel-ctl/kernel-ctl.h b/src/common/kernel-ctl/kernel-ctl.h index 6736937d0..2a448e0ec 100644 --- a/src/common/kernel-ctl/kernel-ctl.h +++ b/src/common/kernel-ctl/kernel-ctl.h @@ -92,6 +92,7 @@ int kernctl_get_subbuf(int fd, unsigned long *pos); int kernctl_put_subbuf(int fd); int kernctl_buffer_flush(int fd); +int kernctl_buffer_flush_empty(int fd); int kernctl_get_metadata_version(int fd, uint64_t *version); /* index */ diff --git a/src/common/kernel-ctl/kernel-ioctl.h b/src/common/kernel-ctl/kernel-ioctl.h index 68056dcf1..cddea3fc4 100644 --- a/src/common/kernel-ctl/kernel-ioctl.h +++ b/src/common/kernel-ctl/kernel-ioctl.h @@ -47,10 +47,12 @@ #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) +/* Flush the current sub-buffer, even if empty. */ +#define RING_BUFFER_FLUSH_EMPTY _IO(0xF6, 0x0F) /* returns the timestamp begin of the current sub-buffer */ #define LTTNG_RING_BUFFER_GET_TIMESTAMP_BEGIN _IOR(0xF6, 0x20, uint64_t) -- 2.34.1