Skip to content

Commit b70c214

Browse files
committed
Move a few ResourceOwnerEnlarge() calls for safety and clarity.
These are functions where a lot of things happen between the ResourceOwnerEnlarge and ResourceOwnerRemember calls. It's important that there are no unrelated ResourceOwnerRemember calls in the code in between, otherwise the reserved entry might be used up by the intervening ResourceOwnerRemember and not be available at the intended ResourceOwnerRemember call anymore. I don't see any bugs here, but the longer the code path between the calls is, the harder it is to verify. In bufmgr.c, there is a function similar to ResourceOwnerEnlarge, ReservePrivateRefCountEntry(), to ensure that the private refcount array has enough space. The ReservePrivateRefCountEntry() calls were made at different places than the ResourceOwnerEnlargeBuffers() calls. Move the ResourceOwnerEnlargeBuffers() and ReservePrivateRefCountEntry() calls together for consistency. Reviewed-by: Aleksander Alekseev, Michael Paquier, Julien Rouhaud Reviewed-by: Kyotaro Horiguchi, Hayato Kuroda, Álvaro Herrera, Zhihong Yu Reviewed-by: Peter Eisentraut, Andres Freund Discussion: https://www.postgresql.org/message-id/cbfabeb0-cd3c-e951-a572-19b365ed314d%40iki.fi
1 parent e9f075f commit b70c214

File tree

3 files changed

+27
-29
lines changed

3 files changed

+27
-29
lines changed

src/backend/storage/buffer/bufmgr.c

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,9 +1023,6 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
10231023
forkNum, strategy, flags);
10241024
}
10251025

1026-
/* Make sure we will have room to remember the buffer pin */
1027-
ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
1028-
10291026
TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
10301027
smgr->smgr_rlocator.locator.spcOid,
10311028
smgr->smgr_rlocator.locator.dbOid,
@@ -1230,6 +1227,10 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
12301227
BufferDesc *victim_buf_hdr;
12311228
uint32 victim_buf_state;
12321229

1230+
/* Make sure we will have room to remember the buffer pin */
1231+
ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
1232+
ReservePrivateRefCountEntry();
1233+
12331234
/* create a tag so we can lookup the buffer */
12341235
InitBufferTag(&newTag, &smgr->smgr_rlocator.locator, forkNum, blockNum);
12351236

@@ -1591,7 +1592,7 @@ GetVictimBuffer(BufferAccessStrategy strategy, IOContext io_context)
15911592

15921593
/*
15931594
* Ensure, while the spinlock's not yet held, that there's a free refcount
1594-
* entry.
1595+
* entry, and a resource owner slot for the pin.
15951596
*/
15961597
ReservePrivateRefCountEntry();
15971598
ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
@@ -1859,9 +1860,6 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
18591860
MemSet((char *) buf_block, 0, BLCKSZ);
18601861
}
18611862

1862-
/* in case we need to pin an existing buffer below */
1863-
ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
1864-
18651863
/*
18661864
* Lock relation against concurrent extensions, unless requested not to.
18671865
*
@@ -1947,6 +1945,10 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
19471945
LWLock *partition_lock;
19481946
int existing_id;
19491947

1948+
/* in case we need to pin an existing buffer below */
1949+
ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
1950+
ReservePrivateRefCountEntry();
1951+
19501952
InitBufferTag(&tag, &bmr.smgr->smgr_rlocator.locator, fork, first_block + i);
19511953
hash = BufTableHashCode(&tag);
19521954
partition_lock = BufMappingPartitionLock(hash);
@@ -2281,7 +2283,8 @@ ReleaseAndReadBuffer(Buffer buffer,
22812283
* taking the buffer header lock; instead update the state variable in loop of
22822284
* CAS operations. Hopefully it's just a single CAS.
22832285
*
2284-
* Note that ResourceOwnerEnlargeBuffers must have been done already.
2286+
* Note that ResourceOwnerEnlargeBuffers and ReservePrivateRefCountEntry()
2287+
* must have been done already.
22852288
*
22862289
* Returns true if buffer is BM_VALID, else false. This provision allows
22872290
* some callers to avoid an extra spinlock cycle.
@@ -2294,6 +2297,7 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
22942297
PrivateRefCountEntry *ref;
22952298

22962299
Assert(!BufferIsLocal(b));
2300+
Assert(ReservedRefCountEntry != NULL);
22972301

22982302
ref = GetPrivateRefCountEntry(b, true);
22992303

@@ -2302,7 +2306,6 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
23022306
uint32 buf_state;
23032307
uint32 old_buf_state;
23042308

2305-
ReservePrivateRefCountEntry();
23062309
ref = NewPrivateRefCountEntry(b);
23072310

23082311
old_buf_state = pg_atomic_read_u32(&buf->state);
@@ -2375,7 +2378,8 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
23752378
* The spinlock is released before return.
23762379
*
23772380
* As this function is called with the spinlock held, the caller has to
2378-
* previously call ReservePrivateRefCountEntry().
2381+
* previously call ReservePrivateRefCountEntry() and
2382+
* ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
23792383
*
23802384
* Currently, no callers of this function want to modify the buffer's
23812385
* usage_count at all, so there's no need for a strategy parameter.
@@ -2550,9 +2554,6 @@ BufferSync(int flags)
25502554
int mask = BM_DIRTY;
25512555
WritebackContext wb_context;
25522556

2553-
/* Make sure we can handle the pin inside SyncOneBuffer */
2554-
ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
2555-
25562557
/*
25572558
* Unless this is a shutdown checkpoint or we have been explicitly told,
25582559
* we write only permanent, dirty buffers. But at shutdown or end of
@@ -3029,9 +3030,6 @@ BgBufferSync(WritebackContext *wb_context)
30293030
* requirements, or hit the bgwriter_lru_maxpages limit.
30303031
*/
30313032

3032-
/* Make sure we can handle the pin inside SyncOneBuffer */
3033-
ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
3034-
30353033
num_to_scan = bufs_to_lap;
30363034
num_written = 0;
30373035
reusable_buffers = reusable_buffers_est;
@@ -3113,8 +3111,6 @@ BgBufferSync(WritebackContext *wb_context)
31133111
*
31143112
* (BUF_WRITTEN could be set in error if FlushBuffer finds the buffer clean
31153113
* after locking it, but we don't care all that much.)
3116-
*
3117-
* Note: caller must have done ResourceOwnerEnlargeBuffers.
31183114
*/
31193115
static int
31203116
SyncOneBuffer(int buf_id, bool skip_recently_used, WritebackContext *wb_context)
@@ -3124,7 +3120,9 @@ SyncOneBuffer(int buf_id, bool skip_recently_used, WritebackContext *wb_context)
31243120
uint32 buf_state;
31253121
BufferTag tag;
31263122

3123+
/* Make sure we can handle the pin */
31273124
ReservePrivateRefCountEntry();
3125+
ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
31283126

31293127
/*
31303128
* Check whether buffer needs writing.
@@ -4169,9 +4167,6 @@ FlushRelationBuffers(Relation rel)
41694167
return;
41704168
}
41714169

4172-
/* Make sure we can handle the pin inside the loop */
4173-
ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
4174-
41754170
for (i = 0; i < NBuffers; i++)
41764171
{
41774172
uint32 buf_state;
@@ -4185,7 +4180,9 @@ FlushRelationBuffers(Relation rel)
41854180
if (!BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator))
41864181
continue;
41874182

4183+
/* Make sure we can handle the pin */
41884184
ReservePrivateRefCountEntry();
4185+
ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
41894186

41904187
buf_state = LockBufHdr(bufHdr);
41914188
if (BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator) &&
@@ -4242,9 +4239,6 @@ FlushRelationsAllBuffers(SMgrRelation *smgrs, int nrels)
42424239
if (use_bsearch)
42434240
pg_qsort(srels, nrels, sizeof(SMgrSortArray), rlocator_comparator);
42444241

4245-
/* Make sure we can handle the pin inside the loop */
4246-
ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
4247-
42484242
for (i = 0; i < NBuffers; i++)
42494243
{
42504244
SMgrSortArray *srelent = NULL;
@@ -4283,7 +4277,9 @@ FlushRelationsAllBuffers(SMgrRelation *smgrs, int nrels)
42834277
if (srelent == NULL)
42844278
continue;
42854279

4280+
/* Make sure we can handle the pin */
42864281
ReservePrivateRefCountEntry();
4282+
ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
42874283

42884284
buf_state = LockBufHdr(bufHdr);
42894285
if (BufTagMatchesRelFileLocator(&bufHdr->tag, &srelent->rlocator) &&
@@ -4478,9 +4474,6 @@ FlushDatabaseBuffers(Oid dbid)
44784474
int i;
44794475
BufferDesc *bufHdr;
44804476

4481-
/* Make sure we can handle the pin inside the loop */
4482-
ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
4483-
44844477
for (i = 0; i < NBuffers; i++)
44854478
{
44864479
uint32 buf_state;
@@ -4494,7 +4487,9 @@ FlushDatabaseBuffers(Oid dbid)
44944487
if (bufHdr->tag.dbOid != dbid)
44954488
continue;
44964489

4490+
/* Make sure we can handle the pin */
44974491
ReservePrivateRefCountEntry();
4492+
ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
44984493

44994494
buf_state = LockBufHdr(bufHdr);
45004495
if (bufHdr->tag.dbOid == dbid &&

src/backend/storage/buffer/localbuf.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum,
130130
if (LocalBufHash == NULL)
131131
InitLocalBuffers();
132132

133+
ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
134+
133135
/* See if the desired buffer already exists */
134136
hresult = (LocalBufferLookupEnt *)
135137
hash_search(LocalBufHash, &newTag, HASH_FIND, NULL);

src/backend/utils/cache/catcache.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1605,8 +1605,6 @@ SearchCatCacheList(CatCache *cache,
16051605
* block to ensure we can undo those refcounts if we get an error before
16061606
* we finish constructing the CatCList.
16071607
*/
1608-
ResourceOwnerEnlargeCatCacheListRefs(CurrentResourceOwner);
1609-
16101608
ctlist = NIL;
16111609

16121610
PG_TRY();
@@ -1694,6 +1692,9 @@ SearchCatCacheList(CatCache *cache,
16941692

16951693
table_close(relation, AccessShareLock);
16961694

1695+
/* Make sure the resource owner has room to remember this entry. */
1696+
ResourceOwnerEnlargeCatCacheListRefs(CurrentResourceOwner);
1697+
16971698
/* Now we can build the CatCList entry. */
16981699
oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
16991700
nmembers = list_length(ctlist);

0 commit comments

Comments
 (0)