From patchwork Thu Feb 6 22:57:01 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13964051 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DB4302417E2 for ; Thu, 6 Feb 2025 22:57:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882622; cv=none; b=Eg1uTx5LAixk1od4eXIgE3rUhQpwhVQy0vPStnlT2dUCyhV5GSBm0ah6HxMB3dcPHrKmllRYdJmsYerCSVOciZy7uY3GlIQpbbqW2XQiDBHQWvj+91188fJlJXceBM+jMwAZOKUCsY6CfqDMSJiQK7seWX2DAaoByJ8ANVnzH4g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882622; c=relaxed/simple; bh=t+x3oYrFcR51PS/fc62bLZuXP2esQ05If2Egij+4Z3k=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ogRRPgIbfOfXvS7R69I3EIKuPd3bQznzAJgRwcXzcaT+ffSKNsLFfNY1Y5UzWPPpEi6E0YEm8/NKHoXdcF8uDBM7FEV1HcBkdOG5JixSdkkVI9YgJ7D6mcD+YH4rfqguRGErbZu0smWv6vwSVSg/XW9xcbcBgiscAAuAmZ69bTM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hlBqvdNO; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hlBqvdNO" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4D8E0C4CEDF; Thu, 6 Feb 2025 22:57:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882622; bh=t+x3oYrFcR51PS/fc62bLZuXP2esQ05If2Egij+4Z3k=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=hlBqvdNO1Dysn/loQrelu8Xz6EqpECCI7ZxOGXZgoayBKmquGyebFa7/i7CGWA/Q1 XkBylKiSKk5BcMJ0jcYbGwGc3Xe3/K1yjdxSUybfuXzqcqnuGgJT4SpJau8cQtMk2P gFsZGnrMZJBoNalcyFMDXaEyYnNkI9VOx6+3Namac4HTQg5YDIHWcZXYKbVYThIjGE nsIpuScFDedm3tADoHfsyr0Qt2Pt7MqhGP+GxYOTtjYomuS2VaSwhuX0zcY3fIIHro +cCe5RDHQec5thbyC9puFhLRmyVVGH4ZDRB5IDcRquer5RzkDZNOHvycgjZNgyQfMt yKHRPV+M7x2Fg== Date: Thu, 06 Feb 2025 14:57:01 -0800 Subject: [PATCH 01/22] libxfs: compute the rt refcount btree maxlevels during initialization From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088950.2741962.6915597562604311279.stgit@frogsfrogsfrogs> In-Reply-To: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> References: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Compute max rt refcount btree height information when we set up libxfs. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- libxfs/init.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libxfs/init.c b/libxfs/init.c index f92805620c33f1..00bd46a6013e28 100644 --- a/libxfs/init.c +++ b/libxfs/init.c @@ -597,7 +597,8 @@ static inline void xfs_rtbtree_compute_maxlevels( struct xfs_mount *mp) { - mp->m_rtbtree_maxlevels = mp->m_rtrmap_maxlevels; + mp->m_rtbtree_maxlevels = max(mp->m_rtrmap_maxlevels, + mp->m_rtrefc_maxlevels); } /* Compute maximum possible height of all btrees. */ @@ -615,6 +616,7 @@ libxfs_compute_all_maxlevels( xfs_rmapbt_compute_maxlevels(mp); xfs_rtrmapbt_compute_maxlevels(mp); xfs_refcountbt_compute_maxlevels(mp); + xfs_rtrefcountbt_compute_maxlevels(mp); xfs_agbtree_compute_maxlevels(mp); xfs_rtbtree_compute_maxlevels(mp); From patchwork Thu Feb 6 22:57:17 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13964052 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7538C2417D6 for ; Thu, 6 Feb 2025 22:57:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882638; cv=none; b=Z0KJ7g3L80YJbVAzOzVJufhNVpj8NZ/21K0lUbUByA9twMozD9VhNRgECNKyh/L4FFIHSh0Q7sWRbctAnohwOXPzJ0L+R4gNvaO1wgxtGiAkbrWhvr0gZ7JzvC9+yEb+Mdcf78+k0NYqDwXdNKYZ1yTqCCfbpukQMRIBx/HaTPQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882638; c=relaxed/simple; bh=dbrGcm4jdptWmqRtrXgJDUrBcyrGTteXHj6xuovA7O0=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=bWmjREIb+xNCK/+KAqOvHCDXlTUbguJJ2tTdAvqxotm6Rn8+YfbLyDhwZAMJYnBCY2JIiGgF5r/3JiMKPqsjMfPeOQE73hliwcDtkyQUgUKl1M8cmXshcHAmawCnQTxU5/JQeCel9vNnobqOvjwJ69F11/A8CTnWmF2T7ElnoTw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=YiDqY3hk; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="YiDqY3hk" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E89DFC4CEDD; Thu, 6 Feb 2025 22:57:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882638; bh=dbrGcm4jdptWmqRtrXgJDUrBcyrGTteXHj6xuovA7O0=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=YiDqY3hkM0nnZ7vLnkRR23xKvP5CazlmU4j6wUnF6iJuMv2uuEkqluO/ET47KRJCu vUfclRZ09y4HFKY0BQG7qZqCDZV8xsS/MLUXPDYa3K/jhRPX1WkGjV33aMIvpJs4Ph EuJW1vTl/Udpa2WkVD5m0m4QUwO6+rlNUeXbgpkhiqRXjl6j236r+5XHXpFHNAhG0o UAYR5QNB0F+lqzbj3brCyVXO5srUwSrbIFWpxlexOs+Lmix99l2obKn9zXm0PsaXja J8ECb2bPmXtW7ppXNiwlkNftKwOLP7Sv/0xvkTui5idXAp5dDclLTpF4KAOsVa8VaR 0/Up10k31IOtA== Date: Thu, 06 Feb 2025 14:57:17 -0800 Subject: [PATCH 02/22] libxfs: add a realtime flag to the refcount update log redo items From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088965.2741962.5146151692664108906.stgit@frogsfrogsfrogs> In-Reply-To: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> References: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Extend the refcount update (CUI) log items with a new realtime flag that indicates that the updates apply against the realtime refcountbt. We'll wire up the actual refcount code later. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- libxfs/defer_item.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/libxfs/defer_item.c b/libxfs/defer_item.c index 1ca9ce15ecfe3d..6beefa6a439980 100644 --- a/libxfs/defer_item.c +++ b/libxfs/defer_item.c @@ -442,9 +442,18 @@ xfs_refcount_defer_add( trace_xfs_refcount_defer(mp, ri); + /* + * Deferred refcount updates for the realtime and data sections must + * use separate transactions to finish deferred work because updates to + * realtime metadata files can lock AGFs to allocate btree blocks and + * we don't want that mixing with the AGF locks taken to finish data + * section updates. + */ ri->ri_group = xfs_group_intent_get(mp, ri->ri_startblock, - XG_TYPE_AG); - xfs_defer_add(tp, &ri->ri_list, &xfs_refcount_update_defer_type); + ri->ri_realtime ? XG_TYPE_RTG : XG_TYPE_AG); + xfs_defer_add(tp, &ri->ri_list, ri->ri_realtime ? + &xfs_rtrefcount_update_defer_type : + &xfs_refcount_update_defer_type); } /* Cancel a deferred refcount update. */ @@ -516,6 +525,27 @@ const struct xfs_defer_op_type xfs_refcount_update_defer_type = { .cancel_item = xfs_refcount_update_cancel_item, }; +/* Clean up after calling xfs_rtrefcount_finish_one. */ +STATIC void +xfs_rtrefcount_finish_one_cleanup( + struct xfs_trans *tp, + struct xfs_btree_cur *rcur, + int error) +{ + if (rcur) + xfs_btree_del_cursor(rcur, error); +} + +const struct xfs_defer_op_type xfs_rtrefcount_update_defer_type = { + .name = "rtrefcount", + .create_intent = xfs_refcount_update_create_intent, + .abort_intent = xfs_refcount_update_abort_intent, + .create_done = xfs_refcount_update_create_done, + .finish_item = xfs_refcount_update_finish_item, + .finish_cleanup = xfs_rtrefcount_finish_one_cleanup, + .cancel_item = xfs_refcount_update_cancel_item, +}; + /* Inode Block Mapping */ static inline struct xfs_bmap_intent *bi_entry(const struct list_head *e) From patchwork Thu Feb 6 22:57:33 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13964053 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ABB6A2417C2 for ; Thu, 6 Feb 2025 22:57:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882653; cv=none; b=gTIDjQIRArbjdDLhL+eeWuaobz2eJhueZd2ey8NFd4czx5pFJUeFSqr8mDspeOcpQze/vDmMgYpNkTXYr8qObW7ZYoRNW1iRwgHdbMP1++JTffN+45Zma5ezgCwIe/Pn5oaZCPVkvcpS7IfLkwarmsCHRO448nRKuZ4Od2PXyUA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882653; c=relaxed/simple; bh=/0ATUlKOBOUBlzUtNCIjajKYiEN1NsNdRHRo21rysmM=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=WVgUYbZOSItQLpA+OqBWFPsRnml7co0HnIj2E+sA3Z7Y1gEN7P0pqtGk3tlM95edWRSEbL17Gaeppm22m3gUOZzyhSCarp4FntvIa0phkN2/Q2dbi24w+0sLyYhV4yG71tKBZnJ/NcxfT0lfIe2uQFMV2NTZLLTvLQiH3e+v83g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NkMr1mIK; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="NkMr1mIK" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8401AC4CEDD; Thu, 6 Feb 2025 22:57:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882653; bh=/0ATUlKOBOUBlzUtNCIjajKYiEN1NsNdRHRo21rysmM=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=NkMr1mIKgWbffAR2Weg2WnBSn+VcC7WbAUuV6XMbj7HW4l7UJQpnc5McO7UKmGkKQ IeZMKlADsEktI91ipYj8zQ+XSTUv8WeoTCH95dZJMmmEAdGuqOQWIlADK+wXMS4Ckh gklnIF1zWdKp2+OwDmqQ+x1+bUWY+c4yp73EChcX5DVUgHOr1iB6FST3AbaQeq1lrr vvd7ZTC89PmRuevHDXFHd//oLtqziJIq5/Vfz89JVWgHhGhB+3nXky/xcQMLYddnCl nFT9+ouA3Z1t/7xzi8EVPrYoDeGb3RC6dOTFU62XvUEDT35mMjlLjYSQi0Add4HXIy wBu4LTyZkjCVQ== Date: Thu, 06 Feb 2025 14:57:33 -0800 Subject: [PATCH 03/22] libxfs: apply rt extent alignment constraints to CoW extsize hint From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088980.2741962.5884510369918809895.stgit@frogsfrogsfrogs> In-Reply-To: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> References: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong The copy-on-write extent size hint is subject to the same alignment constraints as the regular extent size hint. Since we're in the process of adding reflink (and therefore CoW) to the realtime device, we must apply the same scattered rextsize alignment validation strategies to both hints to deal with the possibility of rextsize changing. Therefore, fix the inode validator to perform rextsize alignment checks on regular realtime files, and to remove misaligned directory hints. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- libxfs/logitem.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libxfs/logitem.c b/libxfs/logitem.c index 7757259dfc5e42..062d6311b942ae 100644 --- a/libxfs/logitem.c +++ b/libxfs/logitem.c @@ -233,6 +233,20 @@ xfs_inode_item_precommit( if (flags & XFS_ILOG_IVERSION) flags = ((flags & ~XFS_ILOG_IVERSION) | XFS_ILOG_CORE); + /* + * Inode verifiers do not check that the CoW extent size hint is an + * integer multiple of the rt extent size on a directory with both + * rtinherit and cowextsize flags set. If we're logging a directory + * that is misconfigured in this way, clear the hint. + */ + if ((ip->i_diflags & XFS_DIFLAG_RTINHERIT) && + (ip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE) && + xfs_extlen_to_rtxmod(ip->i_mount, ip->i_cowextsize) > 0) { + ip->i_diflags2 &= ~XFS_DIFLAG2_COWEXTSIZE; + ip->i_cowextsize = 0; + flags |= XFS_ILOG_CORE; + } + if (!iip->ili_item.li_buf) { struct xfs_buf *bp; int error; From patchwork Thu Feb 6 22:57:48 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13964054 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 54D412417CD for ; Thu, 6 Feb 2025 22:57:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882669; cv=none; b=Ajg8X7yBIVD099cqOzjI29FiOpxDQSCH7++MguVjVm/8itsmtgOr698x8cDFGN94UJ/SMJ1bDZbEXqutUQQlv9VlefUGGnKacJ0I92NCylbPbXc3oaG54B96PEi2jqf7RTntzE/U3VASlnCX37wQAgtJCru6172Jyp0/rS8sG8g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882669; c=relaxed/simple; bh=Y1kCCBfPADLDpzd9UJdQp7p4k1pfZr2qn3Un/we2+7w=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=bNi9FODYVZrjml8HF/zSJvnYYEA8osqdZfNctlCi8kGjYWvttow/uOoTQHwmL0MaCTAoxvEDCybXUs6llcbg1xEWyaohzDmWEwgpujAYqGgfvEPSAEUYxHG+2rQ2dolQoszScEyXw3t7q8YshvORnK40Kn4CPvwls2gOL3aUyAw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GMsY8u6m; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="GMsY8u6m" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2A6E2C4CEDD; Thu, 6 Feb 2025 22:57:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882669; bh=Y1kCCBfPADLDpzd9UJdQp7p4k1pfZr2qn3Un/we2+7w=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=GMsY8u6mOcEHswXMYUFFzm1io5e2QziMSQyUoeXofNvY17qdD5cxJhQnULxRVj282 mzvX+Fy5paH2KTYsy/xN0LXWvnwJn7ngazqMqP7aqjroay3XMInG+1AQ+O/pOB6wOx HUascDZktDrnVtM4ZW97bCUoMMPE6GhIr/TZMBtQkbtCMYlTp2amdH9+uDpgrXNdTU VHlQg7FtC22khjSuODexJOsiCCdpBtVbVs9HtzWgZydR+F5tXvMYIoD3bYCJ5PW6NS uC+yTPuts3cUsDFuhF5R4MzCbvwEc7dSuBMwaA5q1IxAHDzjwtq5+gVI2DGMKmL28Z xj+7KM1kanewQ== Date: Thu, 06 Feb 2025 14:57:48 -0800 Subject: [PATCH 04/22] libfrog: enable scrubbing of the realtime refcount data From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088996.2741962.5133912501507693446.stgit@frogsfrogsfrogs> In-Reply-To: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> References: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Add a new entry so that we can scrub the rtrefcountbt and its metadata directory tree path. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- libfrog/scrub.c | 10 ++++++++++ scrub/repair.c | 1 + 2 files changed, 11 insertions(+) diff --git a/libfrog/scrub.c b/libfrog/scrub.c index 11d467666d6b5a..9ffe4698e864ab 100644 --- a/libfrog/scrub.c +++ b/libfrog/scrub.c @@ -169,6 +169,11 @@ const struct xfrog_scrub_descr xfrog_scrubbers[XFS_SCRUB_TYPE_NR] = { .descr = "realtime reverse mapping btree", .group = XFROG_SCRUB_GROUP_RTGROUP, }, + [XFS_SCRUB_TYPE_RTREFCBT] = { + .name = "rtrefcountbt", + .descr = "realtime reference count btree", + .group = XFROG_SCRUB_GROUP_RTGROUP, + }, }; const struct xfrog_scrub_descr xfrog_metapaths[XFS_SCRUB_METAPATH_NR] = { @@ -217,6 +222,11 @@ const struct xfrog_scrub_descr xfrog_metapaths[XFS_SCRUB_METAPATH_NR] = { .descr = "rtgroup rmap btree", .group = XFROG_SCRUB_GROUP_RTGROUP, }, + [XFS_SCRUB_METAPATH_RTREFCOUNTBT] = { + .name = "rtrefcbt", + .descr = "rtgroup refcount btree", + .group = XFROG_SCRUB_GROUP_RTGROUP, + }, }; /* Invoke the scrub ioctl. Returns zero or negative error code. */ diff --git a/scrub/repair.c b/scrub/repair.c index e6906cbd37d0b3..b2c4232fe8cea1 100644 --- a/scrub/repair.c +++ b/scrub/repair.c @@ -548,6 +548,7 @@ repair_item_difficulty( case XFS_SCRUB_TYPE_RTBITMAP: case XFS_SCRUB_TYPE_RTSUM: case XFS_SCRUB_TYPE_RGSUPER: + case XFS_SCRUB_TYPE_RTREFCBT: ret |= REPAIR_DIFFICULTY_PRIMARY; break; } From patchwork Thu Feb 6 22:58:04 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13964055 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E9A472417F2 for ; Thu, 6 Feb 2025 22:58:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882685; cv=none; b=hrR6bXsjDBiIONx/aYmNWhDkFshCExCWAByo2qAi2yIb7XrN99GxXwyUTdArjCj3fWdjjctpjySdz9GT/HcD10O3NjzOtm9LZplrDTMx4ZOcGbbOngXhSDmkDDBeel4gX0Mi/GrnsOXheN35EGoVlhNAjJUa7afvf3IKbpPjylc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882685; c=relaxed/simple; bh=NK3w8bCzybL5p4FIajuycmJd6W1SvtTb9a7pRLkuqr8=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=aL/3z9B+xpz1hlY4zfK4bjCo8ri3vAaNST+ITjXLlpk+q1ihpNQ98zAV4Z5OLmDlZrEpw06DFtCOwke/IAAClqGg0Hkzflq/Lxi/F0ZjsYYiylB2kixtyAdDuDs3CL2qeNL7QdB6+HUOP266rvGMA71LrKjad1So+SapFnGCW10= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=d/M2imEO; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="d/M2imEO" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C2936C4CEE2; Thu, 6 Feb 2025 22:58:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882684; bh=NK3w8bCzybL5p4FIajuycmJd6W1SvtTb9a7pRLkuqr8=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=d/M2imEOPCmm3uHqAP/NH+ayadMUkGAw5s0N9rGLTloljE46jRzuPmww325320Lfi 3fhPdBIGoEQNnYFps+VS3Aae2uioDZtL/muNO8iU91qW19Br59RS+KQ1bnfqkyL1l5 zo/C2/QwZA2NQVqLtMoqLXuvhm/eW2CbSynff8xHe6WZdXCgmwe5W2zU7Gaa/Uc/Dd Hq4uabkMJcQRrd3vfJv30wTeKhQlMryFlz2JUPftd41xagfnTSrM9DdobTCy3obdr5 iEh4Yby4U91ZI4CQuK+B+d1HiRPh8K5llxWRSKrzp3FeeDa8QDw9Gehfp9ghMXs75a 6HpRQDVCFFTxA== Date: Thu, 06 Feb 2025 14:58:04 -0800 Subject: [PATCH 05/22] man: document userspace API changes due to rt reflink From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888089011.2741962.7359133860691988618.stgit@frogsfrogsfrogs> In-Reply-To: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> References: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Update documentation to describe userspace ABI changes made for realtime reflink support. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- man/man2/ioctl_xfs_scrub_metadata.2 | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/man/man2/ioctl_xfs_scrub_metadata.2 b/man/man2/ioctl_xfs_scrub_metadata.2 index f06bb98de708a4..c72f1c5c568b01 100644 --- a/man/man2/ioctl_xfs_scrub_metadata.2 +++ b/man/man2/ioctl_xfs_scrub_metadata.2 @@ -181,11 +181,12 @@ .SH DESCRIPTION .nf .B XFS_SCRUB_TYPE_RTBITMAP .B XFS_SCRUB_TYPE_RTSUM -.fi -.TP .B XFS_SCRUB_TYPE_RTRMAPBT +.fi +.TP +.B XFS_SCRUB_TYPE_RTREFCBT Examine a given realtime allocation group's free space bitmap, summary file, -or reverse mapping btree, respectively. +reverse mapping btree, or reference count btree, respectively. .PP .nf @@ -250,6 +251,9 @@ .SH DESCRIPTION .TP .B XFS_SCRUB_METAPATH_RTRMAPBT Realtime rmap btree file. +.TP +.B XFS_SCRUB_METAPATH_RTREFCOUNTBT +Realtime reference count btree file. .RE The values of From patchwork Thu Feb 6 22:58:19 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13964056 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E5CD22417D7 for ; Thu, 6 Feb 2025 22:58:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882701; cv=none; b=IsXYQmx0fKNCQkpAXIYH8w1Lp0CDXf/NAfkU6J/nk764XeGuJYeuB6e40SF+rVGqYDEO0VFosedESoyCBUahLBlCiOfJK5G6Hsz6oJco6pOjGXYGaJMKuQdnI207jhBpmPi2UsEzu4FWh9ESLcagHrCAT6WygLHbrhcKFRktaos= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882701; c=relaxed/simple; bh=Nq2ym94rUVALXVraOVsIkbFIpo29ZfzpfMQZ9ixKLpY=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=U7+muGZ07prCkG/PtextOJQ7Ydum0yDiZwU1aOrKCj680rC4BE30w5kinfJgHS4uRoVK4R8KQeKZ9UF1pXzpAztuNNog7Mx9Tc1qKh+LlIRK7Oe56D/ju6FJolsZoluoRuTY6cR33AgWqyNL+OA3sSSdYXTD4xhbpMb7jYrF9qI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VzWJewU2; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="VzWJewU2" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6472CC4CEDD; Thu, 6 Feb 2025 22:58:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882700; bh=Nq2ym94rUVALXVraOVsIkbFIpo29ZfzpfMQZ9ixKLpY=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=VzWJewU2MbOiHpf27iUEJhHzvwV2WbYj/KAnBaYkzc+eCpsL8nj5S47KKOqOpps39 xNjP6N2CT4206Z+s0n185hnfBkIbx52Sw/0rOnY6mHjeKfYsK3t361XagyM8JxC08G qIiwMYTyOZmcEeED1lLBH49d0McG9gYT8SgqvZUd+vUGlv3FZhMpXoZ20qM9o5hf0x pQTnIk4339BBrpeJ4U+MQtMXIX5H1+j8lAFhaAqytV6gV2JXRUQEqAQqmUXk4mgg/h lpGbcvIJ1QqOlpaQQSgxQfTNiKpDZ59nzW0xy8hY54Ebx6yTIyoSZ/qe/V0KMdKFOT JCQtCm5R4TCJw== Date: Thu, 06 Feb 2025 14:58:19 -0800 Subject: [PATCH 06/22] xfs_db: display the realtime refcount btree contents From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888089026.2741962.9721869790463624969.stgit@frogsfrogsfrogs> In-Reply-To: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> References: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Implement all the code we need to dump rtrefcountbt contents, starting from the inode root. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- db/bmroot.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++ db/bmroot.h | 2 + db/btblock.c | 50 ++++++++++++++++ db/btblock.h | 5 ++ db/field.c | 15 +++++ db/field.h | 6 ++ db/inode.c | 22 +++++++ db/type.c | 5 ++ db/type.h | 1 libxfs/libxfs_api_defs.h | 4 + man/man8/xfs_db.8 | 48 +++++++++++++++ 11 files changed, 304 insertions(+), 2 deletions(-) diff --git a/db/bmroot.c b/db/bmroot.c index 19490bd24998c5..cb334aa45837d1 100644 --- a/db/bmroot.c +++ b/db/bmroot.c @@ -31,6 +31,13 @@ static int rtrmaproot_key_offset(void *obj, int startoff, int idx); static int rtrmaproot_ptr_count(void *obj, int startoff); static int rtrmaproot_ptr_offset(void *obj, int startoff, int idx); +static int rtrefcroot_rec_count(void *obj, int startoff); +static int rtrefcroot_rec_offset(void *obj, int startoff, int idx); +static int rtrefcroot_key_count(void *obj, int startoff); +static int rtrefcroot_key_offset(void *obj, int startoff, int idx); +static int rtrefcroot_ptr_count(void *obj, int startoff); +static int rtrefcroot_ptr_offset(void *obj, int startoff, int idx); + #define OFF(f) bitize(offsetof(xfs_bmdr_block_t, bb_ ## f)) const field_t bmroota_flds[] = { { "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE }, @@ -73,6 +80,19 @@ const field_t rtrmaproot_flds[] = { FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_RTRMAPBT }, { NULL } }; + +/* realtime refcount btree root */ +const field_t rtrefcroot_flds[] = { + { "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE }, + { "numrecs", FLDT_UINT16D, OI(OFF(numrecs)), C1, 0, TYP_NONE }, + { "recs", FLDT_RTREFCBTREC, rtrefcroot_rec_offset, rtrefcroot_rec_count, + FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, + { "keys", FLDT_RTREFCBTKEY, rtrefcroot_key_offset, rtrefcroot_key_count, + FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, + { "ptrs", FLDT_RTREFCBTPTR, rtrefcroot_ptr_offset, rtrefcroot_ptr_count, + FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_RTREFCBT }, + { NULL } +}; #undef OFF static int @@ -390,3 +410,131 @@ rtrmaproot_size( dip = obj; return bitize((int)XFS_DFORK_DSIZE(dip, mp)); } + +/* realtime refcount root */ +static int +rtrefcroot_rec_count( + void *obj, + int startoff) +{ + struct xfs_rtrefcount_root *block; +#ifdef DEBUG + struct xfs_dinode *dip = obj; +#endif + + ASSERT(bitoffs(startoff) == 0); + ASSERT(obj == iocur_top->data); + block = (struct xfs_rtrefcount_root *)((char *)obj + byteize(startoff)); + ASSERT((char *)block == XFS_DFORK_DPTR(dip)); + if (be16_to_cpu(block->bb_level) > 0) + return 0; + return be16_to_cpu(block->bb_numrecs); +} + +static int +rtrefcroot_rec_offset( + void *obj, + int startoff, + int idx) +{ + struct xfs_rtrefcount_root *block; + struct xfs_refcount_rec *kp; + + ASSERT(bitoffs(startoff) == 0); + ASSERT(obj == iocur_top->data); + block = (struct xfs_rtrefcount_root *)((char *)obj + byteize(startoff)); + ASSERT(be16_to_cpu(block->bb_level) == 0); + kp = xfs_rtrefcount_droot_rec_addr(block, idx); + return bitize((int)((char *)kp - (char *)block)); +} + +static int +rtrefcroot_key_count( + void *obj, + int startoff) +{ + struct xfs_rtrefcount_root *block; +#ifdef DEBUG + struct xfs_dinode *dip = obj; +#endif + + ASSERT(bitoffs(startoff) == 0); + ASSERT(obj == iocur_top->data); + block = (struct xfs_rtrefcount_root *)((char *)obj + byteize(startoff)); + ASSERT((char *)block == XFS_DFORK_DPTR(dip)); + if (be16_to_cpu(block->bb_level) == 0) + return 0; + return be16_to_cpu(block->bb_numrecs); +} + +static int +rtrefcroot_key_offset( + void *obj, + int startoff, + int idx) +{ + struct xfs_rtrefcount_root *block; + struct xfs_refcount_key *kp; + + ASSERT(bitoffs(startoff) == 0); + ASSERT(obj == iocur_top->data); + block = (struct xfs_rtrefcount_root *)((char *)obj + byteize(startoff)); + ASSERT(be16_to_cpu(block->bb_level) > 0); + kp = xfs_rtrefcount_droot_key_addr(block, idx); + return bitize((int)((char *)kp - (char *)block)); +} + +static int +rtrefcroot_ptr_count( + void *obj, + int startoff) +{ + struct xfs_rtrefcount_root *block; +#ifdef DEBUG + struct xfs_dinode *dip = obj; +#endif + + ASSERT(bitoffs(startoff) == 0); + ASSERT(obj == iocur_top->data); + block = (struct xfs_rtrefcount_root *)((char *)obj + byteize(startoff)); + ASSERT((char *)block == XFS_DFORK_DPTR(dip)); + if (be16_to_cpu(block->bb_level) == 0) + return 0; + return be16_to_cpu(block->bb_numrecs); +} + +static int +rtrefcroot_ptr_offset( + void *obj, + int startoff, + int idx) +{ + struct xfs_rtrefcount_root *block; + xfs_rtrefcount_ptr_t *pp; + struct xfs_dinode *dip; + int dmxr; + + ASSERT(bitoffs(startoff) == 0); + ASSERT(obj == iocur_top->data); + dip = obj; + block = (struct xfs_rtrefcount_root *)((char *)obj + byteize(startoff)); + ASSERT(be16_to_cpu(block->bb_level) > 0); + dmxr = libxfs_rtrefcountbt_droot_maxrecs(XFS_DFORK_DSIZE(dip, mp), false); + pp = xfs_rtrefcount_droot_ptr_addr(block, idx, dmxr); + return bitize((int)((char *)pp - (char *)block)); +} + +int +rtrefcroot_size( + void *obj, + int startoff, + int idx) +{ + struct xfs_dinode *dip; + + ASSERT(bitoffs(startoff) == 0); + ASSERT(obj == iocur_top->data); + ASSERT(idx == 0); + dip = obj; + return bitize((int)XFS_DFORK_DSIZE(dip, mp)); +} diff --git a/db/bmroot.h b/db/bmroot.h index a2c5cfb18f0bb2..70bc8483cd85bc 100644 --- a/db/bmroot.h +++ b/db/bmroot.h @@ -9,7 +9,9 @@ extern const struct field bmroota_key_flds[]; extern const struct field bmrootd_flds[]; extern const struct field bmrootd_key_flds[]; extern const struct field rtrmaproot_flds[]; +extern const struct field rtrefcroot_flds[]; extern int bmroota_size(void *obj, int startoff, int idx); extern int bmrootd_size(void *obj, int startoff, int idx); extern int rtrmaproot_size(void *obj, int startoff, int idx); +extern int rtrefcroot_size(void *obj, int startoff, int idx); diff --git a/db/btblock.c b/db/btblock.c index 70f6c3f6aedde5..40913a094375aa 100644 --- a/db/btblock.c +++ b/db/btblock.c @@ -104,6 +104,12 @@ static struct xfs_db_btree { sizeof(struct xfs_refcount_rec), sizeof(__be32), }, + { XFS_RTREFC_CRC_MAGIC, + XFS_BTREE_LBLOCK_CRC_LEN, + sizeof(struct xfs_refcount_key), + sizeof(struct xfs_refcount_rec), + sizeof(__be64), + }, { 0, }, }; @@ -962,3 +968,47 @@ const field_t refcbt_rec_flds[] = { { NULL } }; #undef ROFF + +/* realtime refcount btree blocks */ +const field_t rtrefcbt_crc_hfld[] = { + { "", FLDT_RTREFCBT_CRC, OI(0), C1, 0, TYP_NONE }, + { NULL } +}; + +#define OFF(f) bitize(offsetof(struct xfs_btree_block, bb_ ## f)) +const field_t rtrefcbt_crc_flds[] = { + { "magic", FLDT_UINT32X, OI(OFF(magic)), C1, 0, TYP_NONE }, + { "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE }, + { "numrecs", FLDT_UINT16D, OI(OFF(numrecs)), C1, 0, TYP_NONE }, + { "leftsib", FLDT_DFSBNO, OI(OFF(u.l.bb_leftsib)), C1, 0, TYP_RTREFCBT }, + { "rightsib", FLDT_DFSBNO, OI(OFF(u.l.bb_rightsib)), C1, 0, TYP_RTREFCBT }, + { "bno", FLDT_DFSBNO, OI(OFF(u.l.bb_blkno)), C1, 0, TYP_REFCBT }, + { "lsn", FLDT_UINT64X, OI(OFF(u.l.bb_lsn)), C1, 0, TYP_NONE }, + { "uuid", FLDT_UUID, OI(OFF(u.l.bb_uuid)), C1, 0, TYP_NONE }, + { "owner", FLDT_INO, OI(OFF(u.l.bb_owner)), C1, 0, TYP_NONE }, + { "crc", FLDT_CRC, OI(OFF(u.l.bb_crc)), C1, 0, TYP_NONE }, + { "recs", FLDT_RTREFCBTREC, btblock_rec_offset, btblock_rec_count, + FLD_ARRAY | FLD_ABASE1 | FLD_COUNT | FLD_OFFSET, TYP_NONE }, + { "keys", FLDT_RTREFCBTKEY, btblock_key_offset, btblock_key_count, + FLD_ARRAY | FLD_ABASE1 | FLD_COUNT | FLD_OFFSET, TYP_NONE }, + { "ptrs", FLDT_RTREFCBTPTR, btblock_ptr_offset, btblock_key_count, + FLD_ARRAY | FLD_ABASE1 | FLD_COUNT | FLD_OFFSET, TYP_RTREFCBT }, + { NULL } +}; +#undef OFF + +const field_t rtrefcbt_key_flds[] = { + { "startblock", FLDT_CRGBLOCK, OI(REFCNTBT_STARTBLOCK_BITOFF), C1, 0, TYP_DATA }, + { "cowflag", FLDT_CCOWFLG, OI(REFCNTBT_COWFLAG_BITOFF), C1, 0, TYP_DATA }, + { NULL } +}; + +#define ROFF(f) bitize(offsetof(struct xfs_refcount_rec, rc_ ## f)) +const field_t rtrefcbt_rec_flds[] = { + { "startblock", FLDT_CRGBLOCK, OI(REFCNTBT_STARTBLOCK_BITOFF), C1, 0, TYP_DATA }, + { "blockcount", FLDT_EXTLEN, OI(ROFF(blockcount)), C1, 0, TYP_NONE }, + { "refcount", FLDT_UINT32D, OI(ROFF(refcount)), C1, 0, TYP_DATA }, + { "cowflag", FLDT_CCOWFLG, OI(REFCNTBT_COWFLAG_BITOFF), C1, 0, TYP_DATA }, + { NULL } +}; +#undef ROFF diff --git a/db/btblock.h b/db/btblock.h index b4013ea8073ec6..5bbe857a7effd0 100644 --- a/db/btblock.h +++ b/db/btblock.h @@ -63,4 +63,9 @@ extern const struct field refcbt_crc_hfld[]; extern const struct field refcbt_key_flds[]; extern const struct field refcbt_rec_flds[]; +extern const struct field rtrefcbt_crc_flds[]; +extern const struct field rtrefcbt_crc_hfld[]; +extern const struct field rtrefcbt_key_flds[]; +extern const struct field rtrefcbt_rec_flds[]; + extern int btblock_size(void *obj, int startoff, int idx); diff --git a/db/field.c b/db/field.c index 60c4e16d781f48..62c983fc3d4938 100644 --- a/db/field.c +++ b/db/field.c @@ -214,6 +214,21 @@ const ftattr_t ftattrtab[] = { { FLDT_REFCBTREC, "refcntbtrec", fp_sarray, (char *)refcbt_rec_flds, SI(bitsz(struct xfs_refcount_rec)), 0, NULL, refcbt_rec_flds }, + { FLDT_CRGBLOCK, "crgblock", fp_num, "%u", SI(REFCNTBT_AGBLOCK_BITLEN), + FTARG_DONULL, NULL, NULL }, + { FLDT_RTREFCBT_CRC, "rtrefcntbt", NULL, (char *)rtrefcbt_crc_flds, + btblock_size, FTARG_SIZE, NULL, rtrefcbt_crc_flds }, + { FLDT_RTREFCBTKEY, "rtrefcntbtkey", fp_sarray, + (char *)rtrefcbt_key_flds, SI(bitsz(struct xfs_refcount_key)), 0, + NULL, rtrefcbt_key_flds }, + { FLDT_RTREFCBTPTR, "rtrefcntbtptr", fp_num, "%u", + SI(bitsz(xfs_rtrefcount_ptr_t)), 0, fa_dfsbno, NULL }, + { FLDT_RTREFCBTREC, "rtrefcntbtrec", fp_sarray, + (char *)rtrefcbt_rec_flds, SI(bitsz(struct xfs_refcount_rec)), 0, + NULL, rtrefcbt_rec_flds }, + { FLDT_RTREFCROOT, "rtrefcroot", NULL, (char *)rtrefcroot_flds, + rtrefcroot_size, FTARG_SIZE, NULL, rtrefcroot_flds }, + /* CRC field */ { FLDT_CRC, "crc", fp_crc, "%#x (%s)", SI(bitsz(uint32_t)), 0, NULL, NULL }, diff --git a/db/field.h b/db/field.h index 67b6cb2a798719..27df5a0fcd1bdd 100644 --- a/db/field.h +++ b/db/field.h @@ -93,6 +93,12 @@ typedef enum fldt { FLDT_REFCBTKEY, FLDT_REFCBTPTR, FLDT_REFCBTREC, + FLDT_CRGBLOCK, + FLDT_RTREFCBT_CRC, + FLDT_RTREFCBTKEY, + FLDT_RTREFCBTPTR, + FLDT_RTREFCBTREC, + FLDT_RTREFCROOT, /* CRC field type */ FLDT_CRC, diff --git a/db/inode.c b/db/inode.c index 45368a3343a17a..46f83f18f083ce 100644 --- a/db/inode.c +++ b/db/inode.c @@ -49,6 +49,7 @@ static int inode_u_sfdir2_count(void *obj, int startoff); static int inode_u_sfdir3_count(void *obj, int startoff); static int inode_u_symlink_count(void *obj, int startoff); static int inode_u_rtrmapbt_count(void *obj, int startoff); +static int inode_u_rtrefcbt_count(void *obj, int startoff); static const cmdinfo_t inode_cmd = { "inode", NULL, inode_f, 0, 1, 1, "[inode#]", @@ -236,6 +237,8 @@ const field_t inode_u_flds[] = { TYP_NONE }, { "rtrmapbt", FLDT_RTRMAPROOT, NULL, inode_u_rtrmapbt_count, FLD_COUNT, TYP_NONE }, + { "rtrefcbt", FLDT_RTREFCROOT, NULL, inode_u_rtrefcbt_count, FLD_COUNT, + TYP_NONE }, { NULL } }; @@ -302,7 +305,7 @@ fp_dinode_fmt( static const char *metatype_name[] = { "unknown", "dir", "usrquota", "grpquota", "prjquota", "rtbitmap", - "rtsummary", "rtrmap" + "rtsummary", "rtrmap", "rtrefcount" }; static const int metatype_name_size = ARRAY_SIZE(metatype_name); @@ -722,6 +725,8 @@ inode_next_type(void) return TYP_RGSUMMARY; case XFS_METAFILE_RTRMAP: return TYP_RTRMAPBT; + case XFS_METAFILE_RTREFCOUNT: + return TYP_RTREFCBT; default: return TYP_DATA; } @@ -886,6 +891,21 @@ inode_u_rtrmapbt_count( dip->di_metatype == cpu_to_be16(XFS_METAFILE_RTRMAP); } +static int +inode_u_rtrefcbt_count( + void *obj, + int startoff) +{ + struct xfs_dinode *dip; + + ASSERT(bitoffs(startoff) == 0); + ASSERT(obj == iocur_top->data); + dip = obj; + ASSERT((char *)XFS_DFORK_DPTR(dip) - (char *)dip == byteize(startoff)); + return dip->di_format == XFS_DINODE_FMT_META_BTREE && + dip->di_metatype == cpu_to_be16(XFS_METAFILE_RTREFCOUNT); +} + int inode_u_size( void *obj, diff --git a/db/type.c b/db/type.c index 1dfc33ffb44b87..324f416a49cc4d 100644 --- a/db/type.c +++ b/db/type.c @@ -53,6 +53,7 @@ static const typ_t __typtab[] = { { TYP_RMAPBT, NULL }, { TYP_RTRMAPBT, NULL }, { TYP_REFCBT, NULL }, + { TYP_RTREFCBT, NULL }, { TYP_DATA, "data", handle_block, NULL, NULL, TYP_F_NO_CRC_OFF }, { TYP_DIR2, "dir2", handle_struct, dir2_hfld, NULL, TYP_F_NO_CRC_OFF }, { TYP_DQBLK, "dqblk", handle_struct, dqblk_hfld, NULL, TYP_F_NO_CRC_OFF }, @@ -96,6 +97,8 @@ static const typ_t __typtab_crc[] = { &xfs_rtrmapbt_buf_ops, XFS_BTREE_LBLOCK_CRC_OFF }, { TYP_REFCBT, "refcntbt", handle_struct, refcbt_crc_hfld, &xfs_refcountbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF }, + { TYP_RTREFCBT, "rtrefcntbt", handle_struct, rtrefcbt_crc_hfld, + &xfs_rtrefcountbt_buf_ops, XFS_BTREE_LBLOCK_CRC_OFF }, { TYP_DATA, "data", handle_block, NULL, NULL, TYP_F_NO_CRC_OFF }, { TYP_DIR2, "dir3", handle_struct, dir3_hfld, &xfs_dir3_db_buf_ops, TYP_F_CRC_FUNC, xfs_dir3_set_crc }, @@ -148,6 +151,8 @@ static const typ_t __typtab_spcrc[] = { &xfs_rtrmapbt_buf_ops, XFS_BTREE_LBLOCK_CRC_OFF }, { TYP_REFCBT, "refcntbt", handle_struct, refcbt_crc_hfld, &xfs_refcountbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF }, + { TYP_RTREFCBT, "rtrefcntbt", handle_struct, rtrefcbt_crc_hfld, + &xfs_rtrefcountbt_buf_ops, XFS_BTREE_LBLOCK_CRC_OFF }, { TYP_DATA, "data", handle_block, NULL, NULL, TYP_F_NO_CRC_OFF }, { TYP_DIR2, "dir3", handle_struct, dir3_hfld, &xfs_dir3_db_buf_ops, TYP_F_CRC_FUNC, xfs_dir3_set_crc }, diff --git a/db/type.h b/db/type.h index c98f3640202e87..a2488a663dbd79 100644 --- a/db/type.h +++ b/db/type.h @@ -22,6 +22,7 @@ typedef enum typnm TYP_RMAPBT, TYP_RTRMAPBT, TYP_REFCBT, + TYP_RTREFCBT, TYP_DATA, TYP_DIR2, TYP_DQBLK, diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index df24f36f0d2874..167df04df8fb1b 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -319,6 +319,10 @@ #define xfs_update_rtsb libxfs_update_rtsb #define xfs_rtgroup_get libxfs_rtgroup_get #define xfs_rtgroup_put libxfs_rtgroup_put + +#define xfs_rtrefcountbt_droot_maxrecs libxfs_rtrefcountbt_droot_maxrecs +#define xfs_rtrefcountbt_maxrecs libxfs_rtrefcountbt_maxrecs + #define xfs_rtrmapbt_calc_reserves libxfs_rtrmapbt_calc_reserves #define xfs_rtrmapbt_calc_size libxfs_rtrmapbt_calc_size #define xfs_rtrmapbt_commit_staged_btree libxfs_rtrmapbt_commit_staged_btree diff --git a/man/man8/xfs_db.8 b/man/man8/xfs_db.8 index 784aa3cb46c588..8326bddcef8378 100644 --- a/man/man8/xfs_db.8 +++ b/man/man8/xfs_db.8 @@ -1308,7 +1308,7 @@ .SH COMMANDS .BR agf ", " agfl ", " agi ", " attr ", " bmapbta ", " bmapbtd , .BR bnobt ", " cntbt ", " data ", " dir ", " dir2 ", " dqblk , .BR inobt ", " inode ", " log ", " refcntbt ", " rmapbt ", " rtbitmap , -.BR rtsummary ", " sb ", " symlink ", " rtrmapbt ", and " text . +.BR rtsummary ", " sb ", " symlink ", " rtrmapbt ", " rtrefcbt ", and " text . See the TYPES section below for more information on these data types. .TP .BI "timelimit [" OPTIONS ] @@ -2402,6 +2402,52 @@ .SH TYPES .PD .RE .TP +.B rtrefcbt +There is one reference count Btree for the entire realtime device. The +.BR startblock " and " +.B blockcount +fields are 32 bits wide and record block counts within a realtime group. +The root of this Btree is the realtime refcount inode, which is recorded in the +metadata directory. +Blocks are linked to sibling left and right blocks at each level, as well as by +pointers from parent to child blocks. +Each block has the following fields: +.RS 1.4i +.PD 0 +.TP 1.2i +.B magic +RTREFC block magic number, 0x52434e54 ('RCNT'). +.TP +.B level +level number of this block, 0 is a leaf. +.TP +.B numrecs +number of data entries in the block. +.TP +.B leftsib +left (logically lower) sibling block, 0 if none. +.TP +.B rightsib +right (logically higher) sibling block, 0 if none. +.TP +.B recs +[leaf blocks only] array of reference count records. Each record contains +.BR startblock , +.BR blockcount , +and +.BR refcount . +.TP +.B keys +[non-leaf blocks only] array of key records. These are the first value +of each block in the level below this one. Each record contains +.BR startblock . +.TP +.B ptrs +[non-leaf blocks only] array of child block pointers. Each pointer is a +block number within the allocation group to the next level in the Btree. +.PD +.RE +.TP .B rmapbt There is one set of filesystem blocks forming the reverse mapping Btree for each allocation group. The root block of this Btree is designated by the From patchwork Thu Feb 6 22:58:35 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13964057 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 35C892417C7 for ; Thu, 6 Feb 2025 22:58:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882716; cv=none; b=AEXeRdaF2w0UJP/DhuieJG/+GfMtfSJRJ12D3kRdw9YpGhThOlQckzes2KUqr2ddWxPianrvwTeIuA6SqMnfQ9Acspw6OFOp4F+UZUn8CTOH1CrsQDgzvtmrZpJguync8Bm2RDbCmK4jkBqbNr0zQ5yVpvrSCaBDzZI0qMLrJfE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882716; c=relaxed/simple; bh=nOV+cSI4wsstJSOX4eqyWbozoKJgzsu+h1bg9yd8qqE=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=A+BbWTHYXyrJaKcg77okhQAn0ncUxRwgReKYi2u+hPzhiNonIp/3tD+n872QFPD4YKQYO6c+osUNlUsymtCsLcVMoX8UXn/EaG0wFWGFZVDg+JvTd0X+schwk2Nr7MqAxzES3hqpaw5NN4ce77kcKGQLVDGbOnvFdvTWuOjkYXE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=K5uHiaPC; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="K5uHiaPC" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0931CC4CEDD; Thu, 6 Feb 2025 22:58:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882716; bh=nOV+cSI4wsstJSOX4eqyWbozoKJgzsu+h1bg9yd8qqE=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=K5uHiaPCMoK7nvSdLR2raGeFiyh8iXf4eq8tX+sf5Po26zsK/nl8M2h2QpRsOG8iv 93TBVljexob3harSiEdEdJF7c5VF/o+XCq2kdnB2SMm8/Kp6XOEBpVxp0GQNvovMMO 9wMzbFBANgZCViqIltRtj7wsIszZiahkKRBW4GdSvp2MF1UVhJjX6LR8xifLZXWA6k sOEVFyxvQB1rvpofO9L1ibmO+NfaOSCk8eNTCpoAdkoejxXhSzC3USXAz5ZLiwQPQv 4FGMSQBe5FY8ajjafih8bRPVp80TqfNllx9DZf2aMcEm2MYZcCj4+H43XWPhqBb1DO bgOtE4vRbLc+g== Date: Thu, 06 Feb 2025 14:58:35 -0800 Subject: [PATCH 07/22] xfs_db: support the realtime refcountbt From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888089041.2741962.5577654086707722081.stgit@frogsfrogsfrogs> In-Reply-To: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> References: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Wire up various parts of xfs_db for realtime refcount support so that we can dump the rt refcount btree contents. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- db/btblock.c | 3 +++ db/btdump.c | 8 ++++++++ db/btheight.c | 5 +++++ libxfs/libxfs_api_defs.h | 1 + man/man8/xfs_db.8 | 1 + 5 files changed, 18 insertions(+) diff --git a/db/btblock.c b/db/btblock.c index 40913a094375aa..e9e5d2f86b9f01 100644 --- a/db/btblock.c +++ b/db/btblock.c @@ -159,6 +159,9 @@ block_to_bt( case TYP_REFCBT: magic = crc ? XFS_REFC_CRC_MAGIC : 0; break; + case TYP_RTREFCBT: + magic = crc ? XFS_RTREFC_CRC_MAGIC : 0; + break; default: ASSERT(0); } diff --git a/db/btdump.c b/db/btdump.c index 55301d25de10cd..29ff28f1639977 100644 --- a/db/btdump.c +++ b/db/btdump.c @@ -456,6 +456,7 @@ dump_btree_inode( char *prefix; struct xfs_dinode *dip = iocur_top->data; struct xfs_rtrmap_root *rtrmap; + struct xfs_rtrefcount_root *rtrefc; int level; int numrecs; int ret; @@ -467,6 +468,12 @@ dump_btree_inode( level = be16_to_cpu(rtrmap->bb_level); numrecs = be16_to_cpu(rtrmap->bb_numrecs); break; + case XFS_METAFILE_RTREFCOUNT: + prefix = "u3.rtrefcbt"; + rtrefc = (struct xfs_rtrefcount_root *)XFS_DFORK_DPTR(dip); + level = be16_to_cpu(rtrefc->bb_level); + numrecs = be16_to_cpu(rtrefc->bb_numrecs); + break; default: dbprintf("Unknown metadata inode btree type %u\n", be16_to_cpu(dip->di_metatype)); @@ -549,6 +556,7 @@ btdump_f( case TYP_BMAPBTA: case TYP_BMAPBTD: case TYP_RTRMAPBT: + case TYP_RTREFCBT: return dump_btree_long(iflag); case TYP_INODE: if (is_btree_inode()) diff --git a/db/btheight.c b/db/btheight.c index 31dff1c924a2e0..14081c969a922c 100644 --- a/db/btheight.c +++ b/db/btheight.c @@ -58,6 +58,11 @@ struct btmap { .maxlevels = libxfs_rtrmapbt_maxlevels_ondisk, .maxrecs = libxfs_rtrmapbt_maxrecs, }, + { + .tag = "rtrefcountbt", + .maxlevels = libxfs_rtrefcountbt_maxlevels_ondisk, + .maxrecs = libxfs_rtrefcountbt_maxrecs, + }, }; static void diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index 167df04df8fb1b..87a598f346f86a 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -321,6 +321,7 @@ #define xfs_rtgroup_put libxfs_rtgroup_put #define xfs_rtrefcountbt_droot_maxrecs libxfs_rtrefcountbt_droot_maxrecs +#define xfs_rtrefcountbt_maxlevels_ondisk libxfs_rtrefcountbt_maxlevels_ondisk #define xfs_rtrefcountbt_maxrecs libxfs_rtrefcountbt_maxrecs #define xfs_rtrmapbt_calc_reserves libxfs_rtrmapbt_calc_reserves diff --git a/man/man8/xfs_db.8 b/man/man8/xfs_db.8 index 8326bddcef8378..08f38f37ca01cc 100644 --- a/man/man8/xfs_db.8 +++ b/man/man8/xfs_db.8 @@ -536,6 +536,7 @@ .SH COMMANDS .IR bmapbt , .IR refcountbt , .IR rmapbt , +.IR rtrefcountbt , and .IR rtrmapbt . The magic value From patchwork Thu Feb 6 22:58:51 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13964058 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 39BF72417CA for ; Thu, 6 Feb 2025 22:58:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882732; cv=none; b=szQEXJYOzoBpq6klCTLDUnnooFLStZ4KC/4jJ6n/oMs2KN6uRw7VMv9dIN53zdonvEe5Y6W03DeNtifs5rRWyI2wTfMVVj7wZ1GeGe4lieVHI38lQg8ta0yApjZwfzMiUArYyCPXz4nkk9a19jvt+3MqvUoCJ0gI3gNE7KVVzF4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882732; c=relaxed/simple; bh=qoy2NNl35N1xqgpuYFJXMBIkZv6ESGy/uF0yWBljZg4=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=r2F/0EHJlkX/CrXPu4hnGIkxxnqnbaOUt8Tk8aMI6Xa1+AxfpD1e04mqx3MxK40cUC+0vF8lVzc4WBlAKl6t0FJRNpFqXnipSTsMVVnmny7vs18bSBeCOx92teKi9Q9QXzpblp0/JJdSezdN5COM6GbcEARW77j5ERID0kyt/d4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MZ78ZYNL; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="MZ78ZYNL" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A25B1C4CEDD; Thu, 6 Feb 2025 22:58:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882731; bh=qoy2NNl35N1xqgpuYFJXMBIkZv6ESGy/uF0yWBljZg4=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=MZ78ZYNLU1tIorGFNEathUtRcz6SJYLL9rHXxe71IygICTqmsRrA2cI3srtznZ1kX fTISrDyg6sBVGYMYi/owj69vqIJAOvGDrPPU0ZIq6E3u2PMB6zfrF3C2foUcKvtcNF 6CZ3Dwl/cikC05LM66jaUQvRrjSFaxU4HBJNH+nTOg1b8Aw1wJgih5obfcJkkn586+ UmchhEhURqgcLf/tMWLEV7fIAfMGtju3zlU4YMFFuEI+K4Rclp3b/uFLFKmEIB+qws Rjo7nQlPaxpf3JPFWKIL9iQKE5bzRoNJ0f3R657S7wauovAFRgyC5PLItMXrvLN4ge Pf7rhdii72dHQ== Date: Thu, 06 Feb 2025 14:58:51 -0800 Subject: [PATCH 08/22] xfs_db: copy the realtime refcount btree From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888089055.2741962.11135146687529271423.stgit@frogsfrogsfrogs> In-Reply-To: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> References: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Copy the realtime refcountbt when we're metadumping the filesystem. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- db/metadump.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/db/metadump.c b/db/metadump.c index aa946746cdfa68..3e00e6de817752 100644 --- a/db/metadump.c +++ b/db/metadump.c @@ -710,6 +710,55 @@ copy_refcount_btree( return scan_btree(agno, root, levels, TYP_REFCBT, agf, scanfunc_refcntbt); } +static int +scanfunc_rtrefcbt( + struct xfs_btree_block *block, + xfs_agnumber_t agno, + xfs_agblock_t agbno, + int level, + typnm_t btype, + void *arg) +{ + xfs_rtrefcount_ptr_t *pp; + int i; + int numrecs; + + if (level == 0) + return 1; + + numrecs = be16_to_cpu(block->bb_numrecs); + if (numrecs > mp->m_rtrefc_mxr[1]) { + if (metadump.show_warnings) + print_warning("invalid numrecs (%u) in %s block %u/%u", + numrecs, typtab[btype].name, agno, agbno); + return 1; + } + + pp = xfs_rtrefcount_ptr_addr(block, 1, mp->m_rtrefc_mxr[1]); + for (i = 0; i < numrecs; i++) { + xfs_agnumber_t pagno; + xfs_agblock_t pbno; + + pagno = XFS_FSB_TO_AGNO(mp, get_unaligned_be64(&pp[i])); + pbno = XFS_FSB_TO_AGBNO(mp, get_unaligned_be64(&pp[i])); + + if (pbno == 0 || pbno > mp->m_sb.sb_agblocks || + pagno > mp->m_sb.sb_agcount) { + if (metadump.show_warnings) + print_warning("invalid block number (%u/%u) " + "in inode %llu %s block %u/%u", + pagno, pbno, + (unsigned long long)metadump.cur_ino, + typtab[btype].name, agno, agbno); + continue; + } + if (!scan_btree(pagno, pbno, level, btype, arg, + scanfunc_rtrefcbt)) + return 0; + } + return 1; +} + /* filename and extended attribute obfuscation routines */ struct name_ent { @@ -2437,6 +2486,69 @@ process_rtrmap( return 1; } +static int +process_rtrefc( + struct xfs_dinode *dip) +{ + int whichfork = XFS_DATA_FORK; + struct xfs_rtrefcount_root *dib = + (struct xfs_rtrefcount_root *)XFS_DFORK_PTR(dip, whichfork); + int level = be16_to_cpu(dib->bb_level); + int nrecs = be16_to_cpu(dib->bb_numrecs); + typnm_t btype = TYP_RTREFCBT; + int maxrecs; + xfs_rtrefcount_ptr_t *pp; + int i; + + if (level > mp->m_rtrefc_maxlevels) { + if (metadump.show_warnings) + print_warning("invalid level (%u) in inode %lld %s " + "root", level, + (unsigned long long)metadump.cur_ino, + typtab[btype].name); + return 1; + } + + if (level == 0) + return 1; + + maxrecs = libxfs_rtrefcountbt_droot_maxrecs( + XFS_DFORK_SIZE(dip, mp, whichfork), + false); + if (nrecs > maxrecs) { + if (metadump.show_warnings) + print_warning("invalid numrecs (%u) in inode %lld %s " + "root", nrecs, + (unsigned long long)metadump.cur_ino, + typtab[btype].name); + return 1; + } + + pp = xfs_rtrefcount_droot_ptr_addr(dib, 1, maxrecs); + for (i = 0; i < nrecs; i++) { + xfs_agnumber_t ag; + xfs_agblock_t bno; + + ag = XFS_FSB_TO_AGNO(mp, get_unaligned_be64(&pp[i])); + bno = XFS_FSB_TO_AGBNO(mp, get_unaligned_be64(&pp[i])); + + if (bno == 0 || bno > mp->m_sb.sb_agblocks || + ag > mp->m_sb.sb_agcount) { + if (metadump.show_warnings) + print_warning("invalid block number (%u/%u) " + "in inode %llu %s root", ag, + bno, + (unsigned long long)metadump.cur_ino, + typtab[btype].name); + continue; + } + + if (!scan_btree(ag, bno, level, btype, NULL, scanfunc_rtrefcbt)) + return 0; + } + return 1; +} + static int process_inode_data( struct xfs_dinode *dip) @@ -2483,6 +2595,8 @@ process_inode_data( switch (be16_to_cpu(dip->di_metatype)) { case XFS_METAFILE_RTRMAP: return process_rtrmap(dip); + case XFS_METAFILE_RTREFCOUNT: + return process_rtrefc(dip); default: return 1; } From patchwork Thu Feb 6 22:59:06 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13964059 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CE1B92417CA for ; Thu, 6 Feb 2025 22:59:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882747; cv=none; b=ChbMNqe7LeJ4rhhGzTnN/CqbhDR/TspaGMMBUh9reO5kY+cEf5aq6PKKsWX28vU+11hMWtZCN5NFF+JQ6clIq7bbDDlsLdTd2ZT7HTRsYkDEc1RthpuyQLQT8YDjKq9VIJoSKd7mrMGmfKC8bapnszlKiAbAm1K4D02r7TDrpqw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882747; c=relaxed/simple; bh=f6RldL/JDT0hNZNrxFZq+1iMC7iRtjXMKx3HL07lYxg=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=fGyx7w6Be99Hk/H6mR1Cala2uBQ6qDspjPEZJe9hy+C2oEUlgkwQni439T9F7aAXCYsBx4dIXMVSJAFy/FJXLZZvlBqwfX7xhk9V8YJFCys8OgiIK2gxkyOps+kPdyvbzQtsPAxIDQUR+au4/7bjNM5Zkp1JGYf4R/22jLA0Jvc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=HR+RWwud; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="HR+RWwud" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4BB2DC4CEDD; Thu, 6 Feb 2025 22:59:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882747; bh=f6RldL/JDT0hNZNrxFZq+1iMC7iRtjXMKx3HL07lYxg=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=HR+RWwudODRZIDAtS4X/NC3j0w9Tr10anainT6KDo45pthikH9D/VPFasGV/JZ5aU HIWyatiUrgJo6cxfke9D3Mtnrk0F+mkE8lxcaJfXMbruBpHKX2iz8oMSRsKkj1vFPi t+rkfMUsu8NwBvz+3b2qtyQkwAiiduhqCbSv1ElkodBwj6htudSyZqXICfmVUFWdmU hE/oviN9gIi7qVXvsszyB4ej12Ato6r0QtRsz4anNIZsBykWFn14mKydbEh1gwclTK k2kgFrmvGnCK9HJZSEGYHITqoqaTQS5ZOo0RMWzimUeFGLzXF9BeIitXxehHoPknNb RZ6PqyBFgwoXg== Date: Thu, 06 Feb 2025 14:59:06 -0800 Subject: [PATCH 09/22] xfs_db: add rtrefcount reservations to the rgresv command From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888089070.2741962.16480973892880802520.stgit@frogsfrogsfrogs> In-Reply-To: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> References: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Report rt refcount btree reservations in the rgresv subcommand output. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- db/info.c | 13 +++++++++++++ libxfs/libxfs_api_defs.h | 1 + 2 files changed, 14 insertions(+) diff --git a/db/info.c b/db/info.c index ce6f358420a79d..6ad3e23832faa3 100644 --- a/db/info.c +++ b/db/info.c @@ -202,6 +202,19 @@ print_rgresv_info( ask += libxfs_rtrmapbt_calc_reserves(mp); + /* rtrefcount */ + error = -libxfs_rtginode_load(rtg, XFS_RTGI_REFCOUNT, tp); + if (error) { + dbprintf(_("Cannot load rtgroup %u refcount inode, error %d\n"), + rtg_rgno(rtg), error); + goto out_rele_dp; + } + if (rtg_refcount(rtg)) + used += rtg_refcount(rtg)->i_nblocks; + libxfs_rtginode_irele(&rtg->rtg_inodes[XFS_RTGI_REFCOUNT]); + + ask += libxfs_rtrefcountbt_calc_reserves(mp); + printf(_("rtg %d: dblocks: %llu fdblocks: %llu reserved: %llu used: %llu"), rtg_rgno(rtg), (unsigned long long)mp->m_sb.sb_dblocks, diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index 87a598f346f86a..7ce10c408de1a0 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -320,6 +320,7 @@ #define xfs_rtgroup_get libxfs_rtgroup_get #define xfs_rtgroup_put libxfs_rtgroup_put +#define xfs_rtrefcountbt_calc_reserves libxfs_rtrefcountbt_calc_reserves #define xfs_rtrefcountbt_droot_maxrecs libxfs_rtrefcountbt_droot_maxrecs #define xfs_rtrefcountbt_maxlevels_ondisk libxfs_rtrefcountbt_maxlevels_ondisk #define xfs_rtrefcountbt_maxrecs libxfs_rtrefcountbt_maxrecs From patchwork Thu Feb 6 22:59:22 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13964063 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7F1B62417CA for ; Thu, 6 Feb 2025 22:59:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882763; cv=none; b=Eumgi28Y46cAtsXl//SubypBqo43Gz3oqMSV7/oozCMxAMBJjD/odC5k7no/FvyJanvOVdDfDdPPA1brEzvPTaOymYFWPYhwSvENkZvmYRb3TWSjh6YfrCOlM6TbFOX/7hJxyT+0yR6zr+zlof2jHeGuvgInkj98JCRuqvZUr5w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882763; c=relaxed/simple; bh=8wAjtw1BgcgBlJwtKxLngsGeYn0QtP3sZsu15hyP6LE=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=XnMrdJAFDQu1UfxIGg4uyIoZsZq7MMk58yYl0pFYN4snqHx6uFffrbqusDByaVdGnLqeMCK9xCc3UvvW5pjZUVLJjAFVzLEJ3R6CZj6N5ejxMqS9Nx19xki37vNoYXrDcUxeDB4nObZUdETVcw9NcoZaNjk0IrIx//ual/8mXDs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hwEBWOTA; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hwEBWOTA" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EDCAEC4CEDD; Thu, 6 Feb 2025 22:59:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882763; bh=8wAjtw1BgcgBlJwtKxLngsGeYn0QtP3sZsu15hyP6LE=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=hwEBWOTAC3Y+NMPam/uTZLvrmZsR2jxkawrp7dLz+CMV/XnirxZ2GQd3BHEzEek/I ZmzxPP0AauLxhLGiaZ3w/cNdQ3HGYrD8Y2d/EzH+OqTOx/jNXVeJgdRuL5hsIb71Dc FyRYFm2snWLmOrAZDbe/MWW4x0zCJW1MgWy8hkf06Ie46u5meBYZobHQ8se82/DEBa uO7YW+ZBLV2/+R33pTrYEavVxzggCJ4YuV8V6+GhReRYnCrZJgmk6Yw13u46MV/5MV bnxk3lU+yyo6K6kcUN+fWTAdPYHu4NTWPG8Dh6fdv2En1z/DQ09i/8Y6fDwZs98sCH IssqErVN8ar7A== Date: Thu, 06 Feb 2025 14:59:22 -0800 Subject: [PATCH 10/22] xfs_spaceman: report health of the realtime refcount btree From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888089085.2741962.7445820399757044454.stgit@frogsfrogsfrogs> In-Reply-To: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> References: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Report the health of the realtime reference count btree. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- spaceman/health.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/spaceman/health.c b/spaceman/health.c index 5774d609a28de3..efe2a7261de5c4 100644 --- a/spaceman/health.c +++ b/spaceman/health.c @@ -47,6 +47,11 @@ static bool has_rtrmapbt(const struct xfs_fsop_geom *g) return g->rtblocks > 0 && (g->flags & XFS_FSOP_GEOM_FLAGS_RMAPBT); } +static bool has_rtreflink(const struct xfs_fsop_geom *g) +{ + return g->rtblocks > 0 && (g->flags & XFS_FSOP_GEOM_FLAGS_REFLINK); +} + struct flag_map { unsigned int mask; bool (*has_fn)(const struct xfs_fsop_geom *g); @@ -156,6 +161,11 @@ static const struct flag_map rtgroup_flags[] = { .descr = "realtime reverse mappings btree", .has_fn = has_rtrmapbt, }, + { + .mask = XFS_RTGROUP_GEOM_SICK_REFCNTBT, + .descr = "realtime reference count btree", + .has_fn = has_rtreflink, + }, {0}, }; From patchwork Thu Feb 6 22:59:38 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13964064 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B1F572417D5 for ; Thu, 6 Feb 2025 22:59:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882778; cv=none; b=t5KqNdU74DISgyS0zuM4ea5ZNt3ppv0LN7IjpQPSmyA9kwau38ED5Is8D54pwbq5+Pnh5ApgthbWVDFzBaUPpoe9PUiEaYl0FY5FLkG/Hx0/abkOwxyP9FmA+p18GlU06W4tMVfCuTbUiE2PCbECG9s89KUpYQyqNSDnRDSuvQI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882778; c=relaxed/simple; bh=4HCzjCZlDWg/xI1eENdpRt1+Px9HjZ5CfyZxL7L4k4g=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=G0Puxh+x9gFdpbGhYgCcrfYcQpeQvElBBGJ3+g5RpP0ARyccj/uC75Ne2UObpupD1i8OUzgKii3XyIYcBDrYo/KRbXMcFf9kximbeCLrlU9Lp8QDNW3Bt3DRLT8RT0VSu4aL6/8VKu3j5qkOPb90X64nwrF2q+GgwCppB4PA+7s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=pnsqQOZ+; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="pnsqQOZ+" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 87391C4CEDD; Thu, 6 Feb 2025 22:59:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882778; bh=4HCzjCZlDWg/xI1eENdpRt1+Px9HjZ5CfyZxL7L4k4g=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=pnsqQOZ+AY1c/GbgCAlRreY8Wx2xclC0Y4bKSrBHbKC1VHhYKcSvpT3E3FvLvmtGB h5hjGtYLJTJO4OCak+INEELH12sz+9z7d/SNfU2IjlppJa9xtXejopL1mp9HZDDSd0 DRE3DWMzaHCbU7X6o7l92AcVY4h24tvT9bm6k9L8UijGqnWwLsGf5q1eeRgvFGgWka wnFc+t1kIINM8wTw6ylzm4LPb5YBpa/IVwkNdBKEb+x11C1VXijM7dUQWHkPAeri5P 80UdtfFw9qmbj/3P7war++0at/bAoaZ7TY7LsaI82qU1eY9+IhdPWCfQpwz7/1dKOO JXHkvLFdYJCdA== Date: Thu, 06 Feb 2025 14:59:38 -0800 Subject: [PATCH 11/22] xfs_repair: allow CoW staging extents in the realtime rmap records From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888089101.2741962.17270845980448624809.stgit@frogsfrogsfrogs> In-Reply-To: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> References: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Don't flag the rt rmap btree as having errors if there are CoW staging extent records in it and the filesystem supports reflink. As far as reporting leftover staging extents, we'll report them when we scan the rt refcount btree, in a future patch. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- repair/scan.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/repair/scan.c b/repair/scan.c index 7a74f87c5f0c61..7980795e3a6f9f 100644 --- a/repair/scan.c +++ b/repair/scan.c @@ -1407,9 +1407,20 @@ _("invalid length %llu in record %u of %s\n"), continue; } - /* We only store file data and superblocks in the rtrmap. */ - if (XFS_RMAP_NON_INODE_OWNER(owner) && - owner != XFS_RMAP_OWN_FS) { + /* + * We only store file data, COW data, and superblocks in the + * rtrmap. + */ + if (owner == XFS_RMAP_OWN_COW) { + if (!xfs_has_reflink(mp)) { + do_warn( +_("invalid CoW staging extent in record %u of %s\n"), + i, name); + suspect++; + continue; + } + } else if (XFS_RMAP_NON_INODE_OWNER(owner) && + owner != XFS_RMAP_OWN_FS) { do_warn( _("invalid owner %lld in record %u of %s\n"), (long long int)owner, i, name); From patchwork Thu Feb 6 22:59:53 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13964065 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6CBBA2417E3 for ; Thu, 6 Feb 2025 22:59:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882794; cv=none; b=NAUsqOK7wFv68JvR/irmE3a+n3tiamY/qZJSSqBsAmuxx5EldoBlF5Squa0NRPKckUurLF9+JKyDF653jIsTsoqC8u974fIpx0bTVbH8/XW5paOIh6kb/YSWAKrEwCJYT4weDDKiIvwlKqFz24ZCdPFilXAxeTZKm+MrT3vXNig= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882794; c=relaxed/simple; bh=9H2LtOiRbq/J+02nVXkMD+zoQ+XDkhS3g4kQr4eCT0g=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Ts02OlkLlV3d6THXEEH0EqZyuv/aZK+Z0U1km47Q7ndMOLEluqeFrTsLu3hJvpZ5QnqQnWrMTHwEgtqtHa2tXeCbpd7ZGIEVJ9i2vnSH/rLzjfm9XVUFo0U80q6FeNx3pMhR1qAAKYQHdSA/k6qe587FkrRXJPBFLOdnUHFEVgc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=BU3gbFiS; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="BU3gbFiS" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 34334C4CEE7; Thu, 6 Feb 2025 22:59:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882794; bh=9H2LtOiRbq/J+02nVXkMD+zoQ+XDkhS3g4kQr4eCT0g=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=BU3gbFiSKOHN5C2ta0i1nbYsWeN73Jg05xH4RdTL9aX5vA/x4jwy9EwIAd/f34+Ay 4X8LTtnzXKjqgDJkSitqXgPUmVVVoHNIRr9jaoA6tr3YyrBBu6Sco9FFA7jKxzyCGC whlf9ay0LZj7uDLouUdghdBuvtVKpXjjNVvfEUGMdv69YvJJ8bmkwipfdSJ1EGKXAr 0zPrEcLWb4b+BH03PaJ4IM8ijRb7cfsYPArFf1l+kP72wvvkoOL9r1hSMUhhtsWTzO 42rgkbLOKU3o5fKBrgtZJeV8a+aUws92iR7slADg7Ui3qWRKKSXq0aKtYTZ/gNRMj7 1LO+BIKRPPg8A== Date: Thu, 06 Feb 2025 14:59:53 -0800 Subject: [PATCH 12/22] xfs_repair: use realtime refcount btree data to check block types From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888089116.2741962.13761732561620436172.stgit@frogsfrogsfrogs> In-Reply-To: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> References: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Use the realtime refcount btree to pre-populate the block type information so that when repair iterates the primary metadata, we can confirm the block type. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- libxfs/libxfs_api_defs.h | 1 repair/dinode.c | 154 +++++++++++++++++++++++ repair/rt.h | 4 + repair/scan.c | 314 +++++++++++++++++++++++++++++++++++++++++++++- repair/scan.h | 33 +++++ 5 files changed, 500 insertions(+), 6 deletions(-) diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index 7ce10c408de1a0..0dc6f0350dd0f6 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -394,6 +394,7 @@ #define xfs_verify_fsbext libxfs_verify_fsbext #define xfs_verify_fsbno libxfs_verify_fsbno #define xfs_verify_ino libxfs_verify_ino +#define xfs_verify_rgbno libxfs_verify_rgbno #define xfs_verify_rtbno libxfs_verify_rtbno #define xfs_zero_extent libxfs_zero_extent diff --git a/repair/dinode.c b/repair/dinode.c index 3995584a364771..ac5db8b0ea4392 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -308,6 +308,8 @@ _("bad state in rt extent map %" PRIu64 "\n"), break; case XR_E_INUSE: case XR_E_MULT: + if (xfs_has_rtreflink(mp)) + break; set_rtbmap(ext, XR_E_MULT); break; case XR_E_FREE1: @@ -382,6 +384,8 @@ _("data fork in rt inode %" PRIu64 " found rt metadata extent %" PRIu64 " in rt return 1; case XR_E_INUSE: case XR_E_MULT: + if (xfs_has_rtreflink(mp)) + break; do_warn( _("data fork in rt inode %" PRIu64 " claims used rt extent %" PRIu64 "\n"), ino, b); @@ -1083,6 +1087,149 @@ _("bad rtrmap btree ptr 0x%" PRIx64 " in ino %" PRIu64 "\n"), return suspect ? 1 : 0; } +/* + * return 1 if inode should be cleared, 0 otherwise + */ +static int +process_rtrefc( + struct xfs_mount *mp, + xfs_agnumber_t agno, + xfs_agino_t ino, + struct xfs_dinode *dip, + int type, + int *dirty, + xfs_rfsblock_t *tot, + uint64_t *nex, + blkmap_t **blkmapp, + int check_dups) +{ + struct refc_priv priv = { .nr_blocks = 0 }; + struct xfs_rtrefcount_root *dib; + xfs_rtrefcount_ptr_t *pp; + struct xfs_refcount_key *kp; + struct xfs_refcount_rec *rp; + char *forkname = get_forkname(XFS_DATA_FORK); + xfs_rgblock_t oldkey, key; + xfs_ino_t lino; + xfs_fsblock_t bno; + size_t droot_sz; + int i; + int level; + int numrecs; + int dmxr; + int suspect = 0; + int error; + + /* We rebuild the rtrefcountbt, so no need to process blocks again. */ + if (check_dups) { + *tot = be64_to_cpu(dip->di_nblocks); + return 0; + } + + lino = XFS_AGINO_TO_INO(mp, agno, ino); + + /* + * This refcount btree inode must be a metadata inode reachable via + * /rtgroups/$rgno.refcount in the metadata directory tree. + */ + if (!(dip->di_flags2 & be64_to_cpu(XFS_DIFLAG2_METADATA))) { + do_warn( +_("rtrefcount inode %" PRIu64 " not flagged as metadata\n"), + lino); + return 1; + } + + if (!is_rtrefcount_inode(lino)) { + do_warn( +_("could not associate refcount inode %" PRIu64 " with any rtgroup\n"), + lino); + return 1; + } + + priv.rgno = metafile_rgnumber(dip); + + dib = (struct xfs_rtrefcount_root *)XFS_DFORK_PTR(dip, XFS_DATA_FORK); + *tot = 0; + *nex = 0; + + level = be16_to_cpu(dib->bb_level); + numrecs = be16_to_cpu(dib->bb_numrecs); + + if (level > mp->m_rtrefc_maxlevels) { + do_warn( +_("bad level %d in inode %" PRIu64 " rtrefcount btree root block\n"), + level, lino); + return 1; + } + + /* + * use rtroot/dfork_dsize since the root block is in the data fork + */ + droot_sz = xfs_rtrefcount_droot_space_calc(level, numrecs); + if (droot_sz > XFS_DFORK_SIZE(dip, mp, XFS_DATA_FORK)) { + do_warn( +_("computed size of rtrefcountbt root (%zu bytes) is greater than space in " + "inode %" PRIu64 " %s fork\n"), + droot_sz, lino, forkname); + return 1; + } + + if (level == 0) { + rp = xfs_rtrefcount_droot_rec_addr(dib, 1); + error = process_rtrefc_reclist(mp, rp, numrecs, + &priv, "rtrefcountbt root"); + if (error) { + refcount_avoid_check(); + return 1; + } + return 0; + } + + dmxr = libxfs_rtrefcountbt_droot_maxrecs( + XFS_DFORK_SIZE(dip, mp, XFS_DATA_FORK), false); + pp = xfs_rtrefcount_droot_ptr_addr(dib, 1, dmxr); + + /* check for in-order keys */ + for (i = 0; i < numrecs; i++) { + kp = xfs_rtrefcount_droot_key_addr(dib, i + 1); + + key = be32_to_cpu(kp->rc_startblock); + if (i == 0) { + oldkey = key; + continue; + } + if (key < oldkey) { + do_warn( +_("out of order key %u in rtrefcount root ino %" PRIu64 "\n"), + i, lino); + suspect++; + continue; + } + oldkey = key; + } + + /* probe keys */ + for (i = 0; i < numrecs; i++) { + bno = get_unaligned_be64(&pp[i]); + + if (!libxfs_verify_fsbno(mp, bno)) { + do_warn( +_("bad rtrefcount btree ptr 0x%" PRIx64 " in ino %" PRIu64 "\n"), + bno, lino); + return 1; + } + + if (scan_lbtree(bno, level, scan_rtrefcbt, + type, XFS_DATA_FORK, lino, tot, nex, blkmapp, + NULL, 0, 1, check_dups, XFS_RTREFC_CRC_MAGIC, + &priv, &xfs_rtrefcountbt_buf_ops)) + return 1; + } + + *tot = priv.nr_blocks; + return suspect ? 1 : 0; +} + /* * return 1 if inode should be cleared, 0 otherwise */ @@ -1883,6 +2030,7 @@ check_dinode_mode_format( case XFS_DINODE_FMT_META_BTREE: switch (be16_to_cpu(dinoc->di_metatype)) { case XFS_METAFILE_RTRMAP: + case XFS_METAFILE_RTREFCOUNT: return 0; default: return -1; @@ -2333,6 +2481,11 @@ process_inode_data_fork( totblocks, nextents, dblkmap, check_dups); break; + case XFS_METAFILE_RTREFCOUNT: + err = process_rtrefc(mp, agno, ino, dino, type, dirty, + totblocks, nextents, dblkmap, + check_dups); + break; default: do_error( _("unknown meta btree type %d, ino %" PRIu64 " (mode = %d)\n"), @@ -2406,6 +2559,7 @@ _("would have tried to rebuild inode %"PRIu64" data fork\n"), case XFS_DINODE_FMT_META_BTREE: switch (be16_to_cpu(dino->di_metatype)) { case XFS_METAFILE_RTRMAP: + case XFS_METAFILE_RTREFCOUNT: err = 0; break; default: diff --git a/repair/rt.h b/repair/rt.h index 13558706e4ec15..e4f3d5d9af3188 100644 --- a/repair/rt.h +++ b/repair/rt.h @@ -33,6 +33,10 @@ static inline bool is_rtrmap_inode(xfs_ino_t ino) { return is_rtgroup_inode(ino, XFS_RTGI_RMAP); } +static inline bool is_rtrefcount_inode(xfs_ino_t ino) +{ + return is_rtgroup_inode(ino, XFS_RTGI_REFCOUNT); +} void mark_rtgroup_inodes_bad(struct xfs_mount *mp, enum xfs_rtg_inodes type); bool rtgroup_inodes_were_bad(enum xfs_rtg_inodes type); diff --git a/repair/scan.c b/repair/scan.c index 7980795e3a6f9f..21fa9018800c77 100644 --- a/repair/scan.c +++ b/repair/scan.c @@ -1745,12 +1745,6 @@ _("bad %s btree ptr 0x%llx in ino %" PRIu64 "\n"), return 0; } -struct refc_priv { - struct xfs_refcount_irec last_rec; - xfs_agblock_t nr_blocks; -}; - - static void scan_refcbt( struct xfs_btree_block *block, @@ -1990,6 +1984,314 @@ _("extent (%u/%u) len %u claimed, state is %d\n"), return; } + +int +process_rtrefc_reclist( + struct xfs_mount *mp, + struct xfs_refcount_rec *rp, + int numrecs, + struct refc_priv *refc_priv, + const char *name) +{ + struct xfs_rtgroup *rtg; + xfs_rgnumber_t rgno = refc_priv->rgno; + xfs_rtblock_t lastblock = 0; + int state; + int suspect = 0; + int i; + + rtg = libxfs_rtgroup_get(mp, rgno); + if (!rtg) { + if (numrecs) { + do_warn( +_("no rt group 0x%x but %d rtrefcount records\n"), + rgno, numrecs); + suspect++; + } + + return suspect; + } + + for (i = 0; i < numrecs; i++) { + enum xfs_refc_domain domain; + xfs_rgblock_t b, rgbno, end; + xfs_extlen_t len; + xfs_nlink_t nr; + + b = rgbno = be32_to_cpu(rp[i].rc_startblock); + len = be32_to_cpu(rp[i].rc_blockcount); + nr = be32_to_cpu(rp[i].rc_refcount); + + if (b & XFS_REFC_COWFLAG) { + domain = XFS_REFC_DOMAIN_COW; + rgbno &= ~XFS_REFC_COWFLAG; + } else { + domain = XFS_REFC_DOMAIN_SHARED; + } + + if (domain == XFS_REFC_DOMAIN_COW && nr != 1) { + do_warn( +_("leftover rt CoW extent has incorrect refcount in record %u of %s\n"), + i, name); + suspect++; + } + if (nr == 1) { + if (domain != XFS_REFC_DOMAIN_COW) { + do_warn( +_("leftover rt CoW extent has invalid startblock in record %u of %s\n"), + i, name); + suspect++; + } + } + end = rgbno + len; + + if (!libxfs_verify_rgbno(rtg, rgbno)) { + do_warn( +_("invalid start block %llu in record %u of %s\n"), + (unsigned long long)b, i, name); + suspect++; + continue; + } + + if (len == 0 || end <= rgbno || + !libxfs_verify_rgbno(rtg, end - 1)) { + do_warn( +_("invalid length %llu in record %u of %s\n"), + (unsigned long long)len, i, name); + suspect++; + continue; + } + + if (nr < 2 || nr > XFS_REFC_REFCOUNT_MAX) { + do_warn( +_("invalid rt reference count %u in record %u of %s\n"), + nr, i, name); + suspect++; + continue; + } + + if (nr == 1) { + xfs_rgblock_t b; + xfs_extlen_t blen; + + for (b = rgbno; b < end; b += len) { + state = get_bmap_ext(rgno, b, end, &blen, true); + blen = min(blen, len); + + switch (state) { + case XR_E_UNKNOWN: + case XR_E_COW: + do_warn( +_("leftover CoW rtextent (%llu)\n"), + (unsigned long long)rgbno); + set_bmap_ext(rgno, b, len, XR_E_FREE, + true); + break; + default: + do_warn( +_("rtextent (%llu) claimed, state is %d\n"), + (unsigned long long)rgbno, state); + break; + } + suspect++; + } + } + + if (b && b <= lastblock) { + do_warn(_( +"out-of-order %s btree record %d (%llu %llu) in %s\n"), + name, i, (unsigned long long)b, + (unsigned long long)len, name); + suspect++; + } else { + lastblock = end - 1; + } + + /* Is this record mergeable with the last one? */ + if (refc_priv->last_rec.rc_domain == domain && + refc_priv->last_rec.rc_startblock + + refc_priv->last_rec.rc_blockcount == rgbno && + refc_priv->last_rec.rc_refcount == nr) { + do_warn( +_("record %d of %s tree should be merged with previous record\n"), + i, name); + suspect++; + refc_priv->last_rec.rc_blockcount += len; + } else { + refc_priv->last_rec.rc_domain = domain; + refc_priv->last_rec.rc_startblock = rgbno; + refc_priv->last_rec.rc_blockcount = len; + refc_priv->last_rec.rc_refcount = nr; + } + + /* XXX: probably want to mark the reflinked areas? */ + } + + libxfs_rtgroup_put(rtg); + return suspect; +} + +int +scan_rtrefcbt( + struct xfs_btree_block *block, + int level, + int type, + int whichfork, + xfs_fsblock_t fsbno, + xfs_ino_t ino, + xfs_rfsblock_t *tot, + uint64_t *nex, + struct blkmap **blkmapp, + bmap_cursor_t *bm_cursor, + int suspect, + int isroot, + int check_dups, + int *dirty, + uint64_t magic, + void *priv) +{ + const char *name = "rtrefcount"; + char rootname[256]; + int i; + xfs_rtrefcount_ptr_t *pp; + struct xfs_refcount_rec *rp; + struct refc_priv *refc_priv = priv; + int hdr_errors = 0; + int numrecs; + int state; + xfs_agnumber_t agno; + xfs_agblock_t agbno; + int error; + + agno = XFS_FSB_TO_AGNO(mp, fsbno); + agbno = XFS_FSB_TO_AGBNO(mp, fsbno); + + if (magic != XFS_RTREFC_CRC_MAGIC) { + name = "(unknown)"; + hdr_errors++; + suspect++; + goto out; + } + + if (be32_to_cpu(block->bb_magic) != magic) { + do_warn(_("bad magic # %#x in %s btree block %d/%d\n"), + be32_to_cpu(block->bb_magic), name, agno, + agbno); + hdr_errors++; + if (suspect) + goto out; + } + + if (be16_to_cpu(block->bb_level) != level) { + do_warn(_("expected level %d got %d in %s btree block %d/%d\n"), + level, be16_to_cpu(block->bb_level), name, + agno, agbno); + hdr_errors++; + if (suspect) + goto out; + } + + refc_priv->nr_blocks++; + + /* + * Check for btree blocks multiply claimed. We're going to regenerate + * the btree anyway, so mark the blocks as metadata so they get freed. + */ + state = get_bmap(agno, agbno); + if (!(state == XR_E_UNKNOWN || state == XR_E_INUSE1)) { + do_warn( +_("%s btree block claimed (state %d), agno %d, agbno %d, suspect %d\n"), + name, state, agno, agbno, suspect); + goto out; + } + set_bmap(agno, agbno, XR_E_METADATA); + + numrecs = be16_to_cpu(block->bb_numrecs); + if (level == 0) { + if (numrecs > mp->m_rtrefc_mxr[0]) { + numrecs = mp->m_rtrefc_mxr[0]; + hdr_errors++; + } + if (isroot == 0 && numrecs < mp->m_rtrefc_mnr[0]) { + numrecs = mp->m_rtrefc_mnr[0]; + hdr_errors++; + } + + if (hdr_errors) { + do_warn( + _("bad btree nrecs (%u, min=%u, max=%u) in %s btree block %u/%u\n"), + be16_to_cpu(block->bb_numrecs), + mp->m_rtrefc_mnr[0], + mp->m_rtrefc_mxr[0], name, agno, agbno); + suspect++; + } + + rp = xfs_rtrefcount_rec_addr(block, 1); + snprintf(rootname, 256, "%s btree block %u/%u", name, agno, + agbno); + error = process_rtrefc_reclist(mp, rp, numrecs, refc_priv, + rootname); + if (error) + suspect++; + goto out; + } + + /* + * interior record + */ + pp = xfs_rtrefcount_ptr_addr(block, 1, mp->m_rtrefc_mxr[1]); + + if (numrecs > mp->m_rtrefc_mxr[1]) { + numrecs = mp->m_rtrefc_mxr[1]; + hdr_errors++; + } + if (isroot == 0 && numrecs < mp->m_rtrefc_mnr[1]) { + numrecs = mp->m_rtrefc_mnr[1]; + hdr_errors++; + } + + /* + * don't pass bogus tree flag down further if this block + * looked ok. bail out if two levels in a row look bad. + */ + if (hdr_errors) { + do_warn( + _("bad btree nrecs (%u, min=%u, max=%u) in %s btree block %u/%u\n"), + be16_to_cpu(block->bb_numrecs), + mp->m_rtrefc_mnr[1], mp->m_rtrefc_mxr[1], name, + agno, agbno); + if (suspect) + goto out; + suspect++; + } else if (suspect) { + suspect = 0; + } + + for (i = 0; i < numrecs; i++) { + xfs_fsblock_t pbno = be64_to_cpu(pp[i]); + + if (!libxfs_verify_fsbno(mp, pbno)) { + do_warn( + _("bad btree pointer (%u) in %sbt block %u/%u\n"), + agbno, name, agno, agbno); + suspect++; + return 0; + } + + scan_lbtree(pbno, level, scan_rtrefcbt, type, whichfork, ino, + tot, nex, blkmapp, bm_cursor, suspect, 0, + check_dups, magic, refc_priv, + &xfs_rtrefcountbt_buf_ops); + } +out: + if (suspect) { + refcount_avoid_check(); + return 1; + } + + return 0; +} + /* * The following helpers are to help process and validate individual on-disk * inode btree records. We have two possible inode btrees with slightly diff --git a/repair/scan.h b/repair/scan.h index a624c882734c77..1643a2397aeaf5 100644 --- a/repair/scan.h +++ b/repair/scan.h @@ -100,4 +100,37 @@ int scan_rtrmapbt( uint64_t magic, void *priv); +struct refc_priv { + struct xfs_refcount_irec last_rec; + xfs_agblock_t nr_blocks; + xfs_rgnumber_t rgno; +}; + +int +process_rtrefc_reclist( + struct xfs_mount *mp, + struct xfs_refcount_rec *rp, + int numrecs, + struct refc_priv *refc_priv, + const char *name); + +int +scan_rtrefcbt( + struct xfs_btree_block *block, + int level, + int type, + int whichfork, + xfs_fsblock_t bno, + xfs_ino_t ino, + xfs_rfsblock_t *tot, + uint64_t *nex, + struct blkmap **blkmapp, + bmap_cursor_t *bm_cursor, + int suspect, + int isroot, + int check_dups, + int *dirty, + uint64_t magic, + void *priv); + #endif /* _XR_SCAN_H */ From patchwork Thu Feb 6 23:00:09 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13964066 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 76EDD2417EA for ; Thu, 6 Feb 2025 23:00:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882811; cv=none; b=NK07kggJuAb1pQCdKeRgrEZP6cJo4u82deeoLXeHtOO9z/51O8BkHq2xlQxY1yGGdQ/+iUpXsUY3MejeMELx+5L1x81YNNI5M4FODtno6minZyvcOhzi+xLM+3Y0YcNBX4RCmQvhS75lzdlQwr0JfqobLpdAvyDYb3E0/IX/U8A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882811; c=relaxed/simple; bh=VpwfUgYL2uM7O5yMtjsc1b+/o7boGpg2n+o0G9AXVpY=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=hHLaFZdrvbqlXNBWhNytJGRXDA60KenXPoXjnGdycZPmiRzb4076hFd5nHkTFF8MA5ob95TnIJXmvV8+uNk1zzjQw1mR79voR9n1GwQbsS4edxyGNZ/2v3pMvWO9FZqBPUwj5eaESVkMPxksoRcTFybeNxjPeCEuJvhjbEHEvC4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=T8D8EaXB; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="T8D8EaXB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D28D9C4CEE0; Thu, 6 Feb 2025 23:00:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882809; bh=VpwfUgYL2uM7O5yMtjsc1b+/o7boGpg2n+o0G9AXVpY=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=T8D8EaXBIFcPf1hZe00mGBUizydwXZF/g/3zvV6E+xiUYB2yAw1NQRVCXoYqn20uy lEBqgrY+KmfBI/sdWbps8ErWz7SGxIgtdIDZ35azBDH44/MzHZENZ2E+DRdcGzcck7 TROFsFnsHzZQVmi1ai+6xPcxnwuXsQh4zvhcfFqJ7br/Daulozhe9lWCjf/hbW39Tf BIkPQmt/9QaLYKxCTZALAvHUlzVtkiZ8MCxM27CbT3R+aBgTV9CElH/vTH8XSCtjZS zBmlUe0aokL3nYRkBIp7OamvxG8CVzHxE2gdpOGC8/wMWCs67bFgkpb2Qd6eI4PfBb yGnjzh7LucyLw== Date: Thu, 06 Feb 2025 15:00:09 -0800 Subject: [PATCH 13/22] xfs_repair: find and mark the rtrefcountbt inode From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888089131.2741962.15415300047895957138.stgit@frogsfrogsfrogs> In-Reply-To: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> References: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Make sure that we find the realtime refcountbt inode and mark it appropriately, just in case we find a rogue inode claiming to be an rtrefcount, or just plain garbage in the superblock field. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- repair/dino_chunks.c | 11 +++++++++++ repair/dinode.c | 49 +++++++++++++++++++++++++++++++++++++++++-------- repair/dir2.c | 5 +++++ repair/incore.h | 1 + repair/rmap.c | 5 ++++- repair/rmap.h | 2 +- repair/scan.c | 8 ++++---- 7 files changed, 67 insertions(+), 14 deletions(-) diff --git a/repair/dino_chunks.c b/repair/dino_chunks.c index 8c5387cdf4ea52..250985ec264ead 100644 --- a/repair/dino_chunks.c +++ b/repair/dino_chunks.c @@ -1036,6 +1036,17 @@ process_inode_chunk( _("would clear rtgroup rmap inode %" PRIu64 "\n"), ino); } + } else if (is_rtrefcount_inode(ino)) { + refcount_avoid_check(mp); + if (!no_modify) { + do_warn( + _("cleared rtgroup refcount inode %" PRIu64 "\n"), + ino); + } else { + do_warn( + _("would clear rtgroup refcount inode %" PRIu64 "\n"), + ino); + } } else if (!no_modify) { do_warn(_("cleared inode %" PRIu64 "\n"), ino); diff --git a/repair/dinode.c b/repair/dinode.c index ac5db8b0ea4392..3260df94511ed2 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -181,6 +181,9 @@ clear_dinode( if (is_rtrmap_inode(ino_num)) rmap_avoid_check(mp); + + if (is_rtrefcount_inode(ino_num)) + refcount_avoid_check(mp); } /* @@ -1139,14 +1142,27 @@ _("rtrefcount inode %" PRIu64 " not flagged as metadata\n"), return 1; } - if (!is_rtrefcount_inode(lino)) { - do_warn( -_("could not associate refcount inode %" PRIu64 " with any rtgroup\n"), - lino); - return 1; - } - + /* + * If this rtrefcount file claims to be from an rtgroup that actually + * exists, check that inode discovery actually found it. Note that + * we can have stray rtrefcount files from failed growfsrt operations. + */ priv.rgno = metafile_rgnumber(dip); + if (priv.rgno < mp->m_sb.sb_rgcount) { + if (type != XR_INO_RTREFC) { + do_warn( +_("rtrefcount inode %" PRIu64 " was not found in the metadata directory tree\n"), + lino); + return 1; + } + + if (!is_rtrefcount_inode(lino)) { + do_warn( +_("could not associate refcount inode %" PRIu64 " with any rtgroup\n"), + lino); + return 1; + } + } dib = (struct xfs_rtrefcount_root *)XFS_DFORK_PTR(dip, XFS_DATA_FORK); *tot = 0; @@ -1179,7 +1195,7 @@ _("computed size of rtrefcountbt root (%zu bytes) is greater than space in " error = process_rtrefc_reclist(mp, rp, numrecs, &priv, "rtrefcountbt root"); if (error) { - refcount_avoid_check(); + refcount_avoid_check(mp); return 1; } return 0; @@ -2143,6 +2159,9 @@ process_check_metadata_inodes( if (is_rtrmap_inode(lino)) return process_check_rt_inode(mp, dinoc, lino, type, dirty, XR_INO_RTRMAP, _("realtime rmap btree")); + if (is_rtrefcount_inode(lino)) + return process_check_rt_inode(mp, dinoc, lino, type, dirty, + XR_INO_RTREFC, _("realtime refcount btree")); return 0; } @@ -2253,6 +2272,18 @@ _("found inode %" PRIu64 " claiming to be a rtrmapbt file, but rmapbt is disable } break; + case XR_INO_RTREFC: + /* + * if we have no refcountbt, any inode claiming + * to be a real-time file is bogus + */ + if (!xfs_has_reflink(mp)) { + do_warn( +_("found inode %" PRIu64 " claiming to be a rtrefcountbt file, but reflink is disabled\n"), lino); + return 1; + } + break; + default: break; } @@ -3453,6 +3484,8 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), type = XR_INO_PQUOTA; else if (is_rtrmap_inode(lino)) type = XR_INO_RTRMAP; + else if (is_rtrefcount_inode(lino)) + type = XR_INO_RTREFC; else type = XR_INO_DATA; break; diff --git a/repair/dir2.c b/repair/dir2.c index af00b2d8d6c852..a80160afaea5cf 100644 --- a/repair/dir2.c +++ b/repair/dir2.c @@ -282,6 +282,9 @@ process_sf_dir2( } else if (is_rtrmap_inode(lino)) { junkit = 1; junkreason = _("realtime rmap"); + } else if (is_rtrefcount_inode(lino)) { + junkit = 1; + junkreason = _("realtime refcount"); } else if ((irec_p = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, lino), XFS_INO_TO_AGINO(mp, lino))) != NULL) { @@ -761,6 +764,8 @@ process_dir2_data( clearreason = _("metadata directory root"); } else if (is_rtrmap_inode(ent_ino)) { clearreason = _("realtime rmap"); + } else if (is_rtrefcount_inode(ent_ino)) { + clearreason = _("realtime refcount"); } else { irec_p = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, ent_ino), diff --git a/repair/incore.h b/repair/incore.h index 4add12615e0a04..57019148f588c3 100644 --- a/repair/incore.h +++ b/repair/incore.h @@ -242,6 +242,7 @@ int count_bcnt_extents(xfs_agnumber_t); #define XR_INO_GQUOTA 13 /* group quota inode */ #define XR_INO_PQUOTA 14 /* project quota inode */ #define XR_INO_RTRMAP 15 /* realtime rmap */ +#define XR_INO_RTREFC 16 /* realtime refcount */ /* inode allocation tree */ diff --git a/repair/rmap.c b/repair/rmap.c index 85a65048db9afc..e39c74cc7b44f7 100644 --- a/repair/rmap.c +++ b/repair/rmap.c @@ -1699,8 +1699,11 @@ init_refcount_cursor( * Disable the refcount btree check. */ void -refcount_avoid_check(void) +refcount_avoid_check( + struct xfs_mount *mp) { + if (xfs_has_rtgroups(mp)) + mark_rtgroup_inodes_bad(mp, XFS_RTGI_REFCOUNT); refcbt_suspect = true; } diff --git a/repair/rmap.h b/repair/rmap.h index 23859bf6c2ad42..c0984d97322861 100644 --- a/repair/rmap.h +++ b/repair/rmap.h @@ -41,7 +41,7 @@ extern void rmap_high_key_from_rec(struct xfs_rmap_irec *rec, extern int compute_refcounts(struct xfs_mount *, xfs_agnumber_t); uint64_t refcount_record_count(struct xfs_mount *mp, xfs_agnumber_t agno); extern int init_refcount_cursor(xfs_agnumber_t, struct xfs_slab_cursor **); -extern void refcount_avoid_check(void); +extern void refcount_avoid_check(struct xfs_mount *mp); void check_refcounts(struct xfs_mount *mp, xfs_agnumber_t agno); extern void record_inode_reflink_flag(struct xfs_mount *, struct xfs_dinode *, diff --git a/repair/scan.c b/repair/scan.c index 21fa9018800c77..86565ebb9f2faf 100644 --- a/repair/scan.c +++ b/repair/scan.c @@ -1980,7 +1980,7 @@ _("extent (%u/%u) len %u claimed, state is %d\n"), libxfs_perag_put(pag); out: if (suspect) - refcount_avoid_check(); + refcount_avoid_check(mp); return; } @@ -2285,7 +2285,7 @@ _("%s btree block claimed (state %d), agno %d, agbno %d, suspect %d\n"), } out: if (suspect) { - refcount_avoid_check(); + refcount_avoid_check(mp); return 1; } @@ -3148,7 +3148,7 @@ validate_agf( if (levels == 0 || levels > mp->m_refc_maxlevels) { do_warn(_("bad levels %u for refcountbt root, agno %d\n"), levels, agno); - refcount_avoid_check(); + refcount_avoid_check(mp); } bno = be32_to_cpu(agf->agf_refcount_root); @@ -3166,7 +3166,7 @@ validate_agf( } else { do_warn(_("bad agbno %u for refcntbt root, agno %d\n"), bno, agno); - refcount_avoid_check(); + refcount_avoid_check(mp); } } From patchwork Thu Feb 6 23:00:25 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13964067 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A19BF2417C9 for ; Thu, 6 Feb 2025 23:00:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882825; cv=none; b=B+C6Jx6L7DG6/bgAgSxOz5ru4yOXWPO1IAe/GQtlNvxdwg15tmXMkh4v/2NPeg14QUXnXH/90WIBFel1Mdx6sEKlc9gF4SLw5Q9g8LVpTrHkp1Mtx3V2N9ebqZmntIGnhVRMGRWLa1s3qJf45qhOFM6FNucgDnE8EeXybCkh5gY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882825; c=relaxed/simple; bh=jkpuSZgOJfZtZtXi9uecRZKMCPxX672uVCQsj6GdIpw=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=LYvmH9BURx4YTW6ZjN/1jFmMQwNqHhmoUOPMspG8kPUJEPFqrT9UxAyixiUlakzoVf1OAEdhU+mysH0z/O/67IcMhxGv9r/jfTOFb7hltiOb20Vl1CusqB+z11aOdelrsbHYwJbuhQKXkEw3sVTFf/snsRyVe4hNg+sF7c3Uprc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ajtCWMit; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ajtCWMit" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7F2E5C4CEDD; Thu, 6 Feb 2025 23:00:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882825; bh=jkpuSZgOJfZtZtXi9uecRZKMCPxX672uVCQsj6GdIpw=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=ajtCWMitZ3GCelkF/8Xjh/9N/bQJKukhf+YfvJ+OHcpJHlc2IsPlY26SGYr4s50b+ eyRP9HND2V/mjdz6o5nupHurMRhhgGsGeGDNx4/aupoj4EuDHjpnrf9P1+pTfXD8lA 1ACzGTsXHlFKfThBUsGMCJj+lwKLkDuwIEvHk/5+OBv5TXF0NJWlztjHDXITW7oG6b l6/c6iK1UjIWlh+kzo92lJvJalzBYBURFWhjvMsnSCyfF1jgvcWda55Ed5d1pI9pl2 VSYW2K9HXX7IRsmdgfvS+zHkmG+EwufuDx05Ruxny1t+HJDHjsDB3rc39Pr/9zDObi bLUIUIYV/A1jQ== Date: Thu, 06 Feb 2025 15:00:25 -0800 Subject: [PATCH 14/22] xfs_repair: compute refcount data for the realtime groups From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888089146.2741962.17033508683404359801.stgit@frogsfrogsfrogs> In-Reply-To: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> References: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong At the end of phase 4, compute reference count information for realtime groups from the realtime rmap information collected, just like we do for AGs in the data section. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- repair/phase4.c | 21 ++++++++++++++++++++- repair/rmap.c | 17 ++++++++++++----- repair/rmap.h | 2 +- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/repair/phase4.c b/repair/phase4.c index 29efa58af33178..4cfad1a6911764 100644 --- a/repair/phase4.c +++ b/repair/phase4.c @@ -177,13 +177,28 @@ compute_ag_refcounts( { int error; - error = compute_refcounts(wq->wq_ctx, agno); + error = compute_refcounts(wq->wq_ctx, false, agno); if (error) do_error( _("%s while computing reference count records.\n"), strerror(error)); } +static void +compute_rt_refcounts( + struct workqueue*wq, + xfs_agnumber_t rgno, + void *arg) +{ + int error; + + error = compute_refcounts(wq->wq_ctx, true, rgno); + if (error) + do_error( +_("%s while computing realtime reference count records.\n"), + strerror(error)); +} + static void process_inode_reflink_flags( struct workqueue *wq, @@ -233,6 +248,10 @@ process_rmap_data( create_work_queue(&wq, mp, platform_nproc()); for (i = 0; i < mp->m_sb.sb_agcount; i++) queue_work(&wq, compute_ag_refcounts, i, NULL); + if (xfs_has_rtreflink(mp)) { + for (i = 0; i < mp->m_sb.sb_rgcount; i++) + queue_work(&wq, compute_rt_refcounts, i, NULL); + } destroy_work_queue(&wq); create_work_queue(&wq, mp, platform_nproc()); diff --git a/repair/rmap.c b/repair/rmap.c index e39c74cc7b44f7..64a9f06d0ee915 100644 --- a/repair/rmap.c +++ b/repair/rmap.c @@ -125,6 +125,11 @@ rmaps_init_rt( if (error) goto nomem; + error = init_slab(&ag_rmap->ar_refcount_items, + sizeof(struct xfs_refcount_irec)); + if (error) + goto nomem; + return; nomem: do_error( @@ -878,6 +883,7 @@ mark_reflink_inodes( static void refcount_emit( struct xfs_mount *mp, + bool isrt, xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, @@ -887,7 +893,7 @@ refcount_emit( int error; struct xfs_slab *rlslab; - rlslab = rmaps_for_group(false, agno)->ar_refcount_items; + rlslab = rmaps_for_group(isrt, agno)->ar_refcount_items; ASSERT(nr_rmaps > 0); dbg_printf("REFL: agno=%u pblk=%u, len=%u -> refcount=%zu\n", @@ -1005,6 +1011,7 @@ refcount_push_rmaps_at( int compute_refcounts( struct xfs_mount *mp, + bool isrt, xfs_agnumber_t agno) { struct xfs_btree_cur *rmcur; @@ -1020,12 +1027,12 @@ compute_refcounts( if (!xfs_has_reflink(mp)) return 0; - if (!rmaps_has_observations(rmaps_for_group(false, agno))) + if (!rmaps_has_observations(rmaps_for_group(isrt, agno))) return 0; - nr_rmaps = rmap_record_count(mp, false, agno); + nr_rmaps = rmap_record_count(mp, isrt, agno); - error = rmap_init_mem_cursor(mp, NULL, false, agno, &rmcur); + error = rmap_init_mem_cursor(mp, NULL, isrt, agno, &rmcur); if (error) return error; @@ -1082,7 +1089,7 @@ compute_refcounts( ASSERT(nbno > cbno); if (rcbag_count(rcstack) != old_stack_height) { if (old_stack_height > 1) { - refcount_emit(mp, agno, cbno, + refcount_emit(mp, isrt, agno, cbno, nbno - cbno, old_stack_height); } diff --git a/repair/rmap.h b/repair/rmap.h index c0984d97322861..98f2891692a6f8 100644 --- a/repair/rmap.h +++ b/repair/rmap.h @@ -38,7 +38,7 @@ extern int64_t rmap_diffkeys(struct xfs_rmap_irec *kp1, extern void rmap_high_key_from_rec(struct xfs_rmap_irec *rec, struct xfs_rmap_irec *key); -extern int compute_refcounts(struct xfs_mount *, xfs_agnumber_t); +int compute_refcounts(struct xfs_mount *mp, bool isrt, xfs_agnumber_t agno); uint64_t refcount_record_count(struct xfs_mount *mp, xfs_agnumber_t agno); extern int init_refcount_cursor(xfs_agnumber_t, struct xfs_slab_cursor **); extern void refcount_avoid_check(struct xfs_mount *mp); From patchwork Thu Feb 6 23:00:40 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13964068 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4F8172417C9 for ; Thu, 6 Feb 2025 23:00:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882841; cv=none; b=UG8Th2zBEoPH/uVzCq5quFyeVrk+ghKPUSTkVz0ANjb1MwNmSdeyYT1s16+88jOPtmX4e8S3aYlWy90WppAnE8Kv8ObpfRKZFdiTDHLM5tOhyrnsUhL+EJUNQvqWc53Cj4/Z3QPNXKrYc/OFSG5bwTRrGq1J/v8AJWzhg9rWQaI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882841; c=relaxed/simple; bh=xxBJRip+9xi0Kjp/o1xfpnQmgLV0zakVD/a4p5JfOBI=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Cv5W8pjoTelSC1/3rkRWIYf6pmIACREY67lYHRModctuY91lEDSqE8jViExDWmS/WUgXH02CdBz2vQ+/0PJU5qxqqwiLRWTQQmB2BKjkScPd+cWb0Rh4gqlC9qskS1epkZwcbL7xp8AScqyAHvti/bcZMZlHB5Rjr+84qrpJsbU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QDD7WHhP; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="QDD7WHhP" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 23142C4CEDD; Thu, 6 Feb 2025 23:00:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882841; bh=xxBJRip+9xi0Kjp/o1xfpnQmgLV0zakVD/a4p5JfOBI=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=QDD7WHhPd2gLB8YelmrQejot2rtb8II5nM8P8xPw6uerh31S3fKZpSM6o7jA45kMl DnT3vb6zEk0Hi5uYq4nTmuYitBd+fEUtsDS4B8ceICfsdYhy/6YgzUGP7Npa8+CNvW MyrtnOHQ+vumyiK+WrH6nX2ZNFz+2O41C+UItwhRO7H99hY+FMkVmUH8I/vfm8gnAG T04YeTYYobkTjuKWMnNo3AmCDKPBLiUZ9iQLxHX2azozXIvEkD+k9d0gtDSM8L6++n cslaH6Az6bnUwcrjy8hnXvJDTQyxjnFowsi78xP7vK5KRhFRqeik4YsDIfxpQfjyOg hmBJF80IdV8Nw== Date: Thu, 06 Feb 2025 15:00:40 -0800 Subject: [PATCH 15/22] xfs_repair: check existing realtime refcountbt entries against observed refcounts From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888089162.2741962.5490397729857671375.stgit@frogsfrogsfrogs> In-Reply-To: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> References: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Once we've finished collecting reverse mapping observations from the metadata scan, check those observations against the realtime refcount btree (particularly if we're in -n mode) to detect rtrefcountbt problems. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- libxfs/libxfs_api_defs.h | 1 repair/agbtree.c | 2 repair/phase4.c | 13 +++ repair/rmap.c | 197 +++++++++++++++++++++++++++++++++++----------- repair/rmap.h | 4 + 5 files changed, 169 insertions(+), 48 deletions(-) diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index 0dc6f0350dd0f6..b5a39856bc1e80 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -322,6 +322,7 @@ #define xfs_rtrefcountbt_calc_reserves libxfs_rtrefcountbt_calc_reserves #define xfs_rtrefcountbt_droot_maxrecs libxfs_rtrefcountbt_droot_maxrecs +#define xfs_rtrefcountbt_init_cursor libxfs_rtrefcountbt_init_cursor #define xfs_rtrefcountbt_maxlevels_ondisk libxfs_rtrefcountbt_maxlevels_ondisk #define xfs_rtrefcountbt_maxrecs libxfs_rtrefcountbt_maxrecs diff --git a/repair/agbtree.c b/repair/agbtree.c index 2135147fcf9354..01066130767cb6 100644 --- a/repair/agbtree.c +++ b/repair/agbtree.c @@ -747,7 +747,7 @@ build_refcount_tree( { int error; - error = init_refcount_cursor(agno, &btr->slab_cursor); + error = init_refcount_cursor(false, agno, &btr->slab_cursor); if (error) do_error( _("Insufficient memory to construct refcount cursor.\n")); diff --git a/repair/phase4.c b/repair/phase4.c index 4cfad1a6911764..b752b4c871ea83 100644 --- a/repair/phase4.c +++ b/repair/phase4.c @@ -223,6 +223,15 @@ check_refcount_btrees( check_refcounts(wq->wq_ctx, agno); } +static void +check_rt_refcount_btrees( + struct workqueue *wq, + xfs_agnumber_t agno, + void *arg) +{ + check_rtrefcounts(wq->wq_ctx, agno); +} + static void process_rmap_data( struct xfs_mount *mp) @@ -259,6 +268,10 @@ process_rmap_data( queue_work(&wq, process_inode_reflink_flags, i, NULL); queue_work(&wq, check_refcount_btrees, i, NULL); } + if (xfs_has_rtreflink(mp)) { + for (i = 0; i < mp->m_sb.sb_rgcount; i++) + queue_work(&wq, check_rt_refcount_btrees, i, NULL); + } destroy_work_queue(&wq); } diff --git a/repair/rmap.c b/repair/rmap.c index 64a9f06d0ee915..638e5ea92278cb 100644 --- a/repair/rmap.c +++ b/repair/rmap.c @@ -1694,10 +1694,11 @@ refcount_record_count( */ int init_refcount_cursor( + bool isrt, xfs_agnumber_t agno, struct xfs_slab_cursor **cur) { - struct xfs_ag_rmap *x = rmaps_for_group(false, agno); + struct xfs_ag_rmap *x = rmaps_for_group(isrt, agno); return init_slab_cursor(x->ar_refcount_items, NULL, cur); } @@ -1714,56 +1715,18 @@ refcount_avoid_check( refcbt_suspect = true; } -/* - * Compare the observed reference counts against what's in the ag btree. - */ -void -check_refcounts( - struct xfs_mount *mp, +static int +check_refcount_records( + struct xfs_slab_cursor *rl_cur, + struct xfs_btree_cur *bt_cur, xfs_agnumber_t agno) { struct xfs_refcount_irec tmp; - struct xfs_slab_cursor *rl_cur; - struct xfs_btree_cur *bt_cur = NULL; - struct xfs_buf *agbp = NULL; - struct xfs_perag *pag = NULL; struct xfs_refcount_irec *rl_rec; - int have; int i; + int have; int error; - if (!xfs_has_reflink(mp)) - return; - if (refcbt_suspect) { - if (no_modify && agno == 0) - do_warn(_("would rebuild corrupt refcount btrees.\n")); - return; - } - - /* Create cursors to refcount structures */ - error = init_refcount_cursor(agno, &rl_cur); - if (error) { - do_warn(_("Not enough memory to check refcount data.\n")); - return; - } - - pag = libxfs_perag_get(mp, agno); - error = -libxfs_alloc_read_agf(pag, NULL, 0, &agbp); - if (error) { - do_warn(_("Could not read AGF %u to check refcount btree.\n"), - agno); - goto err_pag; - } - - /* Leave the per-ag data "uninitialized" since we rewrite it later */ - clear_bit(XFS_AGSTATE_AGF_INIT, &pag->pag_opstate); - - bt_cur = libxfs_refcountbt_init_cursor(mp, NULL, agbp, pag); - if (!bt_cur) { - do_warn(_("Not enough memory to check refcount data.\n")); - goto err_agf; - } - rl_rec = pop_slab_cursor(rl_cur); while (rl_rec) { /* Look for a refcount record in the btree */ @@ -1774,7 +1737,7 @@ check_refcounts( do_warn( _("Could not read reference count record for (%u/%u).\n"), agno, rl_rec->rc_startblock); - goto err_cur; + return error; } if (!have) { do_warn( @@ -1789,7 +1752,7 @@ _("Missing reference count record for (%u/%u) len %u count %u\n"), do_warn( _("Could not read reference count record for (%u/%u).\n"), agno, rl_rec->rc_startblock); - goto err_cur; + return error; } if (!i) { do_warn( @@ -1819,6 +1782,59 @@ _("Incorrect reference count: saw (%u/%u) len %u nlinks %u; should be (%u/%u) le rl_rec = pop_slab_cursor(rl_cur); } + return 0; +} + +/* + * Compare the observed reference counts against what's in the ag btree. + */ +void +check_refcounts( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + struct xfs_slab_cursor *rl_cur; + struct xfs_btree_cur *bt_cur = NULL; + struct xfs_buf *agbp = NULL; + struct xfs_perag *pag = NULL; + int error; + + if (!xfs_has_reflink(mp)) + return; + if (refcbt_suspect) { + if (no_modify && agno == 0) + do_warn(_("would rebuild corrupt refcount btrees.\n")); + return; + } + + /* Create cursors to refcount structures */ + error = init_refcount_cursor(false, agno, &rl_cur); + if (error) { + do_warn(_("Not enough memory to check refcount data.\n")); + return; + } + + pag = libxfs_perag_get(mp, agno); + error = -libxfs_alloc_read_agf(pag, NULL, 0, &agbp); + if (error) { + do_warn(_("Could not read AGF %u to check refcount btree.\n"), + agno); + goto err_pag; + } + + /* Leave the per-ag data "uninitialized" since we rewrite it later */ + clear_bit(XFS_AGSTATE_AGF_INIT, &pag->pag_opstate); + + bt_cur = libxfs_refcountbt_init_cursor(mp, NULL, agbp, pag); + if (!bt_cur) { + do_warn(_("Not enough memory to check refcount data.\n")); + goto err_agf; + } + + error = check_refcount_records(rl_cur, bt_cur, agno); + if (error) + goto err_cur; + err_cur: libxfs_btree_del_cursor(bt_cur, error); err_agf: @@ -1828,6 +1844,95 @@ _("Incorrect reference count: saw (%u/%u) len %u nlinks %u; should be (%u/%u) le free_slab_cursor(&rl_cur); } +/* + * Compare the observed reference counts against what's in the ondisk btree. + */ +void +check_rtrefcounts( + struct xfs_mount *mp, + xfs_rgnumber_t rgno) +{ + struct xfs_slab_cursor *rl_cur; + struct xfs_btree_cur *bt_cur = NULL; + struct xfs_rtgroup *rtg = NULL; + struct xfs_inode *ip = NULL; + int error; + + if (!xfs_has_reflink(mp)) + return; + if (refcbt_suspect) { + if (no_modify && rgno == 0) + do_warn(_("would rebuild corrupt refcount btrees.\n")); + return; + } + if (mp->m_sb.sb_rblocks == 0) { + if (rmap_record_count(mp, true, rgno) != 0) + do_error(_("realtime refcounts but no rtdev?\n")); + return; + } + + /* Create cursors to refcount structures */ + error = init_refcount_cursor(true, rgno, &rl_cur); + if (error) { + do_warn(_("Not enough memory to check refcount data.\n")); + return; + } + + rtg = libxfs_rtgroup_get(mp, rgno); + if (!rtg) { + do_warn(_("Could not load rtgroup %u.\n"), rgno); + goto err_rcur; + } + + ip = rtg_refcount(rtg); + if (!ip) { + do_warn(_("Could not find rtgroup %u refcount inode.\n"), + rgno); + goto err_rtg; + } + + if (ip->i_df.if_format != XFS_DINODE_FMT_META_BTREE) { + do_warn( +_("rtgroup %u refcount inode has wrong format 0x%x, expected 0x%x\n"), + rgno, ip->i_df.if_format, + XFS_DINODE_FMT_META_BTREE); + goto err_rtg; + } + + if (ip->i_metatype != XFS_METAFILE_RTREFCOUNT) { + do_warn( +_("rtgroup %u refcount inode has wrong metatype 0x%x, expected 0x%x\n"), + rgno, ip->i_df.if_format, + XFS_METAFILE_RTREFCOUNT); + goto err_rtg; + } + + if (xfs_inode_has_attr_fork(ip) && + !(xfs_has_metadir(mp) && xfs_has_parent(mp))) { + do_warn( +_("rtgroup %u refcount inode should not have extended attributes\n"), + rgno); + goto err_rtg; + } + + bt_cur = libxfs_rtrefcountbt_init_cursor(NULL, rtg); + if (!bt_cur) { + do_warn(_("Not enough memory to check refcount data.\n")); + goto err_rtg; + } + + error = check_refcount_records(rl_cur, bt_cur, rgno); + if (error) + goto err_cur; + +err_cur: + libxfs_btree_del_cursor(bt_cur, error); +err_rtg: + libxfs_rtgroup_put(rtg); +err_rcur: + free_slab_cursor(&rl_cur); +} + /* * Regenerate the AGFL so that we don't run out of it while rebuilding the * rmap btree. If skip_rmapbt is true, don't update the rmapbt (most probably diff --git a/repair/rmap.h b/repair/rmap.h index 98f2891692a6f8..80e82a4ac4c008 100644 --- a/repair/rmap.h +++ b/repair/rmap.h @@ -40,9 +40,11 @@ extern void rmap_high_key_from_rec(struct xfs_rmap_irec *rec, int compute_refcounts(struct xfs_mount *mp, bool isrt, xfs_agnumber_t agno); uint64_t refcount_record_count(struct xfs_mount *mp, xfs_agnumber_t agno); -extern int init_refcount_cursor(xfs_agnumber_t, struct xfs_slab_cursor **); +int init_refcount_cursor(bool isrt, xfs_agnumber_t agno, + struct xfs_slab_cursor **pcur); extern void refcount_avoid_check(struct xfs_mount *mp); void check_refcounts(struct xfs_mount *mp, xfs_agnumber_t agno); +void check_rtrefcounts(struct xfs_mount *mp, xfs_rgnumber_t rgno); extern void record_inode_reflink_flag(struct xfs_mount *, struct xfs_dinode *, xfs_agnumber_t, xfs_agino_t, xfs_ino_t); From patchwork Thu Feb 6 23:00:56 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13964069 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5C68C2417C9 for ; Thu, 6 Feb 2025 23:00:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882857; cv=none; b=VOnNRPY1/Wc28M5oYq7T/2oXOnwCeyS1zSamCxo1sSTicallPjM5JR7Rj4zIlozF4qcsREHtEtiUkvEL/0wRyn5YR9taRTXSPrC0aqdgd2S1b/63n87YwBvd3iUP+aOuCY1V/322W3P1D1+c5VyGg3tvRMZeC01bG9/s5WjykQY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882857; c=relaxed/simple; bh=ABDVfO+uZuwJgXV5FdxvC4uUVIdZqYDj7a0VOjPekHM=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=PI4Fv7cfPj8wzG19WEetPI5ae1AMVfDJvMyiKKLWD3xylq8uU6xgAcK2TAvFwLVd12HqpLm0tFI+9F6JfW1UHsicq6R9Jvpa5kIYUYSfTSd5+gkX4pO5IH5NihYu3+FCObpIuCk8ViXW6COaz6NhydQWi6MTwvvVo6QxfSItCQI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=lgS23lCK; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="lgS23lCK" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BF140C4CEDD; Thu, 6 Feb 2025 23:00:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882856; bh=ABDVfO+uZuwJgXV5FdxvC4uUVIdZqYDj7a0VOjPekHM=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=lgS23lCKbBsXTz/+73VajVry5WDkEaTVE4zGLMfUUFKYntnN93TfsBchWN5m6xp5p Our53tzVwdxE0fzYTp17eHH30YDYb3eJmqEAdXkmN4gtHJShSi+hwEJtqzllNBaH9F LzpAnAG+6BV2FHhTWa/QKZFnYBBMqVyqyYckeUwdp2nQtOog/kMmkrb9OlFQjFLn0g 6IjWtdzeqwkmQtW6l/Hmeysy5F9bnD7oVT/lU1OPEsH/1p7sCe1uX1SI31lNdy5XZc uAgF8ga0kOlqTYFzgGslxhAVXruxcBkOJiHjmdxgTmhjCQyJ5Hdt02H6x8Lx3ixXCm ONjfji3C2YvaA== Date: Thu, 06 Feb 2025 15:00:56 -0800 Subject: [PATCH 16/22] xfs_repair: reject unwritten shared extents From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888089177.2741962.5838383202072252893.stgit@frogsfrogsfrogs> In-Reply-To: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> References: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong We don't allow sharing of unwritten extents, which means that repair should reject an unwritten extent if someone else has already claimed the space. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- repair/dinode.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/repair/dinode.c b/repair/dinode.c index 3260df94511ed2..f49c735d34356b 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -311,7 +311,8 @@ _("bad state in rt extent map %" PRIu64 "\n"), break; case XR_E_INUSE: case XR_E_MULT: - if (xfs_has_rtreflink(mp)) + if (xfs_has_rtreflink(mp) && + irec->br_state == XFS_EXT_NORM) break; set_rtbmap(ext, XR_E_MULT); break; @@ -387,8 +388,14 @@ _("data fork in rt inode %" PRIu64 " found rt metadata extent %" PRIu64 " in rt return 1; case XR_E_INUSE: case XR_E_MULT: - if (xfs_has_rtreflink(mp)) - break; + if (xfs_has_rtreflink(mp)) { + if (irec->br_state == XFS_EXT_NORM) + break; + do_warn( +_("data fork in rt inode %" PRIu64 " claims shared unwritten rt extent %" PRIu64 "\n"), + ino, b); + return 1; + } do_warn( _("data fork in rt inode %" PRIu64 " claims used rt extent %" PRIu64 "\n"), ino, b); @@ -472,6 +479,18 @@ _("inode %" PRIu64 " - bad rt extent overflows - start %" PRIu64 ", " return bad; } +static inline bool +is_reflink_type( + struct xfs_mount *mp, + int type) +{ + if (type == XR_INO_DATA && xfs_has_reflink(mp)) + return true; + if (type == XR_INO_RTDATA && xfs_has_rtreflink(mp)) + return true; + return false; +} + /* * return 1 if inode should be cleared, 0 otherwise * if check_dups should be set to 1, that implies that @@ -717,9 +736,14 @@ _("%s fork in inode %" PRIu64 " claims metadata block %" PRIu64 "\n"), case XR_E_INUSE: case XR_E_MULT: - if (type == XR_INO_DATA && - xfs_has_reflink(mp)) - break; + if (is_reflink_type(mp, type)) { + if (irec.br_state == XFS_EXT_NORM) + break; + do_warn( +_("%s fork in %s inode %" PRIu64 " claims shared unwritten block %" PRIu64 "\n"), + forkname, ftype, ino, b); + goto done; + } do_warn( _("%s fork in %s inode %" PRIu64 " claims used block %" PRIu64 "\n"), forkname, ftype, ino, b); From patchwork Thu Feb 6 23:01:11 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13964070 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A32892417C9 for ; Thu, 6 Feb 2025 23:01:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882872; cv=none; b=SLrQG4Fsjcl/PQwIL5SZAU0AL5RENv2rZbZ6Ky4YQ2icZOOs4eAllDRmvus0SBvWqt7mdu81Z/7/lzvoo6N/uoy/ZruioPhEvUOJ3nzXKsC/mBwXTE153h2WB7GOzQzH9+99U5139yKlD4Q0JW4I4Ip/60DhVcCHBtZb/es2EeI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882872; c=relaxed/simple; bh=HLZWwRQavcix0GHVVd+D50NLm653zeVyTsVnYqIDpTc=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=nYlo85Hil+hjT7NU30gAI57Aw0tpl9lyTSM7jVPJQwEJtMQ5+CR+2Xj2qnFg6Leu96+S/Mq4OK66AoIom5DX183QIjtizrt9EvlWl9a2izEpp43181KmIZHjKrmwFh46ovCW6lRR2blSdKEEKjOJDo6OOtK4W3oZ84Bbk+D2Qxs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=OCUfQveI; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="OCUfQveI" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 700DEC4CEDD; Thu, 6 Feb 2025 23:01:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882872; bh=HLZWwRQavcix0GHVVd+D50NLm653zeVyTsVnYqIDpTc=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=OCUfQveIvY3jjFCkLObYYmUBqwZsyvdssl/E6op2UZvx7xne5Gz/MJ1e+dfRP/LMo qhVPSgf2TTO+f+bUyU91NwQXBuRNlwiSv3+qQGX2MaLjNiYpcV4QfnOfZFj7HXM74h 6tyXFz3ugxqRyNCIABFsrRZP0OFiaNHaMYeNt3WcmCe/aIymrQpBRpCYFsXSgVJEAO JuvlieFGaaAELAbD8hQBKDSounimyezKj09EAcKrlkSyp3Mjh6bgD8cZo2mIgP+5gg 4+pzXVXQiT/RVfIFWzbWIHDTTGiCmn/btU6Yn0orj2oxhh8ux9wYt8idPdDJLqgP7T yFcpt6W55DV/A== Date: Thu, 06 Feb 2025 15:01:11 -0800 Subject: [PATCH 17/22] xfs_repair: rebuild the realtime refcount btree From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888089192.2741962.1542453669085725843.stgit@frogsfrogsfrogs> In-Reply-To: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> References: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Use the collected reference count information to rebuild the btree. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- libxfs/libxfs_api_defs.h | 5 + repair/Makefile | 1 repair/agbtree.c | 2 repair/phase5.c | 6 + repair/phase6.c | 14 ++ repair/rmap.c | 22 ++++ repair/rmap.h | 7 + repair/rtrefcount_repair.c | 257 ++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 308 insertions(+), 6 deletions(-) create mode 100644 repair/rtrefcount_repair.c diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index b5a39856bc1e80..66cbb34f05a48f 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -320,11 +320,16 @@ #define xfs_rtgroup_get libxfs_rtgroup_get #define xfs_rtgroup_put libxfs_rtgroup_put +#define xfs_rtrefcountbt_absolute_maxlevels libxfs_rtrefcountbt_absolute_maxlevels #define xfs_rtrefcountbt_calc_reserves libxfs_rtrefcountbt_calc_reserves +#define xfs_rtrefcountbt_calc_size libxfs_rtrefcountbt_calc_size +#define xfs_rtrefcountbt_commit_staged_btree libxfs_rtrefcountbt_commit_staged_btree +#define xfs_rtrefcountbt_create libxfs_rtrefcountbt_create #define xfs_rtrefcountbt_droot_maxrecs libxfs_rtrefcountbt_droot_maxrecs #define xfs_rtrefcountbt_init_cursor libxfs_rtrefcountbt_init_cursor #define xfs_rtrefcountbt_maxlevels_ondisk libxfs_rtrefcountbt_maxlevels_ondisk #define xfs_rtrefcountbt_maxrecs libxfs_rtrefcountbt_maxrecs +#define xfs_rtrefcountbt_stage_cursor libxfs_rtrefcountbt_stage_cursor #define xfs_rtrmapbt_calc_reserves libxfs_rtrmapbt_calc_reserves #define xfs_rtrmapbt_calc_size libxfs_rtrmapbt_calc_size diff --git a/repair/Makefile b/repair/Makefile index 6f4ec3b3a9c4dc..ff5b1f5abedac0 100644 --- a/repair/Makefile +++ b/repair/Makefile @@ -73,6 +73,7 @@ CFILES = \ rcbag.c \ rmap.c \ rt.c \ + rtrefcount_repair.c \ rtrmap_repair.c \ sb.c \ scan.c \ diff --git a/repair/agbtree.c b/repair/agbtree.c index 01066130767cb6..983b645e1a35a3 100644 --- a/repair/agbtree.c +++ b/repair/agbtree.c @@ -730,7 +730,7 @@ init_refc_cursor( /* Compute how many blocks we'll need. */ error = -libxfs_btree_bload_compute_geometry(btr->cur, &btr->bload, - refcount_record_count(sc->mp, agno)); + refcount_record_count(sc->mp, false, agno)); if (error) do_error( _("Unable to compute refcount btree geometry, error %d.\n"), error); diff --git a/repair/phase5.c b/repair/phase5.c index cacaf74dda3a60..4cf28d8ae1a250 100644 --- a/repair/phase5.c +++ b/repair/phase5.c @@ -705,7 +705,7 @@ are_packed_btrees_needed( * If we don't have inode-based metadata, we can let the AG btrees * pack as needed; there are no global space concerns here. */ - if (!xfs_has_rtrmapbt(mp)) + if (!xfs_has_rtrmapbt(mp) && !xfs_has_rtreflink(mp)) return false; while ((pag = xfs_perag_next(mp, pag))) { @@ -716,8 +716,10 @@ are_packed_btrees_needed( fdblocks += ag_fdblocks; } - while ((rtg = xfs_rtgroup_next(mp, rtg))) + while ((rtg = xfs_rtgroup_next(mp, rtg))) { metadata_blocks += estimate_rtrmapbt_blocks(rtg); + metadata_blocks += estimate_rtrefcountbt_blocks(rtg); + } /* * If we think we'll have more metadata blocks than free space, then diff --git a/repair/phase6.c b/repair/phase6.c index 30ea19fda9fd87..4064a84b24509f 100644 --- a/repair/phase6.c +++ b/repair/phase6.c @@ -696,6 +696,15 @@ ensure_rtgroup_rmapbt( populate_rtgroup_rmapbt(rtg, est_fdblocks); } +static void +ensure_rtgroup_refcountbt( + struct xfs_rtgroup *rtg, + xfs_filblks_t est_fdblocks) +{ + if (ensure_rtgroup_file(rtg, XFS_RTGI_REFCOUNT)) + populate_rtgroup_refcountbt(rtg, est_fdblocks); +} + /* Initialize a root directory. */ static int init_fs_root_dir( @@ -3405,8 +3414,10 @@ reset_rt_metadir_inodes( * maximally. */ if (!need_packed_btrees) { - while ((rtg = xfs_rtgroup_next(mp, rtg))) + while ((rtg = xfs_rtgroup_next(mp, rtg))) { metadata_blocks += estimate_rtrmapbt_blocks(rtg); + metadata_blocks += estimate_rtrefcountbt_blocks(rtg); + } if (mp->m_sb.sb_fdblocks > metadata_blocks) est_fdblocks = mp->m_sb.sb_fdblocks - metadata_blocks; @@ -3427,6 +3438,7 @@ _(" - resetting contents of realtime bitmap and summary inodes\n")); ensure_rtgroup_bitmap(rtg); ensure_rtgroup_summary(rtg); ensure_rtgroup_rmapbt(rtg, est_fdblocks); + ensure_rtgroup_refcountbt(rtg, est_fdblocks); } } diff --git a/repair/rmap.c b/repair/rmap.c index 638e5ea92278cb..97510dd875911a 100644 --- a/repair/rmap.c +++ b/repair/rmap.c @@ -1682,9 +1682,10 @@ _("Unable to fix reflink flag on inode %"PRIu64".\n"), uint64_t refcount_record_count( struct xfs_mount *mp, + bool isrt, xfs_agnumber_t agno) { - struct xfs_ag_rmap *x = rmaps_for_group(false, agno); + struct xfs_ag_rmap *x = rmaps_for_group(isrt, agno); return slab_count(x->ar_refcount_items); } @@ -2081,3 +2082,22 @@ estimate_rtrmapbt_blocks( nr_recs = xmbuf_bytes(x->ar_xmbtp) / sizeof(struct xfs_rmap_rec); return libxfs_rtrmapbt_calc_size(mp, nr_recs); } + +/* Estimate the size of the ondisk rtrefcountbt from the incore data. */ +xfs_filblks_t +estimate_rtrefcountbt_blocks( + struct xfs_rtgroup *rtg) +{ + struct xfs_mount *mp = rtg_mount(rtg); + struct xfs_ag_rmap *x; + + if (!rmap_needs_work(mp) || !xfs_has_rtreflink(mp)) + return 0; + + x = &rg_rmaps[rtg_rgno(rtg)]; + if (!x->ar_refcount_items) + return 0; + + return libxfs_rtrefcountbt_calc_size(mp, + slab_count(x->ar_refcount_items)); +} diff --git a/repair/rmap.h b/repair/rmap.h index 80e82a4ac4c008..1f234b8be32e72 100644 --- a/repair/rmap.h +++ b/repair/rmap.h @@ -39,7 +39,8 @@ extern void rmap_high_key_from_rec(struct xfs_rmap_irec *rec, struct xfs_rmap_irec *key); int compute_refcounts(struct xfs_mount *mp, bool isrt, xfs_agnumber_t agno); -uint64_t refcount_record_count(struct xfs_mount *mp, xfs_agnumber_t agno); +uint64_t refcount_record_count(struct xfs_mount *mp, bool isrt, + xfs_agnumber_t agno); int init_refcount_cursor(bool isrt, xfs_agnumber_t agno, struct xfs_slab_cursor **pcur); extern void refcount_avoid_check(struct xfs_mount *mp); @@ -64,4 +65,8 @@ void populate_rtgroup_rmapbt(struct xfs_rtgroup *rtg, xfs_filblks_t est_fdblocks); xfs_filblks_t estimate_rtrmapbt_blocks(struct xfs_rtgroup *rtg); +int populate_rtgroup_refcountbt(struct xfs_rtgroup *rtg, + xfs_filblks_t est_fdblocks); +xfs_filblks_t estimate_rtrefcountbt_blocks(struct xfs_rtgroup *rtg); + #endif /* RMAP_H_ */ diff --git a/repair/rtrefcount_repair.c b/repair/rtrefcount_repair.c new file mode 100644 index 00000000000000..228d080e5a5dcb --- /dev/null +++ b/repair/rtrefcount_repair.c @@ -0,0 +1,257 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2021-2025 Oracle. All Rights Reserved. + * Author: Darrick J. Wong + */ +#include +#include "btree.h" +#include "err_protos.h" +#include "libxlog.h" +#include "incore.h" +#include "globals.h" +#include "dinode.h" +#include "slab.h" +#include "rmap.h" +#include "bulkload.h" + +/* + * Realtime Reference Count (RTREFCBT) Repair + * ========================================== + * + * Gather all the reference count records for the realtime device, reset the + * incore fork, then recreate the btree. + */ +struct xrep_rtrefc { + /* rtrefcbt slab cursor */ + struct xfs_slab_cursor *slab_cursor; + + /* New fork. */ + struct bulkload new_fork_info; + struct xfs_btree_bload rtrefc_bload; + + struct repair_ctx *sc; + struct xfs_rtgroup *rtg; + + /* Estimated free space after building all rt btrees */ + xfs_filblks_t est_fdblocks; +}; + +/* Retrieve rtrefc data for bulk load. */ +STATIC int +xrep_rtrefc_get_records( + struct xfs_btree_cur *cur, + unsigned int idx, + struct xfs_btree_block *block, + unsigned int nr_wanted, + void *priv) +{ + struct xfs_refcount_irec *rec; + struct xrep_rtrefc *rc = priv; + union xfs_btree_rec *block_rec; + unsigned int loaded; + + for (loaded = 0; loaded < nr_wanted; loaded++, idx++) { + rec = pop_slab_cursor(rc->slab_cursor); + memcpy(&cur->bc_rec.rc, rec, sizeof(struct xfs_refcount_irec)); + + block_rec = libxfs_btree_rec_addr(cur, idx, block); + cur->bc_ops->init_rec_from_cur(cur, block_rec); + } + + return loaded; +} + +/* Feed one of the new btree blocks to the bulk loader. */ +STATIC int +xrep_rtrefc_claim_block( + struct xfs_btree_cur *cur, + union xfs_btree_ptr *ptr, + void *priv) +{ + struct xrep_rtrefc *rr = priv; + + return bulkload_claim_block(cur, &rr->new_fork_info, ptr); +} + +/* Figure out how much space we need to create the incore btree root block. */ +STATIC size_t +xrep_rtrefc_iroot_size( + struct xfs_btree_cur *cur, + unsigned int level, + unsigned int nr_this_level, + void *priv) +{ + return xfs_rtrefcount_broot_space_calc(cur->bc_mp, level, + nr_this_level); +} + +/* Reserve new btree blocks and bulk load all the rtrmap records. */ +STATIC int +xrep_rtrefc_btree_load( + struct xrep_rtrefc *rr, + struct xfs_btree_cur *rtrmap_cur) +{ + struct repair_ctx *sc = rr->sc; + int error; + + rr->rtrefc_bload.get_records = xrep_rtrefc_get_records; + rr->rtrefc_bload.claim_block = xrep_rtrefc_claim_block; + rr->rtrefc_bload.iroot_size = xrep_rtrefc_iroot_size; + bulkload_estimate_inode_slack(sc->mp, &rr->rtrefc_bload, + rr->est_fdblocks); + + /* Compute how many blocks we'll need. */ + error = -libxfs_btree_bload_compute_geometry(rtrmap_cur, + &rr->rtrefc_bload, + refcount_record_count(sc->mp, true, rtg_rgno(rr->rtg))); + if (error) + return error; + + /* + * Guess how many blocks we're going to need to rebuild an entire + * rtrefcountbt from the number of extents we found, and pump up our + * transaction to have sufficient block reservation. + */ + error = -libxfs_trans_reserve_more(sc->tp, rr->rtrefc_bload.nr_blocks, + 0); + if (error) + return error; + + /* + * Reserve the space we'll need for the new btree. Drop the cursor + * while we do this because that can roll the transaction and cursors + * can't handle that. + */ + error = bulkload_alloc_file_blocks(&rr->new_fork_info, + rr->rtrefc_bload.nr_blocks); + if (error) + return error; + + /* Add all observed rtrmap records. */ + error = init_refcount_cursor(true, rtg_rgno(rr->rtg), &rr->slab_cursor); + if (error) + return error; + error = -libxfs_btree_bload(rtrmap_cur, &rr->rtrefc_bload, rr); + free_slab_cursor(&rr->slab_cursor); + return error; +} + +/* Update the inode counters. */ +STATIC int +xrep_rtrefc_reset_counters( + struct xrep_rtrefc *rr) +{ + struct repair_ctx *sc = rr->sc; + + /* + * Update the inode block counts to reflect the btree we just + * generated. + */ + sc->ip->i_nblocks = rr->new_fork_info.ifake.if_blocks; + libxfs_trans_log_inode(sc->tp, sc->ip, XFS_ILOG_CORE); + + /* Quotas don't exist so we're done. */ + return 0; +} + +/* + * Use the collected rmap information to stage a new rt refcount btree. If + * this is successful we'll return with the new btree root information logged + * to the repair transaction but not yet committed. + */ +static int +xrep_rtrefc_build_new_tree( + struct xrep_rtrefc *rr) +{ + struct xfs_owner_info oinfo; + struct xfs_btree_cur *cur; + struct repair_ctx *sc = rr->sc; + struct xbtree_ifakeroot *ifake = &rr->new_fork_info.ifake; + int error; + + /* + * Prepare to construct the new fork by initializing the new btree + * structure and creating a fake ifork in the ifakeroot structure. + */ + libxfs_rmap_ino_bmbt_owner(&oinfo, sc->ip->i_ino, XFS_DATA_FORK); + bulkload_init_inode(&rr->new_fork_info, sc, XFS_DATA_FORK, &oinfo); + cur = libxfs_rtrefcountbt_init_cursor(NULL, rr->rtg); + libxfs_btree_stage_ifakeroot(cur, ifake); + + /* + * Figure out the size and format of the new fork, then fill it with + * all the rtrmap records we've found. Join the inode to the + * transaction so that we can roll the transaction while holding the + * inode locked. + */ + libxfs_trans_ijoin(sc->tp, sc->ip, 0); + ifake->if_fork->if_format = XFS_DINODE_FMT_META_BTREE; + error = xrep_rtrefc_btree_load(rr, cur); + if (error) + goto err_cur; + + /* + * Install the new fork in the inode. After this point the old mapping + * data are no longer accessible and the new tree is live. We delete + * the cursor immediately after committing the staged root because the + * staged fork might be in extents format. + */ + libxfs_rtrefcountbt_commit_staged_btree(cur, sc->tp); + libxfs_btree_del_cursor(cur, 0); + + /* Reset the inode counters now that we've changed the fork. */ + error = xrep_rtrefc_reset_counters(rr); + if (error) + goto err_newbt; + + /* Dispose of any unused blocks and the accounting infomation. */ + error = bulkload_commit(&rr->new_fork_info); + if (error) + return error; + + return -libxfs_trans_roll_inode(&sc->tp, sc->ip); +err_cur: + if (cur) + libxfs_btree_del_cursor(cur, error); +err_newbt: + bulkload_cancel(&rr->new_fork_info); + return error; +} + +/* Store the realtime reference counts in the rtrefcbt. */ +int +populate_rtgroup_refcountbt( + struct xfs_rtgroup *rtg, + xfs_filblks_t est_fdblocks) +{ + struct xfs_mount *mp = rtg_mount(rtg); + struct xfs_inode *ip = rtg_refcount(rtg); + struct repair_ctx sc = { + .mp = mp, + .ip = ip, + }; + struct xrep_rtrefc rr = { + .sc = &sc, + .rtg = rtg, + .est_fdblocks = est_fdblocks, + }; + int error; + + if (!xfs_has_rtreflink(mp)) + return 0; + + error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, + &sc.tp); + if (error) + return error; + + error = xrep_rtrefc_build_new_tree(&rr); + if (error) + goto out_cancel; + + return -libxfs_trans_commit(sc.tp); + +out_cancel: + libxfs_trans_cancel(sc.tp); + return error; +} From patchwork Thu Feb 6 23:01:27 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13964071 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3DADF2417C9 for ; Thu, 6 Feb 2025 23:01:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882888; cv=none; b=IDpTYnCmiGlqriqHQoiwPvDpl0jJcHivLf9AVOW6ayK1d2Pu8v3PODAahjWyTBSieOHhMbEWJqaCnQKVMhS9sLB8FoMwhhASMjxAUtPZjdu6QcgUqwyQwGbH/+5IddB/y5QIhni9CnAzhmY3IRHrF+COptJ+kMhfEfIoj9Dl6s8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882888; c=relaxed/simple; bh=NblbH9LpjGVa+//DviO7apKqVlJXTv4KgAOmQhSycHU=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=OXSMVN1HUhxKVOwh9wmubmD9LqDvcmD4LMLGZop2DRGfUy/1RNUp2hEzcP2M7M1Hzx0z4EfDWk1SxIhLp5lHcd18y1OV//x+iKkiv6gwo+Px0P/N0swWedWUDhO/S3fM6tH16nXv0Nk0OGxKYwHzkYLFWyNbdrLT3/Xtrdxvwys= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ssTRAqc5; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ssTRAqc5" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 150D3C4CEDD; Thu, 6 Feb 2025 23:01:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882888; bh=NblbH9LpjGVa+//DviO7apKqVlJXTv4KgAOmQhSycHU=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=ssTRAqc5SwiXViWbCW9DYE0U6KKOmHV2yx/lWZCCfOXAMf8fYTtPsN0cdW2rFNxeq GlDtKyQJ2AUCVcYji6uwflQsY/lRPs0sEd2P5gzodLd41x1jS2QLUwor6/1yyqG/8b Hp8wnv+ydhySmwCE2+IrPn05edWF82HLB0ngSVJYGA3ovZW8h0vqlVPsW6fR0WOxWS rWj+NeY694ypHKS6wgFbbNGnWAo4KRlvkvm4tkNlfGc/uTJKVVbevx+vWHDVqOnuFn z008XSHFsBldaeNOdGyDEw51NloJIhiVx3+xKGA79DQLEDhmuKdfHMfZeXoj5qCqZ9 fplHVaqPgfJIw== Date: Thu, 06 Feb 2025 15:01:27 -0800 Subject: [PATCH 18/22] xfs_repair: allow realtime files to have the reflink flag set From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888089207.2741962.17336773299406608051.stgit@frogsfrogsfrogs> In-Reply-To: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> References: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Now that we allow reflink on the realtime volume, allow that combination of inode flags if the feature's enabled. Note that we now allow inodes to have rtinherit even if there's no realtime volume, since the kernel has never restricted that. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- repair/dinode.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/repair/dinode.c b/repair/dinode.c index f49c735d34356b..5a1c8e8cb3ec11 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -3356,7 +3356,8 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), } if ((flags2 & XFS_DIFLAG2_REFLINK) && - (flags & (XFS_DIFLAG_REALTIME | XFS_DIFLAG_RTINHERIT))) { + !xfs_has_rtreflink(mp) && + (flags & XFS_DIFLAG_REALTIME)) { if (!uncertain) { do_warn( _("Cannot have a reflinked realtime inode %" PRIu64 "\n"), @@ -3388,7 +3389,8 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), } if ((flags2 & XFS_DIFLAG2_COWEXTSIZE) && - (flags & (XFS_DIFLAG_REALTIME | XFS_DIFLAG_RTINHERIT))) { + !xfs_has_rtreflink(mp) && + (flags & XFS_DIFLAG_REALTIME)) { if (!uncertain) { do_warn( _("Cannot have CoW extent size hint on a realtime inode %" PRIu64 "\n"), From patchwork Thu Feb 6 23:01:43 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13964072 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4D14D2417C0 for ; Thu, 6 Feb 2025 23:01:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882905; cv=none; b=RCUozITvH0TnD5L0FxwEhFKUAjUgHq4+2sjwYE61Mr44kKuQgZ+eiYlZLHyfEH/p2I7JLc7VDbyqljxsoJg+pnp8JyQGUQWQdIN7QzagviNpX0HNl2N8gmic5+1Ec2NA+uQXr/UpPfv5qQO64NxywO4yHji9f0F2RDITNaOnPNY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882905; c=relaxed/simple; bh=8Othlc5lyJEG45HMs44TN1mOoNSy2Z4RXAVK6Ys9cdM=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=dhmeufdsKwizd45GvE3hoNy1SDiBCkVGwSJAQyKeoGrEU2znE1DzjNjpHPREnY0NRbogBwV3iIoePCtBlAhxvtpPCHIubxOqg+0DwlT1WZZjp7IC3n1+eLnEOH9f2UD6Luc/6+oqlcfI4P8tmEt9xetx8KL7G07zRoaNF55jmGg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QJq8M1DC; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="QJq8M1DC" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B1259C4CEDD; Thu, 6 Feb 2025 23:01:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882903; bh=8Othlc5lyJEG45HMs44TN1mOoNSy2Z4RXAVK6Ys9cdM=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=QJq8M1DCyifX2Hitl2aWUSg6VUchfL64XP1Jd3dVzxIXbN3LvT2FWnkUZGOieozZa Qp7MgEbhQvMGQfpdMP16ZgTUST6KuZWgK7xssph5tkN39UkeP3c3RpHhgdvmjTe2W0 Aj/hb+wPQA2Izu/RUyooElo0D0ZrVV/5f+bgEFN9NJfkslhUvQOcow62KQJuW4ZRtD SCM2J5FtDtGVct+XLePhfMzsCREyzoBleSkKkT+vORxoAiEj7LX3e/H0k1OaavXvlC 0cM/KUd2X3IgYDbRzv0oyNqppbTWv3o8CJBNEfiWduYScEQXUSJci4d2e+QfjX9OSx 0DJI1CdH7rI9Q== Date: Thu, 06 Feb 2025 15:01:43 -0800 Subject: [PATCH 19/22] xfs_repair: validate CoW extent size hint on rtinherit directories From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888089222.2741962.6290838942184793559.stgit@frogsfrogsfrogs> In-Reply-To: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> References: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong XFS allows a sysadmin to change the rt extent size when adding a rt section to a filesystem after formatting. If there are any directories with both a cowextsize hint and rtinherit set, the hint could become misaligned with the new rextsize. Offer to fix the problem if we're in modify mode and the verifier didn't trip. If we're in dry run mode, we let the kernel fix it. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- repair/dinode.c | 64 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/repair/dinode.c b/repair/dinode.c index 5a1c8e8cb3ec11..8696a838087f1b 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -2961,6 +2961,47 @@ should_have_metadir_iflag( return false; } +static void +validate_cowextsize( + struct xfs_mount *mp, + struct xfs_dinode *dino, + xfs_ino_t lino, + int *dirty) +{ + uint16_t flags = be16_to_cpu(dino->di_flags); + uint64_t flags2 = be64_to_cpu(dino->di_flags2); + unsigned int value = be32_to_cpu(dino->di_cowextsize); + bool misaligned = false; + bool bad; + + /* + * XFS allows a sysadmin to change the rt extent size when adding a + * rt section to a filesystem after formatting. If there are any + * directories with both a cowextsize hint and rtinherit set, the + * hint could become misaligned with the new rextsize. + */ + if ((flags2 & XFS_DIFLAG2_COWEXTSIZE) && + (flags & XFS_DIFLAG_RTINHERIT) && + value % mp->m_sb.sb_rextsize > 0) + misaligned = true; + + /* Complain if the verifier fails. */ + bad = libxfs_inode_validate_cowextsize(mp, value, + be16_to_cpu(dino->di_mode), flags, flags2) != NULL; + if (bad || misaligned) { + do_warn( +_("Bad CoW extent size hint %u on inode %" PRIu64 ", "), + be32_to_cpu(dino->di_cowextsize), lino); + if (!no_modify) { + do_warn(_("resetting to zero\n")); + dino->di_flags2 &= ~cpu_to_be64(XFS_DIFLAG2_COWEXTSIZE); + dino->di_cowextsize = 0; + *dirty = 1; + } else + do_warn(_("would reset to zero\n")); + } +} + /* * returns 0 if the inode is ok, 1 if the inode is corrupt * check_dups can be set to 1 *only* when called by the @@ -3544,27 +3585,8 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), validate_extsize(mp, dino, lino, dirty); - /* - * Only (regular files and directories) with COWEXTSIZE flags - * set can have extsize set. - */ - if (dino->di_version >= 3 && - libxfs_inode_validate_cowextsize(mp, - be32_to_cpu(dino->di_cowextsize), - be16_to_cpu(dino->di_mode), - be16_to_cpu(dino->di_flags), - be64_to_cpu(dino->di_flags2)) != NULL) { - do_warn( -_("Bad CoW extent size %u on inode %" PRIu64 ", "), - be32_to_cpu(dino->di_cowextsize), lino); - if (!no_modify) { - do_warn(_("resetting to zero\n")); - dino->di_flags2 &= ~cpu_to_be64(XFS_DIFLAG2_COWEXTSIZE); - dino->di_cowextsize = 0; - *dirty = 1; - } else - do_warn(_("would reset to zero\n")); - } + if (dino->di_version >= 3) + validate_cowextsize(mp, dino, lino, dirty); /* nsec fields cannot be larger than 1 billion */ check_nsec("atime", lino, dino, &dino->di_atime, dirty); From patchwork Thu Feb 6 23:01:58 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13964073 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 116F22417C0 for ; Thu, 6 Feb 2025 23:01:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882920; cv=none; b=n0R1eY6bvxHfHL9FjpPA7F1ewScJr4q9E2kG2FymyvU5dYon0iXxgJk+hFSXG065wpQRX+e39Wv/EI4bRurfds2uIYy93tTEdFolmQ1MDvmAdP8FeJa6K7MhZpUEA8j8VtNKshFElpnAMe1R3SiZUYJoCBZTP0ovsUOQYoIGG+8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882920; c=relaxed/simple; bh=tqlFjDEPU+p94UtgLCxiF3UAxK1eibZ7xFwjdGivLtE=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=nLNL9G+IRFfDJ0HUll/H4KVfBUga1G36xnvJjU0ps9oh/Pwbs6tTgCoeJxxiObzIAXpM8NJXdmytO/jzCyoKriy/tNHd1t6oTsRmF/a7EavKwENpoOg5Ze7xs4G9sg1NFE0bfafsUKubDiag/C4XUxYnBLr94vXY9yEEVFS1uLE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=s014ikEB; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="s014ikEB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 693E0C4CEDD; Thu, 6 Feb 2025 23:01:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882919; bh=tqlFjDEPU+p94UtgLCxiF3UAxK1eibZ7xFwjdGivLtE=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=s014ikEBmwdLaI6U2gkb3etUdYnz7Ksp4n1iawY+DUoxj+mX1F5ORIeUqLaZS1x0j NA1sS5RG+c2CLUvX0rKjg88GQ237zdS5fTV1Y/QdkFAHaekOvmjgMnzyaNJtmJjTjl JG8iMSiw8uMjFOv8nhbUWkWKOqMV0pbxyT2jodFa/ZxVoIjLOdCfc3QrLEjVXtMWrX ROIU8kZShY1g5MsQs7ATlEpuGgugwsUJIsHknG2hcKC8sA9FP0AgsJq7XEOnOoBt9O Uhow93EAEDCG5vtiur84O9i6qIoEk0ddq7i4Mev7Ps9895Iyd24Nr0rPGRKDKgUezv FWTEMs17r+TIQ== Date: Thu, 06 Feb 2025 15:01:58 -0800 Subject: [PATCH 20/22] xfs_logprint: report realtime CUIs From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888089238.2741962.6117855127240783512.stgit@frogsfrogsfrogs> In-Reply-To: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> References: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Decode the CUI format just enough to report if an CUI targets the realtime device or not. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- logprint/log_misc.c | 2 ++ logprint/log_print_all.c | 8 ++++++++ logprint/log_redo.c | 24 +++++++++++++++++++----- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/logprint/log_misc.c b/logprint/log_misc.c index aaa9598616a308..144695753211aa 100644 --- a/logprint/log_misc.c +++ b/logprint/log_misc.c @@ -1027,12 +1027,14 @@ xlog_print_record( be32_to_cpu(op_head->oh_len)); break; } + case XFS_LI_CUI_RT: case XFS_LI_CUI: { skip = xlog_print_trans_cui(&ptr, be32_to_cpu(op_head->oh_len), continued); break; } + case XFS_LI_CUD_RT: case XFS_LI_CUD: { skip = xlog_print_trans_cud(&ptr, be32_to_cpu(op_head->oh_len)); diff --git a/logprint/log_print_all.c b/logprint/log_print_all.c index 56e765d64f2df4..1498ef97247d3d 100644 --- a/logprint/log_print_all.c +++ b/logprint/log_print_all.c @@ -430,9 +430,11 @@ xlog_recover_print_logitem( case XFS_LI_RUI: xlog_recover_print_rui(item); break; + case XFS_LI_CUD_RT: case XFS_LI_CUD: xlog_recover_print_cud(item); break; + case XFS_LI_CUI_RT: case XFS_LI_CUI: xlog_recover_print_cui(item); break; @@ -512,6 +514,12 @@ xlog_recover_print_item( case XFS_LI_CUI: printf("CUI"); break; + case XFS_LI_CUD_RT: + printf("CUD_RT"); + break; + case XFS_LI_CUI_RT: + printf("CUI_RT"); + break; case XFS_LI_BUD: printf("BUD"); break; diff --git a/logprint/log_redo.c b/logprint/log_redo.c index a0cc558499ae0b..89d7448342b33d 100644 --- a/logprint/log_redo.c +++ b/logprint/log_redo.c @@ -440,6 +440,7 @@ xlog_print_trans_cui( uint src_len, int continued) { + const char *item_name = "CUI?"; struct xfs_cui_log_format *src_f, *f = NULL; uint dst_len; uint nextents; @@ -480,8 +481,14 @@ xlog_print_trans_cui( goto error; } - printf(_("CUI: #regs: %d num_extents: %d id: 0x%llx\n"), - f->cui_size, f->cui_nextents, (unsigned long long)f->cui_id); + switch (f->cui_type) { + case XFS_LI_CUI: item_name = "CUI"; break; + case XFS_LI_CUI_RT: item_name = "CUI_RT"; break; + } + + printf(_("%s: #regs: %d num_extents: %d id: 0x%llx\n"), + item_name, f->cui_size, f->cui_nextents, + (unsigned long long)f->cui_id); if (continued) { printf(_("CUI extent data skipped (CONTINUE set, no space)\n")); @@ -520,6 +527,7 @@ xlog_print_trans_cud( char **ptr, uint len) { + const char *item_name = "CUD?"; struct xfs_cud_log_format *f; struct xfs_cud_log_format lbuf; @@ -528,11 +536,17 @@ xlog_print_trans_cud( memcpy(&lbuf, *ptr, min(core_size, len)); f = &lbuf; + + switch (f->cud_type) { + case XFS_LI_CUD: item_name = "CUD"; break; + case XFS_LI_CUD_RT: item_name = "CUD_RT"; break; + } + *ptr += len; if (len >= core_size) { - printf(_("CUD: #regs: %d id: 0x%llx\n"), - f->cud_size, - (unsigned long long)f->cud_cui_id); + printf(_("%s: #regs: %d id: 0x%llx\n"), + item_name, f->cud_size, + (unsigned long long)f->cud_cui_id); /* don't print extents as they are not used */ From patchwork Thu Feb 6 23:02:14 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13964074 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 93E4B2417C0 for ; Thu, 6 Feb 2025 23:02:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882938; cv=none; b=ZC4A4VgPVKmPgpbMgcgAXJcBWaZO2UBQQpILE3JvoLkDR3vfKjgrpCdLXzBfhoTfmzMsel5U7KGjxkYJLIfw60P71rwlavfxXM9QC82dmK5swyD2gNOOyCq9cKdzZXrss+mW7CPERj4wsOOikCHFAVyfD2h/gZzCC9VcDB8zg50= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882938; c=relaxed/simple; bh=MnFSh/sNeWPOgNrthk8YXp1LwOhPjso8VqYSVcIuUCA=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=cHnzmZVSUHFVvV2Q3d41slnC3kFe2EscBpfMext6/Tq5sGyKDBWbH6lkxkD5xv20otmJfeuZEklyShQ/7sZ7/ib0GjLydsAyxmziVkcNdC+B1/OQ+rJNZq5sS+wH55RIvexN/e62j5goVzrsrzJppOW3W2Ba6W+Sw+b6Wl4Is9Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=SIY6Vfwt; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="SIY6Vfwt" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 06B73C4CEDD; Thu, 6 Feb 2025 23:02:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882935; bh=MnFSh/sNeWPOgNrthk8YXp1LwOhPjso8VqYSVcIuUCA=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=SIY6Vfwtoum0H2Z75FH+NAlSa5Hbqym+LzQ4Vs8OB3fbjuPsvj5OLHUx4hEQg5Txc iccZfBQtalWma0RBEmrFpDJMTAVF8RM2tmxx5EUqCe4+OimzxPHtqpOagvihChSifC PzepVi93ISslbiQ/u8FO36zO7kmCq3h93Og77SkPie+qz3garrAGogNTq2ryrVyjMq gcASZksDpBLlGY5vWNh5mZl4FPL5wem+qECadpbZwEj7WpRLfFCveDrVJpQVFP5121 1XjlMl/Q3t92s5De1r1xqxvodzrynbZZE5xzevrHiBr1YoCCpxNc9284EUDpch8OZa mhrgtxtQkMlkg== Date: Thu, 06 Feb 2025 15:02:14 -0800 Subject: [PATCH 21/22] mkfs: validate CoW extent size hint when rtinherit is set From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888089253.2741962.7311263148977317330.stgit@frogsfrogsfrogs> In-Reply-To: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> References: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Extent size hints exist to nudge the behavior of the file data block allocator towards trying to make aligned allocations. Therefore, it doesn't make sense to allow a hint that isn't a multiple of the fundamental allocation unit for a given file. This means that if the sysadmin is formatting with rtinherit set on the root dir, validate_cowextsize_hint needs to check the hint value on a simulated realtime file to make sure that it's correct. This hasn't been necessary in the past since one cannot have a CoW hint without a reflink filesystem, and we previously didn't allow rt reflink filesystems. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- mkfs/xfs_mkfs.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index c8042261328171..9239109434d748 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -2985,6 +2985,26 @@ _("illegal CoW extent size hint %lld, must be less than %u.\n"), min(XFS_MAX_BMBT_EXTLEN, mp->m_sb.sb_agblocks / 2)); usage(); } + + /* + * If the value is to be passed on to realtime files, revalidate with + * a realtime file so that we know the hint and flag that get passed on + * to realtime files will be correct. + */ + if (!(cli->fsx.fsx_xflags & FS_XFLAG_RTINHERIT)) + return; + + fa = libxfs_inode_validate_cowextsize(mp, cli->fsx.fsx_cowextsize, + S_IFREG, XFS_DIFLAG_REALTIME, flags2); + + if (fa) { + fprintf(stderr, +_("illegal CoW extent size hint %lld, must be less than %u and a multiple of %u. %p\n"), + (long long)cli->fsx.fsx_cowextsize, + min(XFS_MAX_BMBT_EXTLEN, mp->m_sb.sb_agblocks / 2), + mp->m_sb.sb_rextsize, fa); + usage(); + } } /* Complain if this filesystem is not a supported configuration. */ From patchwork Thu Feb 6 23:02:30 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13964075 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1082E2417C0 for ; Thu, 6 Feb 2025 23:02:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882952; cv=none; b=m8zoEf8NYFJUXRq8go7LPAaJ7VFMHSJmPAseFTuUk43WyNOs779xXkIzlk4Sn0f4Og8XbsXUnr8twK091aH7NAp/OPX1Iz4yzffKJvsfdRbdoKwWTbWzlFZvOro655oVPUctESX8JcV/obPcyumGLgYFrxN9PfBFG6VDabH+FYE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882952; c=relaxed/simple; bh=ezEdjI0Akf98Ov87OqmRFfGjguFgGatB6JhHtp+jkWI=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Zl71k6hkYdRZh5MhwMceKKRURzmrJuD2Ad3Hdkwb/+Oc6HvvpIFjN2158d1hN2DJw84PhcgAYzx3YEFZM10W2L/u9XMpZ9S/FxYgAYhOZ5vcV+pI+82gQDrLh7qpEsGPXqHI8m/45/fQ7vuhaPOuotZFp0fBJwKIBNBfwq2s8SE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Ae9xZ7Fr; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Ae9xZ7Fr" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 93F50C4CEDF; Thu, 6 Feb 2025 23:02:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882950; bh=ezEdjI0Akf98Ov87OqmRFfGjguFgGatB6JhHtp+jkWI=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=Ae9xZ7FrLucOirau8GE9ziw6jwLvN66SMqx+iMINYFNznPgANWUdUjcsVT0xx8IUt mSGI3iX50G0AgA7FgjKobvVJUOOcxkWWtHJ6SI5Isj1W8zxwMqt/25v0y1Qpgyqk0z kTx7NRSex2QM+z7UfQdR13DDIWXd1BiFSHlI+/CRK+WwZICAyN6Qthibhwejdme7Zn yIVT8l315Zy+QQMsaLeOHwf66EzTDNr8loxWhgCmJgNaXrX7LWJxTheKREH2x9fDDZ g4HqE1OS+/EbIAMD3OB9YK2mZMTlh9mlSSrkW50bNHjDLlDOFK32G3dYf0nzox5b2m TaoLbV4EQSJXA== Date: Thu, 06 Feb 2025 15:02:30 -0800 Subject: [PATCH 22/22] mkfs: enable reflink on the realtime device From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888089269.2741962.12417664592407560122.stgit@frogsfrogsfrogs> In-Reply-To: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> References: <173888088900.2741962.15299153246552129567.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Allow the creation of filesystems with both reflink and realtime volumes enabled. For now we don't support a realtime extent size > 1. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- libxfs/init.c | 4 +-- libxfs/libxfs_api_defs.h | 1 + mkfs/xfs_mkfs.c | 63 ++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 60 insertions(+), 8 deletions(-) diff --git a/libxfs/init.c b/libxfs/init.c index 00bd46a6013e28..5b45ed3472762c 100644 --- a/libxfs/init.c +++ b/libxfs/init.c @@ -305,9 +305,9 @@ rtmount_init( if (mp->m_sb.sb_rblocks == 0) return 0; - if (xfs_has_reflink(mp)) { + if (xfs_has_reflink(mp) && mp->m_sb.sb_rextsize > 1) { fprintf(stderr, - _("%s: Reflink not compatible with realtime device. Please try a newer xfsprogs.\n"), + _("%s: Reflink not compatible with realtime extent size > 1. Please try a newer xfsprogs.\n"), progname); return -1; } diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index 66cbb34f05a48f..530feef2a47db8 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -323,6 +323,7 @@ #define xfs_rtrefcountbt_absolute_maxlevels libxfs_rtrefcountbt_absolute_maxlevels #define xfs_rtrefcountbt_calc_reserves libxfs_rtrefcountbt_calc_reserves #define xfs_rtrefcountbt_calc_size libxfs_rtrefcountbt_calc_size +#define xfs_rtrefcountbt_calc_reserves libxfs_rtrefcountbt_calc_reserves #define xfs_rtrefcountbt_commit_staged_btree libxfs_rtrefcountbt_commit_staged_btree #define xfs_rtrefcountbt_create libxfs_rtrefcountbt_create #define xfs_rtrefcountbt_droot_maxrecs libxfs_rtrefcountbt_droot_maxrecs diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index 9239109434d748..c794f918573f91 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -2671,12 +2671,36 @@ _("inode btree counters not supported without finobt support\n")); } if (cli->xi->rt.name) { - if (cli->sb_feat.reflink && cli_opt_set(&mopts, M_REFLINK)) { - fprintf(stderr, -_("reflink not supported with realtime devices\n")); - usage(); + if (cli->rtextsize && cli->sb_feat.reflink) { + if (cli_opt_set(&mopts, M_REFLINK)) { + fprintf(stderr, +_("reflink not supported on realtime devices with rt extent size specified\n")); + usage(); + } + cli->sb_feat.reflink = false; + } + if (cfg->blocksize < XFS_MIN_RTEXTSIZE && cli->sb_feat.reflink) { + if (cli_opt_set(&mopts, M_REFLINK)) { + fprintf(stderr, +_("reflink not supported on realtime devices with blocksize %d < %d\n"), + cli->blocksize, + XFS_MIN_RTEXTSIZE); + usage(); + } + cli->sb_feat.reflink = false; + } + if (!cli->sb_feat.metadir && cli->sb_feat.reflink) { + if (cli_opt_set(&mopts, M_REFLINK) && + cli_opt_set(&mopts, M_METADIR)) { + fprintf(stderr, +_("reflink not supported on realtime devices without metadir feature\n")); + usage(); + } else if (cli_opt_set(&mopts, M_REFLINK)) { + cli->sb_feat.metadir = true; + } else { + cli->sb_feat.reflink = false; + } } - cli->sb_feat.reflink = false; if (!cli->sb_feat.metadir && cli->sb_feat.rmapbt) { if (cli_opt_set(&mopts, M_RMAPBT) && @@ -2874,6 +2898,19 @@ validate_rtextsize( usage(); } cfg->rtextblocks = (xfs_extlen_t)(rtextbytes >> cfg->blocklog); + } else if (cli->sb_feat.reflink && cli->xi->rt.name) { + /* + * reflink doesn't support rt extent size > 1FSB yet, so set + * an extent size of 1FSB. Make sure we still satisfy the + * minimum rt extent size. + */ + if (cfg->blocksize < XFS_MIN_RTEXTSIZE) { + fprintf(stderr, + _("reflink not supported on rt volume with blocksize %d\n"), + cfg->blocksize); + usage(); + } + cfg->rtextblocks = 1; } else { /* * If realtime extsize has not been specified by the user, @@ -2905,6 +2942,12 @@ validate_rtextsize( } } ASSERT(cfg->rtextblocks); + + if (cli->sb_feat.reflink && cfg->rtblocks > 0 && cfg->rtextblocks > 1) { + fprintf(stderr, +_("reflink not supported on realtime with extent sizes > 1\n")); + usage(); + } } /* Validate the incoming extsize hint. */ @@ -5087,11 +5130,19 @@ check_rt_meta_prealloc( error = -libxfs_metafile_resv_init(rtg_rmap(rtg), ask); if (error) prealloc_fail(mp, error, ask, _("realtime rmap btree")); + + ask = libxfs_rtrefcountbt_calc_reserves(mp); + error = -libxfs_metafile_resv_init(rtg_refcount(rtg), ask); + if (error) + prealloc_fail(mp, error, ask, + _("realtime refcount btree")); } /* Unreserve the realtime metadata reservations. */ - while ((rtg = xfs_rtgroup_next(mp, rtg))) + while ((rtg = xfs_rtgroup_next(mp, rtg))) { libxfs_metafile_resv_free(rtg_rmap(rtg)); + libxfs_metafile_resv_free(rtg_refcount(rtg)); + } /* Unreserve the per-AG reservations. */ while ((pag = xfs_perag_next(mp, pag)))