From patchwork Sun Mar 31 14:24:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Lyakas X-Patchwork-Id: 10878769 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C4D0614DE for ; Sun, 31 Mar 2019 14:25:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AE2D728534 for ; Sun, 31 Mar 2019 14:25:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A27FC287E0; Sun, 31 Mar 2019 14:25:35 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 31EF228534 for ; Sun, 31 Mar 2019 14:25:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731176AbfCaOZe (ORCPT ); Sun, 31 Mar 2019 10:25:34 -0400 Received: from mail-wr1-f68.google.com ([209.85.221.68]:34213 "EHLO mail-wr1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731172AbfCaOZe (ORCPT ); Sun, 31 Mar 2019 10:25:34 -0400 Received: by mail-wr1-f68.google.com with SMTP id p10so8514748wrq.1 for ; Sun, 31 Mar 2019 07:25:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=zadara-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id; bh=pWs2bUQ64f/gNRuDNVO2VtX9fwrIlFWcml7DBb+rcTo=; b=ooYgu3znGl4CjpheY8fmTJnl+mcsRb/hM1K/FKdqVX1qtrCdizRip//2M/iolBFC4D ydezR0RAg9+8mqnKHPk7Vczo+EamqW8MtQ/mfG1C6kGCXflGojneWhpRQGPVHL5JLJqJ CnHgcNImXCp3lWvb2nXMb2S7/gedwCmZ6yMnkqBLabyYXhCiKdx7cK4gZzNpH/nalIAj NM6RsFbMtboMMKVLHxPjF3IkbnVCZr9Lry1CEkOB2CLmDuvsebYpHG8UNyKF9XcBSwdR NQFP95afscW6v4uA5CtrkQEEgIl5lI/B7wx4bybvSggC/+CeHPuRdjQP9MnQ1+l3VKoF QkKA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=pWs2bUQ64f/gNRuDNVO2VtX9fwrIlFWcml7DBb+rcTo=; b=VBn1EDpEoHTtuyQWdTOT6MNYQWL4UuAZUhrXDlfg7IOydrVndA7oQKR2Nip4so5YYP uxRuRPEk9d3+mEddbxBalHMM15OEJLV4Tcar94FL4fLCVFRAA61SnUz5LHwVOfU5iDLZ YrpSoZTU6lEZsLsUiIxwQl4FdjW2WkPHRMycWD9tnH0V0wRVg2BMf9pJPAkx++w4jwb9 PTLImqUcMMnHh8K2/SsQgPa6/9SPIXKRYKeoPMY5t2y7+nZmnVpKpf7ByUvv3kgHBghO zUjSWimPB21MkmwbR5PGSlaKCjphWigLsxOcKs1gFbAIxniMVuTgJpBjBTn6zlguv7ap UaKQ== X-Gm-Message-State: APjAAAUBTA4o4lYTebrMABA3KE6RbUC862ObJqWEcb1qf+HpqK3Y6JK9 Z24AMH8uq1eSOIGSD78IBWowkcQQHwk= X-Google-Smtp-Source: APXvYqxP9bIwDqKILL28oQQ79HPQHCMoRzaIyCjfHF256Yqf/VIrTNsc72U5M3G0zrD1W0/W6O68aw== X-Received: by 2002:a5d:4a4f:: with SMTP id v15mr35774580wrs.5.1554042332699; Sun, 31 Mar 2019 07:25:32 -0700 (PDT) Received: from localhost.localdomain ([82.166.81.77]) by smtp.gmail.com with ESMTPSA id o4sm16904218wmo.20.2019.03.31.07.25.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 31 Mar 2019 07:25:32 -0700 (PDT) From: Alex Lyakas To: linux-xfs@vger.kernel.org Cc: stable@vger.kernel.org, darrick.wong@oracle.com, hch@lst.de, shyam@zadara.com Subject: [STABLE PATCH 1/2] xfs: add the ability to join a held buffer to a defer_ops Date: Sun, 31 Mar 2019 17:24:42 +0300 Message-Id: <1554042282-3344-1-git-send-email-alex@zadara.com> X-Mailer: git-send-email 1.9.1 Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: "Darrick J. Wong" In certain cases, defer_ops callers will lock a buffer and want to hold the lock across transaction rolls. Similar to ijoined inodes, we want to dirty & join the buffer with each transaction roll in defer_finish so that afterwards the caller still owns the buffer lock and we haven't inadvertently pinned the log. Signed-off-by: Darrick J. Wong Signed-off-by: Alex Lyakas --- fs/xfs/libxfs/xfs_defer.c | 39 ++++++++++++++++++++++++++++++++++++--- fs/xfs/libxfs/xfs_defer.h | 5 ++++- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index 072ebfe..087fea0 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -249,6 +249,10 @@ for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++) xfs_trans_log_inode(*tp, dop->dop_inodes[i], XFS_ILOG_CORE); + /* Hold the (previously bjoin'd) buffer locked across the roll. */ + for (i = 0; i < XFS_DEFER_OPS_NR_BUFS && dop->dop_bufs[i]; i++) + xfs_trans_dirty_buf(*tp, dop->dop_bufs[i]); + trace_xfs_defer_trans_roll((*tp)->t_mountp, dop); /* Roll the transaction. */ @@ -264,6 +268,12 @@ for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++) xfs_trans_ijoin(*tp, dop->dop_inodes[i], 0); + /* Rejoin the buffers and dirty them so the log moves forward. */ + for (i = 0; i < XFS_DEFER_OPS_NR_BUFS && dop->dop_bufs[i]; i++) { + xfs_trans_bjoin(*tp, dop->dop_bufs[i]); + xfs_trans_bhold(*tp, dop->dop_bufs[i]); + } + return error; } @@ -295,6 +305,31 @@ } } + ASSERT(0); + return -EFSCORRUPTED; +} + +/* + * Add this buffer to the deferred op. Each joined buffer is relogged + * each time we roll the transaction. + */ +int +xfs_defer_bjoin( + struct xfs_defer_ops *dop, + struct xfs_buf *bp) +{ + int i; + + for (i = 0; i < XFS_DEFER_OPS_NR_BUFS; i++) { + if (dop->dop_bufs[i] == bp) + return 0; + else if (dop->dop_bufs[i] == NULL) { + dop->dop_bufs[i] = bp; + return 0; + } + } + + ASSERT(0); return -EFSCORRUPTED; } @@ -493,9 +528,7 @@ struct xfs_defer_ops *dop, xfs_fsblock_t *fbp) { - dop->dop_committed = false; - dop->dop_low = false; - memset(&dop->dop_inodes, 0, sizeof(dop->dop_inodes)); + memset(dop, 0, sizeof(struct xfs_defer_ops)); *fbp = NULLFSBLOCK; INIT_LIST_HEAD(&dop->dop_intake); INIT_LIST_HEAD(&dop->dop_pending); diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index d4f046d..045beac 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -59,6 +59,7 @@ enum xfs_defer_ops_type { }; #define XFS_DEFER_OPS_NR_INODES 2 /* join up to two inodes */ +#define XFS_DEFER_OPS_NR_BUFS 2 /* join up to two buffers */ struct xfs_defer_ops { bool dop_committed; /* did any trans commit? */ @@ -66,8 +67,9 @@ struct xfs_defer_ops { struct list_head dop_intake; /* unlogged pending work */ struct list_head dop_pending; /* logged pending work */ - /* relog these inodes with each roll */ + /* relog these with each roll */ struct xfs_inode *dop_inodes[XFS_DEFER_OPS_NR_INODES]; + struct xfs_buf *dop_bufs[XFS_DEFER_OPS_NR_BUFS]; }; void xfs_defer_add(struct xfs_defer_ops *dop, enum xfs_defer_ops_type type, @@ -77,6 +79,7 @@ void xfs_defer_add(struct xfs_defer_ops *dop, enum xfs_defer_ops_type type, void xfs_defer_init(struct xfs_defer_ops *dop, xfs_fsblock_t *fbp); bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop); int xfs_defer_ijoin(struct xfs_defer_ops *dop, struct xfs_inode *ip); +int xfs_defer_bjoin(struct xfs_defer_ops *dop, struct xfs_buf *bp); /* Description of a deferred type. */ struct xfs_defer_op_type { From patchwork Sun Mar 31 14:24:52 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Lyakas X-Patchwork-Id: 10878771 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DE9A41805 for ; Sun, 31 Mar 2019 14:25:46 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C6CEF28534 for ; Sun, 31 Mar 2019 14:25:46 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BB413287E0; Sun, 31 Mar 2019 14:25:46 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3CDF228534 for ; Sun, 31 Mar 2019 14:25:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731130AbfCaOZp (ORCPT ); Sun, 31 Mar 2019 10:25:45 -0400 Received: from mail-wm1-f65.google.com ([209.85.128.65]:54209 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731172AbfCaOZp (ORCPT ); Sun, 31 Mar 2019 10:25:45 -0400 Received: by mail-wm1-f65.google.com with SMTP id q16so7445221wmj.3 for ; Sun, 31 Mar 2019 07:25:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=zadara-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id; bh=+YKaJbDwl7rqrdUldkJCb9PkkAUlNSlsglfJ7SvT3Qk=; b=ohYANEGG8tA2f0FCei8QLlZqLKZeofP7K9K+fQXlIln8FWe84JpZ+MO4UtjkWf/83S +MqPFrO5cSZ8kzErTCzgTTJI9jD9bJP4wory+L0NnxOjkdEu8OjNz4dOsfn2irpmUJPM C5EkNB47CCjrfZ1VXfqwHJHcWjaZUfg83tMpquhdrDem+DUWOO21IKrix8hWKHZgtxuN AIlV2tkZ3UNWAo1hlioAT2aw+/8SJHy6AWm2mFvFaeCa4P9ferR+mRDVh8vQmTcu7AB4 BpAfw86z93lPNc5YJBSN1mPtIS/zsynFYs9KfWL6xGDQVfSpLg4f/0R7Ilui5DeIR4Cj XJZQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=+YKaJbDwl7rqrdUldkJCb9PkkAUlNSlsglfJ7SvT3Qk=; b=J7OJfbLUzYmc13MfwKOz8Dar7D1NIFy7hOpanLMtRt8OF/PrxqQxfe3t4GjUjmgGkr H6EJXj/A4lrYCXjLVcasToRBuUQ2Vm2B9wTXeLSF6EW2saVFrpDnydmGtaqKXJ0wn21K Mf0NZ8sjgPKujvZ+B1Vi9JhVwnDSN3mKm34dIg/k9xZT3rOlyPKuuk37srEUK/RGuooe VKyrahsHNfUB/cskj1clq9WAyvXDJuS+2CBas+Qxvevlc2yN3Lw1+uJD8VdHeo0MkGFT g7H8GnXoqnj9JwRgmD5SlZ1SDECthEIHY1j9zLDhsNXMOXfjQ29WqLh4oxj631m+K4PR W3Bw== X-Gm-Message-State: APjAAAULEfkAEM3vgYn+0vXwZy9gyM1VDvOR1iHDhQ8aiBEsOllVlj6z h2le5W+UdYMcCN4cDhFTJMMP4witVB0= X-Google-Smtp-Source: APXvYqxqqL0E92hRHie9cUohT6NDAuZKMXlkbrSbjkMiZv4BfrvWgrmgk3obqqKp97XgEoOooHbncg== X-Received: by 2002:a05:600c:220b:: with SMTP id z11mr9637871wml.73.1554042342983; Sun, 31 Mar 2019 07:25:42 -0700 (PDT) Received: from localhost.localdomain ([82.166.81.77]) by smtp.gmail.com with ESMTPSA id y17sm4968818wrh.60.2019.03.31.07.25.41 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 31 Mar 2019 07:25:42 -0700 (PDT) From: Alex Lyakas To: linux-xfs@vger.kernel.org Cc: stable@vger.kernel.org, darrick.wong@oracle.com, hch@lst.de, shyam@zadara.com Subject: [STABLE PATCH 2/2] xfs: hold xfs_buf locked between shortform->leaf conversion and the addition of an attribute Date: Sun, 31 Mar 2019 17:24:52 +0300 Message-Id: <1554042292-3381-1-git-send-email-alex@zadara.com> X-Mailer: git-send-email 1.9.1 Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: "Darrick J. Wong" The new attribute leaf buffer is not held locked across the transaction roll between the shortform->leaf modification and the addition of the new entry. As a result, the attribute buffer modification being made is not atomic from an operational perspective. Hence the AIL push can grab it in the transient state of "just created" after the initial transaction is rolled, because the buffer has been released. This leads to xfs_attr3_leaf_verify() asserting that hdr.count is zero, treating this as in-memory corruption, and shutting down the filesystem. Darrick ported the original patch to 4.15 and reworked it use the xfs_defer_bjoin helper and hold/join the buffer correctly across the second transaction roll. Signed-off-by: Darrick J. Wong Signed-off-by: Alex Lyakas --- fs/xfs/libxfs/xfs_attr.c | 20 +++++++++++++++----- fs/xfs/libxfs/xfs_attr_leaf.c | 9 ++++++--- fs/xfs/libxfs/xfs_attr_leaf.h | 3 ++- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index ea66f04..e4265db 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -212,6 +212,7 @@ int flags) { struct xfs_mount *mp = dp->i_mount; + struct xfs_buf *leaf_bp = NULL; struct xfs_da_args args; struct xfs_defer_ops dfops; struct xfs_trans_res tres; @@ -327,9 +328,16 @@ * GROT: another possible req'mt for a double-split btree op. */ xfs_defer_init(args.dfops, args.firstblock); - error = xfs_attr_shortform_to_leaf(&args); + error = xfs_attr_shortform_to_leaf(&args, &leaf_bp); if (error) goto out_defer_cancel; + /* + * Prevent the leaf buffer from being unlocked so that a + * concurrent AIL push cannot grab the half-baked leaf + * buffer and run into problems with the write verifier. + */ + xfs_trans_bhold(args.trans, leaf_bp); + xfs_defer_bjoin(args.dfops, leaf_bp); xfs_defer_ijoin(args.dfops, dp); error = xfs_defer_finish(&args.trans, args.dfops); if (error) @@ -337,13 +345,14 @@ /* * Commit the leaf transformation. We'll need another (linked) - * transaction to add the new attribute to the leaf. + * transaction to add the new attribute to the leaf, which + * means that we have to hold & join the leaf buffer here too. */ - error = xfs_trans_roll_inode(&args.trans, dp); if (error) goto out; - + xfs_trans_bjoin(args.trans, leaf_bp); + leaf_bp = NULL; } if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) @@ -374,8 +383,9 @@ out_defer_cancel: xfs_defer_cancel(&dfops); - args.trans = NULL; out: + if (leaf_bp) + xfs_trans_brelse(args.trans, leaf_bp); if (args.trans) xfs_trans_cancel(args.trans); xfs_iunlock(dp, XFS_ILOCK_EXCL); diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c index 40e53a4..73a5417 100644 --- a/fs/xfs/libxfs/xfs_attr_leaf.c +++ b/fs/xfs/libxfs/xfs_attr_leaf.c @@ -739,10 +739,13 @@ STATIC void xfs_attr3_leaf_moveents(struct xfs_da_args *args, } /* - * Convert from using the shortform to the leaf. + * Convert from using the shortform to the leaf. On success, return the + * buffer so that we can keep it locked until we're totally done with it. */ int -xfs_attr_shortform_to_leaf(xfs_da_args_t *args) +xfs_attr_shortform_to_leaf( + struct xfs_da_args *args, + struct xfs_buf **leaf_bp) { xfs_inode_t *dp; xfs_attr_shortform_t *sf; @@ -821,7 +824,7 @@ STATIC void xfs_attr3_leaf_moveents(struct xfs_da_args *args, sfe = XFS_ATTR_SF_NEXTENTRY(sfe); } error = 0; - + *leaf_bp = bp; out: kmem_free(tmpbuffer); return error; diff --git a/fs/xfs/libxfs/xfs_attr_leaf.h b/fs/xfs/libxfs/xfs_attr_leaf.h index f7dda0c..894124e 100644 --- a/fs/xfs/libxfs/xfs_attr_leaf.h +++ b/fs/xfs/libxfs/xfs_attr_leaf.h @@ -48,7 +48,8 @@ void xfs_attr_shortform_add(struct xfs_da_args *args, int forkoff); int xfs_attr_shortform_lookup(struct xfs_da_args *args); int xfs_attr_shortform_getvalue(struct xfs_da_args *args); -int xfs_attr_shortform_to_leaf(struct xfs_da_args *args); +int xfs_attr_shortform_to_leaf(struct xfs_da_args *args, + struct xfs_buf **leaf_bp); int xfs_attr_shortform_remove(struct xfs_da_args *args); int xfs_attr_shortform_allfit(struct xfs_buf *bp, struct xfs_inode *dp); int xfs_attr_shortform_bytesfit(struct xfs_inode *dp, int bytes);