Fix failure to mark init buffers as BM_PERMANENT.
authorRobert Haas
Tue, 14 Mar 2017 15:51:11 +0000 (11:51 -0400)
committerRobert Haas
Tue, 14 Mar 2017 16:06:36 +0000 (12:06 -0400)
This could result in corruption of the init fork of an unlogged index
if the ambuildempty routine for that index used shared buffers to
create the init fork, which was true for gin, gist, and hash indexes.

Patch by me, based on an earlier patch by Michael Paquier, who also
reviewed this one.  This also incorporates an idea from Artur
Zakirov.

Discussion: http://postgr.es/m/CACYUyc8yccE4xfxhqxfh_Mh38j7dRFuxfaK1p6dSNAEUakxUyQ@mail.gmail.com

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

index 1c431240491169df7793b14c331a2614ceacbc33..2803159bc5879ee65c21f11061444e7a0642cc5d 100644 (file)
@@ -869,10 +869,15 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
     * paranoia.  We also reset the usage_count since any recency of use of
     * the old content is no longer relevant.  (The usage_count starts out at
     * 1 so that the buffer can survive one clock-sweep pass.)
+    *
+    * Make sure BM_PERMANENT is set for buffers that must be written at every
+    * checkpoint.  Unlogged buffers only need to be written at shutdown
+    * checkpoints, except for their "init" forks, which need to be treated
+    * just like permanent relations.
     */
    buf->tag = newTag;
    buf->flags &= ~(BM_VALID | BM_DIRTY | BM_JUST_DIRTIED | BM_CHECKPOINT_NEEDED | BM_IO_ERROR | BM_PERMANENT);
-   if (relpersistence == RELPERSISTENCE_PERMANENT)
+   if (relpersistence == RELPERSISTENCE_PERMANENT || forkNum == INIT_FORKNUM)
        buf->flags |= BM_TAG_VALID | BM_PERMANENT;
    else
        buf->flags |= BM_TAG_VALID;
index c019013e7209c48c61eece01e19ed368d60721b8..d20c1399f4299195331718751a5b8a1f71e236cc 100644 (file)
@@ -39,7 +39,7 @@
 #define BM_PIN_COUNT_WAITER        (1 << 6)        /* have waiter for sole pin */
 #define BM_CHECKPOINT_NEEDED   (1 << 7)        /* must write for checkpoint */
 #define BM_PERMANENT           (1 << 8)        /* permanent relation (not
-                                                * unlogged) */
+                                                * unlogged, or init fork) */
 
 typedef bits16 BufFlags;