OSDN Git Service

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 4b7131b..e629b9a 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 2e0ae34..519824f 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
         */