]> granicus.if.org Git - postgresql/commitdiff
Fix initdb --sync-only to also sync tablespaces.
authorAndres Freund <andres@anarazel.de>
Fri, 14 Nov 2014 17:22:12 +0000 (18:22 +0100)
committerAndres Freund <andres@anarazel.de>
Sat, 15 Nov 2014 00:20:07 +0000 (01:20 +0100)
630cd14426dc added initdb --sync-only, for use by pg_upgrade, by just
exposing the existing fsync code. That's wrong, because initdb so far
had absolutely no reason to deal with tablespaces.

Fix --sync-only by additionally explicitly syncing each of the
tablespaces.

Backpatch to 9.3 where --sync-only was introduced.

Abhijit Menon-Sen and Andres Freund

src/bin/initdb/initdb.c

index f884b02eac94c24be7145b11bec5dfb77763508b..5036d01b6086426512d4fbcffbea29ffd8d897d0 100644 (file)
@@ -60,6 +60,7 @@
 #include "sys/mman.h"
 #endif
 
+#include "catalog/catalog.h"
 #include "common/username.h"
 #include "mb/pg_wchar.h"
 #include "getaddrinfo.h"
@@ -218,6 +219,7 @@ static char **filter_lines_with_token(char **lines, const char *token);
 static char **readfile(const char *path);
 static void writefile(char *path, char **lines);
 static void walkdir(char *path, void (*action) (char *fname, bool isdir));
+static void walktblspc_links(char *path, void (*action) (char *fname, bool isdir));
 static void pre_sync_fname(char *fname, bool isdir);
 static void fsync_fname(char *fname, bool isdir);
 static FILE *popen_check(const char *command, const char *mode);
@@ -587,6 +589,55 @@ walkdir(char *path, void (*action) (char *fname, bool isdir))
        (*action) (path, true);
 }
 
+/*
+ * walktblspc_links: call walkdir on each entry under the given
+ * pg_tblspc directory, or do nothing if pg_tblspc doesn't exist.
+ */
+static void
+walktblspc_links(char *path, void (*action) (char *fname, bool isdir))
+{
+       DIR                *dir;
+       struct dirent *direntry;
+       char            subpath[MAXPGPATH];
+
+       dir = opendir(path);
+       if (dir == NULL)
+       {
+               if (errno == ENOENT)
+                       return;
+               fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
+                               progname, path, strerror(errno));
+               exit_nicely();
+       }
+
+       while (errno = 0, (direntry = readdir(dir)) != NULL)
+       {
+               if (strcmp(direntry->d_name, ".") == 0 ||
+                       strcmp(direntry->d_name, "..") == 0)
+                       continue;
+
+               /* fsync the version specific tablespace subdirectory */
+               snprintf(subpath, sizeof(subpath), "%s/%s/%s",
+                                path, direntry->d_name, TABLESPACE_VERSION_DIRECTORY);
+
+               walkdir(subpath, action);
+       }
+
+       if (errno)
+       {
+               fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
+                               progname, path, strerror(errno));
+               exit_nicely();
+       }
+
+       if (closedir(dir))
+       {
+               fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
+                               progname, path, strerror(errno));
+               exit_nicely();
+       }
+}
+
 /*
  * Hint to the OS that it should get ready to fsync() this file.
  */
@@ -2375,6 +2426,7 @@ static void
 perform_fsync(void)
 {
        char            pdir[MAXPGPATH];
+       char            pg_tblspc[MAXPGPATH];
 
        fputs(_("syncing data to disk ... "), stdout);
        fflush(stdout);
@@ -2393,9 +2445,13 @@ perform_fsync(void)
        /* first the parent of the PGDATA directory */
        pre_sync_fname(pdir, true);
 
-       /* then recursively through the directory */
+       /* then recursively through the data directory */
        walkdir(pg_data, pre_sync_fname);
 
+       /* now do the same thing for everything under pg_tblspc */
+       snprintf(pg_tblspc, MAXPGPATH, "%s/pg_tblspc", pg_data);
+       walktblspc_links(pg_tblspc, pre_sync_fname);
+
        /*
         * Now, do the fsync()s in the same order.
         */
@@ -2403,9 +2459,12 @@ perform_fsync(void)
        /* first the parent of the PGDATA directory */
        fsync_fname(pdir, true);
 
-       /* then recursively through the directory */
+       /* then recursively through the data directory */
        walkdir(pg_data, fsync_fname);
 
+       /* and now the same for all tablespaces */
+       walktblspc_links(pg_tblspc, fsync_fname);
+
        check_ok();
 }