Skip to content

Commit 43a8ed2

Browse files
committed
Fix two off-by-one errors in bufmgr.c.
In 4b4b680 I passed a buffer index number (starting from 0) instead of a proper Buffer id (which start from 1 for shared buffers) in two places. This wasn't noticed so far as one of those locations isn't compiled at all (PrintPinnedBufs) and the other one (InvalidBuffer) requires a unlikely, but possible, set of circumstances to trigger a symptom. To reduce the likelihood of such incidents a bit also convert existing open coded mappings from buffer descriptors to buffer ids with BufferDescriptorGetBuffer(). Author: Qingqing Zhou Reported-By: Qingqing Zhou Discussion: CAJjS0u2ai9ooUisKtkV8cuVUtEkMTsbK8c7juNAjv8K11zeCQg@mail.gmail.com Backpatch: 9.5 where the private ref count infrastructure was introduced
1 parent c5bfcc1 commit 43a8ed2

File tree

1 file changed

+19
-17
lines changed

1 file changed

+19
-17
lines changed

src/backend/storage/buffer/bufmgr.c

+19-17
Original file line numberDiff line numberDiff line change
@@ -1273,7 +1273,7 @@ InvalidateBuffer(volatile BufferDesc *buf)
12731273
UnlockBufHdr(buf);
12741274
LWLockRelease(oldPartitionLock);
12751275
/* safety check: should definitely not be our *own* pin */
1276-
if (GetPrivateRefCount(buf->buf_id) > 0)
1276+
if (GetPrivateRefCount(BufferDescriptorGetBuffer(buf)) > 0)
12771277
elog(ERROR, "buffer is pinned in InvalidateBuffer");
12781278
WaitIO(buf);
12791279
goto retry;
@@ -1426,16 +1426,16 @@ ReleaseAndReadBuffer(Buffer buffer,
14261426
static bool
14271427
PinBuffer(volatile BufferDesc *buf, BufferAccessStrategy strategy)
14281428
{
1429-
int b = buf->buf_id;
1429+
Buffer b = BufferDescriptorGetBuffer(buf);
14301430
bool result;
14311431
PrivateRefCountEntry *ref;
14321432

1433-
ref = GetPrivateRefCountEntry(b + 1, true);
1433+
ref = GetPrivateRefCountEntry(b, true);
14341434

14351435
if (ref == NULL)
14361436
{
14371437
ReservePrivateRefCountEntry();
1438-
ref = NewPrivateRefCountEntry(b + 1);
1438+
ref = NewPrivateRefCountEntry(b);
14391439

14401440
LockBufHdr(buf);
14411441
buf->refcount++;
@@ -1460,8 +1460,7 @@ PinBuffer(volatile BufferDesc *buf, BufferAccessStrategy strategy)
14601460

14611461
ref->refcount++;
14621462
Assert(ref->refcount > 0);
1463-
ResourceOwnerRememberBuffer(CurrentResourceOwner,
1464-
BufferDescriptorGetBuffer(buf));
1463+
ResourceOwnerRememberBuffer(CurrentResourceOwner, b);
14651464
return result;
14661465
}
14671466

@@ -1489,23 +1488,24 @@ PinBuffer(volatile BufferDesc *buf, BufferAccessStrategy strategy)
14891488
static void
14901489
PinBuffer_Locked(volatile BufferDesc *buf)
14911490
{
1492-
int b = buf->buf_id;
1491+
Buffer b;
14931492
PrivateRefCountEntry *ref;
14941493

14951494
/*
14961495
* As explained, We don't expect any preexisting pins. That allows us to
14971496
* manipulate the PrivateRefCount after releasing the spinlock
14981497
*/
1499-
Assert(GetPrivateRefCountEntry(b + 1, false) == NULL);
1498+
Assert(GetPrivateRefCountEntry(BufferDescriptorGetBuffer(buf), false) == NULL);
15001499

15011500
buf->refcount++;
15021501
UnlockBufHdr(buf);
15031502

1504-
ref = NewPrivateRefCountEntry(b + 1);
1503+
b = BufferDescriptorGetBuffer(buf);
1504+
1505+
ref = NewPrivateRefCountEntry(b);
15051506
ref->refcount++;
15061507

1507-
ResourceOwnerRememberBuffer(CurrentResourceOwner,
1508-
BufferDescriptorGetBuffer(buf));
1508+
ResourceOwnerRememberBuffer(CurrentResourceOwner, b);
15091509
}
15101510

15111511
/*
@@ -1520,14 +1520,14 @@ static void
15201520
UnpinBuffer(volatile BufferDesc *buf, bool fixOwner)
15211521
{
15221522
PrivateRefCountEntry *ref;
1523+
Buffer b = BufferDescriptorGetBuffer(buf);
15231524

15241525
/* not moving as we're likely deleting it soon anyway */
1525-
ref = GetPrivateRefCountEntry(buf->buf_id + 1, false);
1526+
ref = GetPrivateRefCountEntry(b, false);
15261527
Assert(ref != NULL);
15271528

15281529
if (fixOwner)
1529-
ResourceOwnerForgetBuffer(CurrentResourceOwner,
1530-
BufferDescriptorGetBuffer(buf));
1530+
ResourceOwnerForgetBuffer(CurrentResourceOwner, b);
15311531

15321532
Assert(ref->refcount > 0);
15331533
ref->refcount--;
@@ -2739,6 +2739,7 @@ PrintBufferDescs(void)
27392739
for (i = 0; i < NBuffers; ++i)
27402740
{
27412741
volatile BufferDesc *buf = GetBufferDescriptor(i);
2742+
Buffer b = BufferDescriptorGetBuffer(buf);
27422743

27432744
/* theoretically we should lock the bufhdr here */
27442745
elog(LOG,
@@ -2747,7 +2748,7 @@ PrintBufferDescs(void)
27472748
i, buf->freeNext,
27482749
relpathbackend(buf->tag.rnode, InvalidBackendId, buf->tag.forkNum),
27492750
buf->tag.blockNum, buf->flags,
2750-
buf->refcount, GetPrivateRefCount(i));
2751+
buf->refcount, GetPrivateRefCount(b));
27512752
}
27522753
}
27532754
#endif
@@ -2761,8 +2762,9 @@ PrintPinnedBufs(void)
27612762
for (i = 0; i < NBuffers; ++i)
27622763
{
27632764
volatile BufferDesc *buf = GetBufferDescriptor(i);
2765+
Buffer b = BufferDescriptorGetBuffer(buf);
27642766

2765-
if (GetPrivateRefCount(i + 1) > 0)
2767+
if (GetPrivateRefCount(b) > 0)
27662768
{
27672769
/* theoretically we should lock the bufhdr here */
27682770
elog(LOG,
@@ -2771,7 +2773,7 @@ PrintPinnedBufs(void)
27712773
i, buf->freeNext,
27722774
relpathperm(buf->tag.rnode, buf->tag.forkNum),
27732775
buf->tag.blockNum, buf->flags,
2774-
buf->refcount, GetPrivateRefCount(i + 1));
2776+
buf->refcount, GetPrivateRefCount(b));
27752777
}
27762778
}
27772779
}

0 commit comments

Comments
 (0)