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