Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 304160c

Browse files
committed
Fix ReadBuffer() to correctly handle the case where it's trying to extend
the relation but it finds a pre-existing valid buffer. The buffer does not correspond to any page known to the kernel, so we *must* do smgrextend to ensure that the space becomes allocated. The 7.x branches all do this correctly, but the corner case got lost somewhere during 8.0 bufmgr rewrites. (My fault no doubt :-( ... I think I assumed that such a buffer must be not-BM_VALID, which is not so.)
1 parent 6d41b14 commit 304160c

File tree

1 file changed

+40
-6
lines changed

1 file changed

+40
-6
lines changed

src/backend/storage/buffer/bufmgr.c

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.201 2005/12/29 18:08:05 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.202 2006/01/06 00:04:20 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -164,13 +164,47 @@ ReadBuffer(Relation reln, BlockNumber blockNum)
164164
/* if it was already in the buffer pool, we're done */
165165
if (found)
166166
{
167-
/* Just need to update stats before we exit */
168-
pgstat_count_buffer_hit(&reln->pgstat_info, reln);
167+
if (!isExtend)
168+
{
169+
/* Just need to update stats before we exit */
170+
pgstat_count_buffer_hit(&reln->pgstat_info, reln);
171+
172+
if (VacuumCostActive)
173+
VacuumCostBalance += VacuumCostPageHit;
169174

170-
if (VacuumCostActive)
171-
VacuumCostBalance += VacuumCostPageHit;
175+
return BufferDescriptorGetBuffer(bufHdr);
176+
}
172177

173-
return BufferDescriptorGetBuffer(bufHdr);
178+
/*
179+
* We get here only in the corner case where we are trying to extend
180+
* the relation but we found a pre-existing buffer marked BM_VALID.
181+
* (This can happen because mdread doesn't complain about reads
182+
* beyond EOF --- which is arguably bogus, but changing it seems
183+
* tricky.) We *must* do smgrextend before succeeding, else the
184+
* page will not be reserved by the kernel, and the next P_NEW call
185+
* will decide to return the same page. Clear the BM_VALID bit,
186+
* do the StartBufferIO call that BufferAlloc didn't, and proceed.
187+
*/
188+
if (isLocalBuf)
189+
{
190+
/* Only need to adjust flags */
191+
Assert(bufHdr->flags & BM_VALID);
192+
bufHdr->flags &= ~BM_VALID;
193+
}
194+
else
195+
{
196+
/*
197+
* Loop to handle the very small possibility that someone
198+
* re-sets BM_VALID between our clearing it and StartBufferIO
199+
* inspecting it.
200+
*/
201+
do {
202+
LockBufHdr(bufHdr);
203+
Assert(bufHdr->flags & BM_VALID);
204+
bufHdr->flags &= ~BM_VALID;
205+
UnlockBufHdr(bufHdr);
206+
} while (!StartBufferIO(bufHdr, true));
207+
}
174208
}
175209

176210
/*

0 commit comments

Comments
 (0)