[PATCH] syslogd: try to handle ENOSPC during writes
Joshua Judson Rosen
jrosen at harvestai.com
Tue May 20 05:09:36 UTC 2014
Unlink the oldest rotated-out logfile
and then try writing the rest of the msg.
Signed-off-by: Joshua Judson Rosen <jrosen at harvestai.com>
---
sysklogd/Config.src | 9 ++++++
sysklogd/syslogd.c | 79 ++++++++++++++++++++++++++++++++++++++++++++-------
2 files changed, 78 insertions(+), 10 deletions(-)
diff --git a/sysklogd/Config.src b/sysklogd/Config.src
index 7938f6f..eefd261 100644
--- a/sysklogd/Config.src
+++ b/sysklogd/Config.src
@@ -50,6 +50,15 @@ config FEATURE_LOGROTATE_CMD
an external command to call in order to rotate
logs when they pass the rotation-threshold.
+config FEATURE_LOGROTATE_ENOSPC
+ bool "Support emergency pruning on ENOSPC"
+ default n
+ depends on FEATURE_ROTATE_LOGFILE
+ help
+ This makes the log-writing logic for each
+ logfile try to handle ENOSPC errors by
+ discarding the oldest already-rotated logfiles.
+
config FEATURE_LOGROTATE_TIMESTAMPS
bool "Suffix rotated logfile names with timestamps"
default n
diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c
index 689b036..43c08cd 100644
--- a/sysklogd/syslogd.c
+++ b/sysklogd/syslogd.c
@@ -609,6 +609,32 @@ static void log_locally(time_t now, char *msg, logFile_t *log_file)
struct flock fl;
#endif
int len = strlen(msg);
+#if ENABLE_FEATURE_ROTATE_LOGFILE
+ int oldname_len = strlen(log_file->path);
+#endif
+#if ENABLE_FEATURE_LOGROTATE_TIMESTAMPS
+ char globpat[oldname_len + 1 + 5*14 + 1];
+ /* . YYYYmmddHHMMSS */
+#elif ENABLE_FEATURE_LOGROTATE_ENOSPC
+ char globpat[oldname_len + 1 + 1 + 5 + 1 + 10 + 1 + 1];
+ /* . { [0-9] , [0-9][0-9] } */
+#endif
+#if ENABLE_FEATURE_LOGROTATE_TIMESTAMPS || ENABLE_FEATURE_LOGROTATE_ENOSPC
+ glob_t globres;
+#endif
+#if ENABLE_FEATURE_LOGROTATE_TIMESTAMPS
+ /* FIXME: this glob doesn't DTRT for old series-stamped
+ "^*.[[:digit:]]$" logfiles; may want to use scandir
+ to control sorting:
+ */
+ sprintf(globpat, "%s.[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]", log_file->path);
+#elif ENABLE_FEATURE_LOGROTATE_ENOSPC
+ sprintf(globpat, "%s.{[0-9],[0-9][0-9]}"); /* 0..9 or 10..99 */
+#endif
+
+#if ENABLE_FEATURE_LOGROTATE_ENOSPC
+ int len_written;
+#endif
if (log_file->fd >= 0) {
/* Reopen log file every second. This allows admin
@@ -670,7 +696,6 @@ static void log_locally(time_t now, char *msg, logFile_t *log_file)
* the new file).
*/
} else) if (G.logFileRotate) { /* always 0..99 */
- int oldname_len = strlen(log_file->path);
#if ENABLE_FEATURE_LOGROTATE_TIMESTAMPS
int i = oldname_len + 1 + 4 + 2 + 2 + 2 + 2 + 2 + 1;
/* . Y m d H M S */
@@ -680,17 +705,9 @@ static void log_locally(time_t now, char *msg, logFile_t *log_file)
#endif
char newFile[i];
#if ENABLE_FEATURE_LOGROTATE_TIMESTAMPS
- char globpat[oldname_len + 1 + 5*14 + 1]; /* .YYYYmmddHHMMSS */
- glob_t globres;
-
struct stat statbuf;
struct tm *ltmp;
- /* FIXME: this glob doesn't DTRT for old series-stamped
- "^*.[[:digit:]]$" logfiles; may want to use scandir
- to control sorting:
- */
- sprintf(globpat, "%s.[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]", log_file->path);
glob(globpat, 0, NULL, &globres);
i = 0;
@@ -737,9 +754,51 @@ static void log_locally(time_t now, char *msg, logFile_t *log_file)
close(log_file->fd);
goto reopen;
}
+#if ENABLE_FEATURE_LOGROTATE_ENOSPC
+ len_written = 0;
+#endif
+continue_writing:
log_file->size +=
#endif
- full_write(log_file->fd, msg, len);
+#if ENABLE_FEATURE_LOGROTATE_ENOSPC
+ /* this may be -1 if the write fails *immediately*,
+ * or any other value <= len if full_write needs
+ * to break the write up into multiple chunks
+ * and doesn't fail until one of the later chunks:
+ */
+ (len_written =
+#endif
+ full_write(log_file->fd, msg
+#if ENABLE_FEATURE_LOGROTATE_ENOSPC
+ + (len_written < 0 ? 0 : len_written)
+#endif
+ , len - (len_written < 0 ? 0 : len_written))
+#if ENABLE_FEATURE_LOGROTATE_ENOSPC
+ )
+#endif
+ ;
+#if ENABLE_FEATURE_LOGROTATE_ENOSPC
+ if (len_written < len && errno == ENOSPC) {
+ glob(globpat, GLOB_BRACE, NULL, &globres);
+ if (globres.gl_pathc) {
+#if ENABLE_FEATURE_LOGROTATE_TIMESTAMPS
+ /* older timestamps sort earlier;
+ * remove the oldest=first one:
+ */
+ unlink(globres.gl_pathv[0]);
+#else
+ /* older logfiles have higher sequence-numbers and sort later;
+ * remove the oldest=last one:
+ */
+ unlink(globres.gl_pathv[globres.gl_pathc - 1]);
+#endif
+ }
+
+ globfree(&globres);
+ goto continue_writing;
+ }
+#endif
+
#ifdef SYSLOGD_WRLOCK
fl.l_type = F_UNLCK;
fcntl(log_file->fd, F_SETLKW, &fl);
--
1.7.10.4
More information about the busybox
mailing list