Commit caa0c6ce authored by Michael Paquier's avatar Michael Paquier

Fix initial sync of slot parent directory when restoring status

At the beginning of recovery, information from replication slots is
recovered from disk to memory.  In order to ensure the durability of the
information, the status file as well as its parent directory are
synced.  It happens that the sync on the parent directory was done
directly using the status file path, which is logically incorrect, and
the current code has been doing a sync on the same object twice in a
row.

Reported-by: Konstantin Knizhnik
Diagnosed-by: Konstantin Knizhnik
Author: Michael Paquier
Discussion: https://postgr.es/m/9eb1a6d5-b66f-2640-598d-c5ea46b8f68a@postgrespro.ru
Backpatch-through: 9.4-
parent 4299c323
...@@ -1352,6 +1352,7 @@ RestoreSlotFromDisk(const char *name) ...@@ -1352,6 +1352,7 @@ RestoreSlotFromDisk(const char *name)
{ {
ReplicationSlotOnDisk cp; ReplicationSlotOnDisk cp;
int i; int i;
char slotdir[MAXPGPATH + 12];
char path[MAXPGPATH + 22]; char path[MAXPGPATH + 22];
int fd; int fd;
bool restored = false; bool restored = false;
...@@ -1361,13 +1362,14 @@ RestoreSlotFromDisk(const char *name) ...@@ -1361,13 +1362,14 @@ RestoreSlotFromDisk(const char *name)
/* no need to lock here, no concurrent access allowed yet */ /* no need to lock here, no concurrent access allowed yet */
/* delete temp file if it exists */ /* delete temp file if it exists */
sprintf(path, "pg_replslot/%s/state.tmp", name); sprintf(slotdir, "pg_replslot/%s", name);
sprintf(path, "%s/state.tmp", slotdir);
if (unlink(path) < 0 && errno != ENOENT) if (unlink(path) < 0 && errno != ENOENT)
ereport(PANIC, ereport(PANIC,
(errcode_for_file_access(), (errcode_for_file_access(),
errmsg("could not remove file \"%s\": %m", path))); errmsg("could not remove file \"%s\": %m", path)));
sprintf(path, "pg_replslot/%s/state", name); sprintf(path, "%s/state", slotdir);
elog(DEBUG1, "restoring replication slot from \"%s\"", path); elog(DEBUG1, "restoring replication slot from \"%s\"", path);
...@@ -1402,7 +1404,7 @@ RestoreSlotFromDisk(const char *name) ...@@ -1402,7 +1404,7 @@ RestoreSlotFromDisk(const char *name)
/* Also sync the parent directory */ /* Also sync the parent directory */
START_CRIT_SECTION(); START_CRIT_SECTION();
fsync_fname(path, true); fsync_fname(slotdir, true);
END_CRIT_SECTION(); END_CRIT_SECTION();
/* read part of statefile that's guaranteed to be version independent */ /* read part of statefile that's guaranteed to be version independent */
...@@ -1491,13 +1493,11 @@ RestoreSlotFromDisk(const char *name) ...@@ -1491,13 +1493,11 @@ RestoreSlotFromDisk(const char *name)
*/ */
if (cp.slotdata.persistency != RS_PERSISTENT) if (cp.slotdata.persistency != RS_PERSISTENT)
{ {
sprintf(path, "pg_replslot/%s", name); if (!rmtree(slotdir, true))
if (!rmtree(path, true))
{ {
ereport(WARNING, ereport(WARNING,
(errcode_for_file_access(), (errcode_for_file_access(),
errmsg("could not remove directory \"%s\"", path))); errmsg("could not remove directory \"%s\"", slotdir)));
} }
fsync_fname("pg_replslot", true); fsync_fname("pg_replslot", true);
return; return;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment