952f9f
From 560d88cb5a16636acb0e350d6997fe915cc4253e Mon Sep 17 00:00:00 2001
952f9f
From: Kyle Walker <kwalker@redhat.com>
952f9f
Date: Wed, 30 Jan 2019 07:50:55 -0500
952f9f
Subject: [PATCH] sadc: Add a -f flag to force fdatasync() use
952f9f
952f9f
For quite some time, the sadc utility has not used fdatasync() when writing
952f9f
stat information to disk. This resulted in instances where data files could
952f9f
be corrupted or entries lost if a system encountered a sudden reset
952f9f
condition. This change adds a "-f" flag which can be used to bring back the
952f9f
previous behaviour if end users require it.
952f9f
952f9f
Note, the fdatasync() lowers the likelihood of lost data, but does so at
952f9f
the expense of performance within the write operation.
952f9f
---
952f9f
 man/sadc.in |  8 +++++++-
952f9f
 sa.h        |  2 ++
952f9f
 sadc.c      | 13 ++++++++++++-
952f9f
 3 files changed, 21 insertions(+), 2 deletions(-)
952f9f
952f9f
diff --git a/man/sadc.in b/man/sadc.in
952f9f
index 2d754b71..ce8ee230 100644
952f9f
--- a/man/sadc.in
952f9f
+++ b/man/sadc.in
952f9f
@@ -4,7 +4,7 @@ sadc \- System activity data collector.
952f9f
 .SH SYNOPSIS
952f9f
 .B @SA_LIB_DIR@/sadc [ -C
952f9f
 .I comment
952f9f
-.B ] [ -D ] [ -F ] [ -L ] [ -V ] [ -S { DISK | INT | IPV6 | POWER | SNMP | XDISK | ALL | XALL [,...] } ] [
952f9f
+.B ] [ -D ] [ -F ] [ -L ] [ -V ] [ -f ] [ -S { DISK | INT | IPV6 | POWER | SNMP | XDISK | ALL | XALL [,...] } ] [
952f9f
 .I interval
952f9f
 .B [
952f9f
 .I count
952f9f
@@ -106,6 +106,12 @@ then it will be truncated. This may be useful for daily data files
952f9f
 created by an older version of
952f9f
 .B sadc
952f9f
 and whose format is no longer compatible with current one.
952f9f
+.IP -f
952f9f
+fdatasync() will be used to ensure data is written to disk. This differs
952f9f
+from the normal operation in that a sudden system reset is less likely to
952f9f
+result in the saDD datafiles being corrupted. However, this is at the
952f9f
+expense of performance within the sadc process as forward progress will be
952f9f
+blocked while data is written to underlying disk instead of just to cache.
952f9f
 .IP -L
952f9f
 .B sadc
952f9f
 will try to get an exclusive lock on the
952f9f
diff --git a/sa.h b/sa.h
952f9f
index 1cd0c3d9..d3236f7c 100644
952f9f
--- a/sa.h
952f9f
+++ b/sa.h
952f9f
@@ -110,5 +110,6 @@
952f9f
 #define S_F_HUMAN_READ		0x01000000
952f9f
 #define S_F_ZERO_OMIT		0x02000000
952f9f
+#define S_F_FDATASYNC		0x08000000
952f9f
 
952f9f
 #define WANT_SINCE_BOOT(m)		(((m) & S_F_SINCE_BOOT)   == S_F_SINCE_BOOT)
952f9f
 #define WANT_SA_ROTAT(m)		(((m) & S_F_SA_ROTAT)     == S_F_SA_ROTAT)
952f9f
@@ -138,5 +139,6 @@
952f9f
 #define PACK_VIEWS(m)			(((m) & S_F_SVG_PACKED) == S_F_SVG_PACKED)
952f9f
 #define DISPLAY_HUMAN_READ(m)		(((m) & S_F_HUMAN_READ) == S_F_HUMAN_READ)
952f9f
+#define FDATASYNC(m)			(((m) & S_F_FDATASYNC)    == S_F_FDATASYNC)
952f9f
 
952f9f
 #define AO_F_NULL		0x00000000
952f9f
 
952f9f
diff --git a/sadc.c b/sadc.c
952f9f
index 826f4aed..139d490a 100644
952f9f
--- a/sadc.c
952f9f
+++ b/sadc.c
952f9f
@@ -92,7 +92,7 @@ void usage(char *progname)
952f9f
 		progname);
952f9f
 
952f9f
 	fprintf(stderr, _("Options are:\n"
952f9f
-			  "[ -C <comment> ] [ -D ] [ -F ] [ -L ] [ -V ]\n"
952f9f
+			  "[ -C <comment> ] [ -D ] [ -F ] [ -L ] [ -V ] [ -f ]\n"
952f9f
 			  "[ -S { INT | DISK | IPV6 | POWER | SNMP | XDISK | ALL | XALL } ]\n"));
952f9f
 	exit(1);
952f9f
 }
952f9f
@@ -1109,6 +1109,13 @@ void rw_sa_stat_loop(long count, int stdfd, int ofd, char ofile[],
952f9f
 
952f9f
 		/* Flush data */
952f9f
 		fflush(stdout);
952f9f
+		if (FDATASYNC(flags)) {
952f9f
+			/* If indicated, sync the data to media */
952f9f
+			if (fdatasync(ofd) < 0) {
952f9f
+				perror("fdatasync");
952f9f
+				exit(4);
952f9f
+			}
952f9f
+		}
952f9f
 
952f9f
 		if (count > 0) {
952f9f
 			count--;
952f9f
@@ -1206,6 +1213,10 @@ int main(int argc, char **argv)
952f9f
 			optz = 1;
952f9f
 		}
952f9f
 
952f9f
+		else if (!strcmp(argv[opt], "-f")) {
952f9f
+			flags |= S_F_FDATASYNC;
952f9f
+		}
952f9f
+
952f9f
 		else if (!strcmp(argv[opt], "-C")) {
952f9f
 			if (!argv[++opt]) {
952f9f
 				usage(argv[0]);