From ba30cc562f5ebd58955502a19edbf9720a45b655 Mon Sep 17 00:00:00 2001 From: Mark Reynolds Date: Tue, 8 Aug 2017 13:02:53 -0400 Subject: [PATCH] Ticket 49298 - force sync() on shutdown Bug Description: During shutdown on xfs we would occasionally see a broke dse.ldif (specifically, empty). This happens due to a bug in xfs where the directory isn't synced on rename(). Fix Description: As we shutdown call sync() to force all our writes to disk - dse.ldif, logs, db, all of it. https://pagure.io/389-ds-base/issue/49298 --- ldap/servers/slapd/dse.c | 59 +++++++++++++++++++++++++++++------------------ ldap/servers/slapd/main.c | 9 ++++---- 2 files changed, 42 insertions(+), 26 deletions(-) diff --git a/ldap/servers/slapd/dse.c b/ldap/servers/slapd/dse.c index 5715c83..fa1aacc 100644 --- a/ldap/servers/slapd/dse.c +++ b/ldap/servers/slapd/dse.c @@ -40,6 +40,8 @@ #include "slap.h" #include +#include /* provides fsync/close */ + /* #define SLAPI_DSE_DEBUG */ /* define this to force trace log */ /* messages to always be logged */ @@ -72,11 +74,11 @@ struct dse_callback { int operation; - int flags; - Slapi_DN *base; - int scope; - char *filter; /* NULL means match all entries */ - Slapi_Filter *slapifilter; /* NULL means match all entries */ + int flags; + Slapi_DN *base; + int scope; + char *filter; /* NULL means match all entries */ + Slapi_Filter *slapifilter; /* NULL means match all entries */ int (*fn)(Slapi_PBlock *,Slapi_Entry *,Slapi_Entry *,int*,char*,void *); void *fn_arg; struct slapdplugin *plugin; @@ -89,13 +91,14 @@ struct dse char *dse_tmpfile; /* and written to when changes are made via LDAP */ char *dse_fileback; /* contain the latest info, just before a new change */ char *dse_filestartOK; /* contain the latest info with which the server has successfully started */ + char *dse_configdir; /* The location of config files - allows us to fsync the dir post rename */ Avlnode *dse_tree; struct dse_callback *dse_callback; Slapi_RWLock *dse_rwlock; /* a read-write lock to protect the whole dse backend */ - char **dse_filelist; /* these are additional read only files used to */ - /* initialize the dse */ - int dse_is_updateable; /* if non-zero, this DSE can be written to */ - int dse_readonly_error_reported; /* used to ensure that read-only errors are logged only once */ + char **dse_filelist; /* these are additional read only files used to */ + /* initialize the dse */ + int dse_is_updateable; /* if non-zero, this DSE can be written to */ + int dse_readonly_error_reported; /* used to ensure that read-only errors are logged only once */ }; struct dse_node @@ -361,37 +364,39 @@ dse_new( char *filename, char *tmpfilename, char *backfilename, char *startokfil if (!strstr(filename, realconfigdir)) { pdse->dse_filename = slapi_ch_smprintf("%s/%s", realconfigdir, filename ); - } - else + } else { pdse->dse_filename = slapi_ch_strdup(filename); + } if (!strstr(tmpfilename, realconfigdir)) { pdse->dse_tmpfile = slapi_ch_smprintf("%s/%s", realconfigdir, tmpfilename ); - } - else + } else { pdse->dse_tmpfile = slapi_ch_strdup(tmpfilename); + } + + pdse->dse_configdir = slapi_ch_strdup(realconfigdir); if ( backfilename != NULL ) { if (!strstr(backfilename, realconfigdir)) { pdse->dse_fileback = slapi_ch_smprintf("%s/%s", realconfigdir, backfilename ); - } - else + } else { pdse->dse_fileback = slapi_ch_strdup(backfilename); - } - else + } + } else { pdse->dse_fileback = NULL; + } if ( startokfilename != NULL ) { if (!strstr(startokfilename, realconfigdir)) { pdse->dse_filestartOK = slapi_ch_smprintf("%s/%s", realconfigdir, startokfilename ); - } - else + } else { pdse->dse_filestartOK = slapi_ch_strdup(startokfilename); - } - else + } + } else { pdse->dse_filestartOK = NULL; + } pdse->dse_tree= NULL; pdse->dse_callback= NULL; @@ -440,6 +445,7 @@ dse_destroy(struct dse *pdse) slapi_ch_free((void **)&(pdse->dse_tmpfile)); slapi_ch_free((void **)&(pdse->dse_fileback)); slapi_ch_free((void **)&(pdse->dse_filestartOK)); + slapi_ch_free((void **)&(pdse->dse_configdir)); dse_callback_deletelist(&pdse->dse_callback); charray_free(pdse->dse_filelist); nentries = avl_free(pdse->dse_tree, dse_internal_delete_entry); @@ -991,8 +997,9 @@ dse_write_file_nolock(struct dse* pdse) FPWrapper fpw; int rc = 0; - if (dont_ever_write_dse_files) + if (dont_ever_write_dse_files) { return rc; + } fpw.fpw_rc = 0; fpw.fpw_prfd = NULL; @@ -1042,6 +1049,14 @@ dse_write_file_nolock(struct dse* pdse) pdse->dse_tmpfile, pdse->dse_filename, rc, slapd_system_strerror( rc )); } + /* + * We have now written to the tmp location, and renamed it + * we need to open and fsync the dir to make the rename stick. + */ + int fp_configdir = open(pdse->dse_configdir, O_PATH | O_DIRECTORY); + fsync(fp_configdir); + close(fp_configdir); + } } if (fpw.fpw_prfd) diff --git a/ldap/servers/slapd/main.c b/ldap/servers/slapd/main.c index ba1f5e8..3351464 100644 --- a/ldap/servers/slapd/main.c +++ b/ldap/servers/slapd/main.c @@ -1154,11 +1154,12 @@ cleanup: ndn_cache_destroy(); NSS_Shutdown(); PR_Cleanup(); -#if defined( hpux ) - exit( return_value ); -#else + /* + * Server has stopped, lets force everything to disk: logs + * db, dse.ldif, all of it. + */ + sync(); return return_value; -#endif } -- 2.9.4