summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Munro <tmunro@postgresql.org>2018-11-19 13:40:50 +1300
committerThomas Munro <tmunro@postgresql.org>2018-11-19 13:40:50 +1300
commit28117764db7ed0c9fc589dd9323c439235040b05 (patch)
tree317b9e9f64e7954fcfb9fcf3139e0fc8e5dad940
parent5b16a353543ecec36ffda68269defb7b1b002f60 (diff)
Don't forget about failed fsync() requests.
If fsync() fails, md.c must keep the request in its bitmap, so that future attempts will try again. Back-patch to all supported releases. Author: Thomas Munro Reviewed-by: Amit Kapila Reported-by: Andrew Gierth Discussion: https://postgr.es/m/87y3i1ia4w.fsf%40news-spur.riddles.org.uk
-rw-r--r--src/backend/storage/smgr/md.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c
index f487354f671..64455a41550 100644
--- a/src/backend/storage/smgr/md.c
+++ b/src/backend/storage/smgr/md.c
@@ -1151,10 +1151,8 @@ mdsync(void)
* The bitmap manipulations are slightly tricky, because we can call
* AbsorbFsyncRequests() inside the loop and that could result in
* bms_add_member() modifying and even re-palloc'ing the bitmapsets.
- * This is okay because we unlink each bitmapset from the hashtable
- * entry before scanning it. That means that any incoming fsync
- * requests will be processed now if they reach the table before we
- * begin to scan their fork.
+ * So we detach it, but if we fail we'll merge it with any new
+ * requests that have arrived in the meantime.
*/
for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
{
@@ -1164,7 +1162,8 @@ mdsync(void)
entry->requests[forknum] = NULL;
entry->canceled[forknum] = false;
- while ((segno = bms_first_member(requests)) >= 0)
+ segno = -1;
+ while ((segno = bms_next_member(requests, segno)) >= 0)
{
int failures;
@@ -1245,6 +1244,7 @@ mdsync(void)
longest = elapsed;
total_elapsed += elapsed;
processed++;
+ requests = bms_del_member(requests, segno);
if (log_checkpoints)
elog(DEBUG1, "checkpoint sync: number=%d file=%s time=%.3f msec",
processed,
@@ -1273,10 +1273,23 @@ mdsync(void)
*/
if (!FILE_POSSIBLY_DELETED(errno) ||
failures > 0)
+ {
+ Bitmapset *new_requests;
+
+ /*
+ * We need to merge these unsatisfied requests with
+ * any others that have arrived since we started.
+ */
+ new_requests = entry->requests[forknum];
+ entry->requests[forknum] =
+ bms_join(new_requests, requests);
+
+ errno = save_errno;
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not fsync file \"%s\": %m",
path)));
+ }
else
ereport(DEBUG1,
(errcode_for_file_access(),