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 14:07:19 +1300
commita4a4aede5fabe6d94bd9b6445725db0c57eecd9b (patch)
tree23773e69742e17fda068f56d19fa62123c50ba2a
parentf57b94d9d0bbf42a18690d820f884dc0fc6bf79e (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 849055b191a..fcbe9eac993 100644
--- a/src/backend/storage/smgr/md.c
+++ b/src/backend/storage/smgr/md.c
@@ -1090,10 +1090,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++)
{
@@ -1103,7 +1101,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;
@@ -1182,6 +1181,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,
@@ -1210,10 +1210,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(),