@@ -6348,18 +6348,13 @@ heap_inplace_update_and_unlock(Relation relation,
63486348 HeapTupleHeader htup = oldtup -> t_data ;
63496349 uint32 oldlen ;
63506350 uint32 newlen ;
6351- char * dst ;
6352- char * src ;
63536351
63546352 Assert (ItemPointerEquals (& oldtup -> t_self , & tuple -> t_self ));
63556353 oldlen = oldtup -> t_len - htup -> t_hoff ;
63566354 newlen = tuple -> t_len - tuple -> t_data -> t_hoff ;
63576355 if (oldlen != newlen || htup -> t_hoff != tuple -> t_data -> t_hoff )
63586356 elog (ERROR , "wrong tuple length" );
63596357
6360- dst = (char * ) htup + htup -> t_hoff ;
6361- src = (char * ) tuple -> t_data + tuple -> t_data -> t_hoff ;
6362-
63636358 /*
63646359 * Construct shared cache inval if necessary. Note that because we only
63656360 * pass the new version of the tuple, this mustn't be used for any
@@ -6378,15 +6373,15 @@ heap_inplace_update_and_unlock(Relation relation,
63786373 */
63796374 PreInplace_Inval ();
63806375
6376+ /* NO EREPORT(ERROR) from here till changes are logged */
6377+ START_CRIT_SECTION ();
6378+
6379+ memcpy ((char * ) htup + htup -> t_hoff ,
6380+ (char * ) tuple -> t_data + tuple -> t_data -> t_hoff ,
6381+ newlen );
6382+
63816383 /*----------
6382- * NO EREPORT(ERROR) from here till changes are complete
6383- *
6384- * Our buffer lock won't stop a reader having already pinned and checked
6385- * visibility for this tuple. Hence, we write WAL first, then mutate the
6386- * buffer. Like in MarkBufferDirtyHint() or RecordTransactionCommit(),
6387- * checkpoint delay makes that acceptable. With the usual order of
6388- * changes, a crash after memcpy() and before XLogInsert() could allow
6389- * datfrozenxid to overtake relfrozenxid:
6384+ * XXX A crash here can allow datfrozenxid() to get ahead of relfrozenxid:
63906385 *
63916386 * ["D" is a VACUUM (ONLY_DATABASE_STATS)]
63926387 * ["R" is a VACUUM tbl]
@@ -6396,57 +6391,31 @@ heap_inplace_update_and_unlock(Relation relation,
63966391 * D: raise pg_database.datfrozenxid, XLogInsert(), finish
63976392 * [crash]
63986393 * [recovery restores datfrozenxid w/o relfrozenxid]
6399- *
6400- * Like in MarkBufferDirtyHint() subroutine XLogSaveBufferForHint(), copy
6401- * the buffer to the stack before logging. Here, that facilitates a FPI
6402- * of the post-mutation block before we accept other sessions seeing it.
64036394 */
6404- Assert ((MyProc -> delayChkptFlags & DELAY_CHKPT_START ) == 0 );
6405- START_CRIT_SECTION ();
6406- MyProc -> delayChkptFlags |= DELAY_CHKPT_START ;
6395+
6396+ MarkBufferDirty (buffer );
64076397
64086398 /* XLOG stuff */
64096399 if (RelationNeedsWAL (relation ))
64106400 {
64116401 xl_heap_inplace xlrec ;
6412- PGAlignedBlock copied_buffer ;
6413- char * origdata = (char * ) BufferGetBlock (buffer );
6414- Page page = BufferGetPage (buffer );
6415- uint16 lower = ((PageHeader ) page )-> pd_lower ;
6416- uint16 upper = ((PageHeader ) page )-> pd_upper ;
6417- uintptr_t dst_offset_in_block ;
6418- RelFileLocator rlocator ;
6419- ForkNumber forkno ;
6420- BlockNumber blkno ;
64216402 XLogRecPtr recptr ;
64226403
64236404 xlrec .offnum = ItemPointerGetOffsetNumber (& tuple -> t_self );
64246405
64256406 XLogBeginInsert ();
64266407 XLogRegisterData ((char * ) & xlrec , SizeOfHeapInplace );
64276408
6428- /* register block matching what buffer will look like after changes */
6429- memcpy (copied_buffer .data , origdata , lower );
6430- memcpy (copied_buffer .data + upper , origdata + upper , BLCKSZ - upper );
6431- dst_offset_in_block = dst - origdata ;
6432- memcpy (copied_buffer .data + dst_offset_in_block , src , newlen );
6433- BufferGetTag (buffer , & rlocator , & forkno , & blkno );
6434- Assert (forkno == MAIN_FORKNUM );
6435- XLogRegisterBlock (0 , & rlocator , forkno , blkno , copied_buffer .data ,
6436- REGBUF_STANDARD );
6437- XLogRegisterBufData (0 , src , newlen );
6409+ XLogRegisterBuffer (0 , buffer , REGBUF_STANDARD );
6410+ XLogRegisterBufData (0 , (char * ) htup + htup -> t_hoff , newlen );
64386411
64396412 /* inplace updates aren't decoded atm, don't log the origin */
64406413
64416414 recptr = XLogInsert (RM_HEAP_ID , XLOG_HEAP_INPLACE );
64426415
6443- PageSetLSN (page , recptr );
6416+ PageSetLSN (BufferGetPage ( buffer ) , recptr );
64446417 }
64456418
6446- memcpy (dst , src , newlen );
6447-
6448- MarkBufferDirty (buffer );
6449-
64506419 LockBuffer (buffer , BUFFER_LOCK_UNLOCK );
64516420
64526421 /*
@@ -6459,7 +6428,6 @@ heap_inplace_update_and_unlock(Relation relation,
64596428 */
64606429 AtInplace_Inval ();
64616430
6462- MyProc -> delayChkptFlags &= ~DELAY_CHKPT_START ;
64636431 END_CRIT_SECTION ();
64646432 UnlockTuple (relation , & tuple -> t_self , InplaceUpdateTupleLock );
64656433
0 commit comments