From 0254be55541727d81687bb16106945cb6602b75c Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Fri, 6 Apr 2018 11:54:17 +1200 Subject: [PATCH 1/2] Make sure we don't forget about fsync requests after a failed fsync(). If fsync() fails, the storage manager mustn't forget the fsync request so that future attempts will try again. Author: Thomas Munro and Andrew Gierth Reported-By: Andrew Gierth Discussion: https://postgr.es/m/87y3i1ia4w.fsf%40news-spur.riddles.org.uk --- src/backend/storage/smgr/md.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c index bb96881cad..27c55de16a 100644 --- a/src/backend/storage/smgr/md.c +++ b/src/backend/storage/smgr/md.c @@ -1150,10 +1150,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++) { @@ -1163,7 +1161,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; @@ -1272,10 +1271,28 @@ mdsync(void) */ if (!FILE_POSSIBLY_DELETED(errno) || failures > 0) + { + MemoryContext oldcxt; + Bitmapset *new_requests; + + /* + * We need to merge these unsatisfied requests with + * any others that have arrived since we started. + */ + new_requests = entry->requests[forknum]; + oldcxt = MemoryContextSwitchTo(pendingOpsCxt); + entry->requests[forknum] = + bms_union(new_requests, requests); + MemoryContextSwitchTo(oldcxt); + bms_free(new_requests); + bms_free(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(), -- 2.16.2