From f44275403f866cd0a7e0e40714c249ec5903d356 Mon Sep 17 00:00:00 2001 From: Kyle Walker Date: Wed, 30 Jan 2019 07:50:55 -0500 Subject: [PATCH] sadc: Add a -f flag to force fdatasync() use For quite some time, the sadc utility has not used fdatasync() when writing stat information to disk. This resulted in instances where data files could be corrupted or entries lost if a system encountered a sudden reset condition. This change adds a "-f" flag which can be used to bring back the previous behaviour if end users require it. Note, the fdatasync() lowers the likelihood of lost data, but does so at the expense of performance within the write operation. (cherry picked from commit 560d88cb5a16636acb0e350d6997fe915cc4253e) --- man/sadc.in | 8 +++++++- sa.h | 2 ++ sadc.c | 13 ++++++++++++- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/man/sadc.in b/man/sadc.in index 9b75754..d3574c1 100644 --- a/man/sadc.in +++ b/man/sadc.in @@ -4,7 +4,7 @@ sadc \- System activity data collector. .SH SYNOPSIS .B @SA_LIB_DIR@/sadc [ -C .I comment -.B ] [ -F ] [ -L ] [ -V ] [ -S { INT | DISK | SNMP | IPV6 | POWER | XDISK | ALL | XALL } ] [ +.B ] [ -F ] [ -L ] [ -V ] [ -f ] [ -S { INT | DISK | SNMP | IPV6 | POWER | XDISK | ALL | XALL } ] [ .I interval .B [ .I count @@ -85,6 +85,12 @@ then it will be truncated. This may be useful for daily data files created by an older version of .B sadc and whose format is no longer compatible with current one. +.IP -f +fdatasync() will be used to ensure data is written to disk. This differs +from the normal operation in that a sudden system reset is less likely to +result in the saDD datafiles being corrupted. However, this is at the +expense of performance within the sadc process as forward progress will be +blocked while data is written to underlying disk instead of just to cache. .IP -L .B sadc will try to get an exclusive lock on the diff --git a/sa.h b/sa.h index 54e7a4e..0c3b24c 100644 --- a/sa.h +++ b/sa.h @@ -88,6 +88,7 @@ #define S_F_COMMENT 0x00001000 #define S_F_PERSIST_NAME 0x00002000 #define S_F_LOCAL_TIME 0x00004000 +#define S_F_FDATASYNC 0x00008000 #define WANT_SINCE_BOOT(m) (((m) & S_F_SINCE_BOOT) == S_F_SINCE_BOOT) #define WANT_SA_ROTAT(m) (((m) & S_F_SA_ROTAT) == S_F_SA_ROTAT) @@ -104,6 +105,7 @@ #define DISPLAY_COMMENT(m) (((m) & S_F_COMMENT) == S_F_COMMENT) #define DISPLAY_PERSIST_NAME_S(m) (((m) & S_F_PERSIST_NAME) == S_F_PERSIST_NAME) #define PRINT_LOCAL_TIME(m) (((m) & S_F_LOCAL_TIME) == S_F_LOCAL_TIME) +#define FDATASYNC(m) (((m) & S_F_FDATASYNC) == S_F_FDATASYNC) #define AO_F_NULL 0x00000000 diff --git a/sadc.c b/sadc.c index fb3254d..bac28d4 100644 --- a/sadc.c +++ b/sadc.c @@ -85,7 +85,7 @@ void usage(char *progname) progname); fprintf(stderr, _("Options are:\n" - "[ -C ] [ -F ] [ -L ] [ -V ]\n" + "[ -C ] [ -F ] [ -L ] [ -V ] [ -f ]\n" "[ -S { INT | DISK | IPV6 | POWER | SNMP | XDISK | ALL | XALL } ]\n")); exit(1); } @@ -991,6 +991,13 @@ void rw_sa_stat_loop(long count, struct tm *rectime, int stdfd, int ofd, /* Flush data */ fflush(stdout); + if (FDATASYNC(flags)) { + /* Flush previous file */ + if (fdatasync(ofd) < 0) { + perror("fdatasync"); + exit(4); + } + } if (count > 0) { count--; @@ -1079,6 +1086,10 @@ int main(int argc, char **argv) optz = 1; } + else if (!strcmp(argv[opt], "-f")) { + flags |= S_F_FDATASYNC; + } + else if (!strcmp(argv[opt], "-C")) { if (argv[++opt]) { strncpy(comment, argv[opt], MAX_COMMENT_LEN); -- 2.17.1