@@ -6380,18 +6380,13 @@ heap_inplace_update_and_unlock(Relation relation,
6380
6380
HeapTupleHeader htup = oldtup -> t_data ;
6381
6381
uint32 oldlen ;
6382
6382
uint32 newlen ;
6383
- char * dst ;
6384
- char * src ;
6385
6383
6386
6384
Assert (ItemPointerEquals (& oldtup -> t_self , & tuple -> t_self ));
6387
6385
oldlen = oldtup -> t_len - htup -> t_hoff ;
6388
6386
newlen = tuple -> t_len - tuple -> t_data -> t_hoff ;
6389
6387
if (oldlen != newlen || htup -> t_hoff != tuple -> t_data -> t_hoff )
6390
6388
elog (ERROR , "wrong tuple length" );
6391
6389
6392
- dst = (char * ) htup + htup -> t_hoff ;
6393
- src = (char * ) tuple -> t_data + tuple -> t_data -> t_hoff ;
6394
-
6395
6390
/*
6396
6391
* Construct shared cache inval if necessary. Note that because we only
6397
6392
* pass the new version of the tuple, this mustn't be used for any
@@ -6410,15 +6405,15 @@ heap_inplace_update_and_unlock(Relation relation,
6410
6405
*/
6411
6406
PreInplace_Inval ();
6412
6407
6408
+ /* NO EREPORT(ERROR) from here till changes are logged */
6409
+ START_CRIT_SECTION ();
6410
+
6411
+ memcpy ((char * ) htup + htup -> t_hoff ,
6412
+ (char * ) tuple -> t_data + tuple -> t_data -> t_hoff ,
6413
+ newlen );
6414
+
6413
6415
/*----------
6414
- * NO EREPORT(ERROR) from here till changes are complete
6415
- *
6416
- * Our buffer lock won't stop a reader having already pinned and checked
6417
- * visibility for this tuple. Hence, we write WAL first, then mutate the
6418
- * buffer. Like in MarkBufferDirtyHint() or RecordTransactionCommit(),
6419
- * checkpoint delay makes that acceptable. With the usual order of
6420
- * changes, a crash after memcpy() and before XLogInsert() could allow
6421
- * datfrozenxid to overtake relfrozenxid:
6416
+ * XXX A crash here can allow datfrozenxid() to get ahead of relfrozenxid:
6422
6417
*
6423
6418
* ["D" is a VACUUM (ONLY_DATABASE_STATS)]
6424
6419
* ["R" is a VACUUM tbl]
@@ -6428,57 +6423,31 @@ heap_inplace_update_and_unlock(Relation relation,
6428
6423
* D: raise pg_database.datfrozenxid, XLogInsert(), finish
6429
6424
* [crash]
6430
6425
* [recovery restores datfrozenxid w/o relfrozenxid]
6431
- *
6432
- * Like in MarkBufferDirtyHint() subroutine XLogSaveBufferForHint(), copy
6433
- * the buffer to the stack before logging. Here, that facilitates a FPI
6434
- * of the post-mutation block before we accept other sessions seeing it.
6435
6426
*/
6436
- Assert (!MyProc -> delayChkpt );
6437
- START_CRIT_SECTION ();
6438
- MyProc -> delayChkpt = true;
6427
+
6428
+ MarkBufferDirty (buffer );
6439
6429
6440
6430
/* XLOG stuff */
6441
6431
if (RelationNeedsWAL (relation ))
6442
6432
{
6443
6433
xl_heap_inplace xlrec ;
6444
- PGAlignedBlock copied_buffer ;
6445
- char * origdata = (char * ) BufferGetBlock (buffer );
6446
- Page page = BufferGetPage (buffer );
6447
- uint16 lower = ((PageHeader ) page )-> pd_lower ;
6448
- uint16 upper = ((PageHeader ) page )-> pd_upper ;
6449
- uintptr_t dst_offset_in_block ;
6450
- RelFileNode rnode ;
6451
- ForkNumber forkno ;
6452
- BlockNumber blkno ;
6453
6434
XLogRecPtr recptr ;
6454
6435
6455
6436
xlrec .offnum = ItemPointerGetOffsetNumber (& tuple -> t_self );
6456
6437
6457
6438
XLogBeginInsert ();
6458
6439
XLogRegisterData ((char * ) & xlrec , SizeOfHeapInplace );
6459
6440
6460
- /* register block matching what buffer will look like after changes */
6461
- memcpy (copied_buffer .data , origdata , lower );
6462
- memcpy (copied_buffer .data + upper , origdata + upper , BLCKSZ - upper );
6463
- dst_offset_in_block = dst - origdata ;
6464
- memcpy (copied_buffer .data + dst_offset_in_block , src , newlen );
6465
- BufferGetTag (buffer , & rnode , & forkno , & blkno );
6466
- Assert (forkno == MAIN_FORKNUM );
6467
- XLogRegisterBlock (0 , & rnode , forkno , blkno , copied_buffer .data ,
6468
- REGBUF_STANDARD );
6469
- XLogRegisterBufData (0 , src , newlen );
6441
+ XLogRegisterBuffer (0 , buffer , REGBUF_STANDARD );
6442
+ XLogRegisterBufData (0 , (char * ) htup + htup -> t_hoff , newlen );
6470
6443
6471
6444
/* inplace updates aren't decoded atm, don't log the origin */
6472
6445
6473
6446
recptr = XLogInsert (RM_HEAP_ID , XLOG_HEAP_INPLACE );
6474
6447
6475
- PageSetLSN (page , recptr );
6448
+ PageSetLSN (BufferGetPage ( buffer ) , recptr );
6476
6449
}
6477
6450
6478
- memcpy (dst , src , newlen );
6479
-
6480
- MarkBufferDirty (buffer );
6481
-
6482
6451
LockBuffer (buffer , BUFFER_LOCK_UNLOCK );
6483
6452
6484
6453
/*
@@ -6491,7 +6460,6 @@ heap_inplace_update_and_unlock(Relation relation,
6491
6460
*/
6492
6461
AtInplace_Inval ();
6493
6462
6494
- MyProc -> delayChkpt = false;
6495
6463
END_CRIT_SECTION ();
6496
6464
UnlockTuple (relation , & tuple -> t_self , InplaceUpdateTupleLock );
6497
6465
0 commit comments