Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1ncWvW-0000sX-Fo for pgsql-hackers@arkaria.postgresql.org; Thu, 07 Apr 2022 18:32:14 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1ncWvV-0001KH-29 for pgsql-hackers@arkaria.postgresql.org; Thu, 07 Apr 2022 18:32:13 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1ncWtN-0003Nl-27 for pgsql-hackers@lists.postgresql.org; Thu, 07 Apr 2022 18:30:01 +0000 Received: from mail-pl1-x632.google.com ([2607:f8b0:4864:20::632]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1ncWtK-0001Lu-EX for pgsql-hackers@postgresql.org; Thu, 07 Apr 2022 18:30:00 +0000 Received: by mail-pl1-x632.google.com with SMTP id d15so5760106pll.10 for ; Thu, 07 Apr 2022 11:29:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=date:from:to:subject:message-id:mime-version:content-disposition; bh=tUf60Zyqi9sA4lwUrDtKqIyNgdx1yyrjaOgcoQZ3Ak0=; b=XHafKbsdrZtlNNt1IrVYjXnWwtsJdqSv4KvzvhXOSqH/prAwDPe6BfYXAH2aMbDCnD 7DJYviafVFSkYxPw3NG2GcMCN+6BToKML2nVL9ya897F7CjR6NNEfdj8uALvsWWBlR5V NMYk+LRwiXlEqBDrcIYtWdWrU/sTPL8cYXmJj44MCRfcdEwTnKByC3VLaB0Lma3Xokk5 TVDmCy0wFCLL5AB/y8/BNFRkRCDIavFapJ6kdww2nYY23RhO8xfhyXPDNEjkTd16DVki RQ9q6yofq5eLy+wMFioxoSSUCP71pBGoMXyOPGTk3ZVI4nMHuwrA6RcVvCl9v9V2AeB2 Cmmw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:from:to:subject:message-id:mime-version :content-disposition; bh=tUf60Zyqi9sA4lwUrDtKqIyNgdx1yyrjaOgcoQZ3Ak0=; b=rbNjl2ATSjhIDLfcB7ccXHepxGiMKDh6NfdQVVe9dC9RE7jBJC97najoW64hnKTMNN h6ssy5hz3VFF+DClNXyaxuQr6D0GDluEVsLwyeMYIb3w7oFj9DxyRu1342lo5h+QlDVc StNxiLIcwd3yKX5pT8sXTHCdumj+iNEP0exUbXwocajHwI2/y5RjzMbzxWZ1OKKrPnU4 UBNdiap6Iujxvx2UFW8w4x+ji/3G1pBhcw2KCi5xY9tUCkt3012/4X/6UlnUWIjO9mOH iqMgjjKT6zSASDwHrERj55x3Nm3W4KEM0EA83K/Rs99eFeSGdytcvIouveDZVeGQ1EtO i7pw== X-Gm-Message-State: AOAM531HbkCggiW4tNLuKapxGzoPezP699AYEn/mcBLAdFO+iBtqOSFS AEbC1J0qsRVu7mq5Pmugd2lFmgyd5A4= X-Google-Smtp-Source: ABdhPJyGL6odC2Q/oVT3G11fAYRmbtG5P1aDx2E6DV/Q/AmIvpu3+Kr4Cl23sJgto4sbf08fYEM5JQ== X-Received: by 2002:a17:902:f78d:b0:14d:522e:deb3 with SMTP id q13-20020a170902f78d00b0014d522edeb3mr15245481pln.173.1649356196947; Thu, 07 Apr 2022 11:29:56 -0700 (PDT) Received: from nathanxps13 ([50.54.155.70]) by smtp.gmail.com with ESMTPSA id v8-20020a056a00148800b004fa9bd7ddc9sm24070709pfu.113.2022.04.07.11.29.55 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Apr 2022 11:29:56 -0700 (PDT) Date: Thu, 7 Apr 2022 11:29:54 -0700 From: Nathan Bossart To: pgsql-hackers@postgresql.org Subject: avoid multiple hard links to same WAL file after a crash Message-ID: <20220407182954.GA1231544@nathanxps13> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="5vNYLRcllDrimb99" Content-Disposition: inline List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --5vNYLRcllDrimb99 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hi hackers, I am splitting this off of a previous thread aimed at reducing archiving overhead [0], as I believe this fix might deserve back-patching. Presently, WAL recycling uses durable_rename_excl(), which notes that a crash at an unfortunate moment can result in two links to the same file. My testing [1] demonstrated that it was possible to end up with two links to the same file in pg_wal after a crash just before unlink() during WAL recycling. Specifically, the test produced links to the same file for the current WAL file and the next one because the half-recycled WAL file was re-recycled upon restarting. This seems likely to lead to WAL corruption. The attached patch prevents this problem by using durable_rename() instead of durable_rename_excl() for WAL recycling. This removes the protection against accidentally overwriting an existing WAL file, but there shouldn't be one. This patch also sets the stage for reducing archiving overhead (as discussed in the other thread [0]). The proposed change to reduce archiving overhead will make it more likely that the server will attempt to re-archive segments after a crash. This might lead to archive corruption if the server concurrently writes to the same file via the aforementioned bug. [0] https://www.postgresql.org/message-id/20220222011948.GA3850532%40nathanxps13 [1] https://www.postgresql.org/message-id/20220222173711.GA3852671%40nathanxps13 -- Nathan Bossart Amazon Web Services: https://aws.amazon.com --5vNYLRcllDrimb99 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v1-0001-Avoid-multiple-hard-links-to-same-WAL-file-after-.patch" From 244726f6a78aca52c2fe6e70cef966f152057191 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Thu, 7 Apr 2022 10:07:42 -0700 Subject: [PATCH v1 1/1] Avoid multiple hard links to same WAL file after a crash. Presently, WAL recycling uses durable_rename_excl(), which notes that a crash at an unfortunate moment can result in two links to the same file. My testing demonstrated that it was possible to end up with two links to the same file in pg_wal after a crash just before unlink() during WAL recycling. Specifically, the test produced links to the same file for the current WAL file and the next one because the half-recycled WAL file was re-recycled upon restarting. This seems likely to lead to WAL corruption. This change prevents this problem by using durable_rename() instead of durable_rename_excl() for WAL recycling. This removes the protection against accidentally overwriting an existing WAL file, but there shouldn't be one. Back-patch to all supported versions. Author: Nathan Bossart --- src/backend/access/transam/xlog.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 6770c3ddba..6ab5b2a622 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -3324,13 +3324,15 @@ InstallXLogFileSegment(XLogSegNo *segno, char *tmppath, } /* - * Perform the rename using link if available, paranoidly trying to avoid - * overwriting an existing file (there shouldn't be one). + * Perform the rename. Ideally, we'd use link() and unlink() to avoid + * overwriting an existing file (there shouldn't be one). However, that + * approach opens up the possibility that pg_wal will contain multiple hard + * links to the same WAL file after a crash. */ - if (durable_rename_excl(tmppath, path, LOG) != 0) + if (durable_rename(tmppath, path, LOG) != 0) { LWLockRelease(ControlFileLock); - /* durable_rename_excl already emitted log message */ + /* durable_rename already emitted log message */ return false; } -- 2.25.1 --5vNYLRcllDrimb99--