Blame SOURCES/0059-Ticket-49298-force-sync-on-shutdown.patch

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