location)));
}
- if (InRecovery)
- {
- /*
- * 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.
+ * in a single location. This imitates TablespaceCreateDbspace(), but it
+ * ignores concurrency and missing parent directories. The chmod() would
+ * have failed in the absence of a parent. pg_tablespace_spcname_index
+ * prevents concurrency.
*/
- if (mkdir(location_with_version_dir, S_IRWXU) < 0)
+ if (stat(location_with_version_dir, &st) < 0)
{
- if (errno == EEXIST)
+ if (errno != ENOENT)
ereport(ERROR,
- (errcode(ERRCODE_OBJECT_IN_USE),
- errmsg("directory \"%s\" already in use as a tablespace",
+ (errcode_for_file_access(),
+ errmsg("could not stat directory \"%s\": %m",
location_with_version_dir)));
- else
+ else if (mkdir(location_with_version_dir, S_IRWXU) < 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not create directory \"%s\": %m",
location_with_version_dir)));
}
+ else if (!S_ISDIR(st.st_mode))
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" exists but is not a directory",
+ location_with_version_dir)));
+ else if (!InRecovery)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_IN_USE),
+ errmsg("directory \"%s\" already in use as a tablespace",
+ location_with_version_dir)));
/*
* In recovery, remove old symlink, in case it points to the wrong place.