From 54fc8428c5c4b3fa90347e5ca7d89c2d752a7032 Mon Sep 17 00:00:00 2001 From: Philip Hazel Date: Mon, 22 Jan 2007 16:29:54 +0000 Subject: [PATCH] Cautiously added ENABLE_DISABLE_FSYNC and disable_fsync, hedged about with much warning text. --- doc/doc-txt/ChangeLog | 6 +++++- doc/doc-txt/NewStuff | 13 ++++++++++++- src/src/EDITME | 18 +++++++++++++++++- src/src/config.h.defaults | 4 +++- src/src/deliver.c | 6 +++--- src/src/exim.h | 8 +++++++- src/src/globals.c | 5 ++++- src/src/globals.h | 5 ++++- src/src/readconf.c | 5 ++++- src/src/receive.c | 4 ++-- src/src/spool_out.c | 6 +++--- src/src/transports/appendfile.c | 4 ++-- src/src/transports/smtp.c | 4 ++-- 13 files changed, 68 insertions(+), 20 deletions(-) diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 4c7f8a167..6db4096a7 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -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. diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff index 9cc8f81cc..ac707ae40 100644 --- a/doc/doc-txt/NewStuff +++ b/doc/doc-txt/NewStuff @@ -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 ------------ diff --git a/src/src/EDITME b/src/src/EDITME index 5d5af1ff0..77b4f3686 100644 --- a/src/src/EDITME +++ b/src/src/EDITME @@ -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. diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults index 455f38af4..1949cb7f4 100644 --- a/src/src/config.h.defaults +++ b/src/src/config.h.defaults @@ -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 diff --git a/src/src/deliver.c b/src/src/deliver.c index fb853aa5d..fae67dc79 100644 --- a/src/src/deliver.c +++ b/src/src/deliver.c @@ -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)); } diff --git a/src/src/exim.h b/src/src/exim.h index ea973d3da..8fa6959c8 100644 --- a/src/src/exim.h +++ b/src/src/exim.h @@ -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 #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) diff --git a/src/src/globals.c b/src/src/globals.c index c60ef864f..74b6554cf 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -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; diff --git a/src/src/globals.h b/src/src/globals.h index 090e1b483..660d62fe5 100644 --- a/src/src/globals.h +++ b/src/src/globals.h @@ -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 */ diff --git a/src/src/readconf.c b/src/src/readconf.c index c3514aba5..1b4a04b66 100644 --- a/src/src/readconf.c +++ b/src/src/readconf.c @@ -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 }, diff --git a/src/src/receive.c b/src/src/receive.c index b741b05b2..db86947a4 100644 --- a/src/src/receive.c +++ b/src/src/receive.c @@ -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; diff --git a/src/src/spool_out.c b/src/src/spool_out.c index d64b45de0..724b00e44 100644 --- a/src/src/spool_out.c +++ b/src/src/spool_out.c @@ -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) diff --git a/src/src/transports/appendfile.c b/src/src/transports/appendfile.c index 8266bf9bb..f31232a0f 100644 --- a/src/src/transports/appendfile.c +++ b/src/src/transports/appendfile.c @@ -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. */ diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c index 887b1ff82..c1396b9b4 100644 --- a/src/src/transports/smtp.c +++ b/src/src/transports/smtp.c @@ -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)); } -- 2.30.2