@@ -6348,18 +6348,13 @@ heap_inplace_update_and_unlock(Relation relation,
6348
6348
HeapTupleHeader htup = oldtup -> t_data ;
6349
6349
uint32 oldlen ;
6350
6350
uint32 newlen ;
6351
- char * dst ;
6352
- char * src ;
6353
6351
6354
6352
Assert (ItemPointerEquals (& oldtup -> t_self , & tuple -> t_self ));
6355
6353
oldlen = oldtup -> t_len - htup -> t_hoff ;
6356
6354
newlen = tuple -> t_len - tuple -> t_data -> t_hoff ;
6357
6355
if (oldlen != newlen || htup -> t_hoff != tuple -> t_data -> t_hoff )
6358
6356
elog (ERROR , "wrong tuple length" );
6359
6357
6360
- dst = (char * ) htup + htup -> t_hoff ;
6361
- src = (char * ) tuple -> t_data + tuple -> t_data -> t_hoff ;
6362
-
6363
6358
/*
6364
6359
* Construct shared cache inval if necessary. Note that because we only
6365
6360
* 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,
6378
6373
*/
6379
6374
PreInplace_Inval ();
6380
6375
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
+
6381
6383
/*----------
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:
6390
6385
*
6391
6386
* ["D" is a VACUUM (ONLY_DATABASE_STATS)]
6392
6387
* ["R" is a VACUUM tbl]
@@ -6396,57 +6391,31 @@ heap_inplace_update_and_unlock(Relation relation,
6396
6391
* D: raise pg_database.datfrozenxid, XLogInsert(), finish
6397
6392
* [crash]
6398
6393
* [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.
6403
6394
*/
6404
- Assert ((MyProc -> delayChkptFlags & DELAY_CHKPT_START ) == 0 );
6405
- START_CRIT_SECTION ();
6406
- MyProc -> delayChkptFlags |= DELAY_CHKPT_START ;
6395
+
6396
+ MarkBufferDirty (buffer );
6407
6397
6408
6398
/* XLOG stuff */
6409
6399
if (RelationNeedsWAL (relation ))
6410
6400
{
6411
6401
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 ;
6421
6402
XLogRecPtr recptr ;
6422
6403
6423
6404
xlrec .offnum = ItemPointerGetOffsetNumber (& tuple -> t_self );
6424
6405
6425
6406
XLogBeginInsert ();
6426
6407
XLogRegisterData ((char * ) & xlrec , SizeOfHeapInplace );
6427
6408
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 );
6438
6411
6439
6412
/* inplace updates aren't decoded atm, don't log the origin */
6440
6413
6441
6414
recptr = XLogInsert (RM_HEAP_ID , XLOG_HEAP_INPLACE );
6442
6415
6443
- PageSetLSN (page , recptr );
6416
+ PageSetLSN (BufferGetPage ( buffer ) , recptr );
6444
6417
}
6445
6418
6446
- memcpy (dst , src , newlen );
6447
-
6448
- MarkBufferDirty (buffer );
6449
-
6450
6419
LockBuffer (buffer , BUFFER_LOCK_UNLOCK );
6451
6420
6452
6421
/*
@@ -6459,7 +6428,6 @@ heap_inplace_update_and_unlock(Relation relation,
6459
6428
*/
6460
6429
AtInplace_Inval ();
6461
6430
6462
- MyProc -> delayChkptFlags &= ~DELAY_CHKPT_START ;
6463
6431
END_CRIT_SECTION ();
6464
6432
UnlockTuple (relation , & tuple -> t_self , InplaceUpdateTupleLock );
6465
6433
0 commit comments