summaryrefslogtreecommitdiff
path: root/src/journal/journal-send.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2014-10-30 17:36:02 +0100
committerLennart Poettering <lennart@poettering.net>2014-10-30 17:36:02 +0100
commitc79e98eadd3056a36a662699fa650db5b1bca0c3 (patch)
tree456bcce009973aafa5269f62a4e04f34c339f5e6 /src/journal/journal-send.c
parentdd4540da0e1f983540d862cc657df7161a3bdd06 (diff)
journal: when sending huge log messages prefer memfds over temporary files in /dev/shm
Previously when a log message grew beyond the maximum AF_UNIX/SOCK_DGRAM datagram limit we'd send an fd to a deleted file in /dev/shm instead. Because the sender could still modify the file after delivery we had to immediately copy the data on the receiving side. With memfds we can optimize this logic, and also remove the dependency on /dev/shm: simply send a sealed memfd around, and if we detect the seal memory map the fd and use it directly.
Diffstat (limited to 'src/journal/journal-send.c')
-rw-r--r--src/journal/journal-send.c36
1 files changed, 26 insertions, 10 deletions
diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c
index bb1ef66dc9..bfc404e375 100644
--- a/src/journal/journal-send.c
+++ b/src/journal/journal-send.c
@@ -198,7 +198,7 @@ finish:
_public_ int sd_journal_sendv(const struct iovec *iov, int n) {
PROTECT_ERRNO;
- int fd;
+ int fd, r;
_cleanup_close_ int buffer_fd = -1;
struct iovec *w;
uint64_t *l;
@@ -218,6 +218,7 @@ _public_ int sd_journal_sendv(const struct iovec *iov, int n) {
} control;
struct cmsghdr *cmsg;
bool have_syslog_identifier = false;
+ bool seal = true;
assert_return(iov, -EINVAL);
assert_return(n > 0, -EINVAL);
@@ -304,21 +305,36 @@ _public_ int sd_journal_sendv(const struct iovec *iov, int n) {
if (errno != EMSGSIZE && errno != ENOBUFS)
return -errno;
- /* Message doesn't fit... Let's dump the data in a temporary
- * file and just pass a file descriptor of it to the other
- * side.
+ /* Message doesn't fit... Let's dump the data in a memfd or
+ * temporary file and just pass a file descriptor of it to the
+ * other side.
*
- * We use /dev/shm instead of /tmp here, since we want this to
- * be a tmpfs, and one that is available from early boot on
- * and where unprivileged users can create files. */
- buffer_fd = open_tmpfile("/dev/shm", O_RDWR | O_CLOEXEC);
- if (buffer_fd < 0)
- return buffer_fd;
+ * For the temporary files we use /dev/shm instead of /tmp
+ * here, since we want this to be a tmpfs, and one that is
+ * available from early boot on and where unprivileged users
+ * can create files. */
+ buffer_fd = memfd_create("journal-message", MFD_ALLOW_SEALING | MFD_CLOEXEC);
+ if (buffer_fd < 0) {
+ if (errno == ENOSYS) {
+ buffer_fd = open_tmpfile("/dev/shm", O_RDWR | O_CLOEXEC);
+ if (buffer_fd < 0)
+ return buffer_fd;
+
+ seal = false;
+ } else
+ return -errno;
+ }
n = writev(buffer_fd, w, j);
if (n < 0)
return -errno;
+ if (seal) {
+ r = fcntl(buffer_fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
+ if (r < 0)
+ return -errno;
+ }
+
mh.msg_iov = NULL;
mh.msg_iovlen = 0;