Properly replay CREATE TABLESPACE during crash recovery by deleting
authorBruce Momjian <bruce@momjian.us>
Tue, 20 Jul 2010 18:14:16 +0000 (18:14 +0000)
committerBruce Momjian <bruce@momjian.us>
Tue, 20 Jul 2010 18:14:16 +0000 (18:14 +0000)
directory/symlink before creation.

Report from Tom Lane.

Backpatch to 9.0.

src/backend/commands/dbcommands.c
src/backend/commands/tablespace.c

index 4b7131b7097aa562a2890331e35a0529cb59225c..e629b9ab24874dc95f9879de011170b3dc2fdae7 100644 (file)
@@ -13,7 +13,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.235 2010/02/26 02:00:38 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.236 2010/07/20 18:14:16 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1908,6 +1908,7 @@ dbase_redo(XLogRecPtr lsn, XLogRecord *record)
        if (stat(dst_path, &st) == 0 && S_ISDIR(st.st_mode))
        {
            if (!rmtree(dst_path, true))
+               /* If this failed, copydir() below is going to error. */
                ereport(WARNING,
                        (errmsg("some useless files may be left behind in old database directory \"%s\"",
                                dst_path)));
index 2e0ae340fb1b9a63b760cbb67172afdf17ff5845..519824f3281270960279db7737f5c7207c07b1a3 100644 (file)
@@ -40,7 +40,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.77 2010/07/18 04:47:46 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.78 2010/07/20 18:14:16 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -562,6 +562,25 @@ create_tablespace_directories(const char *location, const Oid tablespaceoid)
                         location)));
    }
 
+   if (InRecovery)
+   {
+       struct stat st;
+
+       /*
+        * Our theory for replaying a CREATE is to forcibly drop the target
+        * subdirectory if present, and then recreate it. This may be
+        * more work than needed, but it is simple to implement.
+        */
+       if (stat(location_with_version_dir, &st) == 0 && S_ISDIR(st.st_mode))
+       {
+           if (!rmtree(location_with_version_dir, true))
+               /* If this failed, mkdir() below is going to error. */
+               ereport(WARNING,
+                       (errmsg("some useless files may be left behind in old database directory \"%s\"",
+                               location_with_version_dir)));
+       }
+   }
+
    /*
     * The creation of the version directory prevents more than one tablespace
     * in a single location.
@@ -580,6 +599,16 @@ create_tablespace_directories(const char *location, const Oid tablespaceoid)
                            location_with_version_dir)));
    }
 
+   /* Remove old symlink in recovery, in case it points to the wrong place */
+   if (InRecovery)
+   {
+       if (unlink(linkloc) < 0 && errno != ENOENT)
+           ereport(ERROR,
+                   (errcode_for_file_access(),
+                    errmsg("could not remove symbolic link \"%s\": %m",
+                           linkloc)));
+   }
+   
    /*
     * Create the symlink under PGDATA
     */