|
|
ff08e8 |
From 628d791b26062945fad4afa5985f6b84f46f16d4 Mon Sep 17 00:00:00 2001
|
|
|
ff08e8 |
From: Jiri Vymazal <jvymazal@redhat.com>
|
|
|
ff08e8 |
Date: Tue, 23 Jul 2019 11:28:31 +0200
|
|
|
ff08e8 |
Subject: [PATCH] Add "fsync" option for imjournal
|
|
|
ff08e8 |
|
|
|
ff08e8 |
The new option makes possible to force physical write of stateFile
|
|
|
ff08e8 |
to persistent storage, ensuring we do not lose/duplicate messages
|
|
|
ff08e8 |
in case of hard crash or power loss.
|
|
|
ff08e8 |
---
|
|
|
ff08e8 |
plugins/imjournal/imjournal.c | 41 +++++++++++++++----
|
|
|
ff08e8 |
1 file changed, 32 insertions(+), 9 deletitions(-)
|
|
|
ff08e8 |
|
|
|
ff08e8 |
diff --git a/plugins/imjournal/imjournal.c b/plugins/imjournal/imjournal.c
|
|
|
ff08e8 |
index 5739bf408c..6c8829243a 100644
|
|
|
ff08e8 |
--- a/plugins/imjournal/imjournal.c
|
|
|
ff08e8 |
+++ b/plugins/imjournal/imjournal.c
|
|
|
ff08e8 |
@@ -24,6 +24,7 @@
|
|
|
ff08e8 |
#include "config.h"
|
|
|
ff08e8 |
#include "rsyslog.h"
|
|
|
ff08e8 |
#include <stdio.h>
|
|
|
ff08e8 |
+#include <dirent.h>
|
|
|
ff08e8 |
#include <assert.h>
|
|
|
ff08e8 |
#include <string.h>
|
|
|
ff08e8 |
#include <stdarg.h>
|
|
|
ff08e8 |
@@ -81,6 +82,7 @@ static struct configSettings_s {
|
|
|
ff08e8 |
int bUseJnlPID;
|
|
|
ff08e8 |
char *dfltTag;
|
|
|
ff08e8 |
int bWorkAroundJournalBug;
|
|
|
ff08e8 |
+ int bFsync;
|
|
|
ff08e8 |
} cs;
|
|
|
ff08e8 |
|
|
|
ff08e8 |
static rsRetVal facilityHdlr(uchar **pp, void *pVal);
|
|
|
ff08e8 |
@@ -99,7 +99,8 @@ static struct cnfparamdescr modpdescr[] = {
|
|
|
ff08e8 |
{ "defaultfacility", eCmdHdlrString, 0 },
|
|
|
ff08e8 |
{ "usepidfromsystem", eCmdHdlrBinary, 0 },
|
|
|
ff08e8 |
{ "defaulttag", eCmdHdlrGetWord, 0 },
|
|
|
ff08e8 |
- { "workaroundjournalbug", eCmdHdlrBinary, 0 }
|
|
|
ff08e8 |
+ { "workaroundjournalbug", eCmdHdlrBinary, 0 },
|
|
|
ff08e8 |
+ { "fsync", eCmdHdlrBinary, 0 }
|
|
|
ff08e8 |
};
|
|
|
ff08e8 |
static struct cnfparamblk modpblk =
|
|
|
ff08e8 |
{ CNFPARAMBLK_VERSION,
|
|
|
ff08e8 |
@@ -437,7 +437,7 @@ persistJournalState(int trySave)
|
|
|
ff08e8 |
persistJournalState(int trySave)
|
|
|
ff08e8 |
{
|
|
|
ff08e8 |
DEFiRet;
|
|
|
ff08e8 |
- FILE *sf; /* state file */
|
|
|
ff08e8 |
+ FILE *sf = NULL; /* state file */
|
|
|
ff08e8 |
char tmp_sf[MAXFNAME];
|
|
|
ff08e8 |
int ret = 0;
|
|
|
ff08e8 |
|
|
|
ff08e8 |
@@ -468,13 +468,6 @@ persistJournalState(int trySave)
|
|
|
ff08e8 |
ret = fputs(last_cursor, sf);
|
|
|
ff08e8 |
if (ret < 0) {
|
|
|
ff08e8 |
errmsg.LogError(errno, RS_RET_IO_ERROR, "imjournal: failed to save cursor to: '%s'", tmp_sf);
|
|
|
ff08e8 |
- ret = fclose(sf);
|
|
|
ff08e8 |
- ABORT_FINALIZE(RS_RET_IO_ERROR);
|
|
|
ff08e8 |
- }
|
|
|
ff08e8 |
-
|
|
|
ff08e8 |
- ret = fclose(sf);
|
|
|
ff08e8 |
- if (ret < 0) {
|
|
|
ff08e8 |
- errmsg.LogError(errno, RS_RET_IO_ERROR, "imjournal: fclose() failed for path: '%s'", tmp_sf);
|
|
|
ff08e8 |
ABORT_FINALIZE(RS_RET_IO_ERROR);
|
|
|
ff08e8 |
}
|
|
|
ff08e8 |
|
|
|
ff08e8 |
@@ -484,7 +477,30 @@ persistJournalState(int trySave)
|
|
|
ff08e8 |
ABORT_FINALIZE(RS_RET_IO_ERROR);
|
|
|
ff08e8 |
}
|
|
|
ff08e8 |
|
|
|
ff08e8 |
+ if (cs.bFsync) {
|
|
|
ff08e8 |
+ if (fsync(fileno(sf)) != 0) {
|
|
|
ff08e8 |
+ LogError(errno, RS_RET_IO_ERROR, "imjournal: fsync on '%s' failed", cs.stateFile);
|
|
|
ff08e8 |
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
|
|
|
ff08e8 |
+ }
|
|
|
ff08e8 |
+ /* In order to guarantee physical write we need to force parent sync as well */
|
|
|
ff08e8 |
+ DIR *wd;
|
|
|
ff08e8 |
+ if (!(wd = opendir((char *)glbl.GetWorkDir()))) {
|
|
|
ff08e8 |
+ LogError(errno, RS_RET_IO_ERROR, "imjournal: failed to open '%s' directory", glbl.GetWorkDir());
|
|
|
ff08e8 |
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
|
|
|
ff08e8 |
+ }
|
|
|
ff08e8 |
+ if (fsync(dirfd(wd)) != 0) {
|
|
|
ff08e8 |
+ LogError(errno, RS_RET_IO_ERROR, "imjournal: fsync on '%s' failed", glbl.GetWorkDir());
|
|
|
ff08e8 |
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
|
|
|
ff08e8 |
+ }
|
|
|
ff08e8 |
+ }
|
|
|
ff08e8 |
+
|
|
|
ff08e8 |
finalize_it:
|
|
|
ff08e8 |
+ if (sf != NULL) {
|
|
|
ff08e8 |
+ if (fclose(sf) == EOF) {
|
|
|
ff08e8 |
+ LogError(errno, RS_RET_IO_ERROR, "imjournal: fclose() failed for path: '%s'", tmp_sf);
|
|
|
ff08e8 |
+ iRet = RS_RET_IO_ERROR;
|
|
|
ff08e8 |
+ }
|
|
|
ff08e8 |
+ }
|
|
|
ff08e8 |
RETiRet;
|
|
|
ff08e8 |
}
|
|
|
ff08e8 |
|
|
|
ff08e8 |
@@ -746,6 +747,8 @@ CODESTARTbeginCnfLoad
|
|
|
ff08e8 |
cs.iDfltFacility = DFLT_FACILITY;
|
|
|
ff08e8 |
cs.dfltTag = NULL;
|
|
|
ff08e8 |
cs.bUseJnlPID = 0;
|
|
|
ff08e8 |
+ cs.bWorkAroundJournalBug = 0;
|
|
|
ff08e8 |
+ cs.bFsync = 0;
|
|
|
ff08e8 |
ENDbeginCnfLoad
|
|
|
ff08e8 |
|
|
|
ff08e8 |
|
|
|
ff08e8 |
@@ -943,6 +963,8 @@ CODESTARTsetModCnf
|
|
|
ff08e8 |
cs.dfltTag = (char *)es_str2cstr(pvals[i].val.d.estr, NULL);
|
|
|
ff08e8 |
} else if (!strcmp(modpblk.descr[i].name, "workaroundjournalbug")) {
|
|
|
ff08e8 |
cs.bWorkAroundJournalBug = (int) pvals[i].val.d.n;
|
|
|
ff08e8 |
+ } else if (!strcmp(modpblk.descr[i].name, "fsync")) {
|
|
|
ff08e8 |
+ cs.bFsync = (int) pvals[i].val.d.n;
|
|
|
ff08e8 |
} else {
|
|
|
ff08e8 |
dbgprintf("imjournal: program error, non-handled "
|
|
|
ff08e8 |
"param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
|