Blob Blame History Raw
From f44275403f866cd0a7e0e40714c249ec5903d356 Mon Sep 17 00:00:00 2001
From: Kyle Walker <kwalker@redhat.com>
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 <comment> ] [ -F ] [ -L ] [ -V ]\n"
+			  "[ -C <comment> ] [ -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