@@ -5677,6 +5677,7 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
56775677 new_xmax ;
56785678 TransactionId priorXmax = InvalidTransactionId ;
56795679 bool cleared_all_frozen = false;
5680+ bool pinned_desired_page ;
56805681 Buffer vmbuffer = InvalidBuffer ;
56815682 BlockNumber block ;
56825683
@@ -5698,7 +5699,8 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
56985699 * chain, and there's no further tuple to lock: return success to
56995700 * caller.
57005701 */
5701- return HeapTupleMayBeUpdated ;
5702+ result = HeapTupleMayBeUpdated ;
5703+ goto out_unlocked ;
57025704 }
57035705
57045706l4 :
@@ -5711,9 +5713,12 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
57115713 * to recheck after we have the lock.
57125714 */
57135715 if (PageIsAllVisible (BufferGetPage (buf )))
5716+ {
57145717 visibilitymap_pin (rel , block , & vmbuffer );
5718+ pinned_desired_page = true;
5719+ }
57155720 else
5716- vmbuffer = InvalidBuffer ;
5721+ pinned_desired_page = false ;
57175722
57185723 LockBuffer (buf , BUFFER_LOCK_EXCLUSIVE );
57195724
@@ -5722,8 +5727,13 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
57225727 * all visible while we were busy locking the buffer, we'll have to
57235728 * unlock and re-lock, to avoid holding the buffer lock across I/O.
57245729 * That's a bit unfortunate, but hopefully shouldn't happen often.
5730+ *
5731+ * Note: in some paths through this function, we will reach here
5732+ * holding a pin on a vm page that may or may not be the one matching
5733+ * this page. If this page isn't all-visible, we won't use the vm
5734+ * page, but we hold onto such a pin till the end of the function.
57255735 */
5726- if (vmbuffer == InvalidBuffer && PageIsAllVisible (BufferGetPage (buf )))
5736+ if (! pinned_desired_page && PageIsAllVisible (BufferGetPage (buf )))
57275737 {
57285738 LockBuffer (buf , BUFFER_LOCK_UNLOCK );
57295739 visibilitymap_pin (rel , block , & vmbuffer );
@@ -5749,8 +5759,8 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
57495759 */
57505760 if (TransactionIdDidAbort (HeapTupleHeaderGetXmin (mytup .t_data )))
57515761 {
5752- UnlockReleaseBuffer ( buf ) ;
5753- return HeapTupleMayBeUpdated ;
5762+ result = HeapTupleMayBeUpdated ;
5763+ goto out_locked ;
57545764 }
57555765
57565766 old_infomask = mytup .t_data -> t_infomask ;
@@ -5957,20 +5967,18 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
59575967 priorXmax = HeapTupleHeaderGetUpdateXid (mytup .t_data );
59585968 ItemPointerCopy (& (mytup .t_data -> t_ctid ), & tupid );
59595969 UnlockReleaseBuffer (buf );
5960- if (vmbuffer != InvalidBuffer )
5961- ReleaseBuffer (vmbuffer );
59625970 }
59635971
59645972 result = HeapTupleMayBeUpdated ;
59655973
59665974out_locked :
59675975 UnlockReleaseBuffer (buf );
59685976
5977+ out_unlocked :
59695978 if (vmbuffer != InvalidBuffer )
59705979 ReleaseBuffer (vmbuffer );
59715980
59725981 return result ;
5973-
59745982}
59755983
59765984/*
0 commit comments