Cautiously added ENABLE_DISABLE_FSYNC and disable_fsync, hedged about
authorPhilip Hazel <ph10@hermes.cam.ac.uk>
Mon, 22 Jan 2007 16:29:54 +0000 (16:29 +0000)
committerPhilip Hazel <ph10@hermes.cam.ac.uk>
Mon, 22 Jan 2007 16:29:54 +0000 (16:29 +0000)
with much warning text.

13 files changed:
doc/doc-txt/ChangeLog
doc/doc-txt/NewStuff
src/src/EDITME
src/src/config.h.defaults
src/src/deliver.c
src/src/exim.h
src/src/globals.c
src/src/globals.h
src/src/readconf.c
src/src/receive.c
src/src/spool_out.c
src/src/transports/appendfile.c
src/src/transports/smtp.c

index 4c7f8a1676dcf18498cb594e36ee6e6806e679aa..6db4096a781d3964f9303816985cec0a99285567 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.456 2007/01/22 15:56:47 steve Exp $
+$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.457 2007/01/22 16:29:54 ph10 Exp $
 
 Change log file for Exim from version 4.21
 -------------------------------------------
@@ -29,6 +29,10 @@ PH/03 Added additional dnslists conditions == and =& which are different from
 PH/04 Added gnutls_require_{kx,mac,protocols} to give more control over the
       cipher suites used by GnuTLS. These options are ignored by OpenSSL.
 
+PH/05 After discussion on the list, added a compile time option ENABLE_DISABLE_
+      FSYNC, which compiles an option called disable_fsync that allows for
+      bypassing fsync(). The documentation is heavily laced with warnings.
+
 SC/01 Updated eximstats to collate all SpamAssassin rejects into one bucket.
 
 
index 9cc8f81cc4da0eb993df2785be09d2fdf398d6cf..ac707ae4018a78ce146b300f159c3fed7f34c0fc 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/NewStuff,v 1.128 2007/01/18 15:35:42 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/NewStuff,v 1.129 2007/01/22 16:29:54 ph10 Exp $
 
 New Features in Exim
 --------------------
@@ -175,6 +175,17 @@ Version 4.67
     preference order for the cipher algorithms. The first one in the client's
     list that is also advertised by the server is tried first.
 
+ 4. There is a new compile-time option called ENABLE_DISABLE_FSYNC. You must
+    not set this option unless you really, really, really understand what you
+    are doing. No pre-compiled distributions of Exim should ever set this
+    option. When it is set, Exim compiles a runtime option called
+    disable_fsync. If this is set true, Exim no longer calls fsync() to force
+    updated files' data to be written to disc. Unexpected events such as
+    crashes and power outages may cause data to be lost or scrambled. Beware.
+
+    When ENABLE_DISABLE_FSYNC is not set, a reference to disable_fsync in a
+    runtime configuration generates an "unknown option" error.
+
 
 Version 4.66
 ------------
index 5d5af1ff0e39af443a1fae6de8bd3e8ab622b779..77b4f36865ac0c5aba86c71cbc25f64de33efb48 100644 (file)
@@ -1,4 +1,4 @@
-# $Cambridge: exim/src/src/EDITME,v 1.19 2006/12/08 03:16:48 jetmore Exp $
+# $Cambridge: exim/src/src/EDITME,v 1.20 2007/01/22 16:29:54 ph10 Exp $
 
 ##################################################
 #          The Exim mail transport agent         #
@@ -1117,4 +1117,20 @@ TMPDIR="/tmp"
 
 # SUPPORT_MOVE_FROZEN_MESSAGES=yes
 
+
+#------------------------------------------------------------------------------
+# Disabling the use of fsync(): DO NOT UNCOMMENT THE FOLLOWING LINE unless you
+# really, really, really know what you are doing. And even then, think again.
+# You should never uncomment this when compiling a binary for distribution.
+# Use it only when compiling Exim for your own use.
+#
+# Uncommenting this line enables the use of a runtime option called
+# disable_fsync, which can be used to stop Exim using fsync() to ensure that
+# files are written to disc before proceeding. When this is disabled, crashes
+# and hardware problems such as power outages can cause data to be lost. This
+# feature should only be used in very exceptional circumstances. YOU HAVE BEEN
+# WARNED.
+
+# ENABLE_DISABLE_FSYNC=yes
+
 # End of EDITME for Exim 4.
index 455f38af46a0dc3265542bbc361e085dc8039f76..1949cb7f4c6c7ba63627c60db372b6186f42ceb1 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/config.h.defaults,v 1.13 2007/01/08 10:50:17 ph10 Exp $ */
+/* $Cambridge: exim/src/src/config.h.defaults,v 1.14 2007/01/22 16:29:54 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -42,6 +42,8 @@ it's a default value. */
 #define DELIVER_OUT_BUFFER_SIZE    8192
 #define DISABLE_D_OPTION
 
+#define ENABLE_DISABLE_FSYNC
+
 #define EXIMDB_DIRECTORY_MODE      0750
 #define EXIMDB_LOCK_TIMEOUT          60
 #define EXIMDB_LOCKFILE_MODE       0640
index fb853aa5d8f05e164166124e365108832af80095..fae67dc79e36643a2b1d6cfc1be83b141e89bc65 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/deliver.c,v 1.40 2007/01/08 10:50:18 ph10 Exp $ */
+/* $Cambridge: exim/src/src/deliver.c,v 1.41 2007/01/22 16:29:54 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -774,7 +774,7 @@ if (addr->return_file >= 0 && addr->return_filename != NULL)
   {
   BOOL return_output = FALSE;
   struct stat statbuf;
-  fsync(addr->return_file);
+  (void)EXIMfsync(addr->return_file);
 
   /* If there is no output, do nothing. */
 
@@ -1979,7 +1979,7 @@ if (!shadowing)
 
   /* Ensure the journal file is pushed out to disk. */
 
-  if (fsync(journal_fd) < 0)
+  if (EXIMfsync(journal_fd) < 0)
     log_write(0, LOG_MAIN|LOG_PANIC, "failed to fsync journal: %s",
       strerror(errno));
   }
index ea973d3dae87c59bbcb5226de42bd80e4af4a602..8fa6959c82f4c97dd2d77e6a624bee68bd72c9e1 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/exim.h,v 1.21 2007/01/08 10:50:18 ph10 Exp $ */
+/* $Cambridge: exim/src/src/exim.h,v 1.22 2007/01/22 16:29:54 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -461,6 +461,12 @@ requires various things that are set therein. */
 #include <dlfcn.h>
 #endif
 
+#ifdef ENABLE_DISABLE_FSYNC
+#define EXIMfsync(f) (disable_fsync? 0 : fsync(f))
+#else
+#define EXIMfsync(f) fsync(f)
+#endif
+
 /* Backward compatibility; LOOKUP_LSEARCH now includes all three */
 
 #if (!defined LOOKUP_LSEARCH) && (defined LOOKUP_WILDLSEARCH || defined LOOKUP_NWILDLSEARCH)
index c60ef864f151b82220b7eed89f91bee8fdc55c10..74b6554cf5119bc1afa44797de774bf777f1c305 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/globals.c,v 1.63 2007/01/18 15:35:42 ph10 Exp $ */
+/* $Cambridge: exim/src/src/globals.c,v 1.64 2007/01/22 16:29:54 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -499,6 +499,9 @@ int     demime_errorlevel      = 0;
 int     demime_ok              = 0;
 uschar *demime_reason          = NULL;
 #endif
+#ifdef ENABLE_DISABLE_FSYNC
+BOOL    disable_fsync          = FALSE;
+#endif
 BOOL    disable_ipv6           = FALSE;
 BOOL    disable_logging        = FALSE;
 
index 090e1b4834d2dbfd98fffb690f5ac4349b86c2fc..660d62fe5c0858787cce487ff5d1f465461821b3 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/globals.h,v 1.44 2007/01/18 15:35:42 ph10 Exp $ */
+/* $Cambridge: exim/src/src/globals.h,v 1.45 2007/01/22 16:29:54 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -278,6 +278,9 @@ extern int     demime_errorlevel;      /* Severity of MIME error */
 extern int     demime_ok;              /* Nonzero if message has been demimed */
 extern uschar *demime_reason;          /* Reason for broken MIME container */
 #endif
+#ifdef ENABLE_DISABLE_FSYNC
+extern BOOL    disable_fsync;          /* Not for normal use */
+#endif
 extern BOOL    disable_ipv6;           /* Don't do any IPv6 things */
 extern BOOL    disable_logging;        /* Disables log writing when TRUE */
 
index c3514aba5ddac919d3925e0af5c514f519fdf59e..1b4a04b668d69462f2491df6cf415044ae14150e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/readconf.c,v 1.27 2007/01/18 15:35:42 ph10 Exp $ */
+/* $Cambridge: exim/src/src/readconf.c,v 1.28 2007/01/22 16:29:54 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -195,6 +195,9 @@ static optionlist optionlist_config[] = {
   { "deliver_drop_privilege",   opt_bool,        &deliver_drop_privilege },
   { "deliver_queue_load_max",   opt_fixed,       &deliver_queue_load_max },
   { "delivery_date_remove",     opt_bool,        &delivery_date_remove },
+#ifdef ENABLE_DISABLE_FSYNC
+  { "disable_fsync",            opt_bool,        &disable_fsync },
+#endif
   { "disable_ipv6",             opt_bool,        &disable_ipv6 },
   { "dns_again_means_nonexist", opt_stringptr,   &dns_again_means_nonexist },
   { "dns_check_names_pattern",  opt_stringptr,   &check_dns_names_pattern },
index b741b05b270ac0e46bcced259263eedf70ccdf5f..db86947a46f3c4767a213b19d658e52f018668d3 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/receive.c,v 1.32 2007/01/08 10:50:18 ph10 Exp $ */
+/* $Cambridge: exim/src/src/receive.c,v 1.33 2007/01/22 16:29:54 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -2730,7 +2730,7 @@ the input in cases of output errors, since the far end doesn't expect to see
 anything until the terminating dot line is sent. */
 
 if (fflush(data_file) == EOF || ferror(data_file) ||
-    fsync(fileno(data_file)) < 0 || (receive_ferror)())
+    EXIMfsync(fileno(data_file)) < 0 || (receive_ferror)())
   {
   uschar *msg_errno = US strerror(errno);
   BOOL input_error = (receive_ferror)() != 0;
index d64b45de016a4c6ccf2ac6b3ef31c9923f426f6b..724b00e44b2db381ea535601d1bd52ea5f91eeb4 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/spool_out.c,v 1.12 2007/01/08 10:50:18 ph10 Exp $ */
+/* $Cambridge: exim/src/src/spool_out.c,v 1.13 2007/01/22 16:29:54 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -287,7 +287,7 @@ if (fflush(f) != 0 || ferror(f))
 just pushes it out of C, and fclose() doesn't guarantee to do the write
 either. That's just the way Unix works... */
 
-if (fsync(fileno(f)) < 0)
+if (EXIMfsync(fileno(f)) < 0)
   return spool_write_error(where, errmsg, US"sync", temp_name, f);
 
 /* Get the size of the file, and close it. */
@@ -325,7 +325,7 @@ sprintf(CS temp_name, "%s/input/%s/.", spool_directory, message_subdir);
 if ((fd = Uopen(temp_name, O_RDONLY|O_DIRECTORY, 0)) < 0)
   return spool_write_error(where, errmsg, US"directory open", name, NULL);
 
-if (fsync(fd) < 0 && errno != EINVAL)
+if (EXIMfsync(fd) < 0 && errno != EINVAL)
   return spool_write_error(where, errmsg, US"directory sync", name, NULL);
 
 if (close(fd) < 0)
index 8266bf9bb49427cc9284d803405eacd6e7b4ed40..f31232a0f496ffd45632b637dffb884b62cd11c0 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/transports/appendfile.c,v 1.20 2007/01/08 10:50:20 ph10 Exp $ */
+/* $Cambridge: exim/src/src/transports/appendfile.c,v 1.21 2007/01/22 16:29:55 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -2791,7 +2791,7 @@ if (temp_file != NULL && ob->mbx_format)
 /* Force out the remaining data to check for any errors; some OS don't allow
 fsync() to be called for a FIFO. */
 
-if (yield == OK && !isfifo && fsync(fd) < 0) yield = DEFER;
+if (yield == OK && !isfifo && EXIMfsync(fd) < 0) yield = DEFER;
 
 /* Update message_size to the accurate count of bytes written, including
 added headers. */
index 887b1ff821a897630a95a73d7007e92d5b637de8..c1396b9b4d996354960621737955775a64884bbd 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/transports/smtp.c,v 1.31 2007/01/18 15:35:43 ph10 Exp $ */
+/* $Cambridge: exim/src/src/transports/smtp.c,v 1.32 2007/01/22 16:29:55 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -1690,7 +1690,7 @@ if (!ok) ok = TRUE; else
 
     /* Ensure the journal file is pushed out to disk. */
 
-    if (fsync(journal_fd) < 0)
+    if (EXIMfsync(journal_fd) < 0)
       log_write(0, LOG_MAIN|LOG_PANIC, "failed to fsync journal: %s",
         strerror(errno));
     }