@@ -5661,6 +5661,7 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
56615661new_xmax ;
56625662TransactionId priorXmax = InvalidTransactionId ;
56635663bool cleared_all_frozen = false;
5664+ bool pinned_desired_page ;
56645665Buffer vmbuffer = InvalidBuffer ;
56655666BlockNumber block ;
56665667
@@ -5682,7 +5683,8 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
56825683 * chain, and there's no further tuple to lock: return success to
56835684 * caller.
56845685 */
5685- return HeapTupleMayBeUpdated ;
5686+ result = HeapTupleMayBeUpdated ;
5687+ gotoout_unlocked ;
56865688}
56875689
56885690l4 :
@@ -5695,9 +5697,12 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
56955697 * to recheck after we have the lock.
56965698 */
56975699if (PageIsAllVisible (BufferGetPage (buf )))
5700+ {
56985701visibilitymap_pin (rel ,block ,& vmbuffer );
5702+ pinned_desired_page = true;
5703+ }
56995704else
5700- vmbuffer = InvalidBuffer ;
5705+ pinned_desired_page = false ;
57015706
57025707LockBuffer (buf ,BUFFER_LOCK_EXCLUSIVE );
57035708
@@ -5706,8 +5711,13 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
57065711 * all visible while we were busy locking the buffer, we'll have to
57075712 * unlock and re-lock, to avoid holding the buffer lock across I/O.
57085713 * That's a bit unfortunate, but hopefully shouldn't happen often.
5714+ *
5715+ * Note: in some paths through this function, we will reach here
5716+ * holding a pin on a vm page that may or may not be the one matching
5717+ * this page. If this page isn't all-visible, we won't use the vm
5718+ * page, but we hold onto such a pin till the end of the function.
57095719 */
5710- if (vmbuffer == InvalidBuffer && PageIsAllVisible (BufferGetPage (buf )))
5720+ if (! pinned_desired_page && PageIsAllVisible (BufferGetPage (buf )))
57115721{
57125722LockBuffer (buf ,BUFFER_LOCK_UNLOCK );
57135723visibilitymap_pin (rel ,block ,& vmbuffer );
@@ -5733,8 +5743,8 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
57335743 */
57345744if (TransactionIdDidAbort (HeapTupleHeaderGetXmin (mytup .t_data )))
57355745{
5736- UnlockReleaseBuffer ( buf ) ;
5737- return HeapTupleMayBeUpdated ;
5746+ result = HeapTupleMayBeUpdated ;
5747+ goto out_locked ;
57385748}
57395749
57405750old_infomask = mytup .t_data -> t_infomask ;
@@ -5941,20 +5951,18 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
59415951priorXmax = HeapTupleHeaderGetUpdateXid (mytup .t_data );
59425952ItemPointerCopy (& (mytup .t_data -> t_ctid ),& tupid );
59435953UnlockReleaseBuffer (buf );
5944- if (vmbuffer != InvalidBuffer )
5945- ReleaseBuffer (vmbuffer );
59465954}
59475955
59485956result = HeapTupleMayBeUpdated ;
59495957
59505958out_locked :
59515959UnlockReleaseBuffer (buf );
59525960
5961+ out_unlocked :
59535962if (vmbuffer != InvalidBuffer )
59545963ReleaseBuffer (vmbuffer );
59555964
59565965return result ;
5957-
59585966}
59595967
59605968/*