#include <common/uri.hpp>
#include <common/utils.hpp>
+#include <fcntl.h>
+
namespace {
struct thread_notifiers {
struct lttng_pipe *quit_pipe;
#include <lttng/session-internal.hpp>
#include <lttng/userspace-probe-internal.hpp>
+#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <stddef.h>
#include <common/pipe.hpp>
#include <common/utils.hpp>
+#include <fcntl.h>
#include <inttypes.h>
#include <sys/stat.h>
#include "thread.hpp"
#include "utils.hpp"
+#include <fcntl.h>
+
namespace {
struct thread_notifiers {
struct lttng_pipe *quit_pipe;
#include <common/pipe.hpp>
#include <common/utils.hpp>
+#include <fcntl.h>
#include <signal.h>
namespace {
#include <common/urcu.hpp>
#include <common/utils.hpp>
+#include <fcntl.h>
+
namespace {
struct thread_notifiers {
struct lttng_pipe *quit_pipe;
#include <common/common.hpp>
#include <common/utils.hpp>
+#include <fcntl.h>
+
namespace {
struct thread_notifiers {
struct lttng_pipe *quit_pipe;
#include <common/shm.hpp>
#include <common/utils.hpp>
+#include <fcntl.h>
#include <stddef.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <lttng/rotate-internal.hpp>
#include <lttng/trigger/trigger.h>
+#include <fcntl.h>
#include <inttypes.h>
#include <memory>
#include <signal.h>
#include <lttng/save-internal.hpp>
+#include <fcntl.h>
#include <inttypes.h>
#include <string.h>
#include <unistd.h>
#include <common/utils.hpp>
+#include <fcntl.h>
#include <pthread.h>
/*
file-descriptor.hpp file-descriptor.cpp \
fd-handle.cpp fd-handle.hpp\
format.hpp \
+ io-hint.cpp \
+ io-hint.hpp \
kernel-probe.cpp \
location.cpp \
locked-reference.hpp \
# libcompat
noinst_LTLIBRARIES += libcompat.la
libcompat_la_SOURCES = \
- compat/compat-fcntl.cpp \
compat/directory-handle.cpp \
compat/directory-handle.hpp \
compat/dirent.hpp \
compat/endian.hpp \
compat/errno.hpp \
- compat/fcntl.hpp \
compat/getenv.hpp \
compat/mman.hpp \
compat/netdb.hpp \
+++ /dev/null
-/*
- * Copyright (C) 2011 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#define _LGPL_SOURCE
-#include <common/compat/fcntl.hpp>
-#include <common/macros.hpp>
-
-#include <unistd.h>
-
-#ifdef __linux__
-
-int compat_sync_file_range(int fd, off_t offset, off_t nbytes, unsigned int flags)
-{
-#ifdef HAVE_SYNC_FILE_RANGE
- return sync_file_range(fd, offset, nbytes, flags);
-#else
- return fdatasync(fd);
-#endif
-}
-
-#endif /* __linux__ */
+++ /dev/null
-/*
- * Copyright (C) 2011 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef _COMPAT_FCNTL_H
-#define _COMPAT_FCNTL_H
-
-#include <common/compat/errno.hpp>
-
-#include <fcntl.h>
-#include <sys/types.h>
-
-static_assert(sizeof(off_t) == sizeof(int64_t),
- "Build system is misconfigured, off_t must be 64-bit wide");
-
-#if (defined(__FreeBSD__) || defined(__sun__))
-typedef off64_t loff_t;
-#endif
-
-#ifdef __linux__
-extern int compat_sync_file_range(int fd, off_t offset, off_t nbytes, unsigned int flags);
-#define lttng_sync_file_range(fd, offset, nbytes, flags) \
- compat_sync_file_range(fd, offset, nbytes, flags)
-
-#endif /* __linux__ */
-
-#if (defined(__FreeBSD__) || defined(__CYGWIN__) || defined(__sun__))
-/*
- * Possible flags under Linux. Simply nullify them and avoid wrapper.
- */
-#define SYNC_FILE_RANGE_WAIT_AFTER 0
-#define SYNC_FILE_RANGE_WAIT_BEFORE 0
-#define SYNC_FILE_RANGE_WRITE 0
-
-static inline int lttng_sync_file_range(int fd __attribute__((unused)),
- off_t offset __attribute__((unused)),
- off_t nbytes __attribute__((unused)),
- unsigned int flags __attribute__((unused)))
-{
- return -ENOSYS;
-}
-#endif
-
-#if (defined(__FreeBSD__) || defined(__CYGWIN__) || defined(__sun__))
-/*
- * Possible flags under Linux. Simply nullify them and avoid wrappers.
- */
-#define SPLICE_F_MOVE 0
-#define SPLICE_F_NONBLOCK 0
-#define SPLICE_F_MORE 0
-#define SPLICE_F_GIFT 0
-
-static inline ssize_t splice(int fd_in __attribute__((unused)),
- loff_t *off_in __attribute__((unused)),
- int fd_out __attribute__((unused)),
- loff_t *off_out __attribute__((unused)),
- size_t len __attribute__((unused)),
- unsigned int flags __attribute__((unused)))
-{
- return -ENOSYS;
-}
-#endif
-
-#if !(defined(__linux__) || defined(__FreeBSD__) || defined(__CYGWIN__) || defined(__sun__) || \
- defined(__APPLE__))
-#error "Please add support for your OS."
-#endif /* __linux__ , __FreeBSD__, __CYGWIN__, __sun__, __APPLE__ */
-
-#endif /* _COMPAT_FCNTL_H */
* epoll(7) implementation.
*/
#ifdef HAVE_EPOLL
-#include <common/compat/fcntl.hpp>
#include <features.h>
#include <stdio.h>
#include <common/ust-consumer/ust-consumer.hpp>
#include <common/utils.hpp>
+#include <fcntl.h>
#include <inttypes.h>
#include <sys/mman.h>
#include <unistd.h>
#include <common/dynamic-array.hpp>
#include <common/index/ctf-index.hpp>
#include <common/index/index.hpp>
+#include <common/io-hint.hpp>
#include <common/kernel-consumer/kernel-consumer.hpp>
#include <common/kernel-ctl/kernel-ctl.hpp>
#include <common/relayd/relayd.hpp>
#include <common/utils.hpp>
#include <bin/lttng-consumerd/health-consumerd.hpp>
+#include <fcntl.h>
#include <inttypes.h>
#include <poll.h>
#include <pthread.h>
*/
static void lttng_consumer_sync_trace_file(struct lttng_consumer_stream *stream, off_t orig_offset)
{
- int ret;
int outfd = stream->out_fd;
/*
if (orig_offset < stream->max_sb_size) {
return;
}
- lttng_sync_file_range(outfd,
- orig_offset - stream->max_sb_size,
- stream->max_sb_size,
- SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE |
- SYNC_FILE_RANGE_WAIT_AFTER);
- /*
- * Give hints to the kernel about how we access the file:
- * POSIX_FADV_DONTNEED : we won't re-access data in a near future after
- * we write it.
- *
- * We need to call fadvise again after the file grows because the
- * kernel does not seem to apply fadvise to non-existing parts of the
- * file.
- *
- * Call fadvise _after_ having waited for the page writeback to
- * complete because the dirty page writeback semantic is not well
- * defined. So it can be expected to lead to lower throughput in
- * streaming.
- */
- ret = posix_fadvise(
- outfd, orig_offset - stream->max_sb_size, stream->max_sb_size, POSIX_FADV_DONTNEED);
- if (ret && ret != -ENOSYS) {
- errno = ret;
- PERROR("posix_fadvise on fd %i", outfd);
- }
+ lttng::io::hint_flush_range_dont_need_sync(
+ outfd, orig_offset - stream->max_sb_size, stream->max_sb_size);
}
/*
/* This call is useless on a socket so better save a syscall. */
if (!relayd) {
/* This won't block, but will start writeout asynchronously */
- lttng_sync_file_range(
- outfd, stream->out_fd_offset, write_len, SYNC_FILE_RANGE_WRITE);
+ lttng::io::hint_flush_range_async(outfd, stream->out_fd_offset, write_len);
stream->out_fd_offset += write_len;
lttng_consumer_sync_trace_file(stream, orig_offset);
}
/* This call is useless on a socket so better save a syscall. */
if (!relayd) {
/* This won't block, but will start writeout asynchronously */
- lttng_sync_file_range(
- outfd, stream->out_fd_offset, ret_splice, SYNC_FILE_RANGE_WRITE);
+ lttng::io::hint_flush_range_async(outfd, stream->out_fd_offset, ret_splice);
stream->out_fd_offset += ret_splice;
}
stream->output_written += ret_splice;
#define LIB_CONSUMER_H
#include <common/buffer-view.hpp>
-#include <common/compat/fcntl.hpp>
#include <common/credentials.hpp>
#include <common/dynamic-array.hpp>
#include <common/hashtable/hashtable.hpp>
--- /dev/null
+/*
+ * Copyright (C) 2023 Michael Jeanson <mjeanson@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#include <common/error.hpp>
+#include <common/io-hint.hpp>
+#include <common/scope-exit.hpp>
+
+#include <cinttypes>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+/*
+ * Use sync_file_range when available.
+ */
+#ifdef HAVE_SYNC_FILE_RANGE
+
+#include <fcntl.h>
+
+namespace {
+int flush_range(int fd, off_t offset, off_t nbytes, unsigned int flags)
+{
+ int ret;
+
+ ret = sync_file_range(fd, offset, nbytes, flags);
+ if (ret) {
+ PERROR("Failed to sync file range: fd=%i, offset=%" PRIu64 ", nbytes=%" PRIu64
+ ", flags=%i",
+ fd,
+ static_cast<uint64_t>(offset),
+ static_cast<uint64_t>(nbytes),
+ flags);
+ }
+
+ return ret;
+}
+
+int flush_range_sync(int fd, off_t offset, off_t nbytes)
+{
+ return flush_range(fd,
+ offset,
+ nbytes,
+ SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE |
+ SYNC_FILE_RANGE_WAIT_AFTER);
+}
+
+int flush_range_async(int fd, off_t offset, off_t nbytes)
+{
+ return flush_range(fd, offset, nbytes, SYNC_FILE_RANGE_WRITE);
+}
+} /* namespace */
+
+#else
+
+namespace {
+/*
+ * Use a memory mapping with msync() to emulate sync_file_range().
+ */
+int flush_range(int fd, off_t offset, off_t nbytes, int flags)
+{
+ void *mapped_region = mmap(NULL, nbytes, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
+ if (mapped_region == MAP_FAILED) {
+ PERROR("Failed to mmap region to flush range: fd=%i, offset=%" PRIu64
+ ", nbytes=%" PRIu64 ", flags=%i",
+ fd,
+ static_cast<uint64_t>(offset),
+ static_cast<uint64_t>(nbytes),
+ flags);
+ return -1;
+ }
+
+ const auto munmap_on_exit = lttng::make_scope_exit([&]() noexcept {
+ const auto munmap_ret = munmap(mapped_region, nbytes);
+ if (munmap_ret) {
+ PERROR("Failed to munmap region while flushing range: fd=%i, offset=%" PRIu64
+ ", nbytes=%" PRIu64 ", flags=%i",
+ fd,
+ static_cast<uint64_t>(offset),
+ static_cast<uint64_t>(nbytes),
+ flags);
+ }
+ });
+
+ const auto msync_ret = msync(mapped_region, nbytes, flags);
+ if (msync_ret) {
+ PERROR("Failed to msync region while flushing range: fd=%i, offset=%" PRIu64
+ ", nbytes=%" PRIu64 ", flags=%i",
+ fd,
+ static_cast<uint64_t>(offset),
+ static_cast<uint64_t>(nbytes),
+ flags);
+ return -1;
+ }
+
+ return 0;
+}
+
+int flush_range_sync(int fd, off_t offset, off_t nbytes)
+{
+ return flush_range(fd, offset, nbytes, MS_SYNC);
+}
+
+int flush_range_async(int fd, off_t offset, off_t nbytes)
+{
+ return flush_range(fd, offset, nbytes, MS_ASYNC);
+}
+} /* namespace */
+#endif
+
+/*
+ * Give a hint to the kernel that we won't need the data at the specified range
+ * so it can be dropped from the page cache and wait for it to be flushed to
+ * disk.
+ */
+void lttng::io::hint_flush_range_dont_need_sync(int fd, off_t offset, off_t nbytes)
+{
+ /* Waited for the page writeback to complete. */
+ flush_range_sync(fd, offset, nbytes);
+
+ /*
+ * Give hints to the kernel about how we access the file:
+ * POSIX_FADV_DONTNEED : we won't re-access data in a near future after
+ * we write it.
+ *
+ * We need to call fadvise again after the file grows because the
+ * kernel does not seem to apply fadvise to non-existing parts of the
+ * file.
+ *
+ * Call fadvise _after_ having waited for the page writeback to
+ * complete because the dirty page writeback semantic is not well
+ * defined. So it can be expected to lead to lower throughput in
+ * streaming.
+ */
+ const int ret = posix_fadvise(fd, offset, nbytes, POSIX_FADV_DONTNEED);
+ if (ret && ret != -ENOSYS) {
+ PERROR("Failed to mark region as DONTNEED with posix_fadvise: fd=%i, offset=%" PRIu64
+ ", nbytes=%" PRIu64,
+ fd,
+ static_cast<uint64_t>(offset),
+ static_cast<uint64_t>(nbytes));
+ errno = ret;
+ }
+}
+
+/*
+ * Give a hint to the kernel that the data at the specified range should be
+ * flushed to disk and wait for it to complete.
+ */
+void lttng::io::hint_flush_range_sync(int fd, off_t offset, off_t nbytes)
+{
+ flush_range_sync(fd, offset, nbytes);
+}
+
+/*
+ * Give a hint to the kernel that the data at the specified range should be
+ * flushed to disk and return immediatly.
+ */
+void lttng::io::hint_flush_range_async(int fd, off_t offset, off_t nbytes)
+{
+ flush_range_async(fd, offset, nbytes);
+}
--- /dev/null
+/*
+ * Copyright (C) 2023 Michael Jeanson <mjeanson@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef _LTTNG_IO_HINT_H
+#define _LTTNG_IO_HINT_H
+
+namespace lttng {
+namespace io {
+
+void hint_flush_range_dont_need_sync(int fd, off_t offset, off_t nbytes);
+void hint_flush_range_sync(int fd, off_t offset, off_t nbytes);
+void hint_flush_range_async(int fd, off_t offset, off_t nbytes);
+
+} /* namespace io */
+} /* namespace lttng */
+
+#endif
#include <common/buffer-view.hpp>
#include <common/common.hpp>
#include <common/compat/endian.hpp>
-#include <common/compat/fcntl.hpp>
#include <common/consumer/consumer-stream.hpp>
#include <common/consumer/consumer-timer.hpp>
#include <common/consumer/consumer.hpp>
#include <common/utils.hpp>
#include <bin/lttng-consumerd/health-consumerd.hpp>
+#include <fcntl.h>
#include <inttypes.h>
#include <poll.h>
#include <pthread.h>
#include <common/common.hpp>
#include <common/compat/endian.hpp>
-#include <common/compat/fcntl.hpp>
#include <common/consumer/consumer-metadata-cache.hpp>
#include <common/consumer/consumer-stream.hpp>
#include <common/consumer/consumer-timer.hpp>
#include <lttng/ust-sigbus.h>
#include <bin/lttng-consumerd/health-consumerd.hpp>
+#include <fcntl.h>
#include <inttypes.h>
#include <poll.h>
#include <pthread.h>
*
*/
-#include <common/compat/fcntl.hpp>
#include <common/payload-view.hpp>
#include <common/payload.hpp>
+#include <fcntl.h>
#include <tap/tap.h>
#include <unistd.h>
*
*/
-#include <common/compat/fcntl.hpp>
#include <common/defaults.hpp>
#include <common/error.hpp>
#include <common/payload-view.hpp>
#include <lttng/constant.h>
#include <algorithm>
+#include <fcntl.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>