Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.89) (envelope-from ) id 1f8nJr-0007ms-Mb for pgsql-hackers@arkaria.postgresql.org; Wed, 18 Apr 2018 13:40:19 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1f8nJq-0006jn-45 for pgsql-hackers@arkaria.postgresql.org; Wed, 18 Apr 2018 13:40:18 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.89) (envelope-from ) id 1f8nGr-0002mm-15 for pgsql-hackers@lists.postgresql.org; Wed, 18 Apr 2018 13:37:13 +0000 Received: from new1-smtp.messagingengine.com ([66.111.4.221]) by magus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.89) (envelope-from ) id 1f8nGh-0007fe-7q for pgsql-hackers@postgresql.org; Wed, 18 Apr 2018 13:37:12 +0000 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailnew.nyi.internal (Postfix) with ESMTP id F29511429; Wed, 18 Apr 2018 09:36:59 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute4.internal (MEProxy); Wed, 18 Apr 2018 09:36:59 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :date:from:in-reply-to:message-id:mime-version:subject:to :x-me-sender:x-me-sender:x-sasl-enc; s=fm2; bh=63zFanP6+a4zL5C+R U6BO07ANlwg2Dwl3m60Wd1nv8I=; b=iSQvLgCVjH6xra6p0vG7lbkdVU20tvG7i NwIQ+IBfPYmCvzJ/F1v1/tXH3gDOnYHH0U1Hiw1N4cTTg0vbwYnGRQw1Tq9mKchG YURmwl7T5f1bw4u9m7QrjQFm/xjnUVzmisiFffavoMqSS+gBwl7bmwII9yIraA1V o0iikoS6EJg9/ArkzWYdgC39AcRLmQuUNjCPjjsy8JAUTDNEg0B3kRfvi0439IWb PwzEw/EhfYWPpKPtEXv45y2LPe8eitSqpyjG1oX1dIa/EzakDwr5lzGwxIvs5hrq MTU57Hr9YpRwm1MmAVQBL2U6uqB5vp+f1w8/Er9sxjQaVMeEhQv/w== X-ME-Sender: Received: from alvin.alvh.no-ip.org (unknown [179.56.29.253]) by mail.messagingengine.com (Postfix) with ESMTPA id 31D1AE5088; Wed, 18 Apr 2018 09:36:59 -0400 (EDT) Received: by alvin.alvh.no-ip.org (Postfix, from userid 1000) id 5846060D; Wed, 18 Apr 2018 10:36:57 -0300 (-03) Date: Wed, 18 Apr 2018 10:36:57 -0300 From: Alvaro Herrera To: Pavan Deolasee Cc: "Wood, Dan" , "pgsql-hackers@postgresql.org" Subject: Re: VM map freeze corruption Message-ID: <20180418133657.gcbg7exanyg5sglw@alvherre.pgsql> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="if2usbmasy6ej2yg" Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: User-Agent: NeoMutt/20170306-137-4415bd-dirty (1.8.0) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk --if2usbmasy6ej2yg Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit Pavan Deolasee wrote: > On Wed, Apr 18, 2018 at 7:37 AM, Wood, Dan wrote: > > My analysis is that heap_prepare_freeze_tuple->FreezeMultiXactId() > > returns FRM_NOOP if the MultiXACT locked rows haven't committed. This > > results in changed=false and totally_frozen=true(as initialized). When > > this returns to lazy_scan_heap(), no rows are added to the frozen[] array. > > Yet, tuple_totally_frozen is true. This means the page is marked frozen in > > the VM, even though the MultiXACT row wasn't left untouch. > > > > A fix to heap_prepare_freeze_tuple() that seems to do the trick is: > > else > > { > > Assert(flags & FRM_NOOP); > > + totally_frozen = false; > > } > > > > That's a great find! Indeed. This family of bugs (introduced by freeze map changes in 9.6) was initially fixed in 38e9f90a227d but this spot was missed in that fix. IMO the cause is the totally_frozen variable, which starts life in a bogus state (true) and the different code paths can set it to the right state, or by inaction end up deciding that the initial bogus state was correct in the first place. Errors of omission are far too easy in that kind of model, ISTM, so I propose this slightly different patch, which albeit yet untested seems easier to verify and easier to get right. -- Álvaro Herrera https://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services --if2usbmasy6ej2yg Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="frozen.patch" diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 4fdb549099..791958a543 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -6800,9 +6800,10 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple, xl_heap_freeze_tuple *frz, bool *totally_frozen_p) { bool changed = false; - bool freeze_xmax = false; + bool xmin_frozen = false; /* is xmin frozen after this? */ + bool freeze_xmax = false; /* whether to freeze xmax now */ + bool xmax_frozen = false; /* ix xmax frozen after this? */ TransactionId xid; - bool totally_frozen = true; frz->frzflags = 0; frz->t_infomask2 = tuple->t_infomask2; @@ -6829,10 +6830,11 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple, frz->t_infomask |= HEAP_XMIN_FROZEN; changed = true; + xmin_frozen = true; } - else - totally_frozen = false; } + else if (HeapTupleHeaderXminFrozen(tuple)) + xmin_frozen = true; /* * Process xmax. To thoroughly examine the current Xmax value we need to @@ -6870,7 +6872,6 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple, if (flags & FRM_MARK_COMMITTED) frz->t_infomask |= HEAP_XMAX_COMMITTED; changed = true; - totally_frozen = false; } else if (flags & FRM_RETURN_IS_MULTI) { @@ -6892,7 +6893,6 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple, frz->xmax = newxmax; changed = true; - totally_frozen = false; } else { @@ -6923,9 +6923,10 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple, xid))); freeze_xmax = true; } - else - totally_frozen = false; } + else if (((tuple->t_infomask & HEAP_XMAX_INVALID) == HEAP_XMAX_INVALID) || + !TransactionIdIsValid(HeapTupleHeaderGetRawXmax(tuple))) + xmax_frozen = true; if (freeze_xmax) { @@ -6941,6 +6942,7 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple, frz->t_infomask2 &= ~HEAP_HOT_UPDATED; frz->t_infomask2 &= ~HEAP_KEYS_UPDATED; changed = true; + xmax_frozen = true; } /* @@ -6981,7 +6983,7 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple, } } - *totally_frozen_p = totally_frozen; + *totally_frozen_p = xmin_frozen && xmax_frozen; return changed; } --if2usbmasy6ej2yg--