From 680f89e5613cc859356152ae65597c78f0cea4dd Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Sun, 2 Sep 2018 12:40:38 -0700 Subject: [PATCH] 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- --- src/backend/replication/slot.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 94f7a99cfa..7368f9653b 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -1352,6 +1352,7 @@ RestoreSlotFromDisk(const char *name) { ReplicationSlotOnDisk cp; int i; + char slotdir[MAXPGPATH + 12]; char path[MAXPGPATH + 22]; int fd; bool restored = false; @@ -1361,13 +1362,14 @@ RestoreSlotFromDisk(const char *name) /* no need to lock here, no concurrent access allowed yet */ /* 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) ereport(PANIC, (errcode_for_file_access(), 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); @@ -1402,7 +1404,7 @@ RestoreSlotFromDisk(const char *name) /* Also sync the parent directory */ START_CRIT_SECTION(); - fsync_fname(path, true); + fsync_fname(slotdir, true); END_CRIT_SECTION(); /* read part of statefile that's guaranteed to be version independent */ @@ -1481,13 +1483,11 @@ RestoreSlotFromDisk(const char *name) */ if (cp.slotdata.persistency != RS_PERSISTENT) { - sprintf(path, "pg_replslot/%s", name); - - if (!rmtree(path, true)) + if (!rmtree(slotdir, true)) { ereport(WARNING, (errcode_for_file_access(), - errmsg("could not remove directory \"%s\"", path))); + errmsg("could not remove directory \"%s\"", slotdir))); } fsync_fname("pg_replslot", true); return; -- 2.40.0