Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vnJF0-004wrU-2J for pgsql-hackers@arkaria.postgresql.org; Tue, 03 Feb 2026 16:27:02 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vnJEz-0069W7-2D for pgsql-hackers@arkaria.postgresql.org; Tue, 03 Feb 2026 16:27:01 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vnJEy-0069Vz-2B for pgsql-hackers@lists.postgresql.org; Tue, 03 Feb 2026 16:27:01 +0000 Received: from fhigh-a3-smtp.messagingengine.com ([103.168.172.154]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1vnJEw-00000000NvU-2oqD for pgsql-hackers@postgresql.org; Tue, 03 Feb 2026 16:26:59 +0000 Received: from phl-compute-01.internal (phl-compute-01.internal [10.202.2.41]) by mailfhigh.phl.internal (Postfix) with ESMTP id 5C0B914000F4; Tue, 3 Feb 2026 11:26:57 -0500 (EST) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-01.internal (MEProxy); Tue, 03 Feb 2026 11:26:57 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=anarazel.de; h= cc:content-type:content-type:date:date:from:from:in-reply-to :message-id:mime-version:reply-to:subject:subject:to:to; s=fm3; t=1770136017; x=1770222417; bh=f8emDAQ1p4pre2yixO9BJzGDCtsDtptc KwF7XZpo6ms=; b=ph5muXJbwzAVfEM9Mkq3UScW9EiD0YmLumGXghCUqhy3KD3G I+E12bHdukxwBKS/SP0ZPe7zgh1evOgM5+2rxwGmmahZgTjIK1/DiGpcDH8VqJOh b5ky2w6pYKlajqQteUtHIOM6ZbQP07NiSNpIMfnUGJxO6/yF3Ikk5F6b0jsCsFbx O+KoxrH0lmuZ6WvYOj6O4wGCuzP61dgaIf3YvEG9+Tdy0OR5QFwxFWmP1cf7ciI1 v+GopPY/JiaZ0aMwPIHWu8HFBpcCJIYsiBvQkEktZx4NiJhFIxMRsWnTFtvWomtL +JZTgpDkD8bHSiMMcgO15TtN/jCud1qPgWYVhw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:message-id :mime-version:reply-to:subject:subject:to:to:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t=1770136017; x= 1770222417; bh=f8emDAQ1p4pre2yixO9BJzGDCtsDtptcKwF7XZpo6ms=; b=B m7qth907VIHhUd+Eo74XpNHnW4sJnidUKnCRQfqTXP2J2SmizQYKZ5vVbx4KXACl iEg8ebdiV4TiFPfHV31kpOHg3oX4kczCVqdZbalqATi24J3MGQc9bJ48loi+d6tG 8iNu9cABTwZ0MmfwSIhBJzvIkNii31/cSDX1xYpzX5hiyrg3m/zT0iCExbciN4DE FqCBsuNIbvQT1eYdXsn33DSkuVbBgdnvJY3ds5h1Wlc40Cn5dJeH6ad6RzlfmkPa XfpgOoM+3GEM9ycrpWSYfpZ+ScQq5jaG896qqm5paERW2gud9LRdSXmFEkzDjhe3 O5a3AMV1AHO9XP81abvNQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefgedrtddtgddukedthedvucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceu rghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujf gurhepfffhvffukfggtggusehttdfstddttddvnecuhfhrohhmpeetnhgurhgvshcuhfhr vghunhguuceorghnughrvghssegrnhgrrhgriigvlhdruggvqeenucggtffrrghtthgvrh hnpeehtdffiefhfeduleffudffkeefleelfeefjeeuieeitdevuddtffejudekteeijeen ucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnhgurh gvshesrghnrghrrgiivghlrdguvgdpnhgspghrtghpthhtohepvddpmhhouggvpehsmhht phhouhhtpdhrtghpthhtoheprggvkhhorhhothhkohhvsehgmhgrihhlrdgtohhmpdhrtg hpthhtohepphhgshhqlhdqhhgrtghkvghrshesphhoshhtghhrvghsqhhlrdhorhhg X-ME-Proxy: Feedback-ID: id4a34324:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 3 Feb 2026 11:26:57 -0500 (EST) Date: Tue, 3 Feb 2026 11:26:56 -0500 From: Andres Freund To: pgsql-hackers@postgresql.org, Alexander Korotkov Subject: Odd code around ginScanToDelete Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Hi, While looking at converting more places to UnlockReleaseBuffer(), in the course of making UnlockReleaseBuffer() faster than the two separate operations, I found this code: static bool ginScanToDelete(GinVacuumState *gvs, BlockNumber blkno, bool isRoot, DataPageDeleteStack *parent, OffsetNumber myoff) ... if (!meDelete) { if (BufferIsValid(me->leftBuffer)) UnlockReleaseBuffer(me->leftBuffer); me->leftBuffer = buffer; } else { if (!isRoot) LockBuffer(buffer, GIN_UNLOCK); ReleaseBuffer(buffer); } if (isRoot) ReleaseBuffer(buffer); Which sure looks like it'd release buffer twice if isRoot is set? I guess that's not reachable, because presumably the root page will always go down the !meDelete path. But it sure made me wonder if there's a hard to reach bug. This code was introduced in commit e14641197a5 Author: Alexander Korotkov Date: 2019-11-19 23:07:36 +0300 Fix deadlock between ginDeletePage() and ginStepRight() I didn't trace it further to see if it existed before that in some fashion. There's another oddity here: ginScanToDelete() requires that the root page has been locked by the caller already, but will afaict re-read the root page? But then have code to avoid locking it again, because that would not have worked? Seems odd. Greetings, Andres Freund