pg_upgrade: throw an error for non-existent tablespace directories
authorBruce Momjian <bruce@momjian.us>
Thu, 17 Apr 2014 15:42:21 +0000 (11:42 -0400)
committerBruce Momjian <bruce@momjian.us>
Thu, 17 Apr 2014 15:42:21 +0000 (11:42 -0400)
Non-existent tablespace directory references can occur if user
tablespaces are created inside data directories and the data directory
is renamed in preparation for running pg_upgrade, and the symbolic links
are not updated.

Backpatch to 9.3.

contrib/pg_upgrade/tablespace.c

index 783ee93cfb6a6d4c2e13c165d6421d137b8ae9c6..94bba087bb7f8ecb4647b9dbc69f56d9db94e06a 100644 (file)
@@ -11,6 +11,8 @@
 
 #include "pg_upgrade.h"
 
+#include <sys/types.h>
+
 static void get_tablespace_paths(void);
 static void set_tablespace_directory_suffix(ClusterInfo *cluster);
 
@@ -65,9 +67,39 @@ get_tablespace_paths(void)
        i_spclocation = PQfnumber(res, "spclocation");
 
        for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
+       {
+               struct stat statBuf;
+
                os_info.old_tablespaces[tblnum] = pg_strdup(
                                                                         PQgetvalue(res, tblnum, i_spclocation));
 
+               /*
+                * Check that the tablespace path exists and is a directory.
+                * Effectively, this is checking only for tables/indexes in
+                * non-existent tablespace directories.  Databases located in
+                * non-existent tablespaces already throw a backend error.
+                * Non-existent tablespace directories can occur when a data
+                * directory that contains user tablespaces is moved as part
+                * of pg_upgrade preparation and the symbolic links are not
+                * updated.
+                */
+               if (stat(os_info.old_tablespaces[tblnum], &statBuf) != 0)
+               {
+                       if (errno == ENOENT)
+                               report_status(PG_FATAL,
+                                                         "tablespace directory \"%s\" does not exist\n",
+                                                         os_info.old_tablespaces[tblnum]);
+                       else
+                               report_status(PG_FATAL,
+                                                         "cannot stat() tablespace directory \"%s\": %s\n",
+                                                         os_info.old_tablespaces[tblnum], getErrorText(errno));
+               }
+               if (!S_ISDIR(statBuf.st_mode))
+                               report_status(PG_FATAL,
+                                                         "tablespace path \"%s\" is not a directory\n",
+                                                         os_info.old_tablespaces[tblnum]);
+       }
+
        PQclear(res);
 
        PQfinish(conn);