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);