diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c index 34cc08f..0bacef8 100644 --- a/src/backend/access/hash/hash.c +++ b/src/backend/access/hash/hash.c @@ -478,7 +478,7 @@ hashrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys, /* Before leaving current page, deal with any killed items */ if (so->numKilled > 0) - _hash_kill_items(scan); + _hash_kill_items(scan, false); _hash_dropscanbuf(rel, so); @@ -509,7 +509,7 @@ hashendscan(IndexScanDesc scan) /* Before leaving current page, deal with any killed items */ if (so->numKilled > 0) - _hash_kill_items(scan); + _hash_kill_items(scan, false); _hash_dropscanbuf(rel, so); diff --git a/src/backend/access/hash/hashsearch.c b/src/backend/access/hash/hashsearch.c index 2d92049..414cc6a 100644 --- a/src/backend/access/hash/hashsearch.c +++ b/src/backend/access/hash/hashsearch.c @@ -467,7 +467,7 @@ _hash_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir) /* Before leaving current page, deal with any killed items */ if (so->numKilled > 0) - _hash_kill_items(scan); + _hash_kill_items(scan, true); /* * ran off the end of this page, try the next @@ -524,7 +524,7 @@ _hash_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir) /* Before leaving current page, deal with any killed items */ if (so->numKilled > 0) - _hash_kill_items(scan); + _hash_kill_items(scan, true); /* * ran off the end of this page, try the next diff --git a/src/backend/access/hash/hashutil.c b/src/backend/access/hash/hashutil.c index 2e99719..f24bc4c 100644 --- a/src/backend/access/hash/hashutil.c +++ b/src/backend/access/hash/hashutil.c @@ -456,11 +456,15 @@ _hash_get_newbucket_from_oldbucket(Relation rel, Bucket old_bucket, * current page and killed tuples thereon (generally, this should only be * called if so->numKilled > 0). * + * The caller must have pin on so->hashso_curbuf, but may or may not have + * read-lock, as indicated by haveLock. Note that we assume read-lock + * is sufficient for setting LP_DEAD hint bits. + * * We match items by heap TID before assuming they are the right ones to * delete. */ void -_hash_kill_items(IndexScanDesc scan) +_hash_kill_items(IndexScanDesc scan, bool haveLock) { HashScanOpaque so = (HashScanOpaque) scan->opaque; Page page; @@ -472,6 +476,10 @@ _hash_kill_items(IndexScanDesc scan) Assert(so->numKilled > 0); Assert(so->killedItems != NULL); + Assert(BufferIsValid(so->hashso_curbuf)); + + if (!haveLock) + LockBuffer(so->hashso_curbuf, BUFFER_LOCK_SHARE); /* * Always reset the scan state, so we don't look for same @@ -513,4 +521,7 @@ _hash_kill_items(IndexScanDesc scan) opaque->hasho_flag |= LH_PAGE_HAS_DEAD_TUPLES; MarkBufferDirtyHint(so->hashso_curbuf, true); } + + if (!haveLock) + LockBuffer(so->hashso_curbuf, BUFFER_LOCK_UNLOCK); } diff --git a/src/include/access/hash.h b/src/include/access/hash.h index eb1df57..89fc319 100644 --- a/src/include/access/hash.h +++ b/src/include/access/hash.h @@ -393,7 +393,7 @@ extern BlockNumber _hash_get_oldblock_from_newbucket(Relation rel, Bucket new_bu extern BlockNumber _hash_get_newblock_from_oldbucket(Relation rel, Bucket old_bucket); extern Bucket _hash_get_newbucket_from_oldbucket(Relation rel, Bucket old_bucket, uint32 lowmask, uint32 maxbucket); -extern void _hash_kill_items(IndexScanDesc scan); +extern void _hash_kill_items(IndexScanDesc scan, bool haveLock); /* hash.c */ extern void hashbucketcleanup(Relation rel, Bucket cur_bucket,