localbuf: Introduce InvalidateLocalBuffer()
authorAndres Freund <andres@anarazel.de>
Sat, 15 Mar 2025 16:30:07 +0000 (12:30 -0400)
committerAndres Freund <andres@anarazel.de>
Sun, 16 Mar 2025 02:07:48 +0000 (22:07 -0400)
Previously, there were three copies of this code, two of them
identical. There's no good reason for that.

This change is nice on its own, but the main motivation is the AIO patchset,
which needs to add extra checks the deduplicated code, which of course is
easier if there is only one version.

Reviewed-by: Melanie Plageman <melanieplageman@gmail.com>
Discussion: https://postgr.es/m/CAAKRu_b9anbWzEs5AAF9WCvcEVmgz-1AkHSQ-CLLy-p7WHzvFw@mail.gmail.com

src/backend/storage/buffer/localbuf.c

index 456a2232f22bdaf87013dea5d37727d7e6f57d57..5331091132d532cd3eb03ab13b9daf7450c9bdc2 100644 (file)
@@ -56,6 +56,7 @@ static int    NLocalPinnedBuffers = 0;
 static void InitLocalBuffers(void);
 static Block GetLocalBufferStorage(void);
 static Buffer GetLocalVictimBuffer(void);
+static void InvalidateLocalBuffer(BufferDesc *bufHdr, bool check_unreferenced);
 
 
 /*
@@ -269,17 +270,7 @@ GetLocalVictimBuffer(void)
     */
    if (pg_atomic_read_u32(&bufHdr->state) & BM_TAG_VALID)
    {
-       uint32      buf_state = pg_atomic_read_u32(&bufHdr->state);
-       LocalBufferLookupEnt *hresult;
-
-       hresult = (LocalBufferLookupEnt *)
-           hash_search(LocalBufHash, &bufHdr->tag, HASH_REMOVE, NULL);
-       if (!hresult)           /* shouldn't happen */
-           elog(ERROR, "local buffer hash table corrupted");
-       /* mark buffer invalid just in case hash insert fails */
-       ClearBufferTag(&bufHdr->tag);
-       buf_state &= ~(BUF_FLAG_MASK | BUF_USAGECOUNT_MASK);
-       pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+       InvalidateLocalBuffer(bufHdr, false);
 
        pgstat_count_io_op(IOOBJECT_TEMP_RELATION, IOCONTEXT_NORMAL, IOOP_EVICT, 1, 0);
    }
@@ -492,6 +483,46 @@ MarkLocalBufferDirty(Buffer buffer)
    pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
 }
 
+/*
+ * InvalidateLocalBuffer -- mark a local buffer invalid.
+ *
+ * If check_unreferenced is true, error out if the buffer is still
+ * pinned. Passing false is appropriate when calling InvalidateLocalBuffer()
+ * as part of changing the identity of a buffer, instead of just dropping the
+ * buffer.
+ *
+ * See also InvalidateBuffer().
+ */
+static void
+InvalidateLocalBuffer(BufferDesc *bufHdr, bool check_unreferenced)
+{
+   Buffer      buffer = BufferDescriptorGetBuffer(bufHdr);
+   int         bufid = -buffer - 1;
+   uint32      buf_state;
+   LocalBufferLookupEnt *hresult;
+
+   buf_state = pg_atomic_read_u32(&bufHdr->state);
+
+   if (check_unreferenced && LocalRefCount[bufid] != 0)
+       elog(ERROR, "block %u of %s is still referenced (local %u)",
+            bufHdr->tag.blockNum,
+            relpathbackend(BufTagGetRelFileLocator(&bufHdr->tag),
+                           MyProcNumber,
+                           BufTagGetForkNum(&bufHdr->tag)).str,
+            LocalRefCount[bufid]);
+
+   /* Remove entry from hashtable */
+   hresult = (LocalBufferLookupEnt *)
+       hash_search(LocalBufHash, &bufHdr->tag, HASH_REMOVE, NULL);
+   if (!hresult)               /* shouldn't happen */
+       elog(ERROR, "local buffer hash table corrupted");
+   /* Mark buffer invalid */
+   ClearBufferTag(&bufHdr->tag);
+   buf_state &= ~BUF_FLAG_MASK;
+   buf_state &= ~BUF_USAGECOUNT_MASK;
+   pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+}
+
 /*
  * DropRelationLocalBuffers
  *     This function removes from the buffer pool all the pages of the
@@ -512,7 +543,6 @@ DropRelationLocalBuffers(RelFileLocator rlocator, ForkNumber forkNum,
    for (i = 0; i < NLocBuffer; i++)
    {
        BufferDesc *bufHdr = GetLocalBufferDescriptor(i);
-       LocalBufferLookupEnt *hresult;
        uint32      buf_state;
 
        buf_state = pg_atomic_read_u32(&bufHdr->state);
@@ -522,24 +552,7 @@ DropRelationLocalBuffers(RelFileLocator rlocator, ForkNumber forkNum,
            BufTagGetForkNum(&bufHdr->tag) == forkNum &&
            bufHdr->tag.blockNum >= firstDelBlock)
        {
-           if (LocalRefCount[i] != 0)
-               elog(ERROR, "block %u of %s is still referenced (local %u)",
-                    bufHdr->tag.blockNum,
-                    relpathbackend(BufTagGetRelFileLocator(&bufHdr->tag),
-                                   MyProcNumber,
-                                   BufTagGetForkNum(&bufHdr->tag)).str,
-                    LocalRefCount[i]);
-
-           /* Remove entry from hashtable */
-           hresult = (LocalBufferLookupEnt *)
-               hash_search(LocalBufHash, &bufHdr->tag, HASH_REMOVE, NULL);
-           if (!hresult)       /* shouldn't happen */
-               elog(ERROR, "local buffer hash table corrupted");
-           /* Mark buffer invalid */
-           ClearBufferTag(&bufHdr->tag);
-           buf_state &= ~BUF_FLAG_MASK;
-           buf_state &= ~BUF_USAGECOUNT_MASK;
-           pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+           InvalidateLocalBuffer(bufHdr, true);
        }
    }
 }
@@ -559,7 +572,6 @@ DropRelationAllLocalBuffers(RelFileLocator rlocator)
    for (i = 0; i < NLocBuffer; i++)
    {
        BufferDesc *bufHdr = GetLocalBufferDescriptor(i);
-       LocalBufferLookupEnt *hresult;
        uint32      buf_state;
 
        buf_state = pg_atomic_read_u32(&bufHdr->state);
@@ -567,23 +579,7 @@ DropRelationAllLocalBuffers(RelFileLocator rlocator)
        if ((buf_state & BM_TAG_VALID) &&
            BufTagMatchesRelFileLocator(&bufHdr->tag, &rlocator))
        {
-           if (LocalRefCount[i] != 0)
-               elog(ERROR, "block %u of %s is still referenced (local %u)",
-                    bufHdr->tag.blockNum,
-                    relpathbackend(BufTagGetRelFileLocator(&bufHdr->tag),
-                                   MyProcNumber,
-                                   BufTagGetForkNum(&bufHdr->tag)).str,
-                    LocalRefCount[i]);
-           /* Remove entry from hashtable */
-           hresult = (LocalBufferLookupEnt *)
-               hash_search(LocalBufHash, &bufHdr->tag, HASH_REMOVE, NULL);
-           if (!hresult)       /* shouldn't happen */
-               elog(ERROR, "local buffer hash table corrupted");
-           /* Mark buffer invalid */
-           ClearBufferTag(&bufHdr->tag);
-           buf_state &= ~BUF_FLAG_MASK;
-           buf_state &= ~BUF_USAGECOUNT_MASK;
-           pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+           InvalidateLocalBuffer(bufHdr, true);
        }
    }
 }