@@ -6139,18 +6139,13 @@ heap_inplace_update_and_unlock(Relation relation,
6139
6139
HeapTupleHeader htup = oldtup -> t_data ;
6140
6140
uint32 oldlen ;
6141
6141
uint32 newlen ;
6142
- char * dst ;
6143
- char * src ;
6144
6142
6145
6143
Assert (ItemPointerEquals (& oldtup -> t_self ,& tuple -> t_self ));
6146
6144
oldlen = oldtup -> t_len - htup -> t_hoff ;
6147
6145
newlen = tuple -> t_len - tuple -> t_data -> t_hoff ;
6148
6146
if (oldlen != newlen || htup -> t_hoff != tuple -> t_data -> t_hoff )
6149
6147
elog (ERROR ,"wrong tuple length" );
6150
6148
6151
- dst = (char * )htup + htup -> t_hoff ;
6152
- src = (char * )tuple -> t_data + tuple -> t_data -> t_hoff ;
6153
-
6154
6149
/*
6155
6150
* Construct shared cache inval if necessary. Note that because we only
6156
6151
* pass the new version of the tuple, this mustn't be used for any
@@ -6169,15 +6164,15 @@ heap_inplace_update_and_unlock(Relation relation,
6169
6164
*/
6170
6165
PreInplace_Inval ();
6171
6166
6167
+ /* NO EREPORT(ERROR) from here till changes are logged */
6168
+ START_CRIT_SECTION ();
6169
+
6170
+ memcpy ((char * )htup + htup -> t_hoff ,
6171
+ (char * )tuple -> t_data + tuple -> t_data -> t_hoff ,
6172
+ newlen );
6173
+
6172
6174
/*----------
6173
- * NO EREPORT(ERROR) from here till changes are complete
6174
- *
6175
- * Our buffer lock won't stop a reader having already pinned and checked
6176
- * visibility for this tuple. Hence, we write WAL first, then mutate the
6177
- * buffer. Like in MarkBufferDirtyHint() or RecordTransactionCommit(),
6178
- * checkpoint delay makes that acceptable. With the usual order of
6179
- * changes, a crash after memcpy() and before XLogInsert() could allow
6180
- * datfrozenxid to overtake relfrozenxid:
6175
+ * XXX A crash here can allow datfrozenxid() to get ahead of relfrozenxid:
6181
6176
*
6182
6177
* ["D" is a VACUUM (ONLY_DATABASE_STATS)]
6183
6178
* ["R" is a VACUUM tbl]
@@ -6187,57 +6182,31 @@ heap_inplace_update_and_unlock(Relation relation,
6187
6182
* D: raise pg_database.datfrozenxid, XLogInsert(), finish
6188
6183
* [crash]
6189
6184
* [recovery restores datfrozenxid w/o relfrozenxid]
6190
- *
6191
- * Like in MarkBufferDirtyHint() subroutine XLogSaveBufferForHint(), copy
6192
- * the buffer to the stack before logging. Here, that facilitates a FPI
6193
- * of the post-mutation block before we accept other sessions seeing it.
6194
6185
*/
6195
- Assert (!MyPgXact -> delayChkpt );
6196
- START_CRIT_SECTION ();
6197
- MyPgXact -> delayChkpt = true;
6186
+
6187
+ MarkBufferDirty (buffer );
6198
6188
6199
6189
/* XLOG stuff */
6200
6190
if (RelationNeedsWAL (relation ))
6201
6191
{
6202
6192
xl_heap_inplace xlrec ;
6203
- PGAlignedBlock copied_buffer ;
6204
- char * origdata = (char * )BufferGetBlock (buffer );
6205
- Page page = BufferGetPage (buffer );
6206
- uint16 lower = ((PageHeader )page )-> pd_lower ;
6207
- uint16 upper = ((PageHeader )page )-> pd_upper ;
6208
- uintptr_t dst_offset_in_block ;
6209
- RelFileNode rnode ;
6210
- ForkNumber forkno ;
6211
- BlockNumber blkno ;
6212
6193
XLogRecPtr recptr ;
6213
6194
6214
6195
xlrec .offnum = ItemPointerGetOffsetNumber (& tuple -> t_self );
6215
6196
6216
6197
XLogBeginInsert ();
6217
6198
XLogRegisterData ((char * )& xlrec ,SizeOfHeapInplace );
6218
6199
6219
- /* register block matching what buffer will look like after changes */
6220
- memcpy (copied_buffer .data ,origdata ,lower );
6221
- memcpy (copied_buffer .data + upper ,origdata + upper ,BLCKSZ - upper );
6222
- dst_offset_in_block = dst - origdata ;
6223
- memcpy (copied_buffer .data + dst_offset_in_block ,src ,newlen );
6224
- BufferGetTag (buffer ,& rnode ,& forkno ,& blkno );
6225
- Assert (forkno == MAIN_FORKNUM );
6226
- XLogRegisterBlock (0 ,& rnode ,forkno ,blkno ,copied_buffer .data ,
6227
- REGBUF_STANDARD );
6228
- XLogRegisterBufData (0 ,src ,newlen );
6200
+ XLogRegisterBuffer (0 ,buffer ,REGBUF_STANDARD );
6201
+ XLogRegisterBufData (0 , (char * )htup + htup -> t_hoff ,newlen );
6229
6202
6230
6203
/* inplace updates aren't decoded atm, don't log the origin */
6231
6204
6232
6205
recptr = XLogInsert (RM_HEAP_ID ,XLOG_HEAP_INPLACE );
6233
6206
6234
- PageSetLSN (page ,recptr );
6207
+ PageSetLSN (BufferGetPage ( buffer ) ,recptr );
6235
6208
}
6236
6209
6237
- memcpy (dst ,src ,newlen );
6238
-
6239
- MarkBufferDirty (buffer );
6240
-
6241
6210
LockBuffer (buffer ,BUFFER_LOCK_UNLOCK );
6242
6211
6243
6212
/*
@@ -6250,7 +6219,6 @@ heap_inplace_update_and_unlock(Relation relation,
6250
6219
*/
6251
6220
AtInplace_Inval ();
6252
6221
6253
- MyPgXact -> delayChkpt = false;
6254
6222
END_CRIT_SECTION ();
6255
6223
UnlockTuple (relation ,& tuple -> t_self ,InplaceUpdateTupleLock );
6256
6224