Skip to content

Commit 771ba90

Browse files
committed
localbuf: Introduce StartLocalBufferIO()
To initiate IO on a shared buffer we have StartBufferIO(). For temporary table buffers no similar function exists - likely because the code for that currently is very simple due to the lack of concurrency. However, the upcoming AIO support will make it possible to re-encounter a local buffer, while the buffer already is the target of IO. In that case we need to wait for already in-progress IO to complete. This commit makes it easier to add the necessary code, by introducing StartLocalBufferIO(). Reviewed-by: Melanie Plageman <melanieplageman@gmail.com> Discussion: https://postgr.es/m/CAAKRu_b9anbWzEs5AAF9WCvcEVmgz-1AkHSQ-CLLy-p7WHzvFw@mail.gmail.com
1 parent 4b4d33b commit 771ba90

File tree

3 files changed

+39
-6
lines changed

3 files changed

+39
-6
lines changed

src/backend/storage/buffer/bufmgr.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,7 +1038,7 @@ ZeroAndLockBuffer(Buffer buffer, ReadBufferMode mode, bool already_valid)
10381038
{
10391039
/* Simple case for non-shared buffers. */
10401040
bufHdr = GetLocalBufferDescriptor(-buffer - 1);
1041-
need_to_zero = (pg_atomic_read_u32(&bufHdr->state) & BM_VALID) == 0;
1041+
need_to_zero = StartLocalBufferIO(bufHdr, true);
10421042
}
10431043
else
10441044
{
@@ -1388,11 +1388,7 @@ static inline bool
13881388
WaitReadBuffersCanStartIO(Buffer buffer, bool nowait)
13891389
{
13901390
if (BufferIsLocal(buffer))
1391-
{
1392-
BufferDesc *bufHdr = GetLocalBufferDescriptor(-buffer - 1);
1393-
1394-
return (pg_atomic_read_u32(&bufHdr->state) & BM_VALID) == 0;
1395-
}
1391+
return StartLocalBufferIO(GetLocalBufferDescriptor(-buffer - 1), true);
13961392
else
13971393
return StartBufferIO(GetBufferDescriptor(buffer - 1), true, nowait);
13981394
}

src/backend/storage/buffer/localbuf.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,13 @@ FlushLocalBuffer(BufferDesc *bufHdr, SMgrRelation reln)
183183
instr_time io_start;
184184
Page localpage = (char *) LocalBufHdrGetBlock(bufHdr);
185185

186+
/*
187+
* Try to start an I/O operation. There currently are no reasons for
188+
* StartLocalBufferIO to return false, so we raise an error in that case.
189+
*/
190+
if (!StartLocalBufferIO(bufHdr, false))
191+
elog(ERROR, "failed to start write IO on local buffer");
192+
186193
/* Find smgr relation for buffer */
187194
if (reln == NULL)
188195
reln = smgropen(BufTagGetRelFileLocator(&bufHdr->tag),
@@ -406,11 +413,17 @@ ExtendBufferedRelLocal(BufferManagerRelation bmr,
406413
PinLocalBuffer(existing_hdr, false);
407414
buffers[i] = BufferDescriptorGetBuffer(existing_hdr);
408415

416+
/*
417+
* Clear the BM_VALID bit, do StartLocalBufferIO() and proceed.
418+
*/
409419
buf_state = pg_atomic_read_u32(&existing_hdr->state);
410420
Assert(buf_state & BM_TAG_VALID);
411421
Assert(!(buf_state & BM_DIRTY));
412422
buf_state &= ~BM_VALID;
413423
pg_atomic_unlocked_write_u32(&existing_hdr->state, buf_state);
424+
425+
/* no need to loop for local buffers */
426+
StartLocalBufferIO(existing_hdr, true);
414427
}
415428
else
416429
{
@@ -425,6 +438,8 @@ ExtendBufferedRelLocal(BufferManagerRelation bmr,
425438
pg_atomic_unlocked_write_u32(&victim_buf_hdr->state, buf_state);
426439

427440
hresult->id = victim_buf_id;
441+
442+
StartLocalBufferIO(victim_buf_hdr, true);
428443
}
429444
}
430445

@@ -489,6 +504,27 @@ MarkLocalBufferDirty(Buffer buffer)
489504
pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
490505
}
491506

507+
/*
508+
* Like StartBufferIO, but for local buffers
509+
*/
510+
bool
511+
StartLocalBufferIO(BufferDesc *bufHdr, bool forInput)
512+
{
513+
uint32 buf_state = pg_atomic_read_u32(&bufHdr->state);
514+
515+
if (forInput ? (buf_state & BM_VALID) : !(buf_state & BM_DIRTY))
516+
{
517+
/* someone else already did the I/O */
518+
return false;
519+
}
520+
521+
/* BM_IO_IN_PROGRESS isn't currently used for local buffers */
522+
523+
/* local buffers don't track IO using resowners */
524+
525+
return true;
526+
}
527+
492528
/*
493529
* Like TerminateBufferIO, but for local buffers
494530
*/

src/include/storage/buf_internals.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,7 @@ extern BlockNumber ExtendBufferedRelLocal(BufferManagerRelation bmr,
473473
extern void MarkLocalBufferDirty(Buffer buffer);
474474
extern void TerminateLocalBufferIO(BufferDesc *bufHdr, bool clear_dirty,
475475
uint32 set_flag_bits);
476+
extern bool StartLocalBufferIO(BufferDesc *bufHdr, bool forInput);
476477
extern void FlushLocalBuffer(BufferDesc *bufHdr, SMgrRelation reln);
477478
extern void DropRelationLocalBuffers(RelFileLocator rlocator,
478479
ForkNumber forkNum,

0 commit comments

Comments
 (0)