aboutsummaryrefslogtreecommitdiff
path: root/src/backend/storage/buffer/bufmgr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/storage/buffer/bufmgr.c')
-rw-r--r--src/backend/storage/buffer/bufmgr.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 13b80aefc5b..405ff61130e 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -1922,9 +1922,24 @@ FlushBuffer(volatile BufferDesc *buf, SMgrRelation reln)
* Force XLOG flush up to buffer's LSN. This implements the basic WAL
* rule that log updates must hit disk before any of the data-file changes
* they describe do.
+ *
+ * However, this rule does not apply to unlogged relations, which will be
+ * lost after a crash anyway. Most unlogged relation pages do not bear
+ * LSNs since we never emit WAL records for them, and therefore flushing
+ * up through the buffer LSN would be useless, but harmless. However, GiST
+ * indexes use LSNs internally to track page-splits, and therefore unlogged
+ * GiST pages bear "fake" LSNs generated by GetFakeLSNForUnloggedRel. It
+ * is unlikely but possible that the fake LSN counter could advance past
+ * the WAL insertion point; and if it did happen, attempting to flush WAL
+ * through that location would fail, with disastrous system-wide
+ * consequences. To make sure that can't happen, skip the flush if the
+ * buffer isn't permanent.
*/
- recptr = BufferGetLSN(buf);
- XLogFlush(recptr);
+ if (buf->flags & BM_PERMANENT)
+ {
+ recptr = BufferGetLSN(buf);
+ XLogFlush(recptr);
+ }
/*
* Now it's safe to write buffer to disk. Note that no one else should