2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-08-28 12:57:42 +00:00

[master] Add option to suppress the use of fsync when writing lease files

The option is dont-use-async <flag> and it defaults to disabled.
This commit is contained in:
Shawn Routhier 2013-11-08 12:00:02 -08:00
parent 1534fff7c5
commit cde11a4cdb
6 changed files with 136 additions and 127 deletions

View File

@ -89,6 +89,13 @@ work on other platforms. Please report any problems and suggested fixes to
key for security reasons. key for security reasons.
[ISC-Bugs 30461] [ISC-Bugs 30461]
- Add a configuration option to the server to suppress using fsync().
Enabling this option will mean that fsync() is never called. This
may provide better performance but there is also a risk that a lease
will not be properly written to the disk after it has been issued
to a client and before the server stops. Using this option is
not recommended.
Changes since 4.2.5 Changes since 4.2.5
- Address static analysis warnings. - Address static analysis warnings.

View File

@ -732,6 +732,7 @@ struct lease_state {
#endif #endif
#endif #endif
#define SV_CACHE_THRESHOLD 78 #define SV_CACHE_THRESHOLD 78
#define SV_DONT_USE_FSYNC 79
#if !defined (DEFAULT_PING_TIMEOUT) #if !defined (DEFAULT_PING_TIMEOUT)
# define DEFAULT_PING_TIMEOUT 1 # define DEFAULT_PING_TIMEOUT 1
@ -1916,6 +1917,7 @@ extern struct timeval cur_tv;
#define cur_time cur_tv.tv_sec #define cur_time cur_tv.tv_sec
extern int ddns_update_style; extern int ddns_update_style;
extern int dont_use_fsync;
extern const char *path_dhcpd_conf; extern const char *path_dhcpd_conf;
extern const char *path_dhcpd_db; extern const char *path_dhcpd_db;

View File

@ -1015,11 +1015,12 @@ int commit_leases ()
just in case the rewrite fails. */ just in case the rewrite fails. */
if (fflush (db_file) == EOF) { if (fflush (db_file) == EOF) {
log_info("commit_leases: unable to commit, fflush(): %m"); log_info("commit_leases: unable to commit, fflush(): %m");
return 0; return (0);
} }
if (fsync (fileno (db_file)) < 0) { if ((dont_use_fsync == 0) &&
(fsync(fileno (db_file)) < 0)) {
log_info ("commit_leases: unable to commit, fsync(): %m"); log_info ("commit_leases: unable to commit, fsync(): %m");
return 0; return (0);
} }
/* send out all deferred ACKs now */ /* send out all deferred ACKs now */
@ -1033,7 +1034,7 @@ int commit_leases ()
write_time = cur_time; write_time = cur_time;
new_lease_file(); new_lease_file();
} }
return 1; return (1);
} }
/* /*

View File

@ -78,6 +78,7 @@ option server.ddns-rev-domainname = \"in-addr.arpa.\";";
#endif /* NSUPDATE */ #endif /* NSUPDATE */
int ddns_update_style; int ddns_update_style;
int dont_use_fsync = 0; /* 0 = default, use fsync, 1 = don't use fsync */
const char *path_dhcpd_conf = _PATH_DHCPD_CONF; const char *path_dhcpd_conf = _PATH_DHCPD_CONF;
const char *path_dhcpd_db = _PATH_DHCPD_DB; const char *path_dhcpd_db = _PATH_DHCPD_DB;
@ -800,7 +801,7 @@ main(int argc, char **argv) {
void postconf_initialization (int quiet) void postconf_initialization (int quiet)
{ {
struct option_state *options = (struct option_state *)0; struct option_state *options = NULL;
struct data_string db; struct data_string db;
struct option_cache *oc; struct option_cache *oc;
char *s; char *s;
@ -816,9 +817,7 @@ void postconf_initialization (int quiet)
memset(&db, 0, sizeof db); memset(&db, 0, sizeof db);
oc = lookup_option(&server_universe, options, SV_LEASE_FILE_NAME); oc = lookup_option(&server_universe, options, SV_LEASE_FILE_NAME);
if (oc && if (oc &&
evaluate_option_cache (&db, (struct packet *)0, evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
(struct lease *)0, (struct client_state *)0,
options, (struct option_state *)0,
&global_scope, oc, MDL)) { &global_scope, oc, MDL)) {
s = dmalloc(db.len + 1, MDL); s = dmalloc(db.len + 1, MDL);
if (!s) if (!s)
@ -831,9 +830,7 @@ void postconf_initialization (int quiet)
oc = lookup_option(&server_universe, options, SV_PID_FILE_NAME); oc = lookup_option(&server_universe, options, SV_PID_FILE_NAME);
if (oc && if (oc &&
evaluate_option_cache (&db, (struct packet *)0, evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
(struct lease *)0, (struct client_state *)0,
options, (struct option_state *)0,
&global_scope, oc, MDL)) { &global_scope, oc, MDL)) {
s = dmalloc(db.len + 1, MDL); s = dmalloc(db.len + 1, MDL);
if (!s) if (!s)
@ -853,9 +850,8 @@ void postconf_initialization (int quiet)
oc = lookup_option(&server_universe, options, oc = lookup_option(&server_universe, options,
SV_DHCPV6_LEASE_FILE_NAME); SV_DHCPV6_LEASE_FILE_NAME);
if (oc && if (oc &&
evaluate_option_cache(&db, NULL, NULL, NULL, evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
options, NULL, &global_scope, &global_scope, oc, MDL)) {
oc, MDL)) {
s = dmalloc(db.len + 1, MDL); s = dmalloc(db.len + 1, MDL);
if (!s) if (!s)
log_fatal("no memory for lease db filename."); log_fatal("no memory for lease db filename.");
@ -868,9 +864,8 @@ void postconf_initialization (int quiet)
oc = lookup_option(&server_universe, options, oc = lookup_option(&server_universe, options,
SV_DHCPV6_PID_FILE_NAME); SV_DHCPV6_PID_FILE_NAME);
if (oc && if (oc &&
evaluate_option_cache(&db, NULL, NULL, NULL, evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
options, NULL, &global_scope, &global_scope, oc, MDL)) {
oc, MDL)) {
s = dmalloc(db.len + 1, MDL); s = dmalloc(db.len + 1, MDL);
if (!s) if (!s)
log_fatal("no memory for pid filename."); log_fatal("no memory for pid filename.");
@ -885,9 +880,7 @@ void postconf_initialization (int quiet)
omapi_port = -1; omapi_port = -1;
oc = lookup_option(&server_universe, options, SV_OMAPI_PORT); oc = lookup_option(&server_universe, options, SV_OMAPI_PORT);
if (oc && if (oc &&
evaluate_option_cache (&db, (struct packet *)0, evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
(struct lease *)0, (struct client_state *)0,
options, (struct option_state *)0,
&global_scope, oc, MDL)) { &global_scope, oc, MDL)) {
if (db.len == 2) { if (db.len == 2) {
omapi_port = getUShort(db.data); omapi_port = getUShort(db.data);
@ -898,10 +891,7 @@ void postconf_initialization (int quiet)
oc = lookup_option(&server_universe, options, SV_OMAPI_KEY); oc = lookup_option(&server_universe, options, SV_OMAPI_KEY);
if (oc && if (oc &&
evaluate_option_cache (&db, (struct packet *)0, evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
(struct lease *)0, (struct client_state *)0,
options,
(struct option_state *)0,
&global_scope, oc, MDL)) { &global_scope, oc, MDL)) {
s = dmalloc(db.len + 1, MDL); s = dmalloc(db.len + 1, MDL);
if (!s) if (!s)
@ -918,10 +908,7 @@ void postconf_initialization (int quiet)
oc = lookup_option(&server_universe, options, SV_LOCAL_PORT); oc = lookup_option(&server_universe, options, SV_LOCAL_PORT);
if (oc && if (oc &&
evaluate_option_cache (&db, (struct packet *)0, evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
(struct lease *)0, (struct client_state *)0,
options,
(struct option_state *)0,
&global_scope, oc, MDL)) { &global_scope, oc, MDL)) {
if (db.len == 2) { if (db.len == 2) {
local_port = htons(getUShort (db.data)); local_port = htons(getUShort (db.data));
@ -932,9 +919,7 @@ void postconf_initialization (int quiet)
oc = lookup_option(&server_universe, options, SV_REMOTE_PORT); oc = lookup_option(&server_universe, options, SV_REMOTE_PORT);
if (oc && if (oc &&
evaluate_option_cache (&db, (struct packet *)0, evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
(struct lease *)0, (struct client_state *)0,
options, (struct option_state *)0,
&global_scope, oc, MDL)) { &global_scope, oc, MDL)) {
if (db.len == 2) { if (db.len == 2) {
remote_port = htons(getUShort (db.data)); remote_port = htons(getUShort (db.data));
@ -946,9 +931,7 @@ void postconf_initialization (int quiet)
oc = lookup_option(&server_universe, options, oc = lookup_option(&server_universe, options,
SV_LIMITED_BROADCAST_ADDRESS); SV_LIMITED_BROADCAST_ADDRESS);
if (oc && if (oc &&
evaluate_option_cache (&db, (struct packet *)0, evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
(struct lease *)0, (struct client_state *)0,
options, (struct option_state *)0,
&global_scope, oc, MDL)) { &global_scope, oc, MDL)) {
if (db.len == 4) { if (db.len == 4) {
memcpy(&limited_broadcast, db.data, 4); memcpy(&limited_broadcast, db.data, 4);
@ -957,12 +940,9 @@ void postconf_initialization (int quiet)
data_string_forget(&db, MDL); data_string_forget(&db, MDL);
} }
oc = lookup_option (&server_universe, options, oc = lookup_option(&server_universe, options, SV_LOCAL_ADDRESS);
SV_LOCAL_ADDRESS);
if (oc && if (oc &&
evaluate_option_cache (&db, (struct packet *)0, evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
(struct lease *)0, (struct client_state *)0,
options, (struct option_state *)0,
&global_scope, oc, MDL)) { &global_scope, oc, MDL)) {
if (db.len == 4) { if (db.len == 4) {
memcpy(&local_address, db.data, 4); memcpy(&local_address, db.data, 4);
@ -973,11 +953,7 @@ void postconf_initialization (int quiet)
oc = lookup_option(&server_universe, options, SV_DDNS_UPDATE_STYLE); oc = lookup_option(&server_universe, options, SV_DDNS_UPDATE_STYLE);
if (oc) { if (oc) {
if (evaluate_option_cache (&db, (struct packet *)0, if (evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
(struct lease *)0,
(struct client_state *)0,
options,
(struct option_state *)0,
&global_scope, oc, MDL)) { &global_scope, oc, MDL)) {
if (db.len == 1) { if (db.len == 1) {
ddns_update_style = db.data[0]; ddns_update_style = db.data[0];
@ -1002,11 +978,7 @@ void postconf_initialization (int quiet)
oc = lookup_option(&server_universe, options, SV_LOG_FACILITY); oc = lookup_option(&server_universe, options, SV_LOG_FACILITY);
if (oc) { if (oc) {
if (evaluate_option_cache (&db, (struct packet *)0, if (evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
(struct lease *)0,
(struct client_state *)0,
options,
(struct option_state *)0,
&global_scope, oc, MDL)) { &global_scope, oc, MDL)) {
if (db.len == 1) { if (db.len == 1) {
closelog (); closelog ();
@ -1058,6 +1030,14 @@ void postconf_initialization (int quiet)
data_string_forget(&db, MDL); data_string_forget(&db, MDL);
} }
oc = lookup_option(&server_universe, options, SV_DONT_USE_FSYNC);
if ((oc != NULL) &&
evaluate_boolean_option_cache(NULL, NULL, NULL, NULL, options, NULL,
&global_scope, oc, MDL)) {
dont_use_fsync = 1;
log_error("Not using fsync() to flush lease writes");
}
/* Don't need the options anymore. */ /* Don't need the options anymore. */
option_state_dereference(&options, MDL); option_state_dereference(&options, MDL);
} }

View File

@ -2110,6 +2110,24 @@ will still honor the setting of the \fBclient-updates\fR flag.
.RE .RE
.PP .PP
The The
.I dont-use-async
statement
.RS 0.25i
.PP
.B dont-use-async \fIflag\fB;\fR
.PP
The \fIdont-use-async\fR statement instructs the DHCP server if
it should call fsync() when writing leases to the lease file. By
default and if the flag is set to false the server \fBwill\fR call
fsync(). Suppressing the call to fsync() may increase the performance
of the server but it also adds a risk that a lease will not be
properly written to the disk after it has been issued to a client
and before the server stops. This can lead to duplicate leases
being issued to different clients. Using this option is \fBnot
recommended\FR.
.RE
.PP
The
.I dynamic-bootp-lease-cutoff .I dynamic-bootp-lease-cutoff
statement statement
.RS 0.25i .RS 0.25i

View File

@ -267,6 +267,7 @@ static struct option server_options[] = {
#endif /* LDAP_USE_SSL */ #endif /* LDAP_USE_SSL */
#endif /* LDAP_CONFIGURATION */ #endif /* LDAP_CONFIGURATION */
{ "dhcp-cache-threshold", "B", &server_universe, 78, 1 }, { "dhcp-cache-threshold", "B", &server_universe, 78, 1 },
{ "dont-use-fsync", "f", &server_universe, 79, 1 },
{ NULL, NULL, NULL, 0, 0 } { NULL, NULL, NULL, 0, 0 }
}; };