Re: Shared buffer access rule violations?
Tom Lane <tgl@sss.pgh.pa.us>
From: Tom Lane <tgl@sss.pgh.pa.us>
To: Asim R P <apraveen@pivotal.io>
Cc: PostgreSQL mailing lists <pgsql-hackers@postgresql.org>
Date: 2018-07-12T22:30:34Z
Lists: pgsql-hackers
Asim R P <apraveen@pivotal.io> writes:
> On Tue, Jul 10, 2018 at 8:33 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>> Asim R P <apraveen@pivotal.io> writes:
>>> One can find several PageInit() calls with no content lock held. See,
>>> for example:
>>> fill_seq_with_data()
>> That would be for a relation that no one else can even see yet, no?
> Yes, when the sequence is being created. No, when the sequence is
> being reset, in ResetSequence().
ResetSequence creates a new relfilenode, which no one else will be able
to see until it commits, so the case is effectively the same as for
creation.
>>> vm_readbuf()
>>> fsm_readbuf()
>> In these cases I'd imagine that the I/O completion interlock is what
>> is preventing other backends from accessing the buffer.
> What is I/O completion interlock?
Oh ... the RBM_ZERO_ON_ERROR action should be done under the I/O lock,
but the ReadBuffer caller isn't holding that lock anymore, so I see your
point here. Probably, nobody's noticed because it's a corner case that
shouldn't happen under normal use, but it's not safe. I think what we
want is more like
if (PageIsNew(BufferGetPage(buf)))
{
LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
if (PageIsNew(BufferGetPage(buf)))
PageInit(BufferGetPage(buf), BLCKSZ, 0);
UnlockReleaseBuffer(buf);
}
to ensure that the page is initialized once and only once, even if
several backends do this concurrently.
regards, tom lane
Commits
-
Fix inadequate buffer locking in FSM and VM page re-initialization.
- 0cf3363c0110 9.3.24 landed
- 6d2d5ab173a9 9.4.19 landed
- 17c3dabbb70c 9.5.14 landed
- 073ffefd8082 9.6.10 landed
- f1963a1e79a4 10.5 landed
- 5586e42b3493 11.0 landed
- 130beba36d6d 12.0 landed