When GIN changes a metapage, we WAL-log its ex-header content and never use a
backup block.  This reduces WAL volume since the vast majority of the metapage
is unused.  However, ginRedoUpdateMetapage() only restores the WAL-logged
content if the metapage LSN predates the WAL record LSN.  If a metapage write
tore and updated the LSN but not the other content, we would fail to complete
the update.  Instead, unconditionally reinitialize the metapage similar to how
_bt_restore_meta() handles the situation.

I found this problem by code reading and did not attempt to build a test case
illustrating its practical consequences.  It's possible that there's no
problem in practice on account of some reason I haven't contemplated.

Thanks,
nm
*** a/src/backend/access/gin/ginxlog.c
--- b/src/backend/access/gin/ginxlog.c
***************
*** 492,504 **** ginRedoUpdateMetapage(XLogRecPtr lsn, XLogRecord *record)
                return;                                 /* assume index was 
deleted, nothing to do */
        metapage = BufferGetPage(metabuffer);
  
!       if (!XLByteLE(lsn, PageGetLSN(metapage)))
!       {
!               memcpy(GinPageGetMeta(metapage), &data->metadata, 
sizeof(GinMetaPageData));
!               PageSetLSN(metapage, lsn);
!               PageSetTLI(metapage, ThisTimeLineID);
!               MarkBufferDirty(metabuffer);
!       }
  
        if (data->ntuples > 0)
        {
--- 492,503 ----
                return;                                 /* assume index was 
deleted, nothing to do */
        metapage = BufferGetPage(metabuffer);
  
!       GinInitMetabuffer(metabuffer);
!       memcpy(GinPageGetMeta(metapage), &data->metadata, 
sizeof(GinMetaPageData));
! 
!       PageSetLSN(metapage, lsn);
!       PageSetTLI(metapage, ThisTimeLineID);
!       MarkBufferDirty(metabuffer);
  
        if (data->ntuples > 0)
        {
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to