@@ -6188,18 +6188,13 @@ heap_inplace_update_and_unlock(Relation relation,
61886188HeapTupleHeader htup = oldtup -> t_data ;
61896189uint32 oldlen ;
61906190uint32 newlen ;
6191- char * dst ;
6192- char * src ;
61936191
61946192Assert (ItemPointerEquals (& oldtup -> t_self ,& tuple -> t_self ));
61956193oldlen = oldtup -> t_len - htup -> t_hoff ;
61966194newlen = tuple -> t_len - tuple -> t_data -> t_hoff ;
61976195if (oldlen != newlen || htup -> t_hoff != tuple -> t_data -> t_hoff )
61986196elog (ERROR ,"wrong tuple length" );
61996197
6200- dst = (char * )htup + htup -> t_hoff ;
6201- src = (char * )tuple -> t_data + tuple -> t_data -> t_hoff ;
6202-
62036198/*
62046199 * Construct shared cache inval if necessary. Note that because we only
62056200 * pass the new version of the tuple, this mustn't be used for any
@@ -6218,15 +6213,15 @@ heap_inplace_update_and_unlock(Relation relation,
62186213 */
62196214PreInplace_Inval ();
62206215
6216+ /* NO EREPORT(ERROR) from here till changes are logged */
6217+ START_CRIT_SECTION ();
6218+
6219+ memcpy ((char * )htup + htup -> t_hoff ,
6220+ (char * )tuple -> t_data + tuple -> t_data -> t_hoff ,
6221+ newlen );
6222+
62216223/*----------
6222- * NO EREPORT(ERROR) from here till changes are complete
6223- *
6224- * Our buffer lock won't stop a reader having already pinned and checked
6225- * visibility for this tuple. Hence, we write WAL first, then mutate the
6226- * buffer. Like in MarkBufferDirtyHint() or RecordTransactionCommit(),
6227- * checkpoint delay makes that acceptable. With the usual order of
6228- * changes, a crash after memcpy() and before XLogInsert() could allow
6229- * datfrozenxid to overtake relfrozenxid:
6224+ * XXX A crash here can allow datfrozenxid() to get ahead of relfrozenxid:
62306225 *
62316226 * ["D" is a VACUUM (ONLY_DATABASE_STATS)]
62326227 * ["R" is a VACUUM tbl]
@@ -6236,57 +6231,31 @@ heap_inplace_update_and_unlock(Relation relation,
62366231 * D: raise pg_database.datfrozenxid, XLogInsert(), finish
62376232 * [crash]
62386233 * [recovery restores datfrozenxid w/o relfrozenxid]
6239- *
6240- * Like in MarkBufferDirtyHint() subroutine XLogSaveBufferForHint(), copy
6241- * the buffer to the stack before logging. Here, that facilitates a FPI
6242- * of the post-mutation block before we accept other sessions seeing it.
62436234 */
6244- Assert ((MyProc -> delayChkptFlags & DELAY_CHKPT_START )== 0 );
6245- START_CRIT_SECTION ();
6246- MyProc -> delayChkptFlags |=DELAY_CHKPT_START ;
6235+
6236+ MarkBufferDirty (buffer );
62476237
62486238/* XLOG stuff */
62496239if (RelationNeedsWAL (relation ))
62506240{
62516241xl_heap_inplace xlrec ;
6252- PGAlignedBlock copied_buffer ;
6253- char * origdata = (char * )BufferGetBlock (buffer );
6254- Page page = BufferGetPage (buffer );
6255- uint16 lower = ((PageHeader )page )-> pd_lower ;
6256- uint16 upper = ((PageHeader )page )-> pd_upper ;
6257- uintptr_t dst_offset_in_block ;
6258- RelFileLocator rlocator ;
6259- ForkNumber forkno ;
6260- BlockNumber blkno ;
62616242XLogRecPtr recptr ;
62626243
62636244xlrec .offnum = ItemPointerGetOffsetNumber (& tuple -> t_self );
62646245
62656246XLogBeginInsert ();
62666247XLogRegisterData ((char * )& xlrec ,SizeOfHeapInplace );
62676248
6268- /* register block matching what buffer will look like after changes */
6269- memcpy (copied_buffer .data ,origdata ,lower );
6270- memcpy (copied_buffer .data + upper ,origdata + upper ,BLCKSZ - upper );
6271- dst_offset_in_block = dst - origdata ;
6272- memcpy (copied_buffer .data + dst_offset_in_block ,src ,newlen );
6273- BufferGetTag (buffer ,& rlocator ,& forkno ,& blkno );
6274- Assert (forkno == MAIN_FORKNUM );
6275- XLogRegisterBlock (0 ,& rlocator ,forkno ,blkno ,copied_buffer .data ,
6276- REGBUF_STANDARD );
6277- XLogRegisterBufData (0 ,src ,newlen );
6249+ XLogRegisterBuffer (0 ,buffer ,REGBUF_STANDARD );
6250+ XLogRegisterBufData (0 , (char * )htup + htup -> t_hoff ,newlen );
62786251
62796252/* inplace updates aren't decoded atm, don't log the origin */
62806253
62816254recptr = XLogInsert (RM_HEAP_ID ,XLOG_HEAP_INPLACE );
62826255
6283- PageSetLSN (page ,recptr );
6256+ PageSetLSN (BufferGetPage ( buffer ) ,recptr );
62846257}
62856258
6286- memcpy (dst ,src ,newlen );
6287-
6288- MarkBufferDirty (buffer );
6289-
62906259LockBuffer (buffer ,BUFFER_LOCK_UNLOCK );
62916260
62926261/*
@@ -6299,7 +6268,6 @@ heap_inplace_update_and_unlock(Relation relation,
62996268 */
63006269AtInplace_Inval ();
63016270
6302- MyProc -> delayChkptFlags &= ~DELAY_CHKPT_START ;
63036271END_CRIT_SECTION ();
63046272UnlockTuple (relation ,& tuple -> t_self ,InplaceUpdateTupleLock );
63056273