]> granicus.if.org Git - postgresql/commitdiff
DropRelFileNodeBuffers failed to fix the state of the lookup hash table
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 17 Nov 2005 17:42:02 +0000 (17:42 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 17 Nov 2005 17:42:02 +0000 (17:42 +0000)
that was added to localbuf.c in 8.1; therefore, applying it to a temp table
left corrupt lookup state in memory.  The only case where this had a
significant chance of causing problems was an ON COMMIT DELETE ROWS temp
table; the other possible paths left bogus state that was unlikely to
be used again.  Per report from Csaba Nagy.

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

index 4d2c869860fcd87804b50ac7011d070adff55e1c..b7331f9abe6af68131e204484393209f0e1d3734 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.198 2005/10/27 17:07:58 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.199 2005/11/17 17:42:02 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1384,34 +1384,17 @@ DropRelFileNodeBuffers(RelFileNode rnode, bool istemp,
                                           BlockNumber firstDelBlock)
 {
        int                     i;
-       volatile BufferDesc *bufHdr;
 
        if (istemp)
        {
-               for (i = 0; i < NLocBuffer; i++)
-               {
-                       bufHdr = &LocalBufferDescriptors[i];
-                       if (RelFileNodeEquals(bufHdr->tag.rnode, rnode) &&
-                               bufHdr->tag.blockNum >= firstDelBlock)
-                       {
-                               if (LocalRefCount[i] != 0)
-                                       elog(ERROR, "block %u of %u/%u/%u is still referenced (local %u)",
-                                                bufHdr->tag.blockNum,
-                                                bufHdr->tag.rnode.spcNode,
-                                                bufHdr->tag.rnode.dbNode,
-                                                bufHdr->tag.rnode.relNode,
-                                                LocalRefCount[i]);
-                               CLEAR_BUFFERTAG(bufHdr->tag);
-                               bufHdr->flags = 0;
-                               bufHdr->usage_count = 0;
-                       }
-               }
+               DropRelFileNodeLocalBuffers(rnode, firstDelBlock);
                return;
        }
 
        for (i = 0; i < NBuffers; i++)
        {
-               bufHdr = &BufferDescriptors[i];
+               volatile BufferDesc *bufHdr = &BufferDescriptors[i];
+
                LockBufHdr(bufHdr);
                if (RelFileNodeEquals(bufHdr->tag.rnode, rnode) &&
                        bufHdr->tag.blockNum >= firstDelBlock)
index ca80255e15ea62535900712ba47bd5b56a11a570..acaf4b9b6e258bf141bb1af0a91c343105dab84c 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/storage/buffer/localbuf.c,v 1.70 2005/10/15 02:49:25 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/storage/buffer/localbuf.c,v 1.71 2005/11/17 17:42:02 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -241,6 +241,52 @@ WriteLocalBuffer(Buffer buffer, bool release)
        }
 }
 
+/*
+ * DropRelFileNodeLocalBuffers
+ *             This function removes from the buffer pool all the pages of the
+ *             specified relation that have block numbers >= firstDelBlock.
+ *             (In particular, with firstDelBlock = 0, all pages are removed.)
+ *             Dirty pages are simply dropped, without bothering to write them
+ *             out first.      Therefore, this is NOT rollback-able, and so should be
+ *             used only with extreme caution!
+ *
+ *             See DropRelFileNodeBuffers in bufmgr.c for more notes.
+ */
+void
+DropRelFileNodeLocalBuffers(RelFileNode rnode, BlockNumber firstDelBlock)
+{
+       int                     i;
+
+       for (i = 0; i < NLocBuffer; i++)
+       {
+               BufferDesc *bufHdr = &LocalBufferDescriptors[i];
+               LocalBufferLookupEnt *hresult;
+
+               if ((bufHdr->flags & BM_TAG_VALID) &&
+                       RelFileNodeEquals(bufHdr->tag.rnode, rnode) &&
+                       bufHdr->tag.blockNum >= firstDelBlock)
+               {
+                       if (LocalRefCount[i] != 0)
+                               elog(ERROR, "block %u of %u/%u/%u is still referenced (local %u)",
+                                        bufHdr->tag.blockNum,
+                                        bufHdr->tag.rnode.spcNode,
+                                        bufHdr->tag.rnode.dbNode,
+                                        bufHdr->tag.rnode.relNode,
+                                        LocalRefCount[i]);
+                       /* Remove entry from hashtable */
+                       hresult = (LocalBufferLookupEnt *)
+                               hash_search(LocalBufHash, (void *) &bufHdr->tag,
+                                                       HASH_REMOVE, NULL);
+                       if (!hresult)                   /* shouldn't happen */
+                               elog(ERROR, "local buffer hash table corrupted");
+                       /* Mark buffer invalid */
+                       CLEAR_BUFFERTAG(bufHdr->tag);
+                       bufHdr->flags = 0;
+                       bufHdr->usage_count = 0;
+               }
+       }
+}
+
 /*
  * InitLocalBuffers -
  *       init the local buffer cache. Since most queries (esp. multi-user ones)
index b2cbf3049e6b94e23ff372bc4acd720654c214ef..c55ce699bcd972ab51808094f08e4c48bf8aab5e 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/storage/buf_internals.h,v 1.81 2005/10/15 02:49:46 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/storage/buf_internals.h,v 1.82 2005/11/17 17:42:02 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -198,6 +198,8 @@ extern void BufTableDelete(BufferTag *tagPtr);
 extern BufferDesc *LocalBufferAlloc(Relation reln, BlockNumber blockNum,
                                 bool *foundPtr);
 extern void WriteLocalBuffer(Buffer buffer, bool release);
+extern void DropRelFileNodeLocalBuffers(RelFileNode rnode,
+                                                                               BlockNumber firstDelBlock);
 extern void AtEOXact_LocalBuffers(bool isCommit);
 
 #endif   /* BUFMGR_INTERNALS_H */