MarkBufferDirtyHint() and LSN update

From: Antonin Houska <ah(at)cybertec(dot)at>
To: pgsql-hackers(at)postgresql(dot)org
Subject: MarkBufferDirtyHint() and LSN update
Date: 2019-10-30 13:44:18
Message-ID: 28452.1572443058@antos
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Please consider this scenario (race conditions):

1. FlushBuffer() has written the buffer but hasn't yet managed to clear the
BM_DIRTY flag (however BM_JUST_DIRTIED could be cleared by now).

2. Another backend modified a hint bit and called MarkBufferDirtyHint().

3. In MarkBufferDirtyHint(), if XLogHintBitIsNeeded() evaluates to true
(e.g. due to checksums enabled), new LSN is computed, however it's not
assigned to the page because the buffer is still dirty:

if (!(buf_state & BM_DIRTY))
{
...

if (!XLogRecPtrIsInvalid(lsn))
PageSetLSN(page, lsn);
}

4. MarkBufferDirtyHint() completes.

5. In the first session, FlushBuffer()->TerminateBufferIO() will not clear
BM_DIRTY because MarkBufferDirtyHint() has eventually set
BM_JUST_DIRTIED. Thus the hint bit change itself will be written by the next
call of FlushBuffer(). However page LSN is hasn't been updated so the
requirement that WAL must be flushed first is not met.

I think that PageSetLSN() should be called regardless BM_DIRTY. Do I miss any
subtle detail?

--
Antonin Houska
Web: https://www.cybertec-postgresql.com

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Peter Eisentraut 2019-10-30 13:49:38 Remove HAVE_LONG_LONG_INT
Previous Message Michael Paquier 2019-10-30 13:00:12 Re: Problem with synchronous replication