mirror of
https://github.com/postgres/postgres.git
synced 2025-07-05 07:21:24 +03:00
Fix bug in bulk extending temp relation after failure
A ResourceOwnerEnlarge() call was missing. That led to an error:
ERROR: ResourceOwnerRemember called but array was full
and an assertion failure, if you tried to extend a temp relation again
after a failure. Alexander's test case used running out of disk space
to trigger the original failure.
This bug was introduced in the large ResourceOwner rewrite commit
b8bff07daa
. Before that, the UnpinLocalBuffer() call guaranteed that
the subsequent PinLocalBuffer() will succeed, but after the rewrite,
releasing an old resource doesn't guarantee that there is space for a
new one.
Add a comment explaining why the UnpinBuffer + PinBuffer calls in
BufferAlloc(), with no ResourceOwnerEnlarge() in between, are safe.
Reported-by: Alexander Lakhin
Discussion: https://www.postgresql.org/message-id/dc574fea-c83e-a600-08cd-10881762e4fa@gmail.com
This commit is contained in:
@ -374,6 +374,9 @@ ExtendBufferedRelLocal(BufferManagerRelation bmr,
|
|||||||
victim_buf_id = -buffers[i] - 1;
|
victim_buf_id = -buffers[i] - 1;
|
||||||
victim_buf_hdr = GetLocalBufferDescriptor(victim_buf_id);
|
victim_buf_hdr = GetLocalBufferDescriptor(victim_buf_id);
|
||||||
|
|
||||||
|
/* in case we need to pin an existing buffer below */
|
||||||
|
ResourceOwnerEnlarge(CurrentResourceOwner);
|
||||||
|
|
||||||
InitBufferTag(&tag, &bmr.smgr->smgr_rlocator.locator, fork, first_block + i);
|
InitBufferTag(&tag, &bmr.smgr->smgr_rlocator.locator, fork, first_block + i);
|
||||||
|
|
||||||
hresult = (LocalBufferLookupEnt *)
|
hresult = (LocalBufferLookupEnt *)
|
||||||
@ -646,6 +649,8 @@ InitLocalBuffers(void)
|
|||||||
* XXX: We could have a slightly more efficient version of PinLocalBuffer()
|
* XXX: We could have a slightly more efficient version of PinLocalBuffer()
|
||||||
* that does not support adjusting the usagecount - but so far it does not
|
* that does not support adjusting the usagecount - but so far it does not
|
||||||
* seem worth the trouble.
|
* seem worth the trouble.
|
||||||
|
*
|
||||||
|
* Note that ResourceOwnerEnlarge() must have been done already.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
PinLocalBuffer(BufferDesc *buf_hdr, bool adjust_usagecount)
|
PinLocalBuffer(BufferDesc *buf_hdr, bool adjust_usagecount)
|
||||||
|
@ -548,8 +548,13 @@ ResourceOwnerRemember(ResourceOwner owner, Datum value, const ResourceOwnerDesc
|
|||||||
/*
|
/*
|
||||||
* Forget that an object is owned by a ResourceOwner
|
* Forget that an object is owned by a ResourceOwner
|
||||||
*
|
*
|
||||||
* Note: if same resource ID is associated with the ResourceOwner more than
|
* Note: If same resource ID is associated with the ResourceOwner more than
|
||||||
* once, one instance is removed.
|
* once, one instance is removed.
|
||||||
|
*
|
||||||
|
* Note: Forgetting a resource does not guarantee that there is room to
|
||||||
|
* remember a new resource. One exception is when you forget the most
|
||||||
|
* recently remembered resource; that does make room for a new remember call.
|
||||||
|
* Some code callers rely on that exception.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
|
ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
|
||||||
|
Reference in New Issue
Block a user