Hi,
If you call XLogNeedsFlush() immediately after calling XLogFlush() in
FlushBuffer(), it can return true.
With this diff:
diff --git a/src/backend/storage/buffer/bufmgr.c
b/src/backend/storage/buffer/bufmgr.c
index 350cc0402aa..91c3fe99d6e 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -4342,7 +4342,11 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln,
IOObject io_object,
* skip the flush if the buffer isn't permanent.
*/
if (buf_state & BM_PERMANENT)
+ {
XLogFlush(recptr);
+ if(XLogNeedsFlush(recptr))
+ elog(ERROR, "should be flushed and isn't");
+ }
recovery/015_promotion_pages errors out.
During an end-of-recovery checkpoint, XLogNeedsFlush() should compare
the provided LSN to the flush pointer and not the min recovery point.
This only errors out during an end-of-recovery checkpoint after a
crash when the ControlFile->minRecoveryPoint has not been correctly
updated. In this case, LocalMinRecoveryPoint is initialized to an
incorrect value potentially causing XLogNeedsFlush() to incorrectly
return true.
This trivial diff makes the test pass:
@@ -3115,7 +3125,7 @@ XLogNeedsFlush(XLogRecPtr record)
* instead. So "needs flush" is taken to mean whether minRecoveryPoint
* would need to be updated.
*/
- if (RecoveryInProgress())
+ if (RecoveryInProgress() && !XLogInsertAllowed())
{
However, since all of this code is new to me, there are some remaining
things I don't understand:
Why is it okay for other processes than the startup process to
initialize LocalMinRecoveryPoint from ControlFile->minRecoveryPoint
during crash recovery?
All of the comments and the code seem to indicate that this is allowed.
Couldn't it just as likely be invalid for them (e.g. checkpointer
here) as it could for the startup process? Like if we crashed before
updating it?
Besides this question, I find the use of the global variable
InRecovery as a proxy for RecoveryInProgress() + "I'm the startup
process" to be confusing. It seems like UpdateMinRecoveryPoint() and
XLogNeedsFlush() could just test MyBackendType == B_STARTUP and make
it explicit.
- Melanie