diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c index 28933f8bbe..06b57ae71f 100644 --- a/src/backend/storage/file/fd.c +++ b/src/backend/storage/file/fd.c @@ -801,17 +801,20 @@ durable_unlink(const char *fname, int elevel) } /* - * durable_rename_excl -- rename a file in a durable manner, without - * overwriting an existing target file + * durable_rename_excl -- rename a file in a durable manner. * - * Similar to durable_rename(), except that this routine will fail if the - * target file already exists. + * Similar to durable_rename(), except that this routine tries (but does not + * guarantee) not to overwrite the target file. * * Note that a crash in an unfortunate moment can leave you with two links to * the target file. * * Log errors with the caller specified severity. * + * On Windows, using a hard link followed by unlink() causes concurrency + * issues, while a simple rename() does not cause that, so be careful when + * changing the logic of this routine. + * * Returns 0 if the operation succeeded, -1 otherwise. Note that errno is not * valid upon return. */ @@ -825,6 +828,7 @@ durable_rename_excl(const char *oldfile, const char *newfile, int elevel) if (fsync_fname_ext(oldfile, false, false, elevel) != 0) return -1; +#ifdef HAVE_WORKING_LINK if (link(oldfile, newfile) < 0) { ereport(elevel, @@ -834,6 +838,16 @@ durable_rename_excl(const char *oldfile, const char *newfile, int elevel) return -1; } unlink(oldfile); +#else + if (rename(oldfile, newfile) < 0) + { + ereport(elevel, + (errcode_for_file_access(), + errmsg("could not rename file \"%s\" to \"%s\": %m", + oldfile, newfile))); + return -1; + } +#endif /* * Make change persistent in case of an OS crash, both the new entry and diff --git a/src/include/pg_config_manual.h b/src/include/pg_config_manual.h index f10ad0acd6..e28c990382 100644 --- a/src/include/pg_config_manual.h +++ b/src/include/pg_config_manual.h @@ -135,6 +135,13 @@ #define EXEC_BACKEND #endif +/* + * Define this if your operating system supports link() + */ +#if !defined(WIN32) && !defined(__CYGWIN__) +#define HAVE_WORKING_LINK 1 +#endif + /* * USE_POSIX_FADVISE controls whether Postgres will attempt to use the * posix_fadvise() kernel call. Usually the automatic configure tests are