]> granicus.if.org Git - sysstat/commitdiff
sadc: Add a -f flag to force fdatasync() use
authorKyle Walker <kwalker@redhat.com>
Wed, 30 Jan 2019 12:50:55 +0000 (07:50 -0500)
committerKyle Walker <kwalker@redhat.com>
Wed, 30 Jan 2019 13:08:58 +0000 (08:08 -0500)
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.

man/sadc.in
sa.h
sadc.c

index 2d754b71467d86616f704ffadbcfde158dbe1707..ce8ee2300eb4881cddcbd662619e216d04ab05f1 100644 (file)
@@ -4,7 +4,7 @@ sadc \- System activity data collector.
 .SH SYNOPSIS
 .B @SA_LIB_DIR@/sadc [ -C
 .I comment
-.B ] [ -D ] [ -F ] [ -L ] [ -V ] [ -S { keyword [,...] | ALL | XALL } ] [
+.B ] [ -D ] [ -F ] [ -L ] [ -V ] [ -f ] [ -S { keyword [,...] | ALL | XALL } ] [
 .I interval
 .B [
 .I count
@@ -106,6 +106,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 1cd0c3d9e5eefc90eac03d46d082f68b3848569a..d3236f7cf7f772c523ada45568293ae61f390725 100644 (file)
--- a/sa.h
+++ b/sa.h
 #define S_F_HUMAN_READ         0x01000000
 #define S_F_ZERO_OMIT          0x02000000
 #define S_F_SVG_SHOW_TOC       0x04000000
+#define S_F_FDATASYNC          0x08000000
 
 #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)
 #define PACK_VIEWS(m)                  (((m) & S_F_SVG_PACKED) == S_F_SVG_PACKED)
 #define DISPLAY_HUMAN_READ(m)          (((m) & S_F_HUMAN_READ) == S_F_HUMAN_READ)
 #define DISPLAY_TOC(m)                 (((m) & S_F_SVG_SHOW_TOC) == S_F_SVG_SHOW_TOC)
+#define FDATASYNC(m)                   (((m) & S_F_FDATASYNC)    == S_F_FDATASYNC)
 
 #define AO_F_NULL              0x00000000
 
diff --git a/sadc.c b/sadc.c
index 826f4aed0c8adc945da9bd58f6c1e83c3b502fdd..139d490a121551d39682bfcfb7ac6aee480c70a6 100644 (file)
--- a/sadc.c
+++ b/sadc.c
@@ -92,7 +92,7 @@ void usage(char *progname)
                progname);
 
        fprintf(stderr, _("Options are:\n"
-                         "[ -C <comment> ] [ -D ] [ -F ] [ -L ] [ -V ]\n"
+                         "[ -C <comment> ] [ -D ] [ -F ] [ -L ] [ -V ] [ -f ]\n"
                          "[ -S { INT | DISK | IPV6 | POWER | SNMP | XDISK | ALL | XALL } ]\n"));
        exit(1);
 }
@@ -1109,6 +1109,13 @@ void rw_sa_stat_loop(long count, int stdfd, int ofd, char ofile[],
 
                /* Flush data */
                fflush(stdout);
+               if (FDATASYNC(flags)) {
+                       /* If indicated, sync the data to media */
+                       if (fdatasync(ofd) < 0) {
+                               perror("fdatasync");
+                               exit(4);
+                       }
+               }
 
                if (count > 0) {
                        count--;
@@ -1206,6 +1213,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]) {
                                usage(argv[0]);