8000 Fix cleanup lock acquisition in SPLIT_ALLOCATE_PAGE replay. · postgres/postgres@1703033 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1703033

Browse files
author
Amit Kapila
committed
Fix cleanup lock acquisition in SPLIT_ALLOCATE_PAGE replay.
During XLOG_HASH_SPLIT_ALLOCATE_PAGE replay, we were checking for a cleanup lock on the new bucket page after acquiring an exclusive lock on it and raising a PANIC error on failure. However, it is quite possible that checkpointer can acquire the pin on the same page before acquiring a lock on it, and then the replay will lead to an error. So instead, directly acquire the cleanup lock on the new bucket page during XLOG_HASH_SPLIT_ALLOCATE_PAGE replay operation. Reported-by: Andres Freund Author: Robert Haas Reviewed-By: Amit Kapila, Andres Freund, Vignesh C Backpatch-through: 11 Discussion: https://postgr.es/m/20220810022617.fvjkjiauaykwrbse@awork3.anarazel.de
1 parent 5eaf3e3 commit 1703033

File tree

2 files changed

+9
-6
lines changed

2 files changed

+9
-6
lines changed

src/backend/access/hash/hash_xlog.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -353,11 +353,10 @@ hash_xlog_split_allocate_page(XLogReaderState *record)
353353
}
354354

355355
/* replay the record for new bucket */
356-
newbuf = XLogInitBufferForRedo(record, 1);
356+
XLogReadBufferForRedoExtended(record, 1, RBM_ZERO_AND_CLEANUP_LOCK, true,
357+
&newbuf);
357358
_hash_initbuf(newbuf, xlrec->new_bucket, xlrec->new_bucket,
358359
xlrec->new_bucket_flag, true);
359-
if (!IsBufferCleanupOK(newbuf))
360-
elog(PANIC, "hash_xlog_split_allocate_page: failed to acquire cleanup lock");
361360
MarkBufferDirty(newbuf);
362361
PageSetLSN(BufferGetPage(newbuf), lsn);
363362

src/backend/access/hash/hashpage.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -817,9 +817,13 @@ _hash_expandtable(Relation rel, Buffer metabuf)
817817
/*
818818
* Physically allocate the new bucket's primary page. We want to do this
819819
* before changing the metapage's mapping info, in case we can't get the
820-
* disk space. Ideally, we don't need to check for cleanup lock on new
821-
* bucket as no other backend could find this bucket unless meta page is
822-
* updated. However, it is good to be consistent with old bucket locking.
820+
* disk space.
821+
*
822+
* XXX It doesn't make sense to call _hash_getnewbuf first, zeroing the
823+
* buffer, and then only afterwards check whether we have a cleanup lock.
824+
* However, since no scan can be accessing the buffer yet, any concurrent
825+
* accesses will just be from processes like the bgwriter or checkpointer
826+
* which don't care about its contents, so it doesn't really matter.
823827
*/
824828
buf_nblkno = _hash_getnewbuf(rel, start_nblkno, MAIN_FORKNUM);
825829
if (!IsBufferCleanupOK(buf_nblkno))

0 commit comments

Comments
 (0)
0