bufmgr: Add some more error checking [infrastructure] around pinning
authorAndres Freund <[email protected]>
Wed, 5 Apr 2023 17:42:17 +0000 (10:42 -0700)
committerAndres Freund <[email protected]>
Wed, 5 Apr 2023 17:42:17 +0000 (10:42 -0700)
This adds a few more assertions against a buffer being local in places we
don't expect, and extracts the check for a buffer being pinned exactly once
from LockBufferForCleanup() into its own function. Later commits will use this
function.

Reviewed-by: Heikki Linnakangas <[email protected]>
Reviewed-by: Melanie Plageman <[email protected]>
Discussion: http://postgr.es/m/419312fd-9255-078c-c3e3-f0525f911d7f@iki.fi

src/backend/storage/buffer/bufmgr.c
src/include/storage/bufmgr.h

index 7f119cd4b0f7869069d56af9b2f9974f8a89a922..2362423b89df09fbeb6ff0f549ec0fdb7f618098 100644 (file)
@@ -1735,6 +1735,8 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
    bool        result;
    PrivateRefCountEntry *ref;
 
+   Assert(!BufferIsLocal(b));
+
    ref = GetPrivateRefCountEntry(b, true);
 
    if (ref == NULL)
@@ -1880,6 +1882,8 @@ UnpinBuffer(BufferDesc *buf)
    PrivateRefCountEntry *ref;
    Buffer      b = BufferDescriptorGetBuffer(buf);
 
+   Assert(!BufferIsLocal(b));
+
    /* not moving as we're likely deleting it soon anyway */
    ref = GetPrivateRefCountEntry(b, false);
    Assert(ref != NULL);
@@ -4253,6 +4257,29 @@ ConditionalLockBuffer(Buffer buffer)
                                    LW_EXCLUSIVE);
 }
 
+/*
+ * Verify that this backend is pinning the buffer exactly once.
+ *
+ * NOTE: Like in BufferIsPinned(), what we check here is that *this* backend
+ * holds a pin on the buffer.  We do not care whether some other backend does.
+ */
+void
+CheckBufferIsPinnedOnce(Buffer buffer)
+{
+   if (BufferIsLocal(buffer))
+   {
+       if (LocalRefCount[-buffer - 1] != 1)
+           elog(ERROR, "incorrect local pin count: %d",
+                LocalRefCount[-buffer - 1]);
+   }
+   else
+   {
+       if (GetPrivateRefCount(buffer) != 1)
+           elog(ERROR, "incorrect local pin count: %d",
+                GetPrivateRefCount(buffer));
+   }
+}
+
 /*
  * LockBufferForCleanup - lock a buffer in preparation for deleting items
  *
@@ -4280,20 +4307,11 @@ LockBufferForCleanup(Buffer buffer)
    Assert(BufferIsPinned(buffer));
    Assert(PinCountWaitBuf == NULL);
 
+   CheckBufferIsPinnedOnce(buffer);
+
+   /* Nobody else to wait for */
    if (BufferIsLocal(buffer))
-   {
-       /* There should be exactly one pin */
-       if (LocalRefCount[-buffer - 1] != 1)
-           elog(ERROR, "incorrect local pin count: %d",
-                LocalRefCount[-buffer - 1]);
-       /* Nobody else to wait for */
        return;
-   }
-
-   /* There should be exactly one local pin */
-   if (GetPrivateRefCount(buffer) != 1)
-       elog(ERROR, "incorrect local pin count: %d",
-            GetPrivateRefCount(buffer));
 
    bufHdr = GetBufferDescriptor(buffer - 1);
 
@@ -4794,6 +4812,8 @@ LockBufHdr(BufferDesc *desc)
    SpinDelayStatus delayStatus;
    uint32      old_buf_state;
 
+   Assert(!BufferIsLocal(BufferDescriptorGetBuffer(desc)));
+
    init_local_spin_delay(&delayStatus);
 
    while (true)
index 73762cb1ec8d6eb743f200953f64da571b423cca..f96dc08021146dabb24d54b3ac1500795a144df3 100644 (file)
@@ -134,6 +134,7 @@ extern void ReleaseBuffer(Buffer buffer);
 extern void UnlockReleaseBuffer(Buffer buffer);
 extern void MarkBufferDirty(Buffer buffer);
 extern void IncrBufferRefCount(Buffer buffer);
+extern void CheckBufferIsPinnedOnce(Buffer buffer);
 extern Buffer ReleaseAndReadBuffer(Buffer buffer, Relation relation,
                                   BlockNumber blockNum);