diff options
-rw-r--r-- | src/basic/log.h | 36 | ||||
-rw-r--r-- | src/journal/journald-audit.c | 15 | ||||
-rw-r--r-- | src/journal/journald-console.c | 4 | ||||
-rw-r--r-- | src/journal/journald-context.c | 6 | ||||
-rw-r--r-- | src/journal/journald-kmsg.c | 10 | ||||
-rw-r--r-- | src/journal/journald-native.c | 71 | ||||
-rw-r--r-- | src/journal/journald-server.c | 162 | ||||
-rw-r--r-- | src/journal/journald-server.h | 2 | ||||
-rw-r--r-- | src/journal/journald-stream.c | 44 | ||||
-rw-r--r-- | src/journal/journald-syslog.c | 9 | ||||
-rw-r--r-- | src/journal/journald-wall.c | 2 | ||||
-rw-r--r-- | src/libsystemd/sd-journal/journal-file.c | 62 |
12 files changed, 270 insertions, 153 deletions
diff --git a/src/basic/log.h b/src/basic/log.h index c51941c141..040b7eb07b 100644 --- a/src/basic/log.h +++ b/src/basic/log.h @@ -375,15 +375,12 @@ typedef struct LogRateLimit { RateLimit ratelimit; } LogRateLimit; -#define log_ratelimit_internal(_level, _error, _format, _file, _line, _func, ...) \ +#define log_ratelimit_internal(_level, _error, _ratelimit, _format, _file, _line, _func, ...) \ ({ \ int _log_ratelimit_error = (_error); \ int _log_ratelimit_level = (_level); \ static LogRateLimit _log_ratelimit = { \ - .ratelimit = { \ - .interval = 1 * USEC_PER_SEC, \ - .burst = 1, \ - }, \ + .ratelimit = (_ratelimit), \ }; \ unsigned _num_dropped_errors = ratelimit_num_dropped(&_log_ratelimit.ratelimit); \ if (_log_ratelimit_error != _log_ratelimit.error || _log_ratelimit_level != _log_ratelimit.level) { \ @@ -391,18 +388,37 @@ typedef struct LogRateLimit { _log_ratelimit.error = _log_ratelimit_error; \ _log_ratelimit.level = _log_ratelimit_level; \ } \ - if (ratelimit_below(&_log_ratelimit.ratelimit)) \ + if (log_get_max_level() == LOG_DEBUG || ratelimit_below(&_log_ratelimit.ratelimit)) \ _log_ratelimit_error = _num_dropped_errors > 0 \ - ? log_internal(_log_ratelimit_level, _log_ratelimit_error, _file, _line, _func, _format " (Dropped %u similar message(s))", __VA_ARGS__, _num_dropped_errors) \ - : log_internal(_log_ratelimit_level, _log_ratelimit_error, _file, _line, _func, _format, __VA_ARGS__); \ + ? log_internal(_log_ratelimit_level, _log_ratelimit_error, _file, _line, _func, _format " (Dropped %u similar message(s))", ##__VA_ARGS__, _num_dropped_errors) \ + : log_internal(_log_ratelimit_level, _log_ratelimit_error, _file, _line, _func, _format, ##__VA_ARGS__); \ _log_ratelimit_error; \ }) -#define log_ratelimit_full_errno(level, error, format, ...) \ +#define log_ratelimit_full_errno(level, error, _ratelimit, format, ...) \ ({ \ int _level = (level), _e = (error); \ _e = (log_get_max_level() >= LOG_PRI(_level)) \ - ? log_ratelimit_internal(_level, _e, format, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \ + ? log_ratelimit_internal(_level, _e, _ratelimit, format, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__) \ : -ERRNO_VALUE(_e); \ _e < 0 ? _e : -ESTRPIPE; \ }) + +#define log_ratelimit_full(level, _ratelimit, format, ...) \ + log_ratelimit_full_errno(level, 0, _ratelimit, format, ##__VA_ARGS__) + +/* Normal logging */ +#define log_ratelimit_debug(...) log_ratelimit_full(LOG_DEBUG, __VA_ARGS__) +#define log_ratelimit_info(...) log_ratelimit_full(LOG_INFO, __VA_ARGS__) +#define log_ratelimit_notice(...) log_ratelimit_full(LOG_NOTICE, __VA_ARGS__) +#define log_ratelimit_warning(...) log_ratelimit_full(LOG_WARNING, __VA_ARGS__) +#define log_ratelimit_error(...) log_ratelimit_full(LOG_ERR, __VA_ARGS__) +#define log_ratelimit_emergency(...) log_ratelimit_full(log_emergency_level(), __VA_ARGS__) + +/* Logging triggered by an errno-like error */ +#define log_ratelimit_debug_errno(error, ...) log_ratelimit_full_errno(LOG_DEBUG, error, __VA_ARGS__) +#define log_ratelimit_info_errno(error, ...) log_ratelimit_full_errno(LOG_INFO, error, __VA_ARGS__) +#define log_ratelimit_notice_errno(error, ...) log_ratelimit_full_errno(LOG_NOTICE, error, __VA_ARGS__) +#define log_ratelimit_warning_errno(error, ...) log_ratelimit_full_errno(LOG_WARNING, error, __VA_ARGS__) +#define log_ratelimit_error_errno(error, ...) log_ratelimit_full_errno(LOG_ERR, error, __VA_ARGS__) +#define log_ratelimit_emergency_errno(error, ...) log_ratelimit_full_errno(log_emergency_level(), error, __VA_ARGS__) diff --git a/src/journal/journald-audit.c b/src/journal/journald-audit.c index 3e87a93a9e..557dfdb7b6 100644 --- a/src/journal/journald-audit.c +++ b/src/journal/journald-audit.c @@ -264,7 +264,8 @@ static int map_all_fields( const char *v; if (*n >= m) { - log_debug( + log_ratelimit_debug( + JOURNALD_LOG_RATELIMIT, "More fields in audit message than audit field limit (%i), skipping remaining fields", N_IOVEC_AUDIT_FIELDS); return 0; @@ -309,7 +310,8 @@ static int map_all_fields( r = mf->map(mf->journal_field, &v, iovec, n); if (r < 0) - return log_debug_errno(r, "Failed to parse audit array: %m"); + return log_ratelimit_debug_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to parse audit array: %m"); if (r > 0) { mapped = true; @@ -321,7 +323,8 @@ static int map_all_fields( if (!mapped) { r = map_generic_field(prefix, &p, iovec, n); if (r < 0) - return log_debug_errno(r, "Failed to parse audit array: %m"); + return log_ratelimit_debug_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to parse audit array: %m"); if (r == 0) /* Couldn't process as generic field, let's just skip over it */ @@ -431,17 +434,17 @@ void server_process_audit_message( salen != sizeof(struct sockaddr_nl) || sa->nl.nl_family != AF_NETLINK || sa->nl.nl_pid != 0) { - log_debug("Audit netlink message from invalid sender."); + log_ratelimit_debug(JOURNALD_LOG_RATELIMIT, "Audit netlink message from invalid sender."); return; } if (!ucred || ucred->pid != 0) { - log_debug("Audit netlink message with invalid credentials."); + log_ratelimit_debug(JOURNALD_LOG_RATELIMIT, "Audit netlink message with invalid credentials."); return; } if (!NLMSG_OK(nl, buffer_size)) { - log_error("Audit netlink message truncated."); + log_ratelimit_error(JOURNALD_LOG_RATELIMIT, "Audit netlink message truncated."); return; } diff --git a/src/journal/journald-console.c b/src/journal/journald-console.c index 2035e2d9b6..40a740ca40 100644 --- a/src/journal/journald-console.c +++ b/src/journal/journald-console.c @@ -94,10 +94,10 @@ void server_forward_console( fd = open_terminal(tty, O_WRONLY|O_NOCTTY|O_CLOEXEC); if (fd < 0) { - log_debug_errno(fd, "Failed to open %s for logging: %m", tty); + log_ratelimit_debug_errno(fd, JOURNALD_LOG_RATELIMIT, "Failed to open %s for logging: %m", tty); return; } if (writev(fd, iovec, n) < 0) - log_debug_errno(errno, "Failed to write to %s for logging: %m", tty); + log_ratelimit_debug_errno(errno, JOURNALD_LOG_RATELIMIT, "Failed to write to %s for logging: %m", tty); } diff --git a/src/journal/journald-context.c b/src/journal/journald-context.c index 27608ff089..6d58422ddd 100644 --- a/src/journal/journald-context.c +++ b/src/journal/journald-context.c @@ -771,7 +771,8 @@ void client_context_acquire_default(Server *s) { r = client_context_acquire(s, ucred.pid, &ucred, NULL, 0, NULL, &s->my_context); if (r < 0) - log_warning_errno(r, "Failed to acquire our own context, ignoring: %m"); + log_ratelimit_warning_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to acquire our own context, ignoring: %m"); } if (!s->namespace && !s->pid1_context) { @@ -780,7 +781,8 @@ void client_context_acquire_default(Server *s) { r = client_context_acquire(s, 1, NULL, NULL, 0, NULL, &s->pid1_context); if (r < 0) - log_warning_errno(r, "Failed to acquire PID1's context, ignoring: %m"); + log_ratelimit_warning_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to acquire PID1's context, ignoring: %m"); } } diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c index 8ae7a23d56..b711df4557 100644 --- a/src/journal/journald-kmsg.c +++ b/src/journal/journald-kmsg.c @@ -80,7 +80,8 @@ void server_forward_kmsg( iovec[n++] = IOVEC_MAKE_STRING("\n"); if (writev(s->dev_kmsg_fd, iovec, n) < 0) - log_debug_errno(errno, "Failed to write to /dev/kmsg for logging: %m"); + log_ratelimit_debug_errno(errno, JOURNALD_LOG_RATELIMIT, + "Failed to write to /dev/kmsg for logging: %m"); } static bool is_us(const char *identifier, const char *pid) { @@ -329,7 +330,7 @@ static int server_read_dev_kmsg(Server *s) { if (ERRNO_IS_TRANSIENT(errno) || errno == EPIPE) return 0; - return log_error_errno(errno, "Failed to read from /dev/kmsg: %m"); + return log_ratelimit_error_errno(errno, JOURNALD_LOG_RATELIMIT, "Failed to read from /dev/kmsg: %m"); } dev_kmsg_record(s, buffer, l); @@ -347,7 +348,7 @@ int server_flush_dev_kmsg(Server *s) { if (!s->dev_kmsg_readable) return 0; - log_debug("Flushing /dev/kmsg..."); + log_ratelimit_debug(JOURNALD_LOG_RATELIMIT, "Flushing /dev/kmsg..."); for (;;) { r = server_read_dev_kmsg(s); @@ -368,7 +369,8 @@ static int dispatch_dev_kmsg(sd_event_source *es, int fd, uint32_t revents, void assert(fd == s->dev_kmsg_fd); if (revents & EPOLLERR) - log_warning("/dev/kmsg buffer overrun, some messages lost."); + log_ratelimit_warning(JOURNALD_LOG_RATELIMIT, + "/dev/kmsg buffer overrun, some messages lost."); if (!(revents & EPOLLIN)) log_error("Got invalid event from epoll for /dev/kmsg: %"PRIx32, revents); diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c index 032578822d..1d2cb0b71a 100644 --- a/src/journal/journald-native.c +++ b/src/journal/journald-native.c @@ -122,7 +122,8 @@ static int server_process_entry( if (!e) { /* Trailing noise, let's ignore it, and flush what we collected */ - log_debug("Received message with trailing noise, ignoring."); + log_ratelimit_debug(JOURNALD_LOG_RATELIMIT, + "Received message with trailing noise, ignoring."); break; /* finish processing of the message */ } @@ -141,7 +142,8 @@ static int server_process_entry( /* A property follows */ if (n > ENTRY_FIELD_COUNT_MAX) { - log_debug("Received an entry that has more than " STRINGIFY(ENTRY_FIELD_COUNT_MAX) " fields, ignoring entry."); + log_ratelimit_debug(JOURNALD_LOG_RATELIMIT, + "Received an entry that has more than " STRINGIFY(ENTRY_FIELD_COUNT_MAX) " fields, ignoring entry."); goto finish; } @@ -161,13 +163,15 @@ static int server_process_entry( l = e - p; if (l > DATA_SIZE_MAX) { - log_debug("Received text block of %zu bytes is too large, ignoring entry.", l); + log_ratelimit_debug(JOURNALD_LOG_RATELIMIT, + "Received text block of %zu bytes is too large, ignoring entry.", l); goto finish; } if (entry_size + l + n + 1 > ENTRY_SIZE_MAX) { /* data + separators + trailer */ - log_debug("Entry is too big (%zu bytes after processing %zu entries), ignoring entry.", - entry_size + l, n + 1); + log_ratelimit_debug(JOURNALD_LOG_RATELIMIT, + "Entry is too big (%zu bytes after processing %zu entries), ignoring entry.", + entry_size + l, n + 1); goto finish; } @@ -191,26 +195,31 @@ static int server_process_entry( char *k; if (*remaining < e - p + 1 + sizeof(uint64_t) + 1) { - log_debug("Failed to parse message, ignoring."); + log_ratelimit_debug(JOURNALD_LOG_RATELIMIT, + "Failed to parse message, ignoring."); break; } l = unaligned_read_le64(e + 1); if (l > DATA_SIZE_MAX) { - log_debug("Received binary data block of %"PRIu64" bytes is too large, ignoring entry.", l); + log_ratelimit_debug(JOURNALD_LOG_RATELIMIT, + "Received binary data block of %"PRIu64" bytes is too large, ignoring entry.", + l); goto finish; } total = (e - p) + 1 + l; if (entry_size + total + n + 1 > ENTRY_SIZE_MAX) { /* data + separators + trailer */ - log_debug("Entry is too big (%"PRIu64"bytes after processing %zu fields), ignoring.", - entry_size + total, n + 1); + log_ratelimit_debug(JOURNALD_LOG_RATELIMIT, + "Entry is too big (%"PRIu64"bytes after processing %zu fields), ignoring.", + entry_size + total, n + 1); goto finish; } if ((uint64_t) *remaining < e - p + 1 + sizeof(uint64_t) + l + 1 || e[1+sizeof(uint64_t)+l] != '\n') { - log_debug("Failed to parse message, ignoring."); + log_ratelimit_debug(JOURNALD_LOG_RATELIMIT, + "Failed to parse message, ignoring."); break; } @@ -250,7 +259,9 @@ static int server_process_entry( entry_size += STRLEN("_TRANSPORT=journal"); if (entry_size + n + 1 > ENTRY_SIZE_MAX) { /* data + separators + trailer */ - log_debug("Entry is too big with %zu properties and %zu bytes, ignoring.", n, entry_size); + log_ratelimit_debug(JOURNALD_LOG_RATELIMIT, + "Entry is too big with %zu properties and %zu bytes, ignoring.", + n, entry_size); goto finish; } @@ -309,7 +320,9 @@ void server_process_native_message( if (ucred && pid_is_valid(ucred->pid)) { r = client_context_get(s, ucred->pid, ucred, label, label_len, NULL, &context); if (r < 0) - log_warning_errno(r, "Failed to retrieve credentials for PID " PID_FMT ", ignoring: %m", ucred->pid); + log_ratelimit_warning_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to retrieve credentials for PID " PID_FMT ", ignoring: %m", + ucred->pid); } do { @@ -348,29 +361,34 @@ void server_process_native_file( r = fd_get_path(fd, &k); if (r < 0) { - log_error_errno(r, "readlink(/proc/self/fd/%i) failed: %m", fd); + log_ratelimit_error_errno(r, JOURNALD_LOG_RATELIMIT, + "readlink(/proc/self/fd/%i) failed: %m", fd); return; } e = PATH_STARTSWITH_SET(k, "/dev/shm/", "/tmp/", "/var/tmp/"); if (!e) { - log_error("Received file outside of allowed directories. Refusing."); + log_ratelimit_error(JOURNALD_LOG_RATELIMIT, + "Received file outside of allowed directories. Refusing."); return; } if (!filename_is_valid(e)) { - log_error("Received file in subdirectory of allowed directories. Refusing."); + log_ratelimit_error(JOURNALD_LOG_RATELIMIT, + "Received file in subdirectory of allowed directories. Refusing."); return; } } if (fstat(fd, &st) < 0) { - log_error_errno(errno, "Failed to stat passed file, ignoring: %m"); + log_ratelimit_error_errno(errno, JOURNALD_LOG_RATELIMIT, + "Failed to stat passed file, ignoring: %m"); return; } if (!S_ISREG(st.st_mode)) { - log_error("File passed is not regular. Ignoring."); + log_ratelimit_error(JOURNALD_LOG_RATELIMIT, + "File passed is not regular. Ignoring."); return; } @@ -380,7 +398,9 @@ void server_process_native_file( /* When !sealed, set a lower memory limit. We have to read the file, * effectively doubling memory use. */ if (st.st_size > ENTRY_SIZE_MAX / (sealed ? 1 : 2)) { - log_error("File passed too large (%"PRIu64" bytes). Ignoring.", (uint64_t) st.st_size); + log_ratelimit_error(JOURNALD_LOG_RATELIMIT, + "File passed too large (%"PRIu64" bytes). Ignoring.", + (uint64_t) st.st_size); return; } @@ -393,7 +413,8 @@ void server_process_native_file( ps = PAGE_ALIGN(st.st_size); p = mmap(NULL, ps, PROT_READ, MAP_PRIVATE, fd, 0); if (p == MAP_FAILED) { - log_error_errno(errno, "Failed to map memfd, ignoring: %m"); + log_ratelimit_error_errno(errno, JOURNALD_LOG_RATELIMIT, + "Failed to map memfd, ignoring: %m"); return; } @@ -405,7 +426,8 @@ void server_process_native_file( ssize_t n; if (fstatvfs(fd, &vfs) < 0) { - log_error_errno(errno, "Failed to stat file system of passed file, not processing it: %m"); + log_ratelimit_error_errno(errno, JOURNALD_LOG_RATELIMIT, + "Failed to stat file system of passed file, not processing it: %m"); return; } @@ -415,7 +437,8 @@ void server_process_native_file( * https://github.com/systemd/systemd/issues/1822 */ if (vfs.f_flag & ST_MANDLOCK) { - log_error("Received file descriptor from file system with mandatory locking enabled, not processing it."); + log_ratelimit_error(JOURNALD_LOG_RATELIMIT, + "Received file descriptor from file system with mandatory locking enabled, not processing it."); return; } @@ -428,7 +451,8 @@ void server_process_native_file( * and so is SMB. */ r = fd_nonblock(fd, true); if (r < 0) { - log_error_errno(r, "Failed to make fd non-blocking, not processing it: %m"); + log_ratelimit_error_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to make fd non-blocking, not processing it: %m"); return; } @@ -444,7 +468,8 @@ void server_process_native_file( n = pread(fd, p, st.st_size, 0); if (n < 0) - log_error_errno(errno, "Failed to read file, ignoring: %m"); + log_ratelimit_error_errno(errno, JOURNALD_LOG_RATELIMIT, + "Failed to read file, ignoring: %m"); else if (n > 0) server_process_native_message(s, p, n, ucred, tv, label, label_len); } diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index c02d73bdc2..3c49d9fa31 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -83,6 +83,8 @@ #define IDLE_TIMEOUT_USEC (30*USEC_PER_SEC) +#define FAILED_TO_WRITE_ENTRY_RATELIMIT ((RateLimit) { .interval = 1 * USEC_PER_SEC, .burst = 1 }) + static int determine_path_usage( Server *s, const char *path, @@ -99,11 +101,12 @@ static int determine_path_usage( d = opendir(path); if (!d) - return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, - errno, "Failed to open %s: %m", path); + return log_ratelimit_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, + errno, JOURNALD_LOG_RATELIMIT, "Failed to open %s: %m", path); if (fstatvfs(dirfd(d), &ss) < 0) - return log_error_errno(errno, "Failed to fstatvfs(%s): %m", path); + return log_ratelimit_error_errno(errno, JOURNALD_LOG_RATELIMIT, + "Failed to fstatvfs(%s): %m", path); *ret_free = ss.f_bsize * ss.f_bavail; *ret_used = 0; @@ -115,7 +118,8 @@ static int determine_path_usage( continue; if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { - log_debug_errno(errno, "Failed to stat %s/%s, ignoring: %m", path, de->d_name); + log_ratelimit_debug_errno(errno, JOURNALD_LOG_RATELIMIT, + "Failed to stat %s/%s, ignoring: %m", path, de->d_name); continue; } @@ -253,7 +257,8 @@ static void server_add_acls(ManagedJournalFile *f, uid_t uid) { r = fd_add_uid_acl_permission(f->file->fd, uid, ACL_READ); if (r < 0) - log_warning_errno(r, "Failed to set ACL on %s, ignoring: %m", f->file->path); + log_ratelimit_warning_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to set ACL on %s, ignoring: %m", f->file->path); #endif } @@ -353,7 +358,8 @@ static int system_journal_open(Server *s, bool flush_requested, bool relinquish_ patch_min_use(&s->system_storage); } else { if (!IN_SET(r, -ENOENT, -EROFS)) - log_warning_errno(r, "Failed to open system journal: %m"); + log_ratelimit_warning_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to open system journal: %m"); r = 0; } @@ -382,7 +388,8 @@ static int system_journal_open(Server *s, bool flush_requested, bool relinquish_ r = open_journal(s, false, fn, O_RDWR, false, &s->runtime_storage.metrics, &s->runtime_journal); if (r < 0) { if (r != -ENOENT) - log_warning_errno(r, "Failed to open runtime journal: %m"); + log_ratelimit_warning_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to open runtime journal: %m"); r = 0; } @@ -396,7 +403,8 @@ static int system_journal_open(Server *s, bool flush_requested, bool relinquish_ r = open_journal(s, true, fn, O_RDWR|O_CREAT, false, &s->runtime_storage.metrics, &s->runtime_journal); if (r < 0) - return log_error_errno(r, "Failed to open runtime journal: %m"); + return log_ratelimit_warning_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to open runtime journal: %m"); } if (s->runtime_journal) { @@ -493,9 +501,11 @@ static int do_rotate( r = managed_journal_file_rotate(f, s->mmap, file_flags, s->compress.threshold_bytes, s->deferred_closes); if (r < 0) { if (*f) - return log_error_errno(r, "Failed to rotate %s: %m", (*f)->file->path); + return log_ratelimit_error_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to rotate %s: %m", (*f)->file->path); else - return log_error_errno(r, "Failed to create new %s journal: %m", name); + return log_ratelimit_error_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to create new %s journal: %m", name); } server_add_acls(*f, uid); @@ -545,7 +555,8 @@ static int vacuum_offline_user_journals(Server *s) { if (errno == ENOENT) return 0; - return log_error_errno(errno, "Failed to open %s: %m", s->system_storage.path); + return log_ratelimit_error_errno(errno, JOURNALD_LOG_RATELIMIT, + "Failed to open %s: %m", s->system_storage.path); } for (;;) { @@ -560,7 +571,9 @@ static int vacuum_offline_user_journals(Server *s) { de = readdir_no_dot(d); if (!de) { if (errno != 0) - log_warning_errno(errno, "Failed to enumerate %s, ignoring: %m", s->system_storage.path); + log_ratelimit_warning_errno(errno, JOURNALD_LOG_RATELIMIT, + "Failed to enumerate %s, ignoring: %m", + s->system_storage.path); break; } @@ -578,7 +591,9 @@ static int vacuum_offline_user_journals(Server *s) { r = parse_uid(u, &uid); if (r < 0) { - log_debug_errno(r, "Failed to parse UID from file name '%s', ignoring: %m", de->d_name); + log_ratelimit_debug_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to parse UID from file name '%s', ignoring: %m", + de->d_name); continue; } @@ -592,8 +607,9 @@ static int vacuum_offline_user_journals(Server *s) { fd = openat(dirfd(d), de->d_name, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW|O_NONBLOCK); if (fd < 0) { - log_full_errno(IN_SET(errno, ELOOP, ENOENT) ? LOG_DEBUG : LOG_WARNING, errno, - "Failed to open journal file '%s' for rotation: %m", full); + log_ratelimit_full_errno(IN_SET(errno, ELOOP, ENOENT) ? LOG_DEBUG : LOG_WARNING, + errno, JOURNALD_LOG_RATELIMIT, + "Failed to open journal file '%s' for rotation: %m", full); continue; } @@ -615,13 +631,18 @@ static int vacuum_offline_user_journals(Server *s) { NULL, &f); if (r < 0) { - log_warning_errno(r, "Failed to read journal file %s for rotation, trying to move it out of the way: %m", full); + log_ratelimit_warning_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to read journal file %s for rotation, trying to move it out of the way: %m", + full); r = journal_file_dispose(dirfd(d), de->d_name); if (r < 0) - log_warning_errno(r, "Failed to move %s out of the way, ignoring: %m", full); + log_ratelimit_warning_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to move %s out of the way, ignoring: %m", + full); else - log_debug("Successfully moved %s out of the way.", full); + log_ratelimit_debug(JOURNALD_LOG_RATELIMIT, + "Successfully moved %s out of the way.", full); continue; } @@ -630,7 +651,8 @@ static int vacuum_offline_user_journals(Server *s) { r = journal_file_archive(f->file, NULL); if (r < 0) - log_debug_errno(r, "Failed to archive journal file '%s', ignoring: %m", full); + log_ratelimit_debug_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to archive journal file '%s', ignoring: %m", full); managed_journal_file_initiate_close(f, s->deferred_closes); f = NULL; @@ -644,7 +666,7 @@ void server_rotate(Server *s) { void *k; int r; - log_debug("Rotating..."); + log_ratelimit_debug(JOURNALD_LOG_RATELIMIT, "Rotating..."); /* First, rotate the system journal (either in its runtime flavour or in its runtime flavour) */ (void) do_rotate(s, &s->runtime_journal, "runtime", false, 0); @@ -675,19 +697,22 @@ void server_sync(Server *s) { if (s->system_journal) { r = managed_journal_file_set_offline(s->system_journal, false); if (r < 0) - log_warning_errno(r, "Failed to sync system journal, ignoring: %m"); + log_ratelimit_warning_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to sync system journal, ignoring: %m"); } ORDERED_HASHMAP_FOREACH(f, s->user_journals) { r = managed_journal_file_set_offline(f, false); if (r < 0) - log_warning_errno(r, "Failed to sync user journal, ignoring: %m"); + log_ratelimit_warning_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to sync user journal, ignoring: %m"); } if (s->sync_event_source) { r = sd_event_source_set_enabled(s->sync_event_source, SD_EVENT_OFF); if (r < 0) - log_error_errno(r, "Failed to disable sync timer source: %m"); + log_ratelimit_error_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to disable sync timer source: %m"); } s->sync_scheduled = false; @@ -709,7 +734,8 @@ static void do_vacuum(Server *s, JournalStorage *storage, bool verbose) { storage->metrics.n_max_files, s->max_retention_usec, &s->oldest_file_usec, verbose); if (r < 0 && r != -ENOENT) - log_warning_errno(r, "Failed to vacuum %s, ignoring: %m", storage->path); + log_ratelimit_warning_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to vacuum %s, ignoring: %m", storage->path); cache_space_invalidate(&storage->space); } @@ -717,7 +743,7 @@ static void do_vacuum(Server *s, JournalStorage *storage, bool verbose) { void server_vacuum(Server *s, bool verbose) { assert(s); - log_debug("Vacuuming..."); + log_ratelimit_debug(JOURNALD_LOG_RATELIMIT, "Vacuuming..."); s->oldest_file_usec = 0; @@ -777,41 +803,43 @@ static bool shall_try_append_again(JournalFile *f, int r) { case -EFBIG: /* Hit fs limit */ case -EDQUOT: /* Quota limit hit */ case -ENOSPC: /* Disk full */ - log_debug("%s: Allocation limit reached, rotating.", f->path); + log_ratelimit_debug(JOURNALD_LOG_RATELIMIT, "%s: Allocation limit reached, rotating.", f->path); return true; case -EIO: /* I/O error of some kind (mmap) */ - log_warning("%s: IO error, rotating.", f->path); + log_ratelimit_warning(JOURNALD_LOG_RATELIMIT, "%s: IO error, rotating.", f->path); return true; case -EHOSTDOWN: /* Other machine */ - log_info("%s: Journal file from other machine, rotating.", f->path); + log_ratelimit_info(JOURNALD_LOG_RATELIMIT, "%s: Journal file from other machine, rotating.", f->path); return true; case -EBUSY: /* Unclean shutdown */ - log_info("%s: Unclean shutdown, rotating.", f->path); + log_ratelimit_info(JOURNALD_LOG_RATELIMIT, "%s: Unclean shutdown, rotating.", f->path); return true; case -EPROTONOSUPPORT: /* Unsupported feature */ - log_info("%s: Unsupported feature, rotating.", f->path); + log_ratelimit_info(JOURNALD_LOG_RATELIMIT, "%s: Unsupported feature, rotating.", f->path); return true; case -EBADMSG: /* Corrupted */ case -ENODATA: /* Truncated */ case -ESHUTDOWN: /* Already archived */ - log_warning("%s: Journal file corrupted, rotating.", f->path); + log_ratelimit_warning(JOURNALD_LOG_RATELIMIT, "%s: Journal file corrupted, rotating.", f->path); return true; case -EIDRM: /* Journal file has been deleted */ - log_warning("%s: Journal file has been deleted, rotating.", f->path); + log_ratelimit_warning(JOURNALD_LOG_RATELIMIT, "%s: Journal file has been deleted, rotating.", f->path); return true; case -ETXTBSY: /* Journal file is from the future */ - log_warning("%s: Journal file is from the future, rotating.", f->path); + log_ratelimit_warning(JOURNALD_LOG_RATELIMIT, "%s: Journal file is from the future, rotating.", f->path); return true; case -EAFNOSUPPORT: - log_warning("%s: underlying file system does not support memory mapping or another required file system feature.", f->path); + log_ratelimit_warning(JOURNALD_LOG_RATELIMIT, + "%s: underlying file system does not support memory mapping or another required file system feature.", + f->path); return false; default: @@ -841,7 +869,7 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, size_t n * to ensure that the entries in the journal files are strictly ordered by time, in order to ensure * bisection works correctly. */ - log_info("Time jumped backwards, rotating."); + log_ratelimit_info(JOURNALD_LOG_RATELIMIT, "Time jumped backwards, rotating."); rotate = true; } else { @@ -850,7 +878,9 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, size_t n return; if (journal_file_rotate_suggested(f->file, s->max_file_usec, LOG_INFO)) { - log_info("%s: Journal header limits reached or header out-of-date, rotating.", f->file->path); + log_ratelimit_info(JOURNALD_LOG_RATELIMIT, + "%s: Journal header limits reached or header out-of-date, rotating.", + f->file->path); rotate = true; } } @@ -874,14 +904,18 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, size_t n } if (vacuumed || !shall_try_append_again(f->file, r)) { - log_ratelimit_full_errno(LOG_ERR, r, "Failed to write entry (%zu items, %zu bytes), ignoring: %m", n, IOVEC_TOTAL_SIZE(iovec, n)); + log_ratelimit_error_errno(r, FAILED_TO_WRITE_ENTRY_RATELIMIT, + "Failed to write entry (%zu items, %zu bytes), ignoring: %m", + n, IOVEC_TOTAL_SIZE(iovec, n)); return; } if (r == -E2BIG) log_debug("Journal file %s is full, rotating to a new file", f->file->path); else - log_ratelimit_full_errno(LOG_INFO, r, "Failed to write entry to %s (%zu items, %zu bytes), rotating before retrying: %m", f->file->path, n, IOVEC_TOTAL_SIZE(iovec, n)); + log_ratelimit_info_errno(r, FAILED_TO_WRITE_ENTRY_RATELIMIT, + "Failed to write entry to %s (%zu items, %zu bytes), rotating before retrying: %m", + f->file->path, n, IOVEC_TOTAL_SIZE(iovec, n)); server_rotate(s); server_vacuum(s, false); @@ -890,10 +924,12 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, size_t n if (!f) return; - log_debug("Retrying write."); + log_ratelimit_debug_errno(r, JOURNALD_LOG_RATELIMIT, "Retrying write."); r = journal_file_append_entry(f->file, &ts, NULL, iovec, n, &s->seqnum, NULL, NULL); if (r < 0) - log_ratelimit_full_errno(LOG_ERR, r, "Failed to write entry to %s (%zu items, %zu bytes) despite vacuuming, ignoring: %m", f->file->path, n, IOVEC_TOTAL_SIZE(iovec, n)); + log_ratelimit_error_errno(r, FAILED_TO_WRITE_ENTRY_RATELIMIT, + "Failed to write entry to %s (%zu items, %zu bytes) despite vacuuming, ignoring: %m", + f->file->path, n, IOVEC_TOTAL_SIZE(iovec, n)); else server_schedule_sync(s, priority); } @@ -1175,13 +1211,14 @@ int server_flush_to_var(Server *s, bool require_flag_file) { if (!s->system_journal) return 0; - log_debug("Flushing to %s...", s->system_storage.path); + log_ratelimit_debug(JOURNALD_LOG_RATELIMIT, "Flushing to %s...", s->system_storage.path); start = now(CLOCK_MONOTONIC); r = sd_journal_open(&j, SD_JOURNAL_RUNTIME_ONLY); if (r < 0) - return log_error_errno(r, "Failed to read runtime journal: %m"); + return log_ratelimit_error_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to read runtime journal: %m"); sd_journal_set_data_threshold(j, 0); @@ -1196,7 +1233,7 @@ int server_flush_to_var(Server *s, bool require_flag_file) { r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o); if (r < 0) { - log_error_errno(r, "Can't read entry: %m"); + log_ratelimit_error_errno(r, JOURNALD_LOG_RATELIMIT, "Can't read entry: %m"); goto finish; } @@ -1205,25 +1242,26 @@ int server_flush_to_var(Server *s, bool require_flag_file) { continue; if (!shall_try_append_again(s->system_journal->file, r)) { - log_error_errno(r, "Can't write entry: %m"); + log_ratelimit_error_errno(r, JOURNALD_LOG_RATELIMIT, "Can't write entry: %m"); goto finish; } - log_info("Rotating system journal."); + log_ratelimit_info(JOURNALD_LOG_RATELIMIT, "Rotating system journal."); server_rotate(s); server_vacuum(s, false); if (!s->system_journal) { - log_notice("Didn't flush runtime journal since rotation of system journal wasn't successful."); + log_ratelimit_notice(JOURNALD_LOG_RATELIMIT, + "Didn't flush runtime journal since rotation of system journal wasn't successful."); r = -EIO; goto finish; } - log_debug("Retrying write."); + log_ratelimit_debug(JOURNALD_LOG_RATELIMIT, "Retrying write."); r = journal_file_copy_entry(f, s->system_journal->file, o, f->current_offset); if (r < 0) { - log_error_errno(r, "Can't write entry: %m"); + log_ratelimit_error_errno(r, JOURNALD_LOG_RATELIMIT, "Can't write entry: %m"); goto finish; } } @@ -1251,7 +1289,8 @@ finish: fn = strjoina(s->runtime_directory, "/flushed"); k = touch(fn); if (k < 0) - log_warning_errno(k, "Failed to touch %s, ignoring: %m", fn); + log_ratelimit_warning_errno(k, JOURNALD_LOG_RATELIMIT, + "Failed to touch %s, ignoring: %m", fn); server_refresh_idle_timer(s); return r; @@ -1270,7 +1309,7 @@ static int server_relinquish_var(Server *s) { if (s->runtime_journal && !s->system_journal) return 0; - log_debug("Relinquishing %s...", s->system_storage.path); + log_ratelimit_debug(JOURNALD_LOG_RATELIMIT, "Relinquishing %s...", s->system_storage.path); (void) system_journal_open(s, false, true); @@ -1280,7 +1319,8 @@ static int server_relinquish_var(Server *s) { fn = strjoina(s->runtime_directory, "/flushed"); if (unlink(fn) < 0 && errno != ENOENT) - log_warning_errno(errno, "Failed to unlink %s, ignoring: %m", fn); + log_ratelimit_warning_errno(errno, JOURNALD_LOG_RATELIMIT, + "Failed to unlink %s, ignoring: %m", fn); server_refresh_idle_timer(s); return 0; @@ -1352,10 +1392,11 @@ int server_process_datagram( if (ERRNO_IS_TRANSIENT(n)) return 0; if (n == -EXFULL) { - log_warning("Got message with truncated control data (too many fds sent?), ignoring."); + log_ratelimit_warning(JOURNALD_LOG_RATELIMIT, + "Got message with truncated control data (too many fds sent?), ignoring."); return 0; } - return log_error_errno(n, "recvmsg() failed: %m"); + return log_ratelimit_error_errno(n, JOURNALD_LOG_RATELIMIT, "recvmsg() failed: %m"); } CMSG_FOREACH(cmsg, &msghdr) @@ -1388,7 +1429,8 @@ int server_process_datagram( if (n > 0 && n_fds == 0) server_process_syslog_message(s, s->buffer, n, ucred, tv, label, label_len); else if (n_fds > 0) - log_warning("Got file descriptors via syslog socket. Ignoring."); + log_ratelimit_warning(JOURNALD_LOG_RATELIMIT, + "Got file descriptors via syslog socket. Ignoring."); } else if (fd == s->native_fd) { if (n > 0 && n_fds == 0) @@ -1396,7 +1438,8 @@ int server_process_datagram( else if (n == 0 && n_fds == 1) server_process_native_file(s, fds[0], ucred, tv, label, label_len); else if (n_fds > 0) - log_warning("Got too many file descriptors via native socket. Ignoring."); + log_ratelimit_warning(JOURNALD_LOG_RATELIMIT, + "Got too many file descriptors via native socket. Ignoring."); } else { assert(fd == s->audit_fd); @@ -1404,7 +1447,8 @@ int server_process_datagram( if (n > 0 && n_fds == 0) server_process_audit_message(s, s->buffer, n, ucred, &sa, msghdr.msg_namelen); else if (n_fds > 0) - log_warning("Got file descriptors via audit socket. Ignoring."); + log_ratelimit_warning(JOURNALD_LOG_RATELIMIT, + "Got file descriptors via audit socket. Ignoring."); } close_many(fds, n_fds); @@ -1457,7 +1501,8 @@ static void server_full_rotate(Server *s) { fn = strjoina(s->runtime_directory, "/rotated"); r = write_timestamp_file_atomic(fn, now(CLOCK_MONOTONIC)); if (r < 0) - log_warning_errno(r, "Failed to write %s, ignoring: %m", fn); + log_ratelimit_warning_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to write %s, ignoring: %m", fn); } static int dispatch_sigusr2(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) { @@ -1560,7 +1605,8 @@ static void server_full_sync(Server *s) { fn = strjoina(s->runtime_directory, "/synced"); r = write_timestamp_file_atomic(fn, now(CLOCK_MONOTONIC)); if (r < 0) - log_warning_errno(r, "Failed to write %s, ignoring: %m", fn); + log_ratelimit_warning_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to write %s, ignoring: %m", fn); return; } diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h index ee8f374190..84efb04265 100644 --- a/src/journal/journald-server.h +++ b/src/journal/journald-server.h @@ -20,6 +20,8 @@ typedef struct Server Server; #include "time-util.h" #include "varlink.h" +#define JOURNALD_LOG_RATELIMIT ((RateLimit) { .interval = 60 * USEC_PER_SEC, .burst = 3 }) + typedef enum Storage { STORAGE_AUTO, STORAGE_VOLATILE, diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c index 8bdcd8c2ae..abfd046837 100644 --- a/src/journal/journald-stream.c +++ b/src/journal/journald-stream.c @@ -160,7 +160,8 @@ static int stdout_stream_save(StdoutStream *s) { r = fstat(s->fd, &st); if (r < 0) - return log_warning_errno(errno, "Failed to stat connected stream: %m"); + return log_ratelimit_warning_errno(errno, JOURNALD_LOG_RATELIMIT, + "Failed to stat connected stream: %m"); /* We use device and inode numbers as identifier for the stream */ r = asprintf(&s->state_file, "%s/streams/%lu:%lu", s->server->runtime_directory, (unsigned long) st.st_dev, (unsigned long) st.st_ino); @@ -231,7 +232,7 @@ static int stdout_stream_save(StdoutStream *s) { if (s->server->notify_event_source) { r = sd_event_source_set_enabled(s->server->notify_event_source, SD_EVENT_ON); if (r < 0) - log_warning_errno(r, "Failed to enable notify event source: %m"); + log_ratelimit_warning_errno(r, JOURNALD_LOG_RATELIMIT, "Failed to enable notify event source: %m"); } } @@ -239,7 +240,8 @@ static int stdout_stream_save(StdoutStream *s) { fail: (void) unlink(s->state_file); - return log_error_errno(r, "Failed to save stream data %s: %m", s->state_file); + return log_ratelimit_error_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to save stream data %s: %m", s->state_file); } static int stdout_stream_log( @@ -266,7 +268,8 @@ static int stdout_stream_log( else if (pid_is_valid(s->ucred.pid)) { r = client_context_acquire(s->server, s->ucred.pid, &s->ucred, s->label, strlen_ptr(s->label), s->unit_id, &s->context); if (r < 0) - log_warning_errno(r, "Failed to acquire client context, ignoring: %m"); + log_ratelimit_warning_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to acquire client context, ignoring: %m"); } priority = s->priority; @@ -363,8 +366,8 @@ static int stdout_stream_line(StdoutStream *s, char *p, LineBreak line_break) { /* line breaks by NUL, line max length or EOF are not permissible during the negotiation part of the protocol */ if (line_break != LINE_BREAK_NEWLINE && s->state != STDOUT_STREAM_RUNNING) - return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), - "Control protocol line not properly terminated."); + return log_ratelimit_warning_errno(SYNTHETIC_ERRNO(EINVAL), JOURNALD_LOG_RATELIMIT, + "Control protocol line not properly terminated."); switch (s->state) { @@ -395,7 +398,8 @@ static int stdout_stream_line(StdoutStream *s, char *p, LineBreak line_break) { priority = syslog_parse_priority_and_facility(p); if (priority < 0) - return log_warning_errno(priority, "Failed to parse log priority line: %m"); + return log_ratelimit_warning_errno(priority, JOURNALD_LOG_RATELIMIT, + "Failed to parse log priority line: %m"); s->priority = priority; s->state = STDOUT_STREAM_LEVEL_PREFIX; @@ -405,7 +409,8 @@ static int stdout_stream_line(StdoutStream *s, char *p, LineBreak line_break) { case STDOUT_STREAM_LEVEL_PREFIX: r = parse_boolean(p); if (r < 0) - return log_warning_errno(r, "Failed to parse level prefix line: %m"); + return log_ratelimit_warning_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to parse level prefix line: %m"); s->level_prefix = r; s->state = STDOUT_STREAM_FORWARD_TO_SYSLOG; @@ -414,7 +419,8 @@ static int stdout_stream_line(StdoutStream *s, char *p, LineBreak line_break) { case STDOUT_STREAM_FORWARD_TO_SYSLOG: r = parse_boolean(p); if (r < 0) - return log_warning_errno(r, "Failed to parse forward to syslog line: %m"); + return log_ratelimit_warning_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to parse forward to syslog line: %m"); s->forward_to_syslog = r; s->state = STDOUT_STREAM_FORWARD_TO_KMSG; @@ -423,7 +429,8 @@ static int stdout_stream_line(StdoutStream *s, char *p, LineBreak line_break) { case STDOUT_STREAM_FORWARD_TO_KMSG: r = parse_boolean(p); if (r < 0) - return log_warning_errno(r, "Failed to parse copy to kmsg line: %m"); + return log_ratelimit_warning_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to parse copy to kmsg line: %m"); s->forward_to_kmsg = r; s->state = STDOUT_STREAM_FORWARD_TO_CONSOLE; @@ -432,7 +439,8 @@ static int stdout_stream_line(StdoutStream *s, char *p, LineBreak line_break) { case STDOUT_STREAM_FORWARD_TO_CONSOLE: r = parse_boolean(p); if (r < 0) - return log_warning_errno(r, "Failed to parse copy to console line."); + return log_ratelimit_warning_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to parse copy to console line."); s->forward_to_console = r; s->state = STDOUT_STREAM_RUNNING; @@ -589,7 +597,7 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, if (ERRNO_IS_TRANSIENT(errno)) return 0; - log_warning_errno(errno, "Failed to read from stream: %m"); + log_ratelimit_warning_errno(errno, JOURNALD_LOG_RATELIMIT, "Failed to read from stream: %m"); goto terminate; } cmsg_close_all(&msghdr); @@ -648,7 +656,7 @@ int stdout_stream_install(Server *s, int fd, StdoutStream **ret) { r = sd_id128_randomize(&id); if (r < 0) - return log_error_errno(r, "Failed to generate stream ID: %m"); + return log_ratelimit_error_errno(r, JOURNALD_LOG_RATELIMIT, "Failed to generate stream ID: %m"); stream = new(StdoutStream, 1); if (!stream) @@ -664,7 +672,7 @@ int stdout_stream_install(Server *s, int fd, StdoutStream **ret) { r = getpeercred(fd, &stream->ucred); if (r < 0) - return log_error_errno(r, "Failed to determine peer credentials: %m"); + return log_ratelimit_error_errno(r, JOURNALD_LOG_RATELIMIT, "Failed to determine peer credentials: %m"); r = setsockopt_int(fd, SOL_SOCKET, SO_PASSCRED, true); if (r < 0) @@ -673,18 +681,18 @@ int stdout_stream_install(Server *s, int fd, StdoutStream **ret) { if (mac_selinux_use()) { r = getpeersec(fd, &stream->label); if (r < 0 && r != -EOPNOTSUPP) - (void) log_warning_errno(r, "Failed to determine peer security context: %m"); + (void) log_ratelimit_warning_errno(r, JOURNALD_LOG_RATELIMIT, "Failed to determine peer security context: %m"); } (void) shutdown(fd, SHUT_WR); r = sd_event_add_io(s->event, &stream->event_source, fd, EPOLLIN, stdout_stream_process, stream); if (r < 0) - return log_error_errno(r, "Failed to add stream to event loop: %m"); + return log_ratelimit_error_errno(r, JOURNALD_LOG_RATELIMIT, "Failed to add stream to event loop: %m"); r = sd_event_source_set_priority(stream->event_source, SD_EVENT_PRIORITY_NORMAL+5); if (r < 0) - return log_error_errno(r, "Failed to adjust stdout event source priority: %m"); + return log_ratelimit_error_errno(r, JOURNALD_LOG_RATELIMIT, "Failed to adjust stdout event source priority: %m"); stream->fd = fd; @@ -716,7 +724,7 @@ static int stdout_stream_new(sd_event_source *es, int listen_fd, uint32_t revent if (ERRNO_IS_ACCEPT_AGAIN(errno)) return 0; - return log_error_errno(errno, "Failed to accept stdout connection: %m"); + return log_ratelimit_error_errno(errno, JOURNALD_LOG_RATELIMIT, "Failed to accept stdout connection: %m"); } if (s->n_stdout_streams >= STDOUT_STREAMS_MAX) { diff --git a/src/journal/journald-syslog.c b/src/journal/journald-syslog.c index ce02378675..4592bc7bba 100644 --- a/src/journal/journald-syslog.c +++ b/src/journal/journald-syslog.c @@ -50,7 +50,8 @@ static void forward_syslog_iovec( j = strjoina(s->runtime_directory, "/syslog"); r = sockaddr_un_set_path(&sa.un, j); if (r < 0) { - log_debug_errno(r, "Forwarding socket path %s too long for AF_UNIX, not forwarding: %m", j); + log_ratelimit_debug_errno(r, JOURNALD_LOG_RATELIMIT, + "Forwarding socket path %s too long for AF_UNIX, not forwarding: %m", j); return; } @@ -104,7 +105,7 @@ static void forward_syslog_iovec( } if (errno != ENOENT) - log_debug_errno(errno, "Failed to forward syslog message: %m"); + log_ratelimit_debug_errno(errno, JOURNALD_LOG_RATELIMIT, "Failed to forward syslog message: %m"); } static void forward_syslog_raw(Server *s, int priority, const char *buffer, size_t buffer_len, const struct ucred *ucred, const struct timeval *tv) { @@ -334,7 +335,9 @@ void server_process_syslog_message( if (ucred && pid_is_valid(ucred->pid)) { r = client_context_get(s, ucred->pid, ucred, label, label_len, NULL, &context); if (r < 0) - log_warning_errno(r, "Failed to retrieve credentials for PID " PID_FMT ", ignoring: %m", ucred->pid); + log_ratelimit_warning_errno(r, JOURNALD_LOG_RATELIMIT, + "Failed to retrieve credentials for PID " PID_FMT ", ignoring: %m", + ucred->pid); } /* We are creating a copy of the message because we want to forward the original message diff --git a/src/journal/journald-wall.c b/src/journal/journald-wall.c index 21ec5a785b..e7d4adca3e 100644 --- a/src/journal/journald-wall.c +++ b/src/journal/journald-wall.c @@ -50,5 +50,5 @@ void server_forward_wall( r = utmp_wall(l, "systemd-journald", NULL, NULL, NULL); if (r < 0) - log_debug_errno(r, "Failed to send wall message: %m"); + log_ratelimit_debug_errno(r, JOURNALD_LOG_RATELIMIT, "Failed to send wall message: %m"); } diff --git a/src/libsystemd/sd-journal/journal-file.c b/src/libsystemd/sd-journal/journal-file.c index 3f0dcaebf1..23eed6f8dd 100644 --- a/src/libsystemd/sd-journal/journal-file.c +++ b/src/libsystemd/sd-journal/journal-file.c @@ -4161,6 +4161,10 @@ int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot_id, u return 1; } +/* Ideally this would be a function parameter but initializers for static fields have to be compile + * time constants so we hardcode the interval instead. */ +#define LOG_RATELIMIT ((RateLimit) { .interval = 60 * USEC_PER_SEC, .burst = 3 }) + bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec, int log_level) { assert(f); assert(f->header); @@ -4178,25 +4182,27 @@ bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec, int log if (JOURNAL_HEADER_CONTAINS(f->header, n_data)) if (le64toh(f->header->n_data) * 4ULL > (le64toh(f->header->data_hash_table_size) / sizeof(HashItem)) * 3ULL) { - log_full(log_level, - "Data hash table of %s has a fill level at %.1f (%"PRIu64" of %"PRIu64" items, %llu file size, %"PRIu64" bytes per hash table item), suggesting rotation.", - f->path, - 100.0 * (double) le64toh(f->header->n_data) / ((double) (le64toh(f->header->data_hash_table_size) / sizeof(HashItem))), - le64toh(f->header->n_data), - le64toh(f->header->data_hash_table_size) / sizeof(HashItem), - (unsigned long long) f->last_stat.st_size, - f->last_stat.st_size / le64toh(f->header->n_data)); + log_ratelimit_full( + log_level, LOG_RATELIMIT, + "Data hash table of %s has a fill level at %.1f (%"PRIu64" of %"PRIu64" items, %llu file size, %"PRIu64" bytes per hash table item), suggesting rotation.", + f->path, + 100.0 * (double) le64toh(f->header->n_data) / ((double) (le64toh(f->header->data_hash_table_size) / sizeof(HashItem))), + le64toh(f->header->n_data), + le64toh(f->header->data_hash_table_size) / sizeof(HashItem), + (unsigned long long) f->last_stat.st_size, + f->last_stat.st_size / le64toh(f->header->n_data)); return true; } if (JOURNAL_HEADER_CONTAINS(f->header, n_fields)) if (le64toh(f->header->n_fields) * 4ULL > (le64toh(f->header->field_hash_table_size) / sizeof(HashItem)) * 3ULL) { - log_full(log_level, - "Field hash table of %s has a fill level at %.1f (%"PRIu64" of %"PRIu64" items), suggesting rotation.", - f->path, - 100.0 * (double) le64toh(f->header->n_fields) / ((double) (le64toh(f->header->field_hash_table_size) / sizeof(HashItem))), - le64toh(f->header->n_fields), - le64toh(f->header->field_hash_table_size) / sizeof(HashItem)); + log_ratelimit_full( + log_level, LOG_RATELIMIT, + "Field hash table of %s has a fill level at %.1f (%"PRIu64" of %"PRIu64" items), suggesting rotation.", + f->path, + 100.0 * (double) le64toh(f->header->n_fields) / ((double) (le64toh(f->header->field_hash_table_size) / sizeof(HashItem))), + le64toh(f->header->n_fields), + le64toh(f->header->field_hash_table_size) / sizeof(HashItem)); return true; } @@ -4204,17 +4210,19 @@ bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec, int log * longest chain is longer than some threshold, let's suggest rotation. */ if (JOURNAL_HEADER_CONTAINS(f->header, data_hash_chain_depth) && le64toh(f->header->data_hash_chain_depth) > HASH_CHAIN_DEPTH_MAX) { - log_full(log_level, - "Data hash table of %s has deepest hash chain of length %" PRIu64 ", suggesting rotation.", - f->path, le64toh(f->header->data_hash_chain_depth)); + log_ratelimit_full( + log_level, LOG_RATELIMIT, + "Data hash table of %s has deepest hash chain of length %" PRIu64 ", suggesting rotation.", + f->path, le64toh(f->header->data_hash_chain_depth)); return true; } if (JOURNAL_HEADER_CONTAINS(f->header, field_hash_chain_depth) && le64toh(f->header->field_hash_chain_depth) > HASH_CHAIN_DEPTH_MAX) { - log_full(log_level, - "Field hash table of %s has deepest hash chain of length at %" PRIu64 ", suggesting rotation.", - f->path, le64toh(f->header->field_hash_chain_depth)); + log_ratelimit_full( + log_level, LOG_RATELIMIT, + "Field hash table of %s has deepest hash chain of length at %" PRIu64 ", suggesting rotation.", + f->path, le64toh(f->header->field_hash_chain_depth)); return true; } @@ -4223,9 +4231,10 @@ bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec, int log JOURNAL_HEADER_CONTAINS(f->header, n_fields) && le64toh(f->header->n_data) > 0 && le64toh(f->header->n_fields) == 0) { - log_full(log_level, - "Data objects of %s are not indexed by field objects, suggesting rotation.", - f->path); + log_ratelimit_full( + log_level, LOG_RATELIMIT, + "Data objects of %s are not indexed by field objects, suggesting rotation.", + f->path); return true; } @@ -4236,9 +4245,10 @@ bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec, int log t = now(CLOCK_REALTIME); if (h > 0 && t > h + max_file_usec) { - log_full(log_level, - "Oldest entry in %s is older than the configured file retention duration (%s), suggesting rotation.", - f->path, FORMAT_TIMESPAN(max_file_usec, USEC_PER_SEC)); + log_ratelimit_full( + log_level, LOG_RATELIMIT, + "Oldest entry in %s is older than the configured file retention duration (%s), suggesting rotation.", + f->path, FORMAT_TIMESPAN(max_file_usec, USEC_PER_SEC)); return true; } } |