From b9282079afe18270403b08220731faae74c9dfd6 Mon Sep 17 00:00:00 2001 From: jcoleman Date: Fri, 2 Jun 2023 10:01:06 -0400 Subject: [PATCH v2 1/6] Allow getting lock before calling heap_page_prune_opt() --- src/backend/access/heap/heapam.c | 2 +- src/backend/access/heap/heapam_handler.c | 4 ++-- src/backend/access/heap/pruneheap.c | 15 +++++++++------ src/include/access/heapam.h | 2 +- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 88a123d38a..a1d3593f21 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -415,7 +415,7 @@ heapgetpage(TableScanDesc sscan, BlockNumber block) /* * Prune and repair fragmentation for the whole page, if possible. */ - heap_page_prune_opt(scan->rs_base.rs_rd, buffer); + heap_page_prune_opt(scan->rs_base.rs_rd, buffer, false); /* * We must hold share lock on the buffer content while examining tuple diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c index 7c28dafb72..ff578db37b 100644 --- a/src/backend/access/heap/heapam_handler.c +++ b/src/backend/access/heap/heapam_handler.c @@ -135,7 +135,7 @@ heapam_index_fetch_tuple(struct IndexFetchTableData *scan, * Prune page, but only if we weren't already on this page */ if (prev_buf != hscan->xs_cbuf) - heap_page_prune_opt(hscan->xs_base.rel, hscan->xs_cbuf); + heap_page_prune_opt(hscan->xs_base.rel, hscan->xs_cbuf, false); } /* Obtain share-lock on the buffer so we can examine visibility */ @@ -2150,7 +2150,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan, /* * Prune and repair fragmentation for the whole page, if possible. */ - heap_page_prune_opt(scan->rs_rd, buffer); + heap_page_prune_opt(scan->rs_rd, buffer, false); /* * We must hold share lock on the buffer content while examining tuple diff --git a/src/backend/access/heap/pruneheap.c b/src/backend/access/heap/pruneheap.c index c5f1abd95a..fa8f5c1dfb 100644 --- a/src/backend/access/heap/pruneheap.c +++ b/src/backend/access/heap/pruneheap.c @@ -81,10 +81,11 @@ static void page_verify_redirects(Page page); * Note: this is called quite often. It's important that it fall out quickly * if there's not any use in pruning. * - * Caller must have pin on the buffer, and must *not* have a lock on it. + * Caller must have pin on the buffer, and must either have an exclusive lock + * (and pass already_locked = true) or not have a lock on it. */ void -heap_page_prune_opt(Relation relation, Buffer buffer) +heap_page_prune_opt(Relation relation, Buffer buffer, bool already_locked) { Page page = BufferGetPage(buffer); TransactionId prune_xid; @@ -135,8 +136,9 @@ heap_page_prune_opt(Relation relation, Buffer buffer) if (PageIsFull(page) || PageGetHeapFreeSpace(page) < minfree) { - /* OK, try to get exclusive buffer lock */ - if (!ConditionalLockBufferForCleanup(buffer)) + /* OK, try to get exclusive buffer lock if necessary */ + if ((!already_locked && !ConditionalLockBufferForCleanup(buffer)) || + (already_locked && !IsBufferCleanupOK(buffer))) return; /* @@ -169,8 +171,9 @@ heap_page_prune_opt(Relation relation, Buffer buffer) presult.ndeleted - presult.nnewlpdead); } - /* And release buffer lock */ - LockBuffer(buffer, BUFFER_LOCK_UNLOCK); + /* And release buffer lock if we acquired it */ + if (!already_locked) + LockBuffer(buffer, BUFFER_LOCK_UNLOCK); /* * We avoid reuse of any free space created on the page by unrelated diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index 62fac1d5d2..d15fa04feb 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -317,7 +317,7 @@ extern TransactionId heap_index_delete_tuples(Relation rel, /* in heap/pruneheap.c */ struct GlobalVisState; -extern void heap_page_prune_opt(Relation relation, Buffer buffer); +extern void heap_page_prune_opt(Relation relation, Buffer buffer, bool already_locked); extern void heap_page_prune(Relation relation, Buffer buffer, struct GlobalVisState *vistest, PruneResult *presult, -- 2.39.3 (Apple Git-145)