summaryrefslogtreecommitdiff
path: root/src/backend/storage/smgr/md.c
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:50:54 +1300
commita4d6d6a25c12ca9a19a5e7ec6f76115bced69521 (patch)
tree489a0a9064be66409406053c3cd3096a97ea7da3 /src/backend/storage/smgr/md.c
parent71b2951ccc433a6dd799efedff9f5927c32440f6 (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
Diffstat (limited to 'src/backend/storage/smgr/md.c')
-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 bfa065d9fb8..91a290c357f 100644
--- a/src/backend/storage/smgr/md.c
+++ b/src/backend/storage/smgr/md.c
@@ -1148,10 +1148,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++)
{
@@ -1161,7 +1159,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;
@@ -1242,6 +1241,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,
@@ -1270,10 +1270,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(),