MarkBufferDirtyHint() and LSN update - Mailing list pgsql-hackers

From Antonin Houska
Subject MarkBufferDirtyHint() and LSN update
Date
Msg-id 28452.1572443058@antos
Whole thread Raw
Responses Re: MarkBufferDirtyHint() and LSN update
Re: MarkBufferDirtyHint() and LSN update
List 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



pgsql-hackers by date:

Previous
From: Michael Paquier
Date:
Subject: Re: Problem with synchronous replication
Next
From: Peter Eisentraut
Date:
Subject: Remove HAVE_LONG_LONG_INT