From patchwork Thu Feb 6 22:49:59 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: 13964018 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 BB9B12376E2 for ; Thu, 6 Feb 2025 22:50:00 +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=1738882200; cv=none; b=krzq8WZWcuMqJoGqDlsuXaHQK7tYCMhwlM/rkG/AfJKSBfKgp8TpM9sJvUhce9HnarUgnFq+en3b9gA9BmmAf4UJSFxetxSnbkKhHn5LhVbxUncEkuog0p64BSLmPYJ9BDaDEz1yfeJGXrk++q42cpeb8xY9SYcFWzJAHzwB8qc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882200; c=relaxed/simple; bh=0yhEhrlfhJt8YJVoEgqqE0sxH32+NoajAYVJLGx0JUY=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=AQaYg6VYCDe9AFDX34qFxyFLq+pdBbOa0TtdlNM8AZ4lorh8uN3RwTgFmDi3Ab5blw5vb+PdDWrKdOrswxHSWssTZrEXKcym3BwZFNFZKlAcNMKQFbmHvSq6UDdOsIxsGIfmeQLUq3rv5RjzZqEb3D813m04rJ5bLs5r1og5WxY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qMJZw3Nz; 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="qMJZw3Nz" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 24C84C4CEDD; Thu, 6 Feb 2025 22:50:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882200; bh=0yhEhrlfhJt8YJVoEgqqE0sxH32+NoajAYVJLGx0JUY=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=qMJZw3Nz2Y5SlOM8kbUxasN2bBNrUdNyigW+PAIiqGVII1lAxEmP06XAe7WvdVy2v j8JSUb6rVp+uSr3AHnMJcBwfoFa3Rq9CEkA02i6YvcA8n+rxQx2SWKSVSSGhlb/b70 T+Cy+pelq47qj7oBK8DfgLpG+tnEfgfddi1iycGXFCIejBJdPyOt7/JS9ETrKpwa61 6/yhx0DNRBwPntrtSDK245UeS+Vnocfs3keHlXei3siNVoPN1eI+i6u7eFRhpju7F1 /S5M6dViacM7OYRE4ygjyUyITt9/YYU5XlyRl8fmgctMz+04rnUbcWIqUHciSHKlIT pTFs/KRcKHOrA== Date: Thu, 06 Feb 2025 14:49:59 -0800 Subject: [PATCH 01/27] libxfs: compute the rt rmap 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: <173888088111.2741033.980299615772826570.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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 rmap btree height information when we set up libxfs. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- libxfs/init.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/libxfs/init.c b/libxfs/init.c index 16291466ac86d3..02a4cfdf38b198 100644 --- a/libxfs/init.c +++ b/libxfs/init.c @@ -21,6 +21,7 @@ #include "xfs_trans.h" #include "xfs_rmap_btree.h" #include "xfs_refcount_btree.h" +#include "xfs_metafile.h" #include "libfrog/platform.h" #include "libfrog/util.h" #include "libxfs/xfile.h" @@ -598,6 +599,14 @@ xfs_agbtree_compute_maxlevels( mp->m_agbtree_maxlevels = max(levels, mp->m_refc_maxlevels); } +/* Compute maximum possible height for realtime btree types for this fs. */ +static inline void +xfs_rtbtree_compute_maxlevels( + struct xfs_mount *mp) +{ + mp->m_rtbtree_maxlevels = mp->m_rtrmap_maxlevels; +} + /* Compute maximum possible height of all btrees. */ void libxfs_compute_all_maxlevels( @@ -611,10 +620,11 @@ libxfs_compute_all_maxlevels( igeo->attr_fork_offset = xfs_bmap_compute_attr_offset(mp); xfs_ialloc_setup_geometry(mp); xfs_rmapbt_compute_maxlevels(mp); + xfs_rtrmapbt_compute_maxlevels(mp); xfs_refcountbt_compute_maxlevels(mp); xfs_agbtree_compute_maxlevels(mp); - + xfs_rtbtree_compute_maxlevels(mp); } /* Mount the metadata files under the metadata directory tree. */ From patchwork Thu Feb 6 22:50:15 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: 13964019 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 59A192376E6 for ; Thu, 6 Feb 2025 22:50: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=1738882218; cv=none; b=h4juig2vrZqBs7gVk7Yni/ubC0BCBRyeZk8KJVo5updACfhfAftEvs3apsBd/NFSNipH9s69tfJ6P7HrwI8TIU/KtvyuGXkJddajstTJ4lu3l0L/GC9zDwe2ysERGVlTpjV0PMWWD7usyAQczkDq2lxky3h3wD0o/dpPwwE1uLM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882218; c=relaxed/simple; bh=nr368d2LlXF6J+WpbWGejMyA+xXMjHVr97WlfNgm4ow=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=nEIZqhuf8oNtpzKfd5m0SSCi1f0LfZkFgYAANLv3MmzLDA/y/UHxu8PxOPxWCsZ5zgmXfdS/octyDfo9E83un9YqXQngJ4nQIQTjGwKqSkk5taLp58NEcj9UaY0aa2KE0ePXeYCkIuj/K7358bj8YSQd4s7pfieZGlYGFup1tX4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cnvm3WXo; 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="cnvm3WXo" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C04D9C4CEDD; Thu, 6 Feb 2025 22:50:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882215; bh=nr368d2LlXF6J+WpbWGejMyA+xXMjHVr97WlfNgm4ow=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=cnvm3WXoy+GmzfrOIjvpHS8SGLp7pbZNeGPetvwJKDK5afnwiiEwZ6D4x2xpvBnAh 2OOyT16DhEYek4R3bOTtB+dbon3Ipm3sOF2iUdyirZiRJ+NF9urQEs9ZYSL/uk3V/V 54En8+toajVUGs/Vtp3NDa8FSz2rGn8wowNg3B8SQKjIL9x0w0ZOk2k7f4pgwFdWfG OM5NzJUleLTzjoG8hDWGpnmG/w+cyU8kZn66Ai2kHz2ofvfRO7lqx4pVZNonXk1Tet bycopMJKenBeOGz7sV6LMPpVDToYwTvgrwDlhKJ71giwEJeT/ns1fl51P6btehAhTV PJYFnX5DgO1Qg== Date: Thu, 06 Feb 2025 14:50:15 -0800 Subject: [PATCH 02/27] libxfs: add a realtime flag to the rmap 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: <173888088127.2741033.14339847563200590694.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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 rmap update (RUI) log items with a new realtime flag that indicates that the updates apply against the realtime rmapbt. We'll wire up the actual rmap code later. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- libxfs/defer_item.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/libxfs/defer_item.c b/libxfs/defer_item.c index 9db0e471cba69c..1ca9ce15ecfe3d 100644 --- a/libxfs/defer_item.c +++ b/libxfs/defer_item.c @@ -29,6 +29,7 @@ #include "xfs_exchmaps.h" #include "defer_item.h" #include "xfs_group.h" +#include "xfs_rtgroup.h" /* Dummy defer item ops, since we don't do logging. */ @@ -289,9 +290,18 @@ xfs_rmap_defer_add( trace_xfs_rmap_defer(mp, ri); + /* + * Deferred rmap 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_bmap.br_startblock, - XG_TYPE_AG); - xfs_defer_add(tp, &ri->ri_list, &xfs_rmap_update_defer_type); + ri->ri_realtime ? XG_TYPE_RTG : XG_TYPE_AG); + xfs_defer_add(tp, &ri->ri_list, ri->ri_realtime ? + &xfs_rtrmap_update_defer_type : + &xfs_rmap_update_defer_type); } /* Cancel a deferred rmap update. */ @@ -356,6 +366,27 @@ const struct xfs_defer_op_type xfs_rmap_update_defer_type = { .cancel_item = xfs_rmap_update_cancel_item, }; +/* Clean up after calling xfs_rtrmap_finish_one. */ +STATIC void +xfs_rtrmap_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_rtrmap_update_defer_type = { + .name = "rtrmap", + .create_intent = xfs_rmap_update_create_intent, + .abort_intent = xfs_rmap_update_abort_intent, + .create_done = xfs_rmap_update_create_done, + .finish_item = xfs_rmap_update_finish_item, + .finish_cleanup = xfs_rtrmap_finish_one_cleanup, + .cancel_item = xfs_rmap_update_cancel_item, +}; + /* Reference Counting */ static inline struct xfs_refcount_intent *ci_entry(const struct list_head *e) From patchwork Thu Feb 6 22:50: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: 13964020 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 E1F1323716E for ; Thu, 6 Feb 2025 22:50:31 +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=1738882232; cv=none; b=fPtiSSoNw6uhpLIvTpIJLDnEKxe4TKdBOo2bLi/NB6bzRDhjUlx+kTZaVS1cfIz0mtlBCE6VJXmMW8GhsqNt0WTzSrq9vGYHTCYzb/AlX9j81n92onfDIhHvCoC9Gr7FN27mZRaOfyWdqN/A2ucoD2Ql9Y3omJtql7wCJh1aob4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882232; c=relaxed/simple; bh=82ANfVjCKEFwbfsfBHQ3QVEDd2yeEU07BNDL9MvkIH8=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=AFw+TiviobGC7Py+jmGWlLtaeLsmuosVSu29tJ67QHYKtVy39NxZNb4R611nkWkQbKsKz94S9QdCcNuETNccyXgDpDFSCi8JuCe3LuSNTS4TX/fOBWpnMYAFsxHyQ9mO0EUul4rf+7s3jRsrT24a7ZTwGWPQMcFzjGtVwJI4Lew= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=sefPnzSo; 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="sefPnzSo" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5B5FDC4CEEE; Thu, 6 Feb 2025 22:50:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882231; bh=82ANfVjCKEFwbfsfBHQ3QVEDd2yeEU07BNDL9MvkIH8=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=sefPnzSoCYrMwrbTqCdf7XqmePidfgOZtO7x1cAKhwRccyZv05ROI0qIxAE5IUYqS HrPsBBRg+qUhll939M/S275c9shpjHeulpSwXoSVaebA/ncmVs1kly2xK28dnO24eT BEx5sQ7f8/1fqnqC+hYbOwwQoWAhz2j8It/Nvurea2gp5Dx8GObj5RHH6/VcV8SlHw 0ZSDJk/krmeH0HncCfVhTRsc/H/DDi+yIg/HnB/EOQM7S05LB9vmoVXbcR5CX7b6NC WVK2rdBLSJQktpnXtZ7R7m9e4tdNyiNa9eavZ1C/SYCwT7lXr5olh8JMHiy5sgEgEc NYYGgyPJo6J2Q== Date: Thu, 06 Feb 2025 14:50:30 -0800 Subject: [PATCH 03/27] libfrog: enable scrubbing of the realtime rmap From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088141.2741033.7748289284781442379.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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 rtrmapbt and its metadata directory tree path too. 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 129f592e108ae1..11d467666d6b5a 100644 --- a/libfrog/scrub.c +++ b/libfrog/scrub.c @@ -164,6 +164,11 @@ const struct xfrog_scrub_descr xfrog_scrubbers[XFS_SCRUB_TYPE_NR] = { .descr = "realtime group superblock", .group = XFROG_SCRUB_GROUP_RTGROUP, }, + [XFS_SCRUB_TYPE_RTRMAPBT] = { + .name = "rtrmapbt", + .descr = "realtime reverse mapping btree", + .group = XFROG_SCRUB_GROUP_RTGROUP, + }, }; const struct xfrog_scrub_descr xfrog_metapaths[XFS_SCRUB_METAPATH_NR] = { @@ -207,6 +212,11 @@ const struct xfrog_scrub_descr xfrog_metapaths[XFS_SCRUB_METAPATH_NR] = { .descr = "project quota file", .group = XFROG_SCRUB_GROUP_FS, }, + [XFS_SCRUB_METAPATH_RTRMAPBT] = { + .name = "rtrmapbt", + .descr = "rtgroup rmap 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 c8cdb98de5457b..e6906cbd37d0b3 100644 --- a/scrub/repair.c +++ b/scrub/repair.c @@ -533,6 +533,7 @@ repair_item_difficulty( switch (scrub_type) { case XFS_SCRUB_TYPE_RMAPBT: + case XFS_SCRUB_TYPE_RTRMAPBT: ret |= REPAIR_DIFFICULTY_SECONDARY; break; case XFS_SCRUB_TYPE_SB: From patchwork Thu Feb 6 22:50:46 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: 13964021 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 8A57C1A5B94 for ; Thu, 6 Feb 2025 22:50:47 +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=1738882247; cv=none; b=bLJEPHMmN0DmcaV4RuNkPUSWS7uoRjK5HvARtzv/rPNOP/j4XL2f3+k6jDCgCfETOaKUlkg8K29xFPJzRIsAWWv6HBo8w56Rvs+Y5C4rveF8diOhPAndOYcD130YAZoq/vfbPXqhhkzHt7TVSgNPpGHxKK59l9WI1y+PGsrF4Eo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882247; c=relaxed/simple; bh=ZKDinG5M9iION68j7zwiwKAtH030s/baXr5yJAPLWHo=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=jKGh6uqwktyZdO+f2CIRnunFKdYRBO41VNbGcxF1gC/k0wSSPwUgWHs36kAzMRfhmHmeyetqH+7qf/Zvr60xstnbijqziN5yKfBuaCctX8om/y0kExMD7l5tJxhO7rM2XnoruXC1D252lG7slDmuVrN0obMKgb8ypV/AR6eM32U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NtIqO3Wp; 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="NtIqO3Wp" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EFC2FC4CEDF; Thu, 6 Feb 2025 22:50:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882247; bh=ZKDinG5M9iION68j7zwiwKAtH030s/baXr5yJAPLWHo=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=NtIqO3Wpp5WFyWpwa3yQhqRRKNtKdjGriOQZvv7eGFjed2dY4vY8CeDIzxIBI0rXT UzkfS9zikL8JGXtLgTaSvVn+WrycKobeZSDwhZfjv2EUts/9HQn3GF9q1hJ/+/p3d/ fKRK4ETIae8qRkOtfqGdWS2wSN501y8DH42MQ1PoJPYZqKIIMBfq8CQ9rdUTmSiRiE jmUSma1JEo15d3osvxstyjBLf597tfqzwSCswhEz2FgswALCk6fyu4damGvhH9CCra yGLHxNayTqk6EqQreSQrayccUPrRLy+pl/elZtt4EAqKMFMSGctPTojBvGCzTq5H63 nIiQv3Sx5uZ7Q== Date: Thu, 06 Feb 2025 14:50:46 -0800 Subject: [PATCH 04/27] man: document userspace API changes due to rt rmap From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088157.2741033.18009447992987469682.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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 rmap support. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- man/man2/ioctl_xfs_rtgroup_geometry.2 | 3 +++ man/man2/ioctl_xfs_scrub_metadata.2 | 12 ++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/man/man2/ioctl_xfs_rtgroup_geometry.2 b/man/man2/ioctl_xfs_rtgroup_geometry.2 index c4b0de94453558..37e229b4335459 100644 --- a/man/man2/ioctl_xfs_rtgroup_geometry.2 +++ b/man/man2/ioctl_xfs_rtgroup_geometry.2 @@ -73,6 +73,9 @@ .SH DESCRIPTION .TP .B XFS_RTGROUP_GEOM_SICK_SUMMARY Realtime summary for this group. +.TP +.B XFS_RTGROUP_GEOM_SICK_RTRMAPBT +Reverse mapping btree for this group. .RE .SH RETURN VALUE On error, \-1 is returned, and diff --git a/man/man2/ioctl_xfs_scrub_metadata.2 b/man/man2/ioctl_xfs_scrub_metadata.2 index 545e3fcbac320e..f06bb98de708a4 100644 --- a/man/man2/ioctl_xfs_scrub_metadata.2 +++ b/man/man2/ioctl_xfs_scrub_metadata.2 @@ -180,11 +180,12 @@ .SH DESCRIPTION .PP .nf .B XFS_SCRUB_TYPE_RTBITMAP -.fi -.TP .B XFS_SCRUB_TYPE_RTSUM -Examine the realtime block bitmap and realtime summary inodes for -corruption. +.fi +.TP +.B XFS_SCRUB_TYPE_RTRMAPBT +Examine a given realtime allocation group's free space bitmap, summary file, +or reverse mapping btree, respectively. .PP .nf @@ -246,6 +247,9 @@ .SH DESCRIPTION .TP .B XFS_SCRUB_METAPATH_PRJQUOTA Project quota file. +.TP +.B XFS_SCRUB_METAPATH_RTRMAPBT +Realtime rmap btree file. .RE The values of From patchwork Thu Feb 6 22:51:02 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: 13964022 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 BEF592376E6 for ; Thu, 6 Feb 2025 22:51: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=1738882262; cv=none; b=IRpMxU1wLNLnw5iBq/tDV5mf1FQC4XEmhO9lRVbPv6vK6jSYwCF6RCjRzuqC7zZKpobigGuC/yo/RCk+0xAF88aIN465nD4b+oDCnYA2jfH7deVHQkBufgMtLVlMxgtKfcqVNCPRM7DGKZr4n9d4ttEDeEh59nQfPkdGbzj9OWc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882262; c=relaxed/simple; bh=Yh+dsNuw+AYg16qsqlYbAmAJg7yIuz+E8rUV96mAFBQ=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=j3DcJzWIwbAE2sjfSTfghImd4xsSt//tphLuGzHgY5r4nzjmvefLB7hPmV49sfN15C+GdBIl26A/rmEMDK6oFq1yjMhCSOdl8S2/cwjHY9lNBPxSuMpwKDFoPGGEIJdSzNcb8gy5g+yhN4gqcxd5DM2OXa1cDjxm9w/MFFX4CHo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LlyChZbz; 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="LlyChZbz" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 978BAC4CEDD; Thu, 6 Feb 2025 22:51:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882262; bh=Yh+dsNuw+AYg16qsqlYbAmAJg7yIuz+E8rUV96mAFBQ=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=LlyChZbzVkxzfSxzC9Peduw2EwxQnbkIDQvLWa+IeBV9Ocn3LS6Ptu5aEbq8TDn6x XnTnTmGzN4BctixLf9MCC86dUSaVk0/pPT4HqhNXDN0In8DtBkh/1WFGWWPY2JbCf2 Y++nqyY66iE6+3/sNMXmSKQ0P5ruVFCcsW7mXrcuJkP2gBuzYQoIqCNF50iepRm7FU A4nXgQVxCuDzx8FnraALrx4ptjZI9MWIwMz1Mww4bv0W4ipr4fjPHjqcTb7N9eWJ2i zgCBLdY3AymTAK44wmTcIn9alwGeCywHJG6vF0MkQwykEroxYo1PvXnZ5SLWqFLYT/ GdPVLI8/CRcSw== Date: Thu, 06 Feb 2025 14:51:02 -0800 Subject: [PATCH 05/27] xfs_db: compute average btree height From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088172.2741033.4230304960811159164.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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 the btree height assuming that the blocks are 75% full. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- db/btheight.c | 31 +++++++++++++++++++++++++++++++ man/man8/xfs_db.8 | 6 +++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/db/btheight.c b/db/btheight.c index 98165b522e4f6f..0456af08b39edf 100644 --- a/db/btheight.c +++ b/db/btheight.c @@ -259,6 +259,7 @@ _("%s: pointer size must be less than selected block size (%u bytes).\n"), #define REPORT_MAX (1 << 0) #define REPORT_MIN (1 << 1) #define REPORT_ABSMAX (1 << 2) +#define REPORT_AVG (1 << 3) static void report_absmax(const char *tag) @@ -317,6 +318,34 @@ _("%s: best case per %u-byte block: %u records (leaf) / %u keyptrs (node)\n"), calc_height(nr_records, records_per_block); } + if (report_what & REPORT_AVG) { + records_per_block[0] *= 3; + records_per_block[0] /= 4; + records_per_block[1] *= 3; + records_per_block[1] /= 4; + + if (records_per_block[0] < 2) { + fprintf(stderr, +_("%s: cannot calculate average case scenario due to leaf geometry underflow.\n"), + tag); + return; + } + + if (records_per_block[1] < 4) { + fprintf(stderr, +_("%s: cannot calculate average case scenario due to node geometry underflow.\n"), + tag); + return; + } + + printf( +_("%s: average case per %u-byte block: %u records (leaf) / %u keyptrs (node)\n"), + tag, blocksize, records_per_block[0], + records_per_block[1]); + + calc_height(nr_records, records_per_block); + } + if (report_what & REPORT_MIN) { records_per_block[0] /= 2; records_per_block[1] /= 2; @@ -393,6 +422,8 @@ btheight_f( report_what = REPORT_MAX; else if (!strcmp(optarg, "absmax")) report_what = REPORT_ABSMAX; + else if (!strcmp(optarg, "avg")) + report_what = REPORT_AVG; else { btheight_help(); return 0; diff --git a/man/man8/xfs_db.8 b/man/man8/xfs_db.8 index 06f4464a928596..acee900adbda50 100644 --- a/man/man8/xfs_db.8 +++ b/man/man8/xfs_db.8 @@ -519,7 +519,7 @@ .SH COMMANDS Dump all keys and pointers in intermediate btree nodes, and all records in leaf btree nodes. .RE .TP -.BI "btheight [\-b " blksz "] [\-n " recs "] [\-w " max "|" min "|" absmax "] btree types..." +.BI "btheight [\-b " blksz "] [\-n " recs "] [\-w " max "|" min "|" absmax "|" avg "] btree types..." For a given number of btree records and a btree type, report the number of records and blocks for each level of the btree, and the total number of blocks. The btree type must be given after the options. @@ -562,6 +562,10 @@ .SH COMMANDS .B \-w min shows only the worst case scenario, which is when the btree blocks are half full. +.TP +.B \-w avg +shows only the average case scenario, which is when the btree blocks are +three quarters full. .RE .TP .BI "convert " "type number" " [" "type number" "] ... " type From patchwork Thu Feb 6 22:51: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: 13964023 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 5E24923716E for ; Thu, 6 Feb 2025 22:51: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=1738882278; cv=none; b=nvdDnl4w9zfVCdPu79m+v+Gy13qBX0ea7Wr2W99Kj4VEQC2jLTlhQ8AIHHnXk+gvbxQa/JkCF3XYl7ZwH6vFjEPdbSbEv8xxKZuf8LLh8xS++RkjzvX4mBjiYkApkNIAzlthDwyjBL43FFf1qzdbLoUmyQg05TJ2qBQE7Nv0nDk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882278; c=relaxed/simple; bh=Ro0THzMcX7jyh7GqQ/vfd7X4eJ6BOfUlpXdVvLJt718=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=BfZ8Irdflbnqsx+UCi1ZVP4uhq8eamjrOrOC0IE1ffuNNNRBPXdiq3rJrT8Yrb9H1NAkBlbIsA+XopJh69LlD9hTVHDHA7mqMkGNqYZGIoVLt0jlOaNAdeZJbXGxXX/mxYWgVzB1LLrumA3QMOzQT3+s/1GJDhpt9xCBxszzjhg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=b1IKwHYL; 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="b1IKwHYL" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 35071C4CEDD; Thu, 6 Feb 2025 22:51:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882278; bh=Ro0THzMcX7jyh7GqQ/vfd7X4eJ6BOfUlpXdVvLJt718=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=b1IKwHYLf0rTbz+H4kvhCUvPJyUpAtreEjQbkP8vC0QQEMDhR6O9KsNucHw671lkl 1IYIftz8CunZt6klu2zQC2fOWz7q88BlLE+H97QCwNO8tGoSDqkhuDC/Drr7KhbwlF ycURMTZ60RJxTPvNieiw3bzyvXJ5cyQO400iVC/9zJeVChM2NBHT6ltkWzSCPgAxH/ LPCUs25XwZi1NcvRv3TFXrqMjZ+jbv1yHh+LD8RKEponOevnlf6+xaf9LvwY+B/dnK FFiYW02zrKYxIT6NMBQTNLdrUNFEDmhmD8gKiw6XNeQUqbl6SVTrc+fXfC+8bLpE0x /jDD0Mbe+UfkA== Date: Thu, 06 Feb 2025 14:51:17 -0800 Subject: [PATCH 06/27] xfs_db: don't abort when bmapping on a non-extents/bmbt fork From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088187.2741033.14219812382210540594.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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're going to introduce new fork formats, so let's fix the problem that xfs_db's bmap command aborts when the fork format isn't one of the existing ones. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- db/bmap.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/db/bmap.c b/db/bmap.c index 1c5694c3f7d281..e8dd98d686cb98 100644 --- a/db/bmap.c +++ b/db/bmap.c @@ -65,16 +65,18 @@ bmap( fmt = (enum xfs_dinode_fmt)XFS_DFORK_FORMAT(dip, whichfork); typ = whichfork == XFS_DATA_FORK ? TYP_BMAPBTD : TYP_BMAPBTA; ASSERT(typtab[typ].typnm == typ); - ASSERT(fmt == XFS_DINODE_FMT_LOCAL || fmt == XFS_DINODE_FMT_EXTENTS || - fmt == XFS_DINODE_FMT_BTREE); - if (fmt == XFS_DINODE_FMT_EXTENTS) { + switch (fmt) { + case XFS_DINODE_FMT_LOCAL: + break; + case XFS_DINODE_FMT_EXTENTS: nextents = xfs_dfork_nextents(dip, whichfork); xp = (xfs_bmbt_rec_t *)XFS_DFORK_PTR(dip, whichfork); for (ep = xp; ep < &xp[nextents] && n < nex; ep++) { if (!bmap_one_extent(ep, &curoffset, eoffset, &n, bep)) break; } - } else if (fmt == XFS_DINODE_FMT_BTREE) { + break; + case XFS_DINODE_FMT_BTREE: push_cur(); rblock = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork); fsize = XFS_DFORK_SIZE(dip, mp, whichfork); @@ -114,6 +116,13 @@ bmap( block = (struct xfs_btree_block *)iocur_top->data; } pop_cur(); + break; + default: + dbprintf( + _("%s fork format %u does not support indexable blocks\n"), + whichfork == XFS_DATA_FORK ? "data" : "attr", + fmt); + break; } pop_cur(); *nexp = n; From patchwork Thu Feb 6 22:51: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: 13964024 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 7627522FF5D for ; Thu, 6 Feb 2025 22:51:34 +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=1738882295; cv=none; b=JPgl+9PN5oNmYIfG5Qir8BMrWS/9avrcSi5kDjTI8mhpCXx2l7lCYitpvc4m2d4/WuqjRpj5lIv7ZK/GaMpjbbb7N2SWJMuQOexIKgifDhEuaEgcxJ1q4mCd2K+L9YgtQP11GYRl57XbHoSrxIFgsoKWUVKGj4/Iih0q16ZPc44= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882295; c=relaxed/simple; bh=rf8sKzhjH7HR06My7ME9mpBuaMECXVPR1QGbTIzhJbQ=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Jlv3xQAxoLzrfidAnkEW3NmZk4ZIGZUzQdny3xW3nvuAyzPrtHZm2NPoMqxaHthv5U5+o4Q5ms8zdOqExYePVsVGWc8OVGYeW8mgybikASCEYrwsl/caTrSq4Cbn4zKaUIbnxI8Fbl67Y2lnQ4zh+YPhTf8f7N+i/vo8wwto1Es= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Hsb4ZDqT; 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="Hsb4ZDqT" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D1167C4CEDD; Thu, 6 Feb 2025 22:51:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882293; bh=rf8sKzhjH7HR06My7ME9mpBuaMECXVPR1QGbTIzhJbQ=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=Hsb4ZDqTrfQZimTesTg0TsJO/X1l+e3WyyukfRGfrXozatWK2wmyb1QY9tTpjvpoy DtZfJxdBW2cPsGe0op2qdGd+NlRM4rBbHbw6L7DFx3WyakFqULRpsQ+KOYz+BYU3fj HP5wOVIp+51M5I3OIWZAKSF01XPxGNPPUKyKjaJ9em+lcV+2YVeByBtH9dxUHzxg4G CobFIxoNfyHCpp7Ln5kJZY399lJZDPuxT9QcJMQwvhuhSTU3jRWyOABLBPPG7AQPi+ mGnu4ZbbSQyiRMvQaGb/iugUsQLNamPHB+kJIJFvQ6QUyaeBw0YUjJ652/JkNs5WUL pyq2VF1WkVXdA== Date: Thu, 06 Feb 2025 14:51:33 -0800 Subject: [PATCH 07/27] xfs_db: display the realtime rmap btree contents From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088203.2741033.164927994313593176.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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 rtrmapbt contents, starting from the inode root. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- db/bmroot.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++ db/bmroot.h | 2 + db/btblock.c | 100 +++++++++++++++++++++++++++++++ db/btblock.h | 5 ++ db/field.c | 11 +++ db/field.h | 5 ++ db/inode.c | 24 +++++++ db/type.c | 5 ++ db/type.h | 1 libxfs/libxfs_api_defs.h | 5 ++ man/man8/xfs_db.8 | 60 ++++++++++++++++++- 11 files changed, 364 insertions(+), 3 deletions(-) diff --git a/db/bmroot.c b/db/bmroot.c index 7ef07da181e6ff..19490bd24998c5 100644 --- a/db/bmroot.c +++ b/db/bmroot.c @@ -24,6 +24,13 @@ static int bmrootd_key_offset(void *obj, int startoff, int idx); static int bmrootd_ptr_count(void *obj, int startoff); static int bmrootd_ptr_offset(void *obj, int startoff, int idx); +static int rtrmaproot_rec_count(void *obj, int startoff); +static int rtrmaproot_rec_offset(void *obj, int startoff, int idx); +static int rtrmaproot_key_count(void *obj, int startoff); +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); + #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 }, @@ -54,6 +61,20 @@ const field_t bmrootd_key_flds[] = { { NULL } }; +/* realtime rmap btree root */ +const field_t rtrmaproot_flds[] = { + { "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE }, + { "numrecs", FLDT_UINT16D, OI(OFF(numrecs)), C1, 0, TYP_NONE }, + { "recs", FLDT_RTRMAPBTREC, rtrmaproot_rec_offset, rtrmaproot_rec_count, + FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, + { "keys", FLDT_RTRMAPBTKEY, rtrmaproot_key_offset, rtrmaproot_key_count, + FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, + { "ptrs", FLDT_RTRMAPBTPTR, rtrmaproot_ptr_offset, rtrmaproot_ptr_count, + FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_RTRMAPBT }, + { NULL } +}; +#undef OFF + static int bmroota_key_count( void *obj, @@ -241,3 +262,131 @@ bmrootd_size( dip = obj; return bitize((int)XFS_DFORK_DSIZE(dip, mp)); } + +/* realtime rmap root */ +static int +rtrmaproot_rec_count( + void *obj, + int startoff) +{ + struct xfs_rtrmap_root *block; +#ifdef DEBUG + struct xfs_dinode *dip = obj; +#endif + + ASSERT(bitoffs(startoff) == 0); + ASSERT(obj == iocur_top->data); + block = (struct xfs_rtrmap_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 +rtrmaproot_rec_offset( + void *obj, + int startoff, + int idx) +{ + struct xfs_rtrmap_root *block; + struct xfs_rmap_rec *kp; + + ASSERT(bitoffs(startoff) == 0); + ASSERT(obj == iocur_top->data); + block = (struct xfs_rtrmap_root *)((char *)obj + byteize(startoff)); + ASSERT(be16_to_cpu(block->bb_level) == 0); + kp = xfs_rtrmap_droot_rec_addr(block, idx); + return bitize((int)((char *)kp - (char *)block)); +} + +static int +rtrmaproot_key_count( + void *obj, + int startoff) +{ + struct xfs_rtrmap_root *block; +#ifdef DEBUG + struct xfs_dinode *dip = obj; +#endif + + ASSERT(bitoffs(startoff) == 0); + ASSERT(obj == iocur_top->data); + block = (struct xfs_rtrmap_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 +rtrmaproot_key_offset( + void *obj, + int startoff, + int idx) +{ + struct xfs_rtrmap_root *block; + struct xfs_rmap_key *kp; + + ASSERT(bitoffs(startoff) == 0); + ASSERT(obj == iocur_top->data); + block = (struct xfs_rtrmap_root *)((char *)obj + byteize(startoff)); + ASSERT(be16_to_cpu(block->bb_level) > 0); + kp = xfs_rtrmap_droot_key_addr(block, idx); + return bitize((int)((char *)kp - (char *)block)); +} + +static int +rtrmaproot_ptr_count( + void *obj, + int startoff) +{ + struct xfs_rtrmap_root *block; +#ifdef DEBUG + struct xfs_dinode *dip = obj; +#endif + + ASSERT(bitoffs(startoff) == 0); + ASSERT(obj == iocur_top->data); + block = (struct xfs_rtrmap_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 +rtrmaproot_ptr_offset( + void *obj, + int startoff, + int idx) +{ + struct xfs_rtrmap_root *block; + xfs_rtrmap_ptr_t *pp; + struct xfs_dinode *dip; + int dmxr; + + ASSERT(bitoffs(startoff) == 0); + ASSERT(obj == iocur_top->data); + dip = obj; + block = (struct xfs_rtrmap_root *)((char *)obj + byteize(startoff)); + ASSERT(be16_to_cpu(block->bb_level) > 0); + dmxr = libxfs_rtrmapbt_droot_maxrecs(XFS_DFORK_DSIZE(dip, mp), false); + pp = xfs_rtrmap_droot_ptr_addr(block, idx, dmxr); + return bitize((int)((char *)pp - (char *)block)); +} + +int +rtrmaproot_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 a1274cf6a94bdf..a2c5cfb18f0bb2 100644 --- a/db/bmroot.h +++ b/db/bmroot.h @@ -8,6 +8,8 @@ extern const struct field bmroota_flds[]; 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 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); diff --git a/db/btblock.c b/db/btblock.c index d5be6adb734cef..5cad166278d98b 100644 --- a/db/btblock.c +++ b/db/btblock.c @@ -92,6 +92,12 @@ static struct xfs_db_btree { sizeof(struct xfs_rmap_rec), sizeof(__be32), }, + { XFS_RTRMAP_CRC_MAGIC, + XFS_BTREE_LBLOCK_CRC_LEN, + 2 * sizeof(struct xfs_rmap_key), + sizeof(struct xfs_rmap_rec), + sizeof(__be64), + }, { XFS_REFC_CRC_MAGIC, XFS_BTREE_SBLOCK_CRC_LEN, sizeof(struct xfs_refcount_key), @@ -813,6 +819,100 @@ const field_t rmapbt_rec_flds[] = { { NULL } }; +/* realtime RMAP btree blocks */ +const field_t rtrmapbt_crc_hfld[] = { + { "", FLDT_RTRMAPBT_CRC, OI(0), C1, 0, TYP_NONE }, + { NULL } +}; + +#define OFF(f) bitize(offsetof(struct xfs_btree_block, bb_ ## f)) +const field_t rtrmapbt_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_RTRMAPBT }, + { "rightsib", FLDT_DFSBNO, OI(OFF(u.l.bb_rightsib)), C1, 0, TYP_RTRMAPBT }, + { "bno", FLDT_DFSBNO, OI(OFF(u.l.bb_blkno)), C1, 0, TYP_RTRMAPBT }, + { "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_RTRMAPBTREC, btblock_rec_offset, btblock_rec_count, + FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, + { "keys", FLDT_RTRMAPBTKEY, btblock_key_offset, btblock_key_count, + FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, + { "ptrs", FLDT_RTRMAPBTPTR, btblock_ptr_offset, btblock_key_count, + FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_RTRMAPBT }, + { NULL } +}; +#undef OFF + +#define KOFF(f) bitize(offsetof(struct xfs_rmap_key, rm_ ## f)) + +#define RTRMAPBK_STARTBLOCK_BITOFF 0 +#define RTRMAPBK_OWNER_BITOFF (RTRMAPBK_STARTBLOCK_BITOFF + RMAPBT_STARTBLOCK_BITLEN) +#define RTRMAPBK_ATTRFLAG_BITOFF (RTRMAPBK_OWNER_BITOFF + RMAPBT_OWNER_BITLEN) +#define RTRMAPBK_BMBTFLAG_BITOFF (RTRMAPBK_ATTRFLAG_BITOFF + RMAPBT_ATTRFLAG_BITLEN) +#define RTRMAPBK_EXNTFLAG_BITOFF (RTRMAPBK_BMBTFLAG_BITOFF + RMAPBT_BMBTFLAG_BITLEN) +#define RTRMAPBK_UNUSED_OFFSET_BITOFF (RTRMAPBK_EXNTFLAG_BITOFF + RMAPBT_EXNTFLAG_BITLEN) +#define RTRMAPBK_OFFSET_BITOFF (RTRMAPBK_UNUSED_OFFSET_BITOFF + RMAPBT_UNUSED_OFFSET_BITLEN) + +#define HI_KOFF(f) bitize(sizeof(struct xfs_rmap_key) + offsetof(struct xfs_rmap_key, rm_ ## f)) + +#define RTRMAPBK_STARTBLOCKHI_BITOFF (bitize(sizeof(struct xfs_rmap_key))) +#define RTRMAPBK_OWNERHI_BITOFF (RTRMAPBK_STARTBLOCKHI_BITOFF + RMAPBT_STARTBLOCK_BITLEN) +#define RTRMAPBK_ATTRFLAGHI_BITOFF (RTRMAPBK_OWNERHI_BITOFF + RMAPBT_OWNER_BITLEN) +#define RTRMAPBK_BMBTFLAGHI_BITOFF (RTRMAPBK_ATTRFLAGHI_BITOFF + RMAPBT_ATTRFLAG_BITLEN) +#define RTRMAPBK_EXNTFLAGHI_BITOFF (RTRMAPBK_BMBTFLAGHI_BITOFF + RMAPBT_BMBTFLAG_BITLEN) +#define RTRMAPBK_UNUSED_OFFSETHI_BITOFF (RTRMAPBK_EXNTFLAGHI_BITOFF + RMAPBT_EXNTFLAG_BITLEN) +#define RTRMAPBK_OFFSETHI_BITOFF (RTRMAPBK_UNUSED_OFFSETHI_BITOFF + RMAPBT_UNUSED_OFFSET_BITLEN) + +const field_t rtrmapbt_key_flds[] = { + { "startblock", FLDT_RGBLOCK, OI(KOFF(startblock)), C1, 0, TYP_DATA }, + { "owner", FLDT_INT64D, OI(KOFF(owner)), C1, 0, TYP_NONE }, + { "offset", FLDT_RFILEOFFD, OI(RTRMAPBK_OFFSET_BITOFF), C1, 0, TYP_NONE }, + { "attrfork", FLDT_RATTRFORKFLG, OI(RTRMAPBK_ATTRFLAG_BITOFF), C1, 0, + TYP_NONE }, + { "bmbtblock", FLDT_RBMBTFLG, OI(RTRMAPBK_BMBTFLAG_BITOFF), C1, 0, + TYP_NONE }, + { "startblock_hi", FLDT_RGBLOCK, OI(HI_KOFF(startblock)), C1, 0, TYP_DATA }, + { "owner_hi", FLDT_INT64D, OI(HI_KOFF(owner)), C1, 0, TYP_NONE }, + { "offset_hi", FLDT_RFILEOFFD, OI(RTRMAPBK_OFFSETHI_BITOFF), C1, 0, TYP_NONE }, + { "attrfork_hi", FLDT_RATTRFORKFLG, OI(RTRMAPBK_ATTRFLAGHI_BITOFF), C1, 0, + TYP_NONE }, + { "bmbtblock_hi", FLDT_RBMBTFLG, OI(RTRMAPBK_BMBTFLAGHI_BITOFF), C1, 0, + TYP_NONE }, + { NULL } +}; +#undef HI_KOFF +#undef KOFF + +#define ROFF(f) bitize(offsetof(struct xfs_rmap_rec, rm_ ## f)) + +#define RTRMAPBT_STARTBLOCK_BITOFF 0 +#define RTRMAPBT_BLOCKCOUNT_BITOFF (RTRMAPBT_STARTBLOCK_BITOFF + RMAPBT_STARTBLOCK_BITLEN) +#define RTRMAPBT_OWNER_BITOFF (RTRMAPBT_BLOCKCOUNT_BITOFF + RMAPBT_BLOCKCOUNT_BITLEN) +#define RTRMAPBT_ATTRFLAG_BITOFF (RTRMAPBT_OWNER_BITOFF + RMAPBT_OWNER_BITLEN) +#define RTRMAPBT_BMBTFLAG_BITOFF (RTRMAPBT_ATTRFLAG_BITOFF + RMAPBT_ATTRFLAG_BITLEN) +#define RTRMAPBT_EXNTFLAG_BITOFF (RTRMAPBT_BMBTFLAG_BITOFF + RMAPBT_BMBTFLAG_BITLEN) +#define RTRMAPBT_UNUSED_OFFSET_BITOFF (RTRMAPBT_EXNTFLAG_BITOFF + RMAPBT_EXNTFLAG_BITLEN) +#define RTRMAPBT_OFFSET_BITOFF (RTRMAPBT_UNUSED_OFFSET_BITOFF + RMAPBT_UNUSED_OFFSET_BITLEN) + +const field_t rtrmapbt_rec_flds[] = { + { "startblock", FLDT_RGBLOCK, OI(RTRMAPBT_STARTBLOCK_BITOFF), C1, 0, TYP_DATA }, + { "blockcount", FLDT_EXTLEN, OI(RTRMAPBT_BLOCKCOUNT_BITOFF), C1, 0, TYP_NONE }, + { "owner", FLDT_INT64D, OI(RTRMAPBT_OWNER_BITOFF), C1, 0, TYP_NONE }, + { "offset", FLDT_RFILEOFFD, OI(RTRMAPBT_OFFSET_BITOFF), C1, 0, TYP_NONE }, + { "extentflag", FLDT_REXTFLG, OI(RTRMAPBT_EXNTFLAG_BITOFF), C1, 0, + TYP_NONE }, + { "attrfork", FLDT_RATTRFORKFLG, OI(RTRMAPBT_ATTRFLAG_BITOFF), C1, 0, + TYP_NONE }, + { "bmbtblock", FLDT_RBMBTFLG, OI(RTRMAPBT_BMBTFLAG_BITOFF), C1, 0, + TYP_NONE }, + { NULL } +}; +#undef ROFF + /* refcount btree blocks */ const field_t refcbt_crc_hfld[] = { { "", FLDT_REFCBT_CRC, OI(0), C1, 0, TYP_NONE }, diff --git a/db/btblock.h b/db/btblock.h index 4168c9e2e15ac4..b4013ea8073ec6 100644 --- a/db/btblock.h +++ b/db/btblock.h @@ -53,6 +53,11 @@ extern const struct field rmapbt_crc_hfld[]; extern const struct field rmapbt_key_flds[]; extern const struct field rmapbt_rec_flds[]; +extern const struct field rtrmapbt_crc_flds[]; +extern const struct field rtrmapbt_crc_hfld[]; +extern const struct field rtrmapbt_key_flds[]; +extern const struct field rtrmapbt_rec_flds[]; + extern const struct field refcbt_crc_flds[]; extern const struct field refcbt_crc_hfld[]; extern const struct field refcbt_key_flds[]; diff --git a/db/field.c b/db/field.c index ca0fe1826f9a80..60c4e16d781f48 100644 --- a/db/field.c +++ b/db/field.c @@ -194,6 +194,17 @@ const ftattr_t ftattrtab[] = { { FLDT_RMAPBTREC, "rmapbtrec", fp_sarray, (char *)rmapbt_rec_flds, SI(bitsz(struct xfs_rmap_rec)), 0, NULL, rmapbt_rec_flds }, + { FLDT_RTRMAPBT_CRC, "rtrmapbt", NULL, (char *)rtrmapbt_crc_flds, btblock_size, + FTARG_SIZE, NULL, rtrmapbt_crc_flds }, + { FLDT_RTRMAPBTKEY, "rtrmapbtkey", fp_sarray, (char *)rtrmapbt_key_flds, + SI(bitize(2 * sizeof(struct xfs_rmap_key))), 0, NULL, rtrmapbt_key_flds }, + { FLDT_RTRMAPBTPTR, "rtrmapbtptr", fp_num, "%llu", + SI(bitsz(xfs_rtrmap_ptr_t)), 0, fa_dfsbno, NULL }, + { FLDT_RTRMAPBTREC, "rtrmapbtrec", fp_sarray, (char *)rtrmapbt_rec_flds, + SI(bitsz(struct xfs_rmap_rec)), 0, NULL, rtrmapbt_rec_flds }, + { FLDT_RTRMAPROOT, "rtrmaproot", NULL, (char *)rtrmaproot_flds, rtrmaproot_size, + FTARG_SIZE, NULL, rtrmaproot_flds }, + { FLDT_REFCBT_CRC, "refcntbt", NULL, (char *)refcbt_crc_flds, btblock_size, FTARG_SIZE, NULL, refcbt_crc_flds }, { FLDT_REFCBTKEY, "refcntbtkey", fp_sarray, (char *)refcbt_key_flds, diff --git a/db/field.h b/db/field.h index 1d7465b4d3e562..67b6cb2a798719 100644 --- a/db/field.h +++ b/db/field.h @@ -84,6 +84,11 @@ typedef enum fldt { FLDT_RMAPBTKEY, FLDT_RMAPBTPTR, FLDT_RMAPBTREC, + FLDT_RTRMAPBT_CRC, + FLDT_RTRMAPBTKEY, + FLDT_RTRMAPBTPTR, + FLDT_RTRMAPBTREC, + FLDT_RTRMAPROOT, FLDT_REFCBT_CRC, FLDT_REFCBTKEY, FLDT_REFCBTPTR, diff --git a/db/inode.c b/db/inode.c index 0a80b8d063603f..45368a3343a17a 100644 --- a/db/inode.c +++ b/db/inode.c @@ -48,6 +48,7 @@ static int inode_u_muuid_count(void *obj, int startoff); 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 const cmdinfo_t inode_cmd = { "inode", NULL, inode_f, 0, 1, 1, "[inode#]", @@ -233,6 +234,8 @@ const field_t inode_u_flds[] = { { "sfdir3", FLDT_DIR3SF, NULL, inode_u_sfdir3_count, FLD_COUNT, TYP_NONE }, { "symlink", FLDT_CHARNS, NULL, inode_u_symlink_count, FLD_COUNT, TYP_NONE }, + { "rtrmapbt", FLDT_RTRMAPROOT, NULL, inode_u_rtrmapbt_count, FLD_COUNT, + TYP_NONE }, { NULL } }; @@ -246,7 +249,7 @@ const field_t inode_a_flds[] = { }; static const char *dinode_fmt_name[] = - { "dev", "local", "extents", "btree", "uuid" }; + { "dev", "local", "extents", "btree", "uuid", "meta_btree" }; static const int dinode_fmt_name_size = sizeof(dinode_fmt_name) / sizeof(dinode_fmt_name[0]); @@ -299,7 +302,7 @@ fp_dinode_fmt( static const char *metatype_name[] = { "unknown", "dir", "usrquota", "grpquota", "prjquota", "rtbitmap", - "rtsummary" + "rtsummary", "rtrmap" }; static const int metatype_name_size = ARRAY_SIZE(metatype_name); @@ -717,6 +720,8 @@ inode_next_type(void) return TYP_RGBITMAP; case XFS_METAFILE_RTSUMMARY: return TYP_RGSUMMARY; + case XFS_METAFILE_RTRMAP: + return TYP_RTRMAPBT; default: return TYP_DATA; } @@ -866,6 +871,21 @@ inode_u_sfdir3_count( xfs_has_ftype(mp); } +static int +inode_u_rtrmapbt_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_RTRMAP); +} + int inode_u_size( void *obj, diff --git a/db/type.c b/db/type.c index 2091b4ac8b139b..1dfc33ffb44b87 100644 --- a/db/type.c +++ b/db/type.c @@ -51,6 +51,7 @@ static const typ_t __typtab[] = { { TYP_BNOBT, "bnobt", handle_struct, bnobt_hfld, NULL, TYP_F_NO_CRC_OFF }, { TYP_CNTBT, "cntbt", handle_struct, cntbt_hfld, NULL, TYP_F_NO_CRC_OFF }, { TYP_RMAPBT, NULL }, + { TYP_RTRMAPBT, NULL }, { TYP_REFCBT, 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 }, @@ -91,6 +92,8 @@ static const typ_t __typtab_crc[] = { &xfs_cntbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF }, { TYP_RMAPBT, "rmapbt", handle_struct, rmapbt_crc_hfld, &xfs_rmapbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF }, + { TYP_RTRMAPBT, "rtrmapbt", handle_struct, rtrmapbt_crc_hfld, + &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_DATA, "data", handle_block, NULL, NULL, TYP_F_NO_CRC_OFF }, @@ -141,6 +144,8 @@ static const typ_t __typtab_spcrc[] = { &xfs_cntbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF }, { TYP_RMAPBT, "rmapbt", handle_struct, rmapbt_crc_hfld, &xfs_rmapbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF }, + { TYP_RTRMAPBT, "rtrmapbt", handle_struct, rtrmapbt_crc_hfld, + &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_DATA, "data", handle_block, NULL, NULL, TYP_F_NO_CRC_OFF }, diff --git a/db/type.h b/db/type.h index e7f0ecc17680bf..c98f3640202e87 100644 --- a/db/type.h +++ b/db/type.h @@ -20,6 +20,7 @@ typedef enum typnm TYP_BNOBT, TYP_CNTBT, TYP_RMAPBT, + TYP_RTRMAPBT, TYP_REFCBT, TYP_DATA, TYP_DIR2, diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index 6b2dc7a30d2547..fcbcaaa11f1025 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -295,6 +295,8 @@ #define xfs_rtginode_name libxfs_rtginode_name #define xfs_rtsummary_create libxfs_rtsummary_create +#define xfs_rtginode_load libxfs_rtginode_load +#define xfs_rtginode_load_parent libxfs_rtginode_load_parent #define xfs_rtgroup_alloc libxfs_rtgroup_alloc #define xfs_rtgroup_extents libxfs_rtgroup_extents #define xfs_rtgroup_grab libxfs_rtgroup_grab @@ -308,6 +310,9 @@ #define xfs_rtfree_extent libxfs_rtfree_extent #define xfs_rtfree_blocks libxfs_rtfree_blocks #define xfs_update_rtsb libxfs_update_rtsb +#define xfs_rtrmapbt_droot_maxrecs libxfs_rtrmapbt_droot_maxrecs +#define xfs_rtrmapbt_maxrecs libxfs_rtrmapbt_maxrecs + #define xfs_sb_from_disk libxfs_sb_from_disk #define xfs_sb_mount_rextsize libxfs_sb_mount_rextsize #define xfs_sb_quota_from_disk libxfs_sb_quota_from_disk diff --git a/man/man8/xfs_db.8 b/man/man8/xfs_db.8 index acee900adbda50..ddbabe36b5fc41 100644 --- a/man/man8/xfs_db.8 +++ b/man/man8/xfs_db.8 @@ -1302,7 +1302,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 " and " text . +.BR rtsummary ", " sb ", " symlink ", " rtrmapbt ", and " text . See the TYPES section below for more information on these data types. .TP .BI "timelimit [" OPTIONS ] @@ -2450,6 +2450,64 @@ .SH TYPES .PD .RE .TP +.B rtrmapbt +There is one reverse mapping Btree for each realtime group. +The +.BR startblock " and " +.B blockcount +fields are 32 bits wide and record blocks within a realtime group. +The root of this Btree is the reverse-mapping 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 +RTRMAP block magic number, 0x4d415052 ('MAPR'). +.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 , +.BR owner , +.BR offset , +.BR attr_fork , +.BR bmbt_block , +and +.BR unwritten . +.TP +.B keys +[non-leaf blocks only] array of double-key records. The first ("low") key +contains the first value of each block in the level below this one. The second +("high") key contains the largest key that can be used to identify any record +in the subtree. Each record contains +.BR startblock , +.BR owner , +.BR offset , +.BR attr_fork , +and +.BR bmbt_block . +.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 rtbitmap If the filesystem has a realtime subvolume, then the .B rbmino From patchwork Thu Feb 6 22:51:49 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: 13964025 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 1AF8E237711 for ; Thu, 6 Feb 2025 22:51: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=1738882310; cv=none; b=WZLLRPewUD8StlEPyXcXbC31Czq6/HpPVsWT3XigIzO2s2uS0Cf5kOAG+EvRhuYwVE76vkfEUM1qbESBMyhTzbZkW9fRRhUkOYCAZNHJ4owQGQnfR68DsCnmwRLdvu0TBdBJXIdAaqbDc03reOI/lmJatPflVz685DC5m+kz0HI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882310; c=relaxed/simple; bh=zmVOTi6pY/U+jx4QcESAizugxO0vRQ2r+bxWLCWxBD8=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=B7pbzSlr3VtLNatmiOuQ/Fep0C+Hu6ZSEQoNM8etrHimF4Y6DNsKVudHhwXsAkui3EhVLq9ks/P1F4uMRrErzlIVNZmmZGQbASfsHa4JqCr/6X8r1TnwmSO3pDWqzZJfSTgnNZfeSymIx6rTc+pWcaD5617xyLD8Dqvp64vI0tA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hFfzF40I; 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="hFfzF40I" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7C2C9C4CEDD; Thu, 6 Feb 2025 22:51:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882309; bh=zmVOTi6pY/U+jx4QcESAizugxO0vRQ2r+bxWLCWxBD8=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=hFfzF40Iic0S5q9yaKJ3sDGCViyvL8KVYqxoHOZNLS0/zU+JMpTGfapoDI//Nb9qx JDJPL8NWnEoklFdpWgUSRszXd8YGXitemE1LqsWs43s4APgqxOo2UT227tLzQWivKP Tux0SM04GJuS1046fpJR62HkPZePV0nExfOQoJQzN0Np0EBlqmoz5ST+VCtMVWSAda 6gfJQM32NJxHAbOZ6mT0W6b2uM4Ddf107MIMYp0cqC1cBoa2iDKWway9dXoV5H/VDW C0+MmythnLV6YdCMTtE8mNcJgT/R4657cPww2pX5ckVpmlFTg6H9bB21HclW5rayuU m0Y3NopYiGL+Q== Date: Thu, 06 Feb 2025 14:51:49 -0800 Subject: [PATCH 08/27] xfs_db: support the realtime rmapbt From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088218.2741033.7947778465817978960.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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 rmap support so that we can dump the btree contents. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- db/btblock.c | 3 ++ db/btdump.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++ db/btheight.c | 5 ++++ libxfs/libxfs_api_defs.h | 1 + man/man8/xfs_db.8 | 3 +- 5 files changed, 74 insertions(+), 1 deletion(-) diff --git a/db/btblock.c b/db/btblock.c index 5cad166278d98b..70f6c3f6aedde5 100644 --- a/db/btblock.c +++ b/db/btblock.c @@ -147,6 +147,9 @@ block_to_bt( case TYP_RMAPBT: magic = crc ? XFS_RMAP_CRC_MAGIC : 0; break; + case TYP_RTRMAPBT: + magic = crc ? XFS_RTRMAP_CRC_MAGIC : 0; + break; case TYP_REFCBT: magic = crc ? XFS_REFC_CRC_MAGIC : 0; break; diff --git a/db/btdump.c b/db/btdump.c index 81642cde2b6d8f..55301d25de10cd 100644 --- a/db/btdump.c +++ b/db/btdump.c @@ -441,6 +441,66 @@ dump_dabtree( return ret; } +static bool +is_btree_inode(void) +{ + struct xfs_dinode *dip = iocur_top->data; + + return dip->di_format == XFS_DINODE_FMT_META_BTREE; +} + +static int +dump_btree_inode( + bool dump_node_blocks) +{ + char *prefix; + struct xfs_dinode *dip = iocur_top->data; + struct xfs_rtrmap_root *rtrmap; + int level; + int numrecs; + int ret; + + switch (be16_to_cpu(dip->di_metatype)) { + case XFS_METAFILE_RTRMAP: + prefix = "u3.rtrmapbt"; + rtrmap = (struct xfs_rtrmap_root *)XFS_DFORK_DPTR(dip); + level = be16_to_cpu(rtrmap->bb_level); + numrecs = be16_to_cpu(rtrmap->bb_numrecs); + break; + default: + dbprintf("Unknown metadata inode btree type %u\n", + be16_to_cpu(dip->di_metatype)); + return 0; + } + + if (numrecs == 0) + return 0; + if (level > 0) { + if (dump_node_blocks) { + ret = eval("print %s.keys", prefix); + if (ret) + goto err; + ret = eval("print %s.ptrs", prefix); + if (ret) + goto err; + } + ret = eval("addr %s.ptrs[1]", prefix); + if (ret) + goto err; + ret = dump_btree_long(dump_node_blocks); + } else { + ret = eval("print %s.recs", prefix); + } + if (ret) + goto err; + + ret = eval("pop"); + return ret; +err: + eval("pop"); + return ret; +} + static int btdump_f( int argc, @@ -488,8 +548,11 @@ btdump_f( return dump_btree_short(iflag); case TYP_BMAPBTA: case TYP_BMAPBTD: + case TYP_RTRMAPBT: return dump_btree_long(iflag); case TYP_INODE: + if (is_btree_inode()) + return dump_btree_inode(iflag); return dump_inode(iflag, aflag); case TYP_ATTR: return dump_dabtree(iflag, crc ? &attr3_print : &attr_print); diff --git a/db/btheight.c b/db/btheight.c index 0456af08b39edf..31dff1c924a2e0 100644 --- a/db/btheight.c +++ b/db/btheight.c @@ -53,6 +53,11 @@ struct btmap { .maxlevels = libxfs_rmapbt_maxlevels_ondisk, .maxrecs = libxfs_rmapbt_maxrecs, }, + { + .tag = "rtrmapbt", + .maxlevels = libxfs_rtrmapbt_maxlevels_ondisk, + .maxrecs = libxfs_rtrmapbt_maxrecs, + }, }; static void diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index fcbcaaa11f1025..cf88656946ab1b 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -311,6 +311,7 @@ #define xfs_rtfree_blocks libxfs_rtfree_blocks #define xfs_update_rtsb libxfs_update_rtsb #define xfs_rtrmapbt_droot_maxrecs libxfs_rtrmapbt_droot_maxrecs +#define xfs_rtrmapbt_maxlevels_ondisk libxfs_rtrmapbt_maxlevels_ondisk #define xfs_rtrmapbt_maxrecs libxfs_rtrmapbt_maxrecs #define xfs_sb_from_disk libxfs_sb_from_disk diff --git a/man/man8/xfs_db.8 b/man/man8/xfs_db.8 index ddbabe36b5fc41..83a8734d3c0b47 100644 --- a/man/man8/xfs_db.8 +++ b/man/man8/xfs_db.8 @@ -535,8 +535,9 @@ .SH COMMANDS .IR finobt , .IR bmapbt , .IR refcountbt , +.IR rmapbt , and -.IR rmapbt . +.IR rtrmapbt . The magic value .I all can be used to walk through all btree types. From patchwork Thu Feb 6 22:52: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: 13964026 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 D85BF23AE65 for ; Thu, 6 Feb 2025 22:52:05 +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=1738882325; cv=none; b=EDKVhWk+tdgCQRSkwbCHVv92nRfpASBq3hnDdC7vcWhMBn1mBXgdj7ZCsZ5F8reblVRVv2u8VI+CJHMOW1f4L7iGqb+hBw3sz+HL1nubTzoHjCJZy4F9hVhR8++wmlMLeK6OqQm7Qj3673txW7lo03PmdqpHDNeOxbzpaEsKUNw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882325; c=relaxed/simple; bh=I5x0kj5mYNwBHiI6Zx2ipHy0Qe6TDUrWEvkU86FeIrc=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=nqYGNO2jQlfh5CpjrJCCQoLvAZIsJWM383uegl8n7czyDkrv4IGoCVaNRKsayE3R2CDgxg7WJ2qdRzyV5NuqdPX4iEV08gDitb36UFfrVY4BDR7Ifzym8D0Z0Fi6bpucCQLn3sEMtAMchEXiyWe+ubkrFdCUtpGPMAdI8ZXvxoQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=rMvduAmC; 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="rMvduAmC" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4E7ADC4CEE0; Thu, 6 Feb 2025 22:52:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882325; bh=I5x0kj5mYNwBHiI6Zx2ipHy0Qe6TDUrWEvkU86FeIrc=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=rMvduAmCGkn6Sz/AfW/8qGBnEA3HDfsPqVuW3ua3+oxrW3tjlkwlnb7qj9jHxceXy yzpI4NOYV/T9ii911p1Z+cqg7iJJIddGmEkNKXqm10j3CYTLKXvMa+7kEy/GZmEe1i P6kZFOprybXOVu7Bj23Er3A0+iGLu0yODa3PkV92qTgYVjbNHn1qBA2oelWDH5FDWX RNSpz5ZSHatsxARuYE3M+j5EE06m739ZoEW8emFPgFmN1UAJvgeBRapqSkdJBEMhFK BEzkdhT3VhXxrM5aVWj8+kYZCQmekOobpYFGmpAcGTKDagoMUetp9Rizxb+4NRd7E0 VRauPPGca9E0Q== Date: Thu, 06 Feb 2025 14:52:04 -0800 Subject: [PATCH 09/27] xfs_db: copy the realtime rmap btree From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088234.2741033.11666132944549575171.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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 rmapbt when we're metadumping the filesystem. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- db/metadump.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/db/metadump.c b/db/metadump.c index 4f4b4f8a39a551..aa946746cdfa68 100644 --- a/db/metadump.c +++ b/db/metadump.c @@ -589,6 +589,55 @@ copy_rmap_btree( return scan_btree(agno, root, levels, TYP_RMAPBT, agf, scanfunc_rmapbt); } +static int +scanfunc_rtrmapbt( + struct xfs_btree_block *block, + xfs_agnumber_t agno, + xfs_agblock_t agbno, + int level, + typnm_t btype, + void *arg) +{ + xfs_rtrmap_ptr_t *pp; + int i; + int numrecs; + + if (level == 0) + return 1; + + numrecs = be16_to_cpu(block->bb_numrecs); + if (numrecs > mp->m_rtrmap_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_rtrmap_ptr_addr(block, 1, mp->m_rtrmap_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_rtrmapbt)) + return 0; + } + return 1; +} + static int scanfunc_refcntbt( struct xfs_btree_block *block, @@ -2325,6 +2374,69 @@ process_exinode( nex); } +static int +process_rtrmap( + struct xfs_dinode *dip) +{ + int whichfork = XFS_DATA_FORK; + struct xfs_rtrmap_root *dib = + (struct xfs_rtrmap_root *)XFS_DFORK_PTR(dip, whichfork); + xfs_rtrmap_ptr_t *pp; + int level = be16_to_cpu(dib->bb_level); + int nrecs = be16_to_cpu(dib->bb_numrecs); + typnm_t btype = TYP_RTRMAPBT; + int maxrecs; + int i; + + if (level > mp->m_rtrmap_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_rtrmapbt_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_rtrmap_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_rtrmapbt)) + return 0; + } + return 1; +} + static int process_inode_data( struct xfs_dinode *dip) @@ -2366,6 +2478,14 @@ process_inode_data( case XFS_DINODE_FMT_BTREE: return process_btinode(dip, XFS_DATA_FORK); + + case XFS_DINODE_FMT_META_BTREE: + switch (be16_to_cpu(dip->di_metatype)) { + case XFS_METAFILE_RTRMAP: + return process_rtrmap(dip); + default: + return 1; + } } return 1; } From patchwork Thu Feb 6 22:52:20 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: 13964027 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 30B4623BF95 for ; Thu, 6 Feb 2025 22:52:21 +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=1738882341; cv=none; b=TrcRbh49WVjiLNvQiaN+NmnSWNnl7pQH8mmcTYKGy4DL6C2a2y4iHy1sv7o4NM0n00ec4SS0sUixXdp0hi3c6PcJex7qfmAgp2oMqiCw+r+WyR3/guC/cOqsb+Cv3KmHziM3ciMJ2ouGVeTLRVsvPNZEA8w+LvrsRyrsRiS7iYw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882341; c=relaxed/simple; bh=XR/JK1aXw6FuNRChb4UMqfIJC6bAOAXYFBs+IrfrRF0=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ixWSAQA7atPwxl3ssRPOwUEiv9jfmWnaCx5EAenJF5UMzyvwN7de9FX3EB0kqWo+9PW6qcrU9+HY4IrtLn9bjW6UgQByHlqW+vAaZr3pSvaohp9DpFiVRIDjI9mSGSwmwTLwUdi92avBH17frLESVESvT0npuEkE7hxZjT00p0g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=S6wBXqQm; 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="S6wBXqQm" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 09364C4CEDD; Thu, 6 Feb 2025 22:52:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882341; bh=XR/JK1aXw6FuNRChb4UMqfIJC6bAOAXYFBs+IrfrRF0=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=S6wBXqQmLo2CVRBmp01WLZfLfoTLSne2bVS//MUw8ab4s5JoU/z8fWO0FOWRFKQPO L0s+cuCdTiaeVtNzMoW95l9/MHcd32EJFhtyDZRTpwOzYhRdfNzybg4hcfuQUClL9v peb4BtVsvM7n2SNLtMJc0EnO7WcHBp1OOjE/ywZIAuUlgb58rRvGfEEJjGvOvT6YU/ vEqZ4h+UX/zzBNwCAgY4F6ny/T9GLPpHXtqJaYpuMIE2fNrthWTeKjUi9+t7xhMR2K EtXIkXNs+inwuv6UKl8PiZeIYbjkTJhu2w6sWkXF2Ve+hGA9qg4VEl5u2yPUof7/QI HjfR9jmH068kg== Date: Thu, 06 Feb 2025 14:52:20 -0800 Subject: [PATCH 10/27] xfs_db: make fsmap query the realtime reverse mapping tree From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088249.2741033.5588270076246724853.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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 'fsmap' debugger command to support querying the realtime rmap btree via a new -r argument. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- db/fsmap.c | 149 +++++++++++++++++++++++++++++++++++++++++++++- libxfs/libxfs_api_defs.h | 3 + 2 files changed, 148 insertions(+), 4 deletions(-) diff --git a/db/fsmap.c b/db/fsmap.c index a9259c4632185b..ddbe4e6a3dfcfa 100644 --- a/db/fsmap.c +++ b/db/fsmap.c @@ -102,6 +102,134 @@ fsmap( } } +static int +fsmap_rt_fn( + struct xfs_btree_cur *cur, + const struct xfs_rmap_irec *rec, + void *priv) +{ + struct fsmap_info *info = priv; + + dbprintf(_("%llu: %u/%u len %u owner %lld offset %llu bmbt %d attrfork %d extflag %d\n"), + info->nr, cur->bc_group->xg_gno, rec->rm_startblock, + rec->rm_blockcount, rec->rm_owner, rec->rm_offset, + !!(rec->rm_flags & XFS_RMAP_BMBT_BLOCK), + !!(rec->rm_flags & XFS_RMAP_ATTR_FORK), + !!(rec->rm_flags & XFS_RMAP_UNWRITTEN)); + info->nr++; + + return 0; +} + +static int +fsmap_rtgroup( + struct xfs_rtgroup *rtg, + const struct xfs_rmap_irec *low, + const struct xfs_rmap_irec *high, + struct fsmap_info *info) +{ + struct xfs_mount *mp = rtg_mount(rtg); + struct xfs_trans *tp; + struct xfs_btree_cur *bt_cur; + int error; + + error = -libxfs_trans_alloc_empty(mp, &tp); + if (error) { + dbprintf( + _("Cannot alloc transaction to look up rtgroup %u rmap inode\n"), + rtg_rgno(rtg)); + return error; + } + + error = -libxfs_rtginode_load_parent(tp); + if (error) { + dbprintf(_("Cannot load realtime metadir, error %d\n"), + error); + goto out_trans; + } + + error = -libxfs_rtginode_load(rtg, XFS_RTGI_RMAP, tp); + if (error) { + dbprintf(_("Cannot load rtgroup %u rmap inode, error %d\n"), + rtg_rgno(rtg), error); + goto out_rele_dp; + } + + bt_cur = libxfs_rtrmapbt_init_cursor(tp, rtg); + if (!bt_cur) { + dbprintf(_("Not enough memory.\n")); + goto out_rele_ip; + } + + error = -libxfs_rmap_query_range(bt_cur, low, high, fsmap_rt_fn, + info); + if (error) { + dbprintf(_("Error %d while querying rt fsmap btree.\n"), + error); + goto out_cur; + } + +out_cur: + libxfs_btree_del_cursor(bt_cur, error); +out_rele_ip: + libxfs_rtginode_irele(&rtg->rtg_inodes[XFS_RTGI_RMAP]); +out_rele_dp: + libxfs_rtginode_irele(&mp->m_rtdirip); +out_trans: + libxfs_trans_cancel(tp); + return error; +} + +static void +fsmap_rt( + xfs_fsblock_t start_fsb, + xfs_fsblock_t end_fsb) +{ + struct fsmap_info info; + xfs_daddr_t eofs; + struct xfs_rmap_irec low; + struct xfs_rmap_irec high; + struct xfs_rtgroup *rtg = NULL; + xfs_rgnumber_t start_rg; + xfs_rgnumber_t end_rg; + int error; + + if (mp->m_sb.sb_rblocks == 0) + return; + + eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks); + if (XFS_FSB_TO_DADDR(mp, end_fsb) >= eofs) + end_fsb = XFS_DADDR_TO_FSB(mp, eofs - 1); + + low.rm_startblock = xfs_rtb_to_rgbno(mp, start_fsb); + low.rm_owner = 0; + low.rm_offset = 0; + low.rm_flags = 0; + high.rm_startblock = -1U; + high.rm_owner = ULLONG_MAX; + high.rm_offset = ULLONG_MAX; + high.rm_flags = XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK | + XFS_RMAP_UNWRITTEN; + + start_rg = xfs_rtb_to_rgno(mp, start_fsb); + end_rg = xfs_rtb_to_rgno(mp, end_fsb); + + info.nr = 0; + while ((rtg = xfs_rtgroup_next_range(mp, rtg, start_rg, end_rg))) { + if (rtg_rgno(rtg) == end_rg) + high.rm_startblock = xfs_rtb_to_rgbno(mp, end_fsb); + + error = fsmap_rtgroup(rtg, &low, &high, &info); + if (error) { + libxfs_rtgroup_put(rtg); + return; + } + + if (rtg_rgno(rtg) == start_rg) + low.rm_startblock = 0; + } +} + static int fsmap_f( int argc, @@ -111,14 +239,18 @@ fsmap_f( int c; xfs_fsblock_t start_fsb = 0; xfs_fsblock_t end_fsb = NULLFSBLOCK; + bool isrt = false; if (!xfs_has_rmapbt(mp)) { dbprintf(_("Filesystem does not support reverse mapping btree.\n")); return 0; } - while ((c = getopt(argc, argv, "")) != EOF) { + while ((c = getopt(argc, argv, "r")) != EOF) { switch (c) { + case 'r': + isrt = true; + break; default: dbprintf(_("Bad option for fsmap command.\n")); return 0; @@ -141,14 +273,23 @@ fsmap_f( } } - fsmap(start_fsb, end_fsb); + if (argc > optind + 2) { + exitcode = 1; + dbprintf(_("Too many arguments to fsmap.\n")); + return 0; + } + + if (isrt) + fsmap_rt(start_fsb, end_fsb); + else + fsmap(start_fsb, end_fsb); return 0; } static const cmdinfo_t fsmap_cmd = - { "fsmap", NULL, fsmap_f, 0, 2, 0, - N_("[start_fsb] [end_fsb]"), + { "fsmap", NULL, fsmap_f, 0, -1, 0, + N_("[-r] [start_fsb] [end_fsb]"), N_("display reverse mapping(s)"), NULL }; void diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index cf88656946ab1b..3e521cd0c76063 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -295,6 +295,7 @@ #define xfs_rtginode_name libxfs_rtginode_name #define xfs_rtsummary_create libxfs_rtsummary_create +#define xfs_rtginode_irele libxfs_rtginode_irele #define xfs_rtginode_load libxfs_rtginode_load #define xfs_rtginode_load_parent libxfs_rtginode_load_parent #define xfs_rtgroup_alloc libxfs_rtgroup_alloc @@ -310,8 +311,10 @@ #define xfs_rtfree_extent libxfs_rtfree_extent #define xfs_rtfree_blocks libxfs_rtfree_blocks #define xfs_update_rtsb libxfs_update_rtsb +#define xfs_rtgroup_put libxfs_rtgroup_put #define xfs_rtrmapbt_droot_maxrecs libxfs_rtrmapbt_droot_maxrecs #define xfs_rtrmapbt_maxlevels_ondisk libxfs_rtrmapbt_maxlevels_ondisk +#define xfs_rtrmapbt_init_cursor libxfs_rtrmapbt_init_cursor #define xfs_rtrmapbt_maxrecs libxfs_rtrmapbt_maxrecs #define xfs_sb_from_disk libxfs_sb_from_disk From patchwork Thu Feb 6 22:52:36 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: 13964028 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 CAB852417C7 for ; Thu, 6 Feb 2025 22:52: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=1738882356; cv=none; b=dOUDr5VwMooPCUQDAmpmuUTdO4IPKL5qYNX2voqHejxjTYRdXu15CZVOgUKmLRRvL0DaDlmHK7TMQ2m7x4JKfHhNqAp5nyZjMtCTjUyvDxA6WQQq0mhluc62ktmRbiSDl746wgpLywuwp4Qz2loaF3LnFZnnAWbbxfe4l45GETA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882356; c=relaxed/simple; bh=YKln6B6t0YiCO23iRTSU8MpqfB6Nq91EjqjOu+w8siI=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=uX5xAiSOgmviiPCFmYVUT7UXii1/j6V8RlcICipBJNmSCW1dLmsH5NC1A0MlGB6bd0Xd8UAj7EL2cpuNU41JESnVV81szrvRkdudp8MVYz80yCn6tDMabTc4A55KDdYCCCikV4aWOnnYioexy4ZNyceMEyB0De+t/f0U0O+Hwrk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=sWPhzFAv; 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="sWPhzFAv" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A05E2C4CEDD; Thu, 6 Feb 2025 22:52:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882356; bh=YKln6B6t0YiCO23iRTSU8MpqfB6Nq91EjqjOu+w8siI=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=sWPhzFAve5Llub2f4aPtIVOhGsJtO/TGN0YPEvSGdK9pMD2QPgFMsuxNr2toOEF+g ocHYbmS8NJC9m5hpNIa3snH2iofASRtHz9DEWWWzyv62tibC/zICQLAADVB9dmp+YN ropa/RHb3L6RnE2HbnW0GUftS6QfbwoPHwigOnS6sF2tIWHHhKOHzx9ui77bakI/Jf zSaXYb8GxfgCVEYe0p2hpU+VZDxDGbeZagw5dIcm4ON/z2jq1Jw61ZtRzNaScqnRS9 rJ6UxbeGDwC1wRCSIU9d58AVwfR6ATZYfyR9j099TjdpwLp4GY9Or/C+d4nZI7aEiM eI6oQOdep902w== Date: Thu, 06 Feb 2025 14:52:36 -0800 Subject: [PATCH 11/27] xfs_db: add an rgresv command From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088264.2741033.15457962498927616155.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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 Create a command to dump rtgroup btree space reservations. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- db/info.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++ libxfs/libxfs_api_defs.h | 2 + man/man8/xfs_db.8 | 5 ++ 3 files changed, 126 insertions(+) diff --git a/db/info.c b/db/info.c index 9a86d247839f84..ce6f358420a79d 100644 --- a/db/info.c +++ b/db/info.c @@ -151,9 +151,128 @@ static const struct cmdinfo agresv_cmd = { .help = agresv_help, }; +static void +rgresv_help(void) +{ + dbprintf(_( +"\n" +" Print the size and per-rtgroup reservation information for some realtime allocation groups.\n" +"\n" +" Specific realtime allocation group numbers can be provided as command line\n" +" arguments. If no arguments are provided, all allocation groups are iterated.\n" +"\n" +)); + +} + +static void +print_rgresv_info( + struct xfs_rtgroup *rtg) +{ + struct xfs_trans *tp; + xfs_filblks_t ask = 0; + xfs_filblks_t used = 0; + int error; + + error = -libxfs_trans_alloc_empty(mp, &tp); + if (error) { + dbprintf( + _("Cannot alloc transaction to look up rtgroup %u rmap inode\n"), + rtg_rgno(rtg)); + return; + } + + error = -libxfs_rtginode_load_parent(tp); + if (error) { + dbprintf(_("Cannot load realtime metadir, error %d\n"), + error); + goto out_trans; + } + + /* rtrmapbt */ + error = -libxfs_rtginode_load(rtg, XFS_RTGI_RMAP, tp); + if (error) { + dbprintf(_("Cannot load rtgroup %u rmap inode, error %d\n"), + rtg_rgno(rtg), error); + goto out_rele_dp; + } + if (rtg_rmap(rtg)) + used += rtg_rmap(rtg)->i_nblocks; + libxfs_rtginode_irele(&rtg->rtg_inodes[XFS_RTGI_RMAP]); + + ask += libxfs_rtrmapbt_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, + (unsigned long long)mp->m_sb.sb_fdblocks, + (unsigned long long)ask, + (unsigned long long)used); + if (ask - used > mp->m_sb.sb_fdblocks) + printf(_(" ")); + printf("\n"); +out_rele_dp: + libxfs_rtginode_irele(&mp->m_rtdirip); +out_trans: + libxfs_trans_cancel(tp); +} + +static int +rgresv_f( + int argc, + char **argv) +{ + struct xfs_rtgroup *rtg = NULL; + int i; + + if (argc > 1) { + for (i = 1; i < argc; i++) { + long a; + char *p; + + errno = 0; + a = strtol(argv[i], &p, 0); + if (p == argv[i]) + errno = ERANGE; + if (errno) { + perror(argv[i]); + continue; + } + + if (a < 0 || a >= mp->m_sb.sb_rgcount) { + fprintf(stderr, "%ld: Not a rtgroup.\n", a); + continue; + } + + rtg = libxfs_rtgroup_get(mp, a); + print_rgresv_info(rtg); + libxfs_rtgroup_put(rtg); + } + return 0; + } + + while ((rtg = xfs_rtgroup_next(mp, rtg))) + print_rgresv_info(rtg); + + return 0; +} + +static const struct cmdinfo rgresv_cmd = { + .name = "rgresv", + .altname = NULL, + .cfunc = rgresv_f, + .argmin = 0, + .argmax = -1, + .canpush = 0, + .args = NULL, + .oneline = N_("print rtgroup reservation stats"), + .help = rgresv_help, +}; + void info_init(void) { add_command(&info_cmd); add_command(&agresv_cmd); + add_command(&rgresv_cmd); } diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index 3e521cd0c76063..9beea4f7ce8535 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -311,7 +311,9 @@ #define xfs_rtfree_extent libxfs_rtfree_extent #define xfs_rtfree_blocks libxfs_rtfree_blocks #define xfs_update_rtsb libxfs_update_rtsb +#define xfs_rtgroup_get libxfs_rtgroup_get #define xfs_rtgroup_put libxfs_rtgroup_put +#define xfs_rtrmapbt_calc_reserves libxfs_rtrmapbt_calc_reserves #define xfs_rtrmapbt_droot_maxrecs libxfs_rtrmapbt_droot_maxrecs #define xfs_rtrmapbt_maxlevels_ondisk libxfs_rtrmapbt_maxlevels_ondisk #define xfs_rtrmapbt_init_cursor libxfs_rtrmapbt_init_cursor diff --git a/man/man8/xfs_db.8 b/man/man8/xfs_db.8 index 83a8734d3c0b47..784aa3cb46c588 100644 --- a/man/man8/xfs_db.8 +++ b/man/man8/xfs_db.8 @@ -1131,6 +1131,11 @@ .SH COMMANDS Exit .BR xfs_db . .TP +.BI "rgresv [" rgno ] +Displays the per-rtgroup reservation size, and per-rtgroup +reservation usage for a given realtime allocation group. +If no argument is given, display information for all rtgroups. +.TP .BI "rtblock [" rtbno ] Set current address to the location on the realtime device given by .IR rtbno . From patchwork Thu Feb 6 22:52: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: 13964029 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 693082417C7 for ; Thu, 6 Feb 2025 22:52:52 +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=1738882372; cv=none; b=VZ6WJsQdaL8NDhLQGLtPptP3OiWSYk7+/Ew9vDp+eOMvqvIuQ+jAlwVzbNIfVCC+CsXtg13tEMuxjK7ZYyJkJNU7wd8ojSuYWbdWspqG1NSQpDY3IZUBgym8yLBcnsZcALLXAkWAs9avLC9T7CVMczA9otgopgArGLpmU3Dzixw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882372; c=relaxed/simple; bh=dje40eFFgL4+4xPRooriCOleqXM3u5TOupZ7XmQmxpw=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=dDt4q1Kg+RwZ/uwgFJG3319FUbefyIv4pVoszKooyRA5niBLv+UjXqDjX1syxCUHA7V2z42IllQ9HiPKai3rzHlENznCh18IYCcBx1M4fURR8gns0duBfPEeUymPxRBV/Gcm0jn6XOtRl2jvgI671+/fpBfEZRBw40wuQjcZzVA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=SGCO+IX9; 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="SGCO+IX9" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3FA8FC4CEDD; Thu, 6 Feb 2025 22:52:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882372; bh=dje40eFFgL4+4xPRooriCOleqXM3u5TOupZ7XmQmxpw=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=SGCO+IX9YgUR0hK/1bpifAV/FHSktM7WDoD5uwMaBcFkoCZPtaE7hNmKYXUW5GK14 pI+wVRaEcoxXqGqHKVlweja4jSfF0dWprohMJNBhT5yl2zs2JWYETvHPRocBS/RSKi ejTmSeP8LSp6IP28PVkTAeNuNxmTK6XxD/Rb8E8wSaGEZLSrQ1bDsDF4Z/Sjmo5tei yZY8N3n8o8tMec56Jl1/kuXjJFZA/Y7XQ9JMpPCtzBDrfOGQOckuK9UspdXZI5m/sb VHAVq1zfrJ7fnBSR61semI80gaoaITCfAgE/8AUcWgEc/JY3RS+lqWj2XtHRuLiEyS xbtanpMStgXKQ== Date: Thu, 06 Feb 2025 14:52:51 -0800 Subject: [PATCH 12/27] xfs_spaceman: report health status of the realtime rmap btree From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088279.2741033.5703668513120399965.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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 reporting of the rt rmap btree health to spaceman. 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 0d2767df424f27..5774d609a28de3 100644 --- a/spaceman/health.c +++ b/spaceman/health.c @@ -42,6 +42,11 @@ static bool has_reflink(const struct xfs_fsop_geom *g) return g->flags & XFS_FSOP_GEOM_FLAGS_REFLINK; } +static bool has_rtrmapbt(const struct xfs_fsop_geom *g) +{ + return g->rtblocks > 0 && (g->flags & XFS_FSOP_GEOM_FLAGS_RMAPBT); +} + struct flag_map { unsigned int mask; bool (*has_fn)(const struct xfs_fsop_geom *g); @@ -146,6 +151,11 @@ static const struct flag_map rtgroup_flags[] = { .mask = XFS_RTGROUP_GEOM_SICK_SUMMARY, .descr = "realtime summary", }, + { + .mask = XFS_RTGROUP_GEOM_SICK_RMAPBT, + .descr = "realtime reverse mappings btree", + .has_fn = has_rtrmapbt, + }, {0}, }; From patchwork Thu Feb 6 22:53:07 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: 13964030 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 754502417CE for ; Thu, 6 Feb 2025 22:53:08 +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=1738882388; cv=none; b=nvHTiqcZynzX0sbpFSjWehhASbneQrnab/s0psh1jxy3JvTbDJEe1zlTGKOcxLgP/ojCHysPRt9M6sFSX9Y3tQxgT72urx+Zmo5jSxpMyhAFfnNgc2ZvIZUSNPrzzCMEWM1pmB0f9Ge3dERFZVJ3XyfkMUO/JTN6hEpaTPvmq1s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882388; c=relaxed/simple; bh=YLyowX5C8VNPHcIV6TapJcMcqIrffdnvchR31XYEAno=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=QHTXMk5s7cyGTZ/TkHew23D397l9OhLBy9kKPJWdKo/dpPj3L8hYZQCOIqWCU2w4CfNHs0zPZfvo+1h4wtChdBA2RPO30xFxAdfuLQ1buvHyO0Ys8qKI1kcOtHGNdlhg2dKJfFnBOF1p7IiloPz1rbKOuDwxbylpfSRcMkfPitU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=i/rHLR2u; 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="i/rHLR2u" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DC414C4CEDD; Thu, 6 Feb 2025 22:53:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882387; bh=YLyowX5C8VNPHcIV6TapJcMcqIrffdnvchR31XYEAno=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=i/rHLR2uprrCYQcCK/yH6RJKv+Sj5H2V8BaWumecJQLFpvuqz7enM7pjVFskyqne7 DzDjOWGmEQsK48lWWAWyZyA4OmdChnMraYpufezi55Ol23Xu4oRIvKGtC8IxD73eAd Eow3o8i8P15RB9LNnUuU/UlNzxCqBv0yJny5Zcv7C6vpp1RgjLP/+AOxlgsWEjgzyq Dc6rFNL4xifAIujr4FcdX6oNrW9GkVn94vMIiJ01ZSIxpfQ5HtF7BS30rDHMBNdh5n kM5y5lZGdWzEFp/s1puR3L6QXKWgWUdiBCg0L/+RYuFeSbAeKtblDnC4nM+CmwA6e2 cFad0Y22qMF8A== Date: Thu, 06 Feb 2025 14:53:07 -0800 Subject: [PATCH 13/27] xfs_repair: tidy up rmap_diffkeys From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088295.2741033.4604651348658562209.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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 Tidy up the comparison code in this function to match the kernel. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- repair/rmap.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/repair/rmap.c b/repair/rmap.c index bd91c721e20e4e..2065bdc0b190ba 100644 --- a/repair/rmap.c +++ b/repair/rmap.c @@ -1267,7 +1267,6 @@ rmap_diffkeys( { __u64 oa; __u64 ob; - int64_t d; struct xfs_rmap_irec tmp; tmp = *kp1; @@ -1277,9 +1276,10 @@ rmap_diffkeys( tmp.rm_flags &= ~XFS_RMAP_REC_FLAGS; ob = libxfs_rmap_irec_offset_pack(&tmp); - d = (int64_t)kp1->rm_startblock - kp2->rm_startblock; - if (d) - return d; + if (kp1->rm_startblock > kp2->rm_startblock) + return 1; + else if (kp2->rm_startblock > kp1->rm_startblock) + return -1; if (kp1->rm_owner > kp2->rm_owner) return 1; From patchwork Thu Feb 6 22:53:23 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: 13964031 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 AE73F2417C2 for ; Thu, 6 Feb 2025 22:53: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=1738882403; cv=none; b=s7DAbsaJmciQlK83T74Wo6gmOYvRBk4GCercSemEgK96wqM3ZwJZDP4OhPHvdvSjTRRlmlb9GjQJ24VkjSlkSTq4Oe/5tyZm+FH88YtAWmMLgOCEwzHpp9noj7RohPFZlmQmLTby2c628Hvw8efhDXfJRCLUR3QDLh1aFOl7CBw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882403; c=relaxed/simple; bh=fJDwr2OXE0H6iP4i3pQwnsNI3O2rq3H9f7IDbS0J9TY=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=CYYa2iyx8xnO1Dny9yMJYa6/3HTJWa4uWFjJ/mytQIp6eayA06vYRXUzzfzsajDP64TRwi+jpbPzVV4uThV9Wl/Q9RimyWWA4Knp0okQvEYq16ff5QIgZV9M2VeqeMDQ7yCYiMISj9mGRpJprbck1hGjrlmXl1fjv+OUfpJbQtw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=abj32C73; 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="abj32C73" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8B955C4CEDD; Thu, 6 Feb 2025 22:53:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882403; bh=fJDwr2OXE0H6iP4i3pQwnsNI3O2rq3H9f7IDbS0J9TY=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=abj32C73QhbvkLP/7yXw3gzLrQ+yABCivLFm2iF7T3qZSMocNTa03zZHIOxaXW8b2 YQKair9Xm/4U2FjluT+Ieiy6eagqkthNUhuJpCIIp3zlYgZBSWDp/0serBHeCttuvy thwgFNYE2qq1aDYeoYRzdDOV1DtL+HqFxeF6XBPJBhGAIoizJgsOv2FxhMedP3zDCg jzCgHdEI/SRkoyDe2w4oNAgJ6rYbPaQaqpAQmkFUXoS7cXV82gypq6GzC6wE4W7Tnp UXRQRzbKmQnUQYwXu4ao1vdYIg3PVoyKu224O+q4dyCUcgFZJ4mTDsoaZqgN83p7Si wL1H82Ot1LywQ== Date: Thu, 06 Feb 2025 14:53:23 -0800 Subject: [PATCH 14/27] xfs_repair: flag suspect long-format btree blocks From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088311.2741033.11494162687682570792.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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 Pass a "suspect" counter through scan_lbtree just like we do for short-format btree blocks, and increment its value when we encounter blocks with bad CRCs or outright corruption. This makes it so that repair actually catches bmbt blocks with bad crcs or other verifier errors. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- repair/dinode.c | 2 +- repair/scan.c | 15 ++++++++++++--- repair/scan.h | 3 +++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/repair/dinode.c b/repair/dinode.c index 9ab193bc5fe973..4eafb2324909e1 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -923,7 +923,7 @@ _("bad bmap btree ptr 0x%" PRIx64 " in ino %" PRIu64 "\n"), if (scan_lbtree(get_unaligned_be64(&pp[i]), level, scan_bmapbt, type, whichfork, lino, tot, nex, blkmapp, - &cursor, 1, check_dups, magic, + &cursor, 0, 1, check_dups, magic, (void *)zap_metadata, &xfs_bmbt_buf_ops)) return(1); /* diff --git a/repair/scan.c b/repair/scan.c index 88fbda6b83f61a..cd44a9b14f3a1c 100644 --- a/repair/scan.c +++ b/repair/scan.c @@ -136,6 +136,7 @@ scan_lbtree( xfs_extnum_t *nex, blkmap_t **blkmapp, bmap_cursor_t *bm_cursor, + int suspect, int isroot, int check_dups, int *dirty, @@ -148,6 +149,7 @@ scan_lbtree( xfs_extnum_t *nex, blkmap_t **blkmapp, bmap_cursor_t *bm_cursor, + int suspect, int isroot, int check_dups, uint64_t magic, @@ -167,6 +169,12 @@ scan_lbtree( XFS_FSB_TO_AGBNO(mp, root)); return(1); } + if (bp->b_error == -EFSBADCRC || bp->b_error == -EFSCORRUPTED) { + do_warn(_("btree block %d/%d is suspect, error %d\n"), + XFS_FSB_TO_AGNO(mp, root), + XFS_FSB_TO_AGBNO(mp, root), bp->b_error); + suspect++; + } /* * only check for bad CRC here - caller will determine if there @@ -182,7 +190,7 @@ scan_lbtree( err = (*func)(XFS_BUF_TO_BLOCK(bp), nlevels - 1, type, whichfork, root, ino, tot, nex, blkmapp, - bm_cursor, isroot, check_dups, &dirty, + bm_cursor, suspect, isroot, check_dups, &dirty, magic, priv); ASSERT(dirty == 0 || (dirty && !no_modify)); @@ -209,6 +217,7 @@ scan_bmapbt( xfs_extnum_t *nex, blkmap_t **blkmapp, bmap_cursor_t *bm_cursor, + int suspect, int isroot, int check_dups, int *dirty, @@ -505,7 +514,7 @@ _("bad bmap btree ptr 0x%llx in ino %" PRIu64 "\n"), err = scan_lbtree(be64_to_cpu(pp[i]), level, scan_bmapbt, type, whichfork, ino, tot, nex, blkmapp, - bm_cursor, 0, check_dups, magic, priv, + bm_cursor, suspect, 0, check_dups, magic, priv, &xfs_bmbt_buf_ops); if (err) return(1); @@ -573,7 +582,7 @@ _("bad fwd (right) sibling pointer (saw %" PRIu64 " should be NULLFSBLOCK)\n" be64_to_cpu(pkey[numrecs - 1].br_startoff); } - return(0); + return suspect > 0 ? 1 : 0; } static void diff --git a/repair/scan.h b/repair/scan.h index 4da788becbef66..aeaf9f1a7f4ba9 100644 --- a/repair/scan.h +++ b/repair/scan.h @@ -23,6 +23,7 @@ int scan_lbtree( xfs_extnum_t *nex, struct blkmap **blkmapp, bmap_cursor_t *bm_cursor, + int suspect, int isroot, int check_dups, int *dirty, @@ -35,6 +36,7 @@ int scan_lbtree( xfs_extnum_t *nex, struct blkmap **blkmapp, bmap_cursor_t *bm_cursor, + int suspect, int isroot, int check_dups, uint64_t magic, @@ -52,6 +54,7 @@ int scan_bmapbt( xfs_extnum_t *nex, struct blkmap **blkmapp, bmap_cursor_t *bm_cursor, + int suspect, int isroot, int check_dups, int *dirty, From patchwork Thu Feb 6 22:53: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: 13964032 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 65F842417E0 for ; Thu, 6 Feb 2025 22:53:39 +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=1738882419; cv=none; b=m5JE6Sk5LPvxWBY+Vln8swqUhqz1uDpasP5yxUbq/0OWurQw8eJsT1NxCnS95lSNEvEek2WfaCFK1H4Rx7iWWnjr1JfljEQzWu9a5p1YDYGrEQALnhf3HjS5nDm4BT2hYUtuQ0f18Byxoa2qstS+KHhpMgwsT0DdYev+zuV5Fd4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882419; c=relaxed/simple; bh=/bCnqfgtxZ0xYt2n12yId4MSKHfIO7TGgoj5eqjYHl4=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=N7P8Ct/uBAxvNBBqYghDKk2ydWmLe3zEaj64guR6P9A3bYRcrsJZ5oeJEO1vxB3i0PxXrTr06y8iV0Dr/swZavDMl3E6hZrhg8AwXLKddFy1sc21sEeFaWwyoYT6Cmzj/NazEzQ0/vQt/MoXU2zBlzhxd7A2QJp8rDcWHtCrdv0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=AuNi7D7m; 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="AuNi7D7m" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 318AFC4CEDD; Thu, 6 Feb 2025 22:53:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882419; bh=/bCnqfgtxZ0xYt2n12yId4MSKHfIO7TGgoj5eqjYHl4=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=AuNi7D7mZ/6epCVEERL1R6Ls5Vi280b8mky8Vl6x10WrROI0pErwl/9cX7X+8yYAI 8YT4w5KKz8RBk0MvXKGsTlv6mFFi/Lo9Ado41vOk2XRDKa7eZnX61sacfA7ZVci6DM gqexUJwKW0VCFVDz6/49rYRWpfqdRhxLxmm8j5kKZEnOkG5LpX0Dj/AJVSf7yPitU9 acNTB6P/WoGEKO6gRg5phh594JiwrKOZGvIYI33eHyhklSIt2noMH47eZbK9NSz4FS Y0Bcknkf5ybLGFrs8sC7kf1jhhitq45i21fawJOGuiFWmPoezuwLzL0JS+hNa9K17S qzo0joojJmbjw== Date: Thu, 06 Feb 2025 14:53:38 -0800 Subject: [PATCH 15/27] xfs_repair: use realtime rmap 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: <173888088326.2741033.4026936578793794237.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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 rmap 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 --- repair/dinode.c | 202 ++++++++++++++++++++++++++++ repair/rmap.c | 9 + repair/rmap.h | 2 repair/rt.h | 4 + repair/scan.c | 390 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- repair/scan.h | 34 +++++ 6 files changed, 631 insertions(+), 10 deletions(-) diff --git a/repair/dinode.c b/repair/dinode.c index 4eafb2324909e1..641beab333f793 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -828,6 +828,160 @@ get_agino_buf( * first, one utility routine for each type of inode */ +/* + * return 1 if inode should be cleared, 0 otherwise + */ +static int +process_rtrmap( + 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 xfs_rmap_irec oldkey; + struct xfs_rmap_irec key; + struct rmap_priv priv; + struct xfs_rtrmap_root *dib; + xfs_rtrmap_ptr_t *pp; + struct xfs_rmap_key *kp; + struct xfs_rmap_rec *rp; + char *forkname = get_forkname(XFS_DATA_FORK); + 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 rtrmapbt, 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 rmap btree inode must be a metadata inode. */ + if (!(dip->di_flags2 & be64_to_cpu(XFS_DIFLAG2_METADATA))) { + do_warn( +_("rtrmap inode %" PRIu64 " not flagged as metadata\n"), + lino); + return 1; + } + + if (!is_rtrmap_inode(lino)) { + do_warn( +_("could not associate rtrmap inode %" PRIu64 " with any rtgroup\n"), + lino); + return 1; + } + + memset(&priv.high_key, 0xFF, sizeof(priv.high_key)); + priv.high_key.rm_blockcount = 0; + priv.agcnts = NULL; + priv.last_rec.rm_owner = XFS_RMAP_OWN_UNKNOWN; + + dib = (struct xfs_rtrmap_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_rtrmap_maxlevels) { + do_warn( +_("bad level %d in inode %" PRIu64 " rtrmap btree root block\n"), + level, lino); + return 1; + } + + /* + * use rtroot/dfork_dsize since the root block is in the data fork + */ + droot_sz = xfs_rtrmap_droot_space_calc(level, numrecs); + if (droot_sz > XFS_DFORK_SIZE(dip, mp, XFS_DATA_FORK)) { + do_warn( +_("computed size of rtrmapbt root (%zu bytes) is greater than space in " + "inode %" PRIu64 " %s fork\n"), + droot_sz, lino, forkname); + return 1; + } + + if (level == 0) { + rp = xfs_rtrmap_droot_rec_addr(dib, 1); + error = process_rtrmap_reclist(mp, rp, numrecs, + &priv.last_rec, NULL, "rtrmapbt root"); + if (error) { + rmap_avoid_check(); + return 1; + } + return 0; + } + + dmxr = libxfs_rtrmapbt_droot_maxrecs( + XFS_DFORK_SIZE(dip, mp, XFS_DATA_FORK), false); + pp = xfs_rtrmap_droot_ptr_addr(dib, 1, dmxr); + + /* check for in-order keys */ + for (i = 0; i < numrecs; i++) { + kp = xfs_rtrmap_droot_key_addr(dib, i + 1); + + key.rm_flags = 0; + key.rm_startblock = be32_to_cpu(kp->rm_startblock); + key.rm_owner = be64_to_cpu(kp->rm_owner); + if (libxfs_rmap_irec_offset_unpack(be64_to_cpu(kp->rm_offset), + &key)) { + /* Look for impossible flags. */ + do_warn( +_("invalid flags in key %u of rtrmap root ino %" PRIu64 "\n"), + i, lino); + suspect++; + continue; + } + if (i == 0) { + oldkey = key; + continue; + } + if (rmap_diffkeys(&oldkey, &key) > 0) { + do_warn( +_("out of order key %u in rtrmap 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 rtrmap btree ptr 0x%" PRIx64 " in ino %" PRIu64 "\n"), + bno, lino); + return 1; + } + + if (scan_lbtree(bno, level, scan_rtrmapbt, + type, XFS_DATA_FORK, lino, tot, nex, blkmapp, + NULL, 0, 1, check_dups, XFS_RTRMAP_CRC_MAGIC, + &priv, &xfs_rtrmapbt_buf_ops)) + return 1; + } + + return suspect ? 1 : 0; +} + /* * return 1 if inode should be cleared, 0 otherwise */ @@ -1606,7 +1760,7 @@ static int check_dinode_mode_format( struct xfs_dinode *dinoc) { - if (dinoc->di_format >= XFS_DINODE_FMT_UUID) + if (dinoc->di_format == XFS_DINODE_FMT_UUID) return -1; /* FMT_UUID is not used */ switch (dinode_fmt(dinoc)) { @@ -1621,8 +1775,19 @@ check_dinode_mode_format( dinoc->di_format > XFS_DINODE_FMT_BTREE) ? -1 : 0; case S_IFREG: - return (dinoc->di_format < XFS_DINODE_FMT_EXTENTS || - dinoc->di_format > XFS_DINODE_FMT_BTREE) ? -1 : 0; + switch (dinoc->di_format) { + case XFS_DINODE_FMT_EXTENTS: + case XFS_DINODE_FMT_BTREE: + return 0; + case XFS_DINODE_FMT_META_BTREE: + switch (be16_to_cpu(dinoc->di_metatype)) { + case XFS_METAFILE_RTRMAP: + return 0; + default: + return -1; + } + } + return -1; case S_IFLNK: return (dinoc->di_format < XFS_DINODE_FMT_LOCAL || @@ -2046,6 +2211,22 @@ process_inode_data_fork( totblocks, nextents, dblkmap, XFS_DATA_FORK, check_dups, zap_metadata); break; + case XFS_DINODE_FMT_META_BTREE: + switch (be16_to_cpu(dino->di_metatype)) { + case XFS_METAFILE_RTRMAP: + err = process_rtrmap(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"), + be16_to_cpu(dino->di_metatype), lino, + be16_to_cpu(dino->di_mode)); + err = 1; + break; + } + break; case XFS_DINODE_FMT_DEV: err = 0; break; @@ -2107,6 +2288,21 @@ _("would have tried to rebuild inode %"PRIu64" data fork\n"), case XFS_DINODE_FMT_DEV: err = 0; break; + case XFS_DINODE_FMT_META_BTREE: + switch (be16_to_cpu(dino->di_metatype)) { + case XFS_METAFILE_RTRMAP: + err = 0; + break; + default: + do_error( + _("unknown meta btree type %d, ino %" PRIu64 " (mode = %d)\n"), + be16_to_cpu(dino->di_metatype), + lino, + be16_to_cpu(dino->di_mode)); + err = 1; + break; + } + break; default: do_error(_("unknown format %d, ino %" PRIu64 " (mode = %d)\n"), dino->di_format, lino, diff --git a/repair/rmap.c b/repair/rmap.c index 2065bdc0b190ba..36e4c9858fba03 100644 --- a/repair/rmap.c +++ b/repair/rmap.c @@ -123,6 +123,15 @@ rmaps_init_ag( _("Insufficient memory while allocating realtime reverse mapping btree.")); } +xfs_rgnumber_t +rtgroup_for_rtrmap_inode( + struct xfs_mount *mp, + xfs_ino_t ino) +{ + /* This will be implemented later. */ + return NULLRGNUMBER; +} + /* * Initialize per-AG reverse map data. */ diff --git a/repair/rmap.h b/repair/rmap.h index 683a51af3fc511..57e5d5b216650e 100644 --- a/repair/rmap.h +++ b/repair/rmap.h @@ -55,4 +55,6 @@ int rmap_init_mem_cursor(struct xfs_mount *mp, struct xfs_trans *tp, xfs_agnumber_t agno, struct xfs_btree_cur **rmcurp); int rmap_get_mem_rec(struct xfs_btree_cur *rmcur, struct xfs_rmap_irec *irec); +xfs_rgnumber_t rtgroup_for_rtrmap_inode(struct xfs_mount *mp, xfs_ino_t ino); + #endif /* RMAP_H_ */ diff --git a/repair/rt.h b/repair/rt.h index 865d950b2bf3c4..13558706e4ec15 100644 --- a/repair/rt.h +++ b/repair/rt.h @@ -29,6 +29,10 @@ static inline bool is_rtsummary_inode(xfs_ino_t ino) { return is_rtgroup_inode(ino, XFS_RTGI_SUMMARY); } +static inline bool is_rtrmap_inode(xfs_ino_t ino) +{ + return is_rtgroup_inode(ino, XFS_RTGI_RMAP); +} 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 cd44a9b14f3a1c..386aaa15f78c33 100644 --- a/repair/scan.c +++ b/repair/scan.c @@ -949,13 +949,6 @@ _("unknown block (%d,%d-%d) mismatch on %s tree, state - %d,%" PRIx64 "\n"), } } -struct rmap_priv { - struct aghdr_cnts *agcnts; - struct xfs_rmap_irec high_key; - struct xfs_rmap_irec last_rec; - xfs_agblock_t nr_blocks; -}; - static bool rmap_in_order( xfs_agblock_t b, @@ -1358,6 +1351,389 @@ _("out of order key %u in %s btree block (%u/%u)\n"), rmap_avoid_check(); } +int +process_rtrmap_reclist( + struct xfs_mount *mp, + struct xfs_rmap_rec *rp, + int numrecs, + struct xfs_rmap_irec *last_rec, + struct xfs_rmap_irec *high_key, + const char *name) +{ + int suspect = 0; + int i; + struct xfs_rmap_irec oldkey; + struct xfs_rmap_irec key; + + for (i = 0; i < numrecs; i++) { + xfs_rgblock_t b, end; + xfs_extlen_t len; + uint64_t owner, offset; + + b = be32_to_cpu(rp[i].rm_startblock); + len = be32_to_cpu(rp[i].rm_blockcount); + owner = be64_to_cpu(rp[i].rm_owner); + offset = be64_to_cpu(rp[i].rm_offset); + + key.rm_flags = 0; + key.rm_startblock = b; + key.rm_blockcount = len; + key.rm_owner = owner; + if (libxfs_rmap_irec_offset_unpack(offset, &key)) { + /* Look for impossible flags. */ + do_warn( +_("invalid flags in record %u of %s\n"), + i, name); + suspect++; + continue; + } + + + end = key.rm_startblock + key.rm_blockcount; + + /* Make sure startblock & len make sense. */ + if (b >= mp->m_groups[XG_TYPE_RTG].blocks) { + do_warn( +_("invalid start block %llu in record %u of %s\n"), + (unsigned long long)b, i, name); + suspect++; + continue; + } + if (len == 0 || end - 1 >= mp->m_groups[XG_TYPE_RTG].blocks) { + do_warn( +_("invalid length %llu in record %u of %s\n"), + (unsigned long long)len, i, name); + suspect++; + continue; + } + + /* We only store file data and superblocks in the rtrmap. */ + 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); + suspect++; + continue; + } + + /* Look for impossible record field combinations. */ + if (key.rm_flags & XFS_RMAP_KEY_FLAGS) { + do_warn( +_("record %d cannot have attr fork/key flags in %s\n"), + i, name); + suspect++; + continue; + } + + /* Check for out of order records. */ + if (i == 0) + oldkey = key; + else { + if (rmap_diffkeys(&oldkey, &key) > 0) + do_warn( +_("out-of-order record %d (%llu %"PRId64" %"PRIu64" %llu) in %s\n"), + i, (unsigned long long)b, owner, offset, + (unsigned long long)len, name); + else + oldkey = key; + } + + /* Is this mergeable with the previous record? */ + if (rmaps_are_mergeable(last_rec, &key)) { + do_warn( +_("record %d in %s should be merged with previous record\n"), + i, name); + last_rec->rm_blockcount += key.rm_blockcount; + } else + *last_rec = key; + + /* Check that we don't go past the high key. */ + key.rm_startblock += key.rm_blockcount - 1; + key.rm_offset += key.rm_blockcount - 1; + key.rm_blockcount = 0; + if (high_key && rmap_diffkeys(&key, high_key) > 0) { + do_warn( +_("record %d greater than high key of %s\n"), + i, name); + suspect++; + } + } + + return suspect; +} + +int +scan_rtrmapbt( + 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, + blkmap_t **blkmapp, + bmap_cursor_t *bm_cursor, + int suspect, + int isroot, + int check_dups, + int *dirty, + uint64_t magic, + void *priv) +{ + const char *name = "rtrmap"; + char rootname[256]; + int i; + xfs_rtrmap_ptr_t *pp; + struct xfs_rmap_rec *rp; + struct rmap_priv *rmap_priv = priv; + int hdr_errors = 0; + int numrecs; + int state; + struct xfs_rmap_key *kp; + struct xfs_rmap_irec oldkey; + struct xfs_rmap_irec key; + 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 anything here is bad, just bail. */ + if (be32_to_cpu(block->bb_magic) != magic) { + do_warn( +_("bad magic # %#x in inode %" PRIu64 " %s block %" PRIu64 "\n"), + be32_to_cpu(block->bb_magic), ino, name, fsbno); + return 1; + } + if (be16_to_cpu(block->bb_level) != level) { + do_warn( +_("expected level %d got %d in inode %" PRIu64 ", %s block %" PRIu64 "\n"), + level, be16_to_cpu(block->bb_level), + ino, name, fsbno); + return(1); + } + + /* verify owner */ + if (be64_to_cpu(block->bb_u.l.bb_owner) != ino) { + do_warn( +_("expected owner inode %" PRIu64 ", got %llu, %s block %" PRIu64 "\n"), + ino, + (unsigned long long)be64_to_cpu(block->bb_u.l.bb_owner), + name, fsbno); + return 1; + } + /* verify block number */ + if (be64_to_cpu(block->bb_u.l.bb_blkno) != + XFS_FSB_TO_DADDR(mp, fsbno)) { + do_warn( +_("expected block %" PRIu64 ", got %llu, %s block %" PRIu64 "\n"), + XFS_FSB_TO_DADDR(mp, fsbno), + (unsigned long long)be64_to_cpu(block->bb_u.l.bb_blkno), + name, fsbno); + return 1; + } + /* verify uuid */ + if (platform_uuid_compare(&block->bb_u.l.bb_uuid, + &mp->m_sb.sb_meta_uuid) != 0) { + do_warn( +_("wrong FS UUID, %s block %" PRIu64 "\n"), + name, fsbno); + return 1; + } + + /* + * Check for btree blocks multiply claimed. We're going to regenerate + * the rtrmap 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, bno %d, suspect %d\n"), + name, state, agno, agbno, suspect); + suspect++; + goto out; + } + set_bmap(agno, agbno, XR_E_METADATA); + + numrecs = be16_to_cpu(block->bb_numrecs); + + /* + * All realtime rmap btree blocks are freed for a fully empty + * filesystem, thus they are counted towards the free data + * block counter. The root lives in an inode and is thus not + * counted. + */ + (*tot)++; + + if (level == 0) { + if (numrecs > mp->m_rtrmap_mxr[0]) { + numrecs = mp->m_rtrmap_mxr[0]; + hdr_errors++; + } + if (isroot == 0 && numrecs < mp->m_rtrmap_mnr[0]) { + numrecs = mp->m_rtrmap_mnr[0]; + hdr_errors++; + } + + if (hdr_errors) { + do_warn( +_("bad btree nrecs (%u, min=%u, max=%u) in bt%s block %u/%u\n"), + be16_to_cpu(block->bb_numrecs), + mp->m_rtrmap_mnr[0], mp->m_rtrmap_mxr[0], + name, agno, agbno); + suspect++; + } + + rp = xfs_rtrmap_rec_addr(block, 1); + snprintf(rootname, 256, "%s btree block %u/%u", name, agno, agbno); + error = process_rtrmap_reclist(mp, rp, numrecs, + &rmap_priv->last_rec, &rmap_priv->high_key, + rootname); + if (error) + suspect++; + goto out; + } + + /* + * interior record + */ + pp = xfs_rtrmap_ptr_addr(block, 1, mp->m_rtrmap_mxr[1]); + + if (numrecs > mp->m_rtrmap_mxr[1]) { + numrecs = mp->m_rtrmap_mxr[1]; + hdr_errors++; + } + if (isroot == 0 && numrecs < mp->m_rtrmap_mnr[1]) { + numrecs = mp->m_rtrmap_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 bt%s block %u/%u\n"), + be16_to_cpu(block->bb_numrecs), + mp->m_rtrmap_mnr[1], mp->m_rtrmap_mxr[1], + name, agno, agbno); + if (suspect) + goto out; + suspect++; + } else if (suspect) { + suspect = 0; + } + + /* check the node's high keys */ + for (i = 0; !isroot && i < numrecs; i++) { + kp = xfs_rtrmap_high_key_addr(block, i + 1); + + key.rm_flags = 0; + key.rm_startblock = be32_to_cpu(kp->rm_startblock); + key.rm_owner = be64_to_cpu(kp->rm_owner); + if (libxfs_rmap_irec_offset_unpack(be64_to_cpu(kp->rm_offset), + &key)) { + /* Look for impossible flags. */ + do_warn( +_("invalid flags in key %u of %s btree block %u/%u\n"), + i, name, agno, agbno); + suspect++; + continue; + } + if (rmap_diffkeys(&key, &rmap_priv->high_key) > 0) { + do_warn( +_("key %d greater than high key of block (%u/%u) in %s tree\n"), + i, agno, agbno, name); + suspect++; + } + } + + /* check for in-order keys */ + for (i = 0; i < numrecs; i++) { + kp = xfs_rtrmap_key_addr(block, i + 1); + + key.rm_flags = 0; + key.rm_startblock = be32_to_cpu(kp->rm_startblock); + key.rm_owner = be64_to_cpu(kp->rm_owner); + if (libxfs_rmap_irec_offset_unpack(be64_to_cpu(kp->rm_offset), + &key)) { + /* Look for impossible flags. */ + do_warn( +_("invalid flags in key %u of %s btree block %u/%u\n"), + i, name, agno, agbno); + suspect++; + continue; + } + if (i == 0) { + oldkey = key; + continue; + } + if (rmap_diffkeys(&oldkey, &key) > 0) { + do_warn( +_("out of order key %u in %s btree block (%u/%u)\n"), + i, name, agno, agbno); + suspect++; + } + oldkey = key; + } + + for (i = 0; i < numrecs; i++) { + xfs_fsblock_t pbno = be64_to_cpu(pp[i]); + + /* + * XXX - put sibling detection right here. + * we know our sibling chain is good. So as we go, + * we check the entry before and after each entry. + * If either of the entries references a different block, + * check the sibling pointer. If there's a sibling + * pointer mismatch, try and extract as much data + * as possible. + */ + kp = xfs_rtrmap_high_key_addr(block, i + 1); + rmap_priv->high_key.rm_flags = 0; + rmap_priv->high_key.rm_startblock = + be32_to_cpu(kp->rm_startblock); + rmap_priv->high_key.rm_owner = + be64_to_cpu(kp->rm_owner); + if (libxfs_rmap_irec_offset_unpack(be64_to_cpu(kp->rm_offset), + &rmap_priv->high_key)) { + /* Look for impossible flags. */ + do_warn( +_("invalid flags in high key %u of %s btree block %u/%u\n"), + i, name, agno, agbno); + suspect++; + continue; + } + + if (!libxfs_verify_fsbno(mp, pbno)) { + do_warn( +_("bad %s btree ptr 0x%llx in ino %" PRIu64 "\n"), + name, (unsigned long long)pbno, ino); + return 1; + } + + error = scan_lbtree(pbno, level, scan_rtrmapbt, + type, whichfork, ino, tot, nex, blkmapp, + bm_cursor, suspect, 0, check_dups, magic, + rmap_priv, &xfs_rtrmapbt_buf_ops); + if (error) { + suspect++; + goto out; + } + } + +out: + if (hdr_errors || suspect) { + rmap_avoid_check(); + return 1; + } + return 0; +} + struct refc_priv { struct xfs_refcount_irec last_rec; xfs_agblock_t nr_blocks; diff --git a/repair/scan.h b/repair/scan.h index aeaf9f1a7f4ba9..a624c882734c77 100644 --- a/repair/scan.h +++ b/repair/scan.h @@ -66,4 +66,38 @@ scan_ags( struct xfs_mount *mp, int scan_threads); +struct rmap_priv { + struct aghdr_cnts *agcnts; + struct xfs_rmap_irec high_key; + struct xfs_rmap_irec last_rec; + xfs_agblock_t nr_blocks; +}; + +int +process_rtrmap_reclist( + struct xfs_mount *mp, + struct xfs_rmap_rec *rp, + int numrecs, + struct xfs_rmap_irec *last_rec, + struct xfs_rmap_irec *high_key, + const char *name); + +int scan_rtrmapbt( + 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 22:53:54 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: 13964033 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 7CB532417C2 for ; Thu, 6 Feb 2025 22:53:55 +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=1738882436; cv=none; b=B+SUFtyTnkUdWHQhkD63U1m9VpK/yUCBQek7fXtdkTopNoNqCPGJDxk23HtjLC6mrmEidvYVZ9UKhF2/8LDmZdWF+3r8Lb3ojIMIrW/t4y0yhnRwjFsAl5VhE/cl5koVLTgn01GoE1mXep0rNUWsaksdwRCBHoNfkprF1rG+ADg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882436; c=relaxed/simple; bh=4Aw6ie7Qlc7674s9J/lrFk7jcLQB3eXQnWnNf38xsIM=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=NTL6q0l5JyoISZb9xWrS4ryowIJDPB4Ct9iOIa91QVkEeKZGW/Zfi5X+chQzQkuIrrPmJqEokgnu74GFCS1RWnseJc6e8DSOKjBfQKjyzVndp5OPiN/F48OoXv1TfiILim+201S66zzXUMpyhJ5l+CupMCJFMZbAWIku/PcgA4k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=SW7Bkd99; 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="SW7Bkd99" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D8C88C4CEDD; Thu, 6 Feb 2025 22:53:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882434; bh=4Aw6ie7Qlc7674s9J/lrFk7jcLQB3eXQnWnNf38xsIM=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=SW7Bkd99uqyZ9m/DuV4fH4ZK6cDgY4Wj+cQdprgBYw3EIPZzkC49Y9sY9JnfozbKW vh8V5Q0EuoZk2CBuZ/K/KhNub6WtoORS0v55LekJtCt6fV9q+C6l18nHUzWNN8lXXj L/lVhbV8l3LhROt4Osn/RXj1pOoyG0j7CtRQKIQ2bP8hmAgjP3Ncz4nJfUVZeU+EWx oYzbBluBF240k816xyeRbKElXy2GB205yL6dKtiK1Nc9ssdkRAiSFaYbo4JC2JmZQb C9O9ScN2OxOUO+qxBsj44zj0M8g/K34XEVaO8SJcyXNM2vuLzVW13ym+6UgrjLR5G2 mBjz8duJhK+Ww== Date: Thu, 06 Feb 2025 14:53:54 -0800 Subject: [PATCH 16/27] xfs_repair: create a new set of incore rmap information for rt groups From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088341.2741033.9571711667950343905.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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 Create a parallel set of "xfs_ag_rmap" structures to cache information about reverse mappings for the realtime groups. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- libxfs/libxfs_api_defs.h | 2 + repair/agbtree.c | 5 +- repair/dinode.c | 2 - repair/rmap.c | 139 +++++++++++++++++++++++++++++++++++++--------- repair/rmap.h | 7 +- 5 files changed, 121 insertions(+), 34 deletions(-) diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index 9beea4f7ce8535..b62efad757470b 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -318,6 +318,8 @@ #define xfs_rtrmapbt_maxlevels_ondisk libxfs_rtrmapbt_maxlevels_ondisk #define xfs_rtrmapbt_init_cursor libxfs_rtrmapbt_init_cursor #define xfs_rtrmapbt_maxrecs libxfs_rtrmapbt_maxrecs +#define xfs_rtrmapbt_mem_init libxfs_rtrmapbt_mem_init +#define xfs_rtrmapbt_mem_cursor libxfs_rtrmapbt_mem_cursor #define xfs_sb_from_disk libxfs_sb_from_disk #define xfs_sb_mount_rextsize libxfs_sb_mount_rextsize diff --git a/repair/agbtree.c b/repair/agbtree.c index 42bfeee9eafbcb..2135147fcf9354 100644 --- a/repair/agbtree.c +++ b/repair/agbtree.c @@ -646,7 +646,7 @@ init_rmapbt_cursor( /* Compute how many blocks we'll need. */ error = -libxfs_btree_bload_compute_geometry(btr->cur, &btr->bload, - rmap_record_count(sc->mp, agno)); + rmap_record_count(sc->mp, false, agno)); if (error) do_error( _("Unable to compute rmap btree geometry, error %d.\n"), error); @@ -663,7 +663,8 @@ build_rmap_tree( { int error; - error = rmap_init_mem_cursor(sc->mp, NULL, agno, &btr->rmapbt_cursor); + error = rmap_init_mem_cursor(sc->mp, NULL, false, agno, + &btr->rmapbt_cursor); if (error) do_error( _("Insufficient memory to construct rmap cursor.\n")); diff --git a/repair/dinode.c b/repair/dinode.c index 641beab333f793..3f78eb064919be 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -708,7 +708,7 @@ _("illegal state %d in block map %" PRIu64 "\n"), } } if (collect_rmaps && !zap_metadata) /* && !check_dups */ - rmap_add_rec(mp, ino, whichfork, &irec); + rmap_add_rec(mp, ino, whichfork, &irec, isrt); *tot += irec.br_blockcount; } error = 0; diff --git a/repair/rmap.c b/repair/rmap.c index 36e4c9858fba03..13e9a06b04f370 100644 --- a/repair/rmap.c +++ b/repair/rmap.c @@ -24,7 +24,7 @@ # define dbg_printf(f, a...) #endif -/* per-AG rmap object anchor */ +/* allocation group (AG or rtgroup) rmap object anchor */ struct xfs_ag_rmap { /* root of rmap observations btree */ struct xfbtree ar_xfbtree; @@ -42,9 +42,17 @@ struct xfs_ag_rmap { }; static struct xfs_ag_rmap *ag_rmaps; +static struct xfs_ag_rmap *rg_rmaps; bool rmapbt_suspect; static bool refcbt_suspect; +static struct xfs_ag_rmap *rmaps_for_group(bool isrt, unsigned int group) +{ + if (isrt) + return &rg_rmaps[group]; + return &ag_rmaps[group]; +} + static inline int rmap_compare(const void *a, const void *b) { return libxfs_rmap_compare(a, b); @@ -83,6 +91,44 @@ rmaps_destroy( xmbuf_free(ag_rmap->ar_xmbtp); } +/* Initialize the in-memory rmap btree for collecting realtime rmap records. */ +STATIC void +rmaps_init_rt( + struct xfs_mount *mp, + xfs_rgnumber_t rgno, + struct xfs_ag_rmap *ag_rmap) +{ + char *descr; + unsigned long long maxbytes; + int error; + + if (!xfs_has_realtime(mp)) + return; + + /* + * Each rtgroup rmap btree file can consume the entire data device, + * even if the metadata space reservation will be smaller than that. + */ + maxbytes = XFS_FSB_TO_B(mp, mp->m_sb.sb_dblocks); + descr = kasprintf(GFP_KERNEL, + "xfs_repair (%s): rtgroup %u rmap records", + mp->m_fsname, rgno); + error = -xmbuf_alloc(mp, descr, maxbytes, &ag_rmap->ar_xmbtp); + kfree(descr); + if (error) + goto nomem; + + error = -libxfs_rtrmapbt_mem_init(mp, &ag_rmap->ar_xfbtree, + ag_rmap->ar_xmbtp, rgno); + if (error) + goto nomem; + + return; +nomem: + do_error( +_("Insufficient memory while allocating realtime reverse mapping btree.")); +} + /* Initialize the in-memory rmap btree for collecting per-AG rmap records. */ STATIC void rmaps_init_ag( @@ -150,6 +196,13 @@ rmaps_init( for (i = 0; i < mp->m_sb.sb_agcount; i++) rmaps_init_ag(mp, i, &ag_rmaps[i]); + + rg_rmaps = calloc(mp->m_sb.sb_rgcount, sizeof(struct xfs_ag_rmap)); + if (!rg_rmaps) + do_error(_("couldn't allocate per-rtgroup reverse map roots\n")); + + for (i = 0; i < mp->m_sb.sb_rgcount; i++) + rmaps_init_rt(mp, i, &rg_rmaps[i]); } /* @@ -164,6 +217,11 @@ rmaps_free( if (!rmap_needs_work(mp)) return; + for (i = 0; i < mp->m_sb.sb_rgcount; i++) + rmaps_destroy(mp, &rg_rmaps[i]); + free(rg_rmaps); + rg_rmaps = NULL; + for (i = 0; i < mp->m_sb.sb_agcount; i++) rmaps_destroy(mp, &ag_rmaps[i]); free(ag_rmaps); @@ -199,22 +257,32 @@ int rmap_init_mem_cursor( struct xfs_mount *mp, struct xfs_trans *tp, + bool isrt, xfs_agnumber_t agno, struct xfs_btree_cur **rmcurp) { struct xfbtree *xfbt; - struct xfs_perag *pag; + struct xfs_perag *pag = NULL; + struct xfs_rtgroup *rtg = NULL; int error; - xfbt = &ag_rmaps[agno].ar_xfbtree; - pag = libxfs_perag_get(mp, agno); - *rmcurp = libxfs_rmapbt_mem_cursor(pag, tp, xfbt); + xfbt = &rmaps_for_group(isrt, agno)->ar_xfbtree; + if (isrt) { + rtg = libxfs_rtgroup_get(mp, agno); + *rmcurp = libxfs_rtrmapbt_mem_cursor(rtg, tp, xfbt); + } else { + pag = libxfs_perag_get(mp, agno); + *rmcurp = libxfs_rmapbt_mem_cursor(pag, tp, xfbt); + } error = -libxfs_btree_goto_left_edge(*rmcurp); if (error) libxfs_btree_del_cursor(*rmcurp, error); - libxfs_perag_put(pag); + if (pag) + libxfs_perag_put(pag); + if (rtg) + libxfs_rtgroup_put(rtg); return error; } @@ -247,6 +315,7 @@ rmap_get_mem_rec( static void rmap_add_mem_rec( struct xfs_mount *mp, + bool isrt, xfs_agnumber_t agno, struct xfs_rmap_irec *rmap) { @@ -255,12 +324,12 @@ rmap_add_mem_rec( struct xfs_trans *tp; int error; - xfbt = &ag_rmaps[agno].ar_xfbtree; + xfbt = &rmaps_for_group(isrt, agno)->ar_xfbtree; error = -libxfs_trans_alloc_empty(mp, &tp); if (error) do_error(_("allocating tx for in-memory rmap update\n")); - error = rmap_init_mem_cursor(mp, tp, agno, &rmcur); + error = rmap_init_mem_cursor(mp, tp, isrt, agno, &rmcur); if (error) do_error(_("reading in-memory rmap btree head\n")); @@ -285,7 +354,8 @@ rmap_add_rec( struct xfs_mount *mp, xfs_ino_t ino, int whichfork, - struct xfs_bmbt_irec *irec) + struct xfs_bmbt_irec *irec, + bool isrt) { struct xfs_rmap_irec rmap; xfs_agnumber_t agno; @@ -294,11 +364,17 @@ rmap_add_rec( if (!rmap_needs_work(mp)) return; - agno = XFS_FSB_TO_AGNO(mp, irec->br_startblock); - agbno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock); - ASSERT(agno != NULLAGNUMBER); - ASSERT(agno < mp->m_sb.sb_agcount); - ASSERT(agbno + irec->br_blockcount <= mp->m_sb.sb_agblocks); + if (isrt) { + agno = xfs_rtb_to_rgno(mp, irec->br_startblock); + agbno = xfs_rtb_to_rgbno(mp, irec->br_startblock); + ASSERT(agbno + irec->br_blockcount <= mp->m_sb.sb_rblocks); + } else { + agno = XFS_FSB_TO_AGNO(mp, irec->br_startblock); + agbno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock); + ASSERT(agno != NULLAGNUMBER); + ASSERT(agno < mp->m_sb.sb_agcount); + ASSERT(agbno + irec->br_blockcount <= mp->m_sb.sb_agblocks); + } ASSERT(ino != NULLFSINO); ASSERT(whichfork == XFS_DATA_FORK || whichfork == XFS_ATTR_FORK); @@ -312,7 +388,7 @@ rmap_add_rec( if (irec->br_state == XFS_EXT_UNWRITTEN) rmap.rm_flags |= XFS_RMAP_UNWRITTEN; - rmap_add_mem_rec(mp, agno, &rmap); + rmap_add_mem_rec(mp, isrt, agno, &rmap); } /* add a raw rmap; these will be merged later */ @@ -339,7 +415,7 @@ __rmap_add_raw_rec( rmap.rm_startblock = agbno; rmap.rm_blockcount = len; - rmap_add_mem_rec(mp, agno, &rmap); + rmap_add_mem_rec(mp, false, agno, &rmap); } /* @@ -408,6 +484,7 @@ rmap_add_agbtree_mapping( .rm_blockcount = len, }; struct xfs_perag *pag; + struct xfs_ag_rmap *x; if (!rmap_needs_work(mp)) return 0; @@ -416,7 +493,8 @@ rmap_add_agbtree_mapping( assert(libxfs_verify_agbext(pag, agbno, len)); libxfs_perag_put(pag); - return slab_add(ag_rmaps[agno].ar_agbtree_rmaps, &rmap); + x = rmaps_for_group(false, agno); + return slab_add(x->ar_agbtree_rmaps, &rmap); } static int @@ -532,7 +610,7 @@ rmap_commit_agbtree_mappings( struct xfs_buf *agflbp = NULL; struct xfs_trans *tp; __be32 *agfl_bno, *b; - struct xfs_ag_rmap *ag_rmap = &ag_rmaps[agno]; + struct xfs_ag_rmap *ag_rmap = rmaps_for_group(false, agno); struct bitmap *own_ag_bitmap = NULL; int error = 0; @@ -795,7 +873,7 @@ refcount_emit( int error; struct xfs_slab *rlslab; - rlslab = ag_rmaps[agno].ar_refcount_items; + rlslab = rmaps_for_group(false, agno)->ar_refcount_items; ASSERT(nr_rmaps > 0); dbg_printf("REFL: agno=%u pblk=%u, len=%u -> refcount=%zu\n", @@ -928,12 +1006,12 @@ compute_refcounts( if (!xfs_has_reflink(mp)) return 0; - if (!rmaps_has_observations(&ag_rmaps[agno])) + if (!rmaps_has_observations(rmaps_for_group(false, agno))) return 0; - nr_rmaps = rmap_record_count(mp, agno); + nr_rmaps = rmap_record_count(mp, false, agno); - error = rmap_init_mem_cursor(mp, NULL, agno, &rmcur); + error = rmap_init_mem_cursor(mp, NULL, false, agno, &rmcur); if (error) return error; @@ -1038,16 +1116,17 @@ count_btree_records( uint64_t rmap_record_count( struct xfs_mount *mp, + bool isrt, xfs_agnumber_t agno) { struct xfs_btree_cur *rmcur; uint64_t nr = 0; int error; - if (!rmaps_has_observations(&ag_rmaps[agno])) + if (!rmaps_has_observations(rmaps_for_group(isrt, agno))) return 0; - error = rmap_init_mem_cursor(mp, NULL, agno, &rmcur); + error = rmap_init_mem_cursor(mp, NULL, isrt, agno, &rmcur); if (error) do_error(_("%s while reading in-memory rmap btree\n"), strerror(error)); @@ -1163,7 +1242,7 @@ rmaps_verify_btree( } /* Create cursors to rmap structures */ - error = rmap_init_mem_cursor(mp, NULL, agno, &rm_cur); + error = rmap_init_mem_cursor(mp, NULL, false, agno, &rm_cur); if (error) { do_warn(_("Not enough memory to check reverse mappings.\n")); return; @@ -1483,7 +1562,9 @@ refcount_record_count( struct xfs_mount *mp, xfs_agnumber_t agno) { - return slab_count(ag_rmaps[agno].ar_refcount_items); + struct xfs_ag_rmap *x = rmaps_for_group(false, agno); + + return slab_count(x->ar_refcount_items); } /* @@ -1494,7 +1575,9 @@ init_refcount_cursor( xfs_agnumber_t agno, struct xfs_slab_cursor **cur) { - return init_slab_cursor(ag_rmaps[agno].ar_refcount_items, NULL, cur); + struct xfs_ag_rmap *x = rmaps_for_group(false, agno); + + return init_slab_cursor(x->ar_refcount_items, NULL, cur); } /* @@ -1695,7 +1778,7 @@ rmap_store_agflcount( if (!rmap_needs_work(mp)) return; - ag_rmaps[agno].ar_flcount = count; + rmaps_for_group(false, agno)->ar_flcount = count; } /* Estimate the size of the ondisk rmapbt from the incore data. */ diff --git a/repair/rmap.h b/repair/rmap.h index 57e5d5b216650e..23871e6d60e774 100644 --- a/repair/rmap.h +++ b/repair/rmap.h @@ -15,7 +15,7 @@ extern void rmaps_init(struct xfs_mount *); extern void rmaps_free(struct xfs_mount *); void rmap_add_rec(struct xfs_mount *mp, xfs_ino_t ino, int whichfork, - struct xfs_bmbt_irec *irec); + struct xfs_bmbt_irec *irec, bool realtime); void rmap_add_bmbt_rec(struct xfs_mount *mp, xfs_ino_t ino, int whichfork, xfs_fsblock_t fsbno); bool rmaps_are_mergeable(struct xfs_rmap_irec *r1, struct xfs_rmap_irec *r2); @@ -26,7 +26,8 @@ int rmap_add_agbtree_mapping(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, uint64_t owner); int rmap_commit_agbtree_mappings(struct xfs_mount *mp, xfs_agnumber_t agno); -uint64_t rmap_record_count(struct xfs_mount *mp, xfs_agnumber_t agno); +uint64_t rmap_record_count(struct xfs_mount *mp, bool isrt, + xfs_agnumber_t agno); extern void rmap_avoid_check(void); void rmaps_verify_btree(struct xfs_mount *mp, xfs_agnumber_t agno); @@ -52,7 +53,7 @@ xfs_extlen_t estimate_rmapbt_blocks(struct xfs_perag *pag); xfs_extlen_t estimate_refcountbt_blocks(struct xfs_perag *pag); int rmap_init_mem_cursor(struct xfs_mount *mp, struct xfs_trans *tp, - xfs_agnumber_t agno, struct xfs_btree_cur **rmcurp); + bool isrt, xfs_agnumber_t agno, struct xfs_btree_cur **rmcurp); int rmap_get_mem_rec(struct xfs_btree_cur *rmcur, struct xfs_rmap_irec *irec); xfs_rgnumber_t rtgroup_for_rtrmap_inode(struct xfs_mount *mp, xfs_ino_t ino); From patchwork Thu Feb 6 22:54:10 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: 13964034 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 A25FD2417C2 for ; Thu, 6 Feb 2025 22:54: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=1738882450; cv=none; b=p5OHn5cOs2k9lIEuvEtg7Mk+4yfdPyf7k7B2vdVjKu/MTJtbg8ML8tiG0ct7twMXcvqOxnHwEr0DtWH5pbppYWllGcUTeg1xEC5YW3Ex+EQqdtkB3W+qa4rq8gRYsC8VOgdFC6QMOrVlN/t3MS3GlVlNo5Mz2RaNojOAELBaS4A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882450; c=relaxed/simple; bh=yboaoym6MpI/cFBHoEiy6fOWf/01Ih3dTw0GLQGj25c=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=MPdaEbkBiwy4lsBUZDgX+9j5w2vSSNHj/miHcS1ruCuCDv7YKTp0QLTCpOE4F38XgiG7+aReVDVMoTwBxPz/Tqr2DaSlAEkC3tJI1r/LoAjD+7TAx8hWQfqR1soCAqmLXyz720PGMIJgPJ6ThgQo3hHus9KPhmPXXmy7Tabwakk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LByeJ71l; 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="LByeJ71l" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7A486C4CEDD; Thu, 6 Feb 2025 22:54:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882450; bh=yboaoym6MpI/cFBHoEiy6fOWf/01Ih3dTw0GLQGj25c=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=LByeJ71lwZlVG4on97cAyIeoDMXBbwU+T+a3Uv1byb/zmlmSLFCABXgpcYr6TLY3v HUUsk9OWDnX04UsXN0AbAmzujf6/41mJghODqWkfXauPP+JRGst+Ey5KzN/d41TEIN ZcWFcIw4DUxz3MdWlsVYrPmbRZP6rqIIZcZcohvW/9OD+XklNJod9l0FofNhBWbY9l dn/PAIbSOckzLMOlM1BUaFMLGISohbOP37PMCogj7fTqBGXS2wET9ivTXqRizvCBMP Im7PunXWNtzTSQWrbXmcwLGOcex2cfCBSyjMZPUTz96R1UnaNodRpir8LQBWDqdr4T bLZrkMWfqYqPQ== Date: Thu, 06 Feb 2025 14:54:10 -0800 Subject: [PATCH 17/27] xfs_repair: refactor realtime inode check From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088356.2741033.18413230775534572246.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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 Refactor the realtime bitmap and summary checks into a helper function. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- repair/dinode.c | 87 +++++++++++++++++++++++++------------------------------ 1 file changed, 39 insertions(+), 48 deletions(-) diff --git a/repair/dinode.c b/repair/dinode.c index 3f78eb064919be..628f02714abc05 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -1798,6 +1798,39 @@ check_dinode_mode_format( return 0; /* invalid modes are checked elsewhere */ } +static int +process_check_rt_inode( + struct xfs_mount *mp, + struct xfs_dinode *dinoc, + xfs_ino_t lino, + int *type, + int *dirty, + int expected_type, + const char *tag) +{ + xfs_extnum_t dnextents = xfs_dfork_data_extents(dinoc); + + if (*type != expected_type) { + do_warn( +_("%s inode %" PRIu64 " has bad type 0x%x, "), + tag, lino, dinode_fmt(dinoc)); + if (!no_modify) { + do_warn(_("resetting to regular file\n")); + change_dinode_fmt(dinoc, S_IFREG); + *dirty = 1; + } else { + do_warn(_("would reset to regular file\n")); + } + } + if (mp->m_sb.sb_rblocks == 0 && dnextents != 0) { + do_warn( +_("bad # of extents (%" PRIu64 ") for %s inode %" PRIu64 "\n"), + dnextents, tag, lino); + return 1; + } + return 0; +} + /* * If inode is a superblock inode, does type check to make sure is it valid. * Returns 0 if it's valid, non-zero if it needs to be cleared. @@ -1811,8 +1844,6 @@ process_check_metadata_inodes( int *type, int *dirty) { - xfs_extnum_t dnextents; - if (lino == mp->m_sb.sb_rootino) { if (*type != XR_INO_DIR) { do_warn(_("root inode %" PRIu64 " has bad type 0x%x\n"), @@ -1854,52 +1885,12 @@ process_check_metadata_inodes( } return 0; } - - dnextents = xfs_dfork_data_extents(dinoc); - if (lino == mp->m_sb.sb_rsumino || - is_rtsummary_inode(lino)) { - if (*type != XR_INO_RTSUM) { - do_warn( -_("realtime summary inode %" PRIu64 " has bad type 0x%x, "), - lino, dinode_fmt(dinoc)); - if (!no_modify) { - do_warn(_("resetting to regular file\n")); - change_dinode_fmt(dinoc, S_IFREG); - *dirty = 1; - } else { - do_warn(_("would reset to regular file\n")); - } - } - if (mp->m_sb.sb_rblocks == 0 && dnextents != 0) { - do_warn( -_("bad # of extents (%" PRIu64 ") for realtime summary inode %" PRIu64 "\n"), - dnextents, lino); - return 1; - } - return 0; - } - if (lino == mp->m_sb.sb_rbmino || - is_rtbitmap_inode(lino)) { - if (*type != XR_INO_RTBITMAP) { - do_warn( -_("realtime bitmap inode %" PRIu64 " has bad type 0x%x, "), - lino, dinode_fmt(dinoc)); - if (!no_modify) { - do_warn(_("resetting to regular file\n")); - change_dinode_fmt(dinoc, S_IFREG); - *dirty = 1; - } else { - do_warn(_("would reset to regular file\n")); - } - } - if (mp->m_sb.sb_rblocks == 0 && dnextents != 0) { - do_warn( -_("bad # of extents (%" PRIu64 ") for realtime bitmap inode %" PRIu64 "\n"), - dnextents, lino); - return 1; - } - return 0; - } + if (lino == mp->m_sb.sb_rsumino || is_rtsummary_inode(lino)) + return process_check_rt_inode(mp, dinoc, lino, type, dirty, + XR_INO_RTSUM, _("realtime summary")); + if (lino == mp->m_sb.sb_rbmino || is_rtbitmap_inode(lino)) + return process_check_rt_inode(mp, dinoc, lino, type, dirty, + XR_INO_RTBITMAP, _("realtime bitmap")); return 0; } From patchwork Thu Feb 6 22:54: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: 13964041 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 AA6632417C9 for ; Thu, 6 Feb 2025 22:54:26 +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=1738882466; cv=none; b=X+3Rm/bF4CYL7wfejXNSLhy0vZZPrkXBWhV3xQ0vQGy038zrjflRtjgKYzOPAhOHbZQlGNduo1Znciu5BEdX6l59KDojt2RyzzyOo9tsx6SN8Fou40z6eHmHvmNA/ceyw1zh5BP+dcw0NoV9gmEds/MMHLEvlu10+BIXvaz5Z6I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882466; c=relaxed/simple; bh=TJYoE7+mbCNc5YFWQmSgcoS8HoGSFVgqLMk3lB/ecBQ=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=LI5WBxug/olVOSO20kVGgBoelqz/oSK/KIU3VX6caUhvrKjuhvRaIrXplqD8PSurIO9doY/iyMyjlzPfaNd/fPLBP4obfQTJ1qd2sHhDR38H4GpC3KmxR+/DhaqaMHGtx/+8nxa0c6FLCGApL4r4Dg0mHztrb7a+cMVhDO4Q1eM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KYrt8obm; 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="KYrt8obm" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1E06FC4CEDD; Thu, 6 Feb 2025 22:54:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882466; bh=TJYoE7+mbCNc5YFWQmSgcoS8HoGSFVgqLMk3lB/ecBQ=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=KYrt8obmQLGyzDQIBdfjNGKu3L0cEwTw0XqLtVbTWfBNZDcjpboMlpdMUXcaBLLpK neN4Y6QoE6jSH62bNNicI5GeeY4cC370zvNiXSEkdpGon6V9l9Vq1TQseeOl+u26Td NpmYXe7ozQ4LlEjMI2aYPA6uSUGusu3n3/PNd+CyctzA1Mf9cnZy7EvXQzwpgStFNu SRxZ9HsbToyybZbdZbfpvQb2TwRYE+qml6AuLIZX6M0vOiNYCgiKTnnlpre5fl9DuO tWw6aJl3h2QtUZugQbbHqfQvkFe5fznbsRROlfuwRXc6FXqOBDQ7sdpUfW858YqguK RXNGlVq2QYlPQ== Date: Thu, 06 Feb 2025 14:54:25 -0800 Subject: [PATCH 18/27] xfs_repair: find and mark the rtrmapbt inodes From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088371.2741033.14204258331206705184.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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 rmapbt inodes and mark them appropriately, just in case we find a rogue inode claiming to be an rtrmap, or garbage in the metadata directory tree. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- repair/dino_chunks.c | 13 ++++++++++ repair/dinode.c | 65 +++++++++++++++++++++++++++++++++++++++++++++----- repair/dir2.c | 7 +++++ repair/incore.h | 1 + repair/rmap.c | 19 ++++++--------- repair/rmap.h | 5 ++-- repair/scan.c | 8 +++--- 7 files changed, 95 insertions(+), 23 deletions(-) diff --git a/repair/dino_chunks.c b/repair/dino_chunks.c index fe106f0b6ab536..8c5387cdf4ea52 100644 --- a/repair/dino_chunks.c +++ b/repair/dino_chunks.c @@ -16,6 +16,8 @@ #include "prefetch.h" #include "progress.h" #include "rt.h" +#include "slab.h" +#include "rmap.h" /* * validates inode block or chunk, returns # of good inodes @@ -1023,6 +1025,17 @@ process_inode_chunk( _("would clear rtgroup summary inode %" PRIu64 "\n"), ino); } + } else if (is_rtrmap_inode(ino)) { + rmap_avoid_check(mp); + if (!no_modify) { + do_warn( + _("cleared rtgroup rmap inode %" PRIu64 "\n"), + ino); + } else { + do_warn( + _("would clear rtgroup rmap 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 628f02714abc05..58691b196bc4cb 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -178,6 +178,9 @@ clear_dinode( if (is_rtsummary_inode(ino_num)) mark_rtgroup_inodes_bad(mp, XFS_RTGI_SUMMARY); + + if (is_rtrmap_inode(ino_num)) + rmap_avoid_check(mp); } /* @@ -823,6 +826,14 @@ get_agino_buf( return bp; } +static inline xfs_rgnumber_t +metafile_rgnumber( + const struct xfs_dinode *dip) +{ + return (xfs_rgnumber_t)be16_to_cpu(dip->di_projid_hi) << 16 | + be16_to_cpu(dip->di_projid_lo); +} + /* * higher level inode processing stuff starts here: * first, one utility routine for each type of inode @@ -870,7 +881,10 @@ process_rtrmap( lino = XFS_AGINO_TO_INO(mp, agno, ino); - /* This rmap btree inode must be a metadata inode. */ + /* + * This rmap btree inode must be a metadata inode reachable via + * /rtgroups/$rgno.rmap in the metadata directory tree. + */ if (!(dip->di_flags2 & be64_to_cpu(XFS_DIFLAG2_METADATA))) { do_warn( _("rtrmap inode %" PRIu64 " not flagged as metadata\n"), @@ -878,11 +892,25 @@ _("rtrmap inode %" PRIu64 " not flagged as metadata\n"), return 1; } - if (!is_rtrmap_inode(lino)) { - do_warn( + /* + * If this rtrmap file claims to be from an rtgroup that actually + * exists, check that inode discovery actually found it. Note that + * we can have stray rtrmap files from failed growfsrt operations. + */ + if (metafile_rgnumber(dip) < mp->m_sb.sb_rgcount) { + if (type != XR_INO_RTRMAP) { + do_warn( +_("rtrmap inode %" PRIu64 " was not found in the metadata directory tree\n"), + lino); + return 1; + } + + if (!is_rtrmap_inode(lino)) { + do_warn( _("could not associate rtrmap inode %" PRIu64 " with any rtgroup\n"), - lino); - return 1; + lino); + return 1; + } } memset(&priv.high_key, 0xFF, sizeof(priv.high_key)); @@ -921,7 +949,7 @@ _("computed size of rtrmapbt root (%zu bytes) is greater than space in " error = process_rtrmap_reclist(mp, rp, numrecs, &priv.last_rec, NULL, "rtrmapbt root"); if (error) { - rmap_avoid_check(); + rmap_avoid_check(mp); return 1; } return 0; @@ -1891,6 +1919,9 @@ process_check_metadata_inodes( if (lino == mp->m_sb.sb_rbmino || is_rtbitmap_inode(lino)) return process_check_rt_inode(mp, dinoc, lino, type, dirty, XR_INO_RTBITMAP, _("realtime bitmap")); + if (is_rtrmap_inode(lino)) + return process_check_rt_inode(mp, dinoc, lino, type, dirty, + XR_INO_RTRMAP, _("realtime rmap btree")); return 0; } @@ -1989,6 +2020,18 @@ _("realtime summary inode %" PRIu64 " has bad size %" PRIu64 " (should be %" PRI } break; + case XR_INO_RTRMAP: + /* + * if we have no rmapbt, any inode claiming + * to be a real-time file is bogus + */ + if (!xfs_has_rmapbt(mp)) { + do_warn( +_("found inode %" PRIu64 " claiming to be a rtrmapbt file, but rmapbt is disabled\n"), lino); + return 1; + } + break; + default: break; } @@ -2017,6 +2060,14 @@ _("bad attr fork offset %d in dev inode %" PRIu64 ", should be %d\n"), return 1; } break; + case XFS_DINODE_FMT_META_BTREE: + if (!xfs_has_metadir(mp) || !xfs_has_parent(mp)) { + do_warn( +_("metadata inode %" PRIu64 " type %d cannot have attr fork\n"), + lino, dino->di_format); + return 1; + } + fallthrough; case XFS_DINODE_FMT_LOCAL: case XFS_DINODE_FMT_EXTENTS: case XFS_DINODE_FMT_BTREE: @@ -3173,6 +3224,8 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), type = XR_INO_GQUOTA; else if (is_quota_inode(XFS_DQTYPE_PROJ, lino)) type = XR_INO_PQUOTA; + else if (is_rtrmap_inode(lino)) + type = XR_INO_RTRMAP; else type = XR_INO_DATA; break; diff --git a/repair/dir2.c b/repair/dir2.c index ed615662009957..af00b2d8d6c852 100644 --- a/repair/dir2.c +++ b/repair/dir2.c @@ -15,6 +15,8 @@ #include "da_util.h" #include "prefetch.h" #include "progress.h" +#include "slab.h" +#include "rmap.h" #include "rt.h" /* @@ -277,6 +279,9 @@ process_sf_dir2( } else if (lino == mp->m_sb.sb_metadirino) { junkit = 1; junkreason = _("metadata directory root"); + } else if (is_rtrmap_inode(lino)) { + junkit = 1; + junkreason = _("realtime rmap"); } else if ((irec_p = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, lino), XFS_INO_TO_AGINO(mp, lino))) != NULL) { @@ -754,6 +759,8 @@ process_dir2_data( clearreason = _("project quota"); } else if (ent_ino == mp->m_sb.sb_metadirino) { clearreason = _("metadata directory root"); + } else if (is_rtrmap_inode(ent_ino)) { + clearreason = _("realtime rmap"); } 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 61730c330911f7..4add12615e0a04 100644 --- a/repair/incore.h +++ b/repair/incore.h @@ -241,6 +241,7 @@ int count_bcnt_extents(xfs_agnumber_t); #define XR_INO_UQUOTA 12 /* user quota inode */ #define XR_INO_GQUOTA 13 /* group quota inode */ #define XR_INO_PQUOTA 14 /* project quota inode */ +#define XR_INO_RTRMAP 15 /* realtime rmap */ /* inode allocation tree */ diff --git a/repair/rmap.c b/repair/rmap.c index 13e9a06b04f370..8656c8df3cbc83 100644 --- a/repair/rmap.c +++ b/repair/rmap.c @@ -15,6 +15,7 @@ #include "libfrog/bitmap.h" #include "libfrog/platform.h" #include "rcbag.h" +#include "rt.h" #undef RMAP_DEBUG @@ -169,15 +170,6 @@ rmaps_init_ag( _("Insufficient memory while allocating realtime reverse mapping btree.")); } -xfs_rgnumber_t -rtgroup_for_rtrmap_inode( - struct xfs_mount *mp, - xfs_ino_t ino) -{ - /* This will be implemented later. */ - return NULLRGNUMBER; -} - /* * Initialize per-AG reverse map data. */ @@ -203,6 +195,8 @@ rmaps_init( for (i = 0; i < mp->m_sb.sb_rgcount; i++) rmaps_init_rt(mp, i, &rg_rmaps[i]); + + discover_rtgroup_inodes(mp); } /* @@ -1142,11 +1136,14 @@ rmap_record_count( } /* - * Disable the refcount btree check. + * Disable the rmap btree check. */ void -rmap_avoid_check(void) +rmap_avoid_check( + struct xfs_mount *mp) { + if (xfs_has_rtgroups(mp)) + mark_rtgroup_inodes_bad(mp, XFS_RTGI_RMAP); rmapbt_suspect = true; } diff --git a/repair/rmap.h b/repair/rmap.h index 23871e6d60e774..b5c8b4f0bef794 100644 --- a/repair/rmap.h +++ b/repair/rmap.h @@ -28,7 +28,7 @@ int rmap_commit_agbtree_mappings(struct xfs_mount *mp, xfs_agnumber_t agno); uint64_t rmap_record_count(struct xfs_mount *mp, bool isrt, xfs_agnumber_t agno); -extern void rmap_avoid_check(void); +extern void rmap_avoid_check(struct xfs_mount *mp); void rmaps_verify_btree(struct xfs_mount *mp, xfs_agnumber_t agno); extern int64_t rmap_diffkeys(struct xfs_rmap_irec *kp1, @@ -56,6 +56,7 @@ int rmap_init_mem_cursor(struct xfs_mount *mp, struct xfs_trans *tp, bool isrt, xfs_agnumber_t agno, struct xfs_btree_cur **rmcurp); int rmap_get_mem_rec(struct xfs_btree_cur *rmcur, struct xfs_rmap_irec *irec); -xfs_rgnumber_t rtgroup_for_rtrmap_inode(struct xfs_mount *mp, xfs_ino_t ino); +void populate_rtgroup_rmapbt(struct xfs_rtgroup *rtg, + xfs_filblks_t est_fdblocks); #endif /* RMAP_H_ */ diff --git a/repair/scan.c b/repair/scan.c index 386aaa15f78c33..7a74f87c5f0c61 100644 --- a/repair/scan.c +++ b/repair/scan.c @@ -1348,7 +1348,7 @@ _("out of order key %u in %s btree block (%u/%u)\n"), out: if (suspect) - rmap_avoid_check(); + rmap_avoid_check(mp); } int @@ -1728,7 +1728,7 @@ _("bad %s btree ptr 0x%llx in ino %" PRIu64 "\n"), out: if (hdr_errors || suspect) { - rmap_avoid_check(); + rmap_avoid_check(mp); return 1; } return 0; @@ -2811,7 +2811,7 @@ validate_agf( if (levels == 0 || levels > mp->m_rmap_maxlevels) { do_warn(_("bad levels %u for rmapbt root, agno %d\n"), levels, agno); - rmap_avoid_check(); + rmap_avoid_check(mp); } bno = be32_to_cpu(agf->agf_rmap_root); @@ -2826,7 +2826,7 @@ validate_agf( } else { do_warn(_("bad agbno %u for rmapbt root, agno %d\n"), bno, agno); - rmap_avoid_check(); + rmap_avoid_check(mp); } } From patchwork Thu Feb 6 22:54:41 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: 13964042 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 5088A2417C2 for ; Thu, 6 Feb 2025 22:54: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=1738882482; cv=none; b=MVhzrTAT8pIusS5qEwaaJf7tGzwt1m9BqMw/sdhuXsKsREVqx0hlAxFccmn7ExPex3ac0kiR5is9b0cCcuVk4y765uKabgEplfHUK4PKv1CLUJtpYRz5uHeE4XRI5RHSirFSrGWxMtssbAFKLE05JkSHFMYXR8GqjfcwvyzQYGc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882482; c=relaxed/simple; bh=nW2CLIoeSdAm1XoF+FA4FCg9tA0I+c1rEV1kmHcRBBM=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=py9UCTh6rsR9RDtXC8HM2s3acT5cMEMHgaNzQ82hc/N7IwM35li1d3sXU0TIiaA1RabNqsNIba5f2SzOAS84gEyYBYH5rO0fvGUGByy2zpnRQ7mNQFy99s9lYbihs3Q/8VhixxM3x9iP9zEiaz40p66xnJb14mllBCPwSIlZtEI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Op7uWPkn; 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="Op7uWPkn" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B871CC4CEDD; Thu, 6 Feb 2025 22:54:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882481; bh=nW2CLIoeSdAm1XoF+FA4FCg9tA0I+c1rEV1kmHcRBBM=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=Op7uWPknp3WVJaF8P09giM8Kaeo7/CbvmqS/yfUW1u5cqj3iWNt+75lA281705eNu XuvBpTvTmgk9Kt5/+jZO4O8UdvdOrXOP7cJrR5Fq8QiUP7uQj/X5XTDc+TVjmTgYUu w/jGT3u/ot4q0GBJHWWspZmwFGN4MInwUcM3w3H+vt72ZXhg53N3vMAHTo1rspiNBB ohJZLbVSJOba+BABX4G0PFvnqPRpYaz2QVJsTqrgeFE4zr8JG/xgZnFULxD4mPlYB8 y8OCwoFW/aMjMg3o8lb0Q1N9y5IoUUU2W5Q1A+OtgVubdaht3jViTCgMpRXa2Lx/+Z fLwZnZtqmb/FQ== Date: Thu, 06 Feb 2025 14:54:41 -0800 Subject: [PATCH 19/27] xfs_repair: check existing realtime rmapbt entries against observed rmaps From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088387.2741033.18417535290564732679.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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 rmap btree (particularly if we're in -n mode) to detect rtrmapbt problems. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- repair/phase4.c | 14 +++ repair/rmap.c | 226 ++++++++++++++++++++++++++++++++++++++++++------------- repair/rmap.h | 2 3 files changed, 188 insertions(+), 54 deletions(-) diff --git a/repair/phase4.c b/repair/phase4.c index 728d9ed84cdc7a..29efa58af33178 100644 --- a/repair/phase4.c +++ b/repair/phase4.c @@ -159,6 +159,16 @@ check_rmap_btrees( rmaps_verify_btree(wq->wq_ctx, agno); } +static void +check_rtrmap_btrees( + struct workqueue *wq, + xfs_agnumber_t agno, + void *arg) +{ + rmap_add_fixed_rtgroup_rec(wq->wq_ctx, agno); + rtrmaps_verify_btree(wq->wq_ctx, agno); +} + static void compute_ag_refcounts( struct workqueue*wq, @@ -211,6 +221,10 @@ process_rmap_data( create_work_queue(&wq, mp, platform_nproc()); for (i = 0; i < mp->m_sb.sb_agcount; i++) queue_work(&wq, check_rmap_btrees, i, NULL); + if (xfs_has_rtrmapbt(mp)) { + for (i = 0; i < mp->m_sb.sb_rgcount; i++) + queue_work(&wq, check_rtrmap_btrees, i, NULL); + } destroy_work_queue(&wq); if (!xfs_has_reflink(mp)) diff --git a/repair/rmap.c b/repair/rmap.c index 8656c8df3cbc83..a40851b4d0dc69 100644 --- a/repair/rmap.c +++ b/repair/rmap.c @@ -16,6 +16,7 @@ #include "libfrog/platform.h" #include "rcbag.h" #include "rt.h" +#include "prefetch.h" #undef RMAP_DEBUG @@ -195,8 +196,6 @@ rmaps_init( for (i = 0; i < mp->m_sb.sb_rgcount; i++) rmaps_init_rt(mp, i, &rg_rmaps[i]); - - discover_rtgroup_inodes(mp); } /* @@ -573,6 +572,27 @@ rmap_add_fixed_ag_rec( } } +/* Add this realtime group's fixed metadata to the incore data. */ +void +rmap_add_fixed_rtgroup_rec( + struct xfs_mount *mp, + xfs_rgnumber_t rgno) +{ + struct xfs_rmap_irec rmap = { + .rm_startblock = 0, + .rm_blockcount = mp->m_sb.sb_rextsize, + .rm_owner = XFS_RMAP_OWN_FS, + .rm_offset = 0, + .rm_flags = 0, + }; + + if (!rmap_needs_work(mp)) + return; + + if (xfs_has_rtsb(mp) && rgno == 0) + rmap_add_mem_rec(mp, true, rgno, &rmap); +} + /* * Copy the per-AG btree reverse-mapping data into the rmapbt. * @@ -1213,62 +1233,25 @@ rmap_is_good( #undef NEXTP #undef NEXTL -/* - * Compare the observed reverse mappings against what's in the ag btree. - */ -void -rmaps_verify_btree( - struct xfs_mount *mp, - xfs_agnumber_t agno) +static int +rmap_compare_records( + struct xfs_btree_cur *rm_cur, + struct xfs_btree_cur *bt_cur, + unsigned int group) { - struct xfs_btree_cur *rm_cur; struct xfs_rmap_irec rm_rec; struct xfs_rmap_irec tmp; - struct xfs_btree_cur *bt_cur = NULL; - struct xfs_buf *agbp = NULL; - struct xfs_perag *pag = NULL; int have; int error; - if (!xfs_has_rmapbt(mp)) - return; - if (rmapbt_suspect) { - if (no_modify && agno == 0) - do_warn(_("would rebuild corrupt rmap btrees.\n")); - return; - } - - /* Create cursors to rmap structures */ - error = rmap_init_mem_cursor(mp, NULL, false, agno, &rm_cur); - if (error) { - do_warn(_("Not enough memory to check reverse mappings.\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 rmap 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_rmapbt_init_cursor(mp, NULL, agbp, pag); - if (!bt_cur) { - do_warn(_("Not enough memory to check reverse mappings.\n")); - goto err_agf; - } - while ((error = rmap_get_mem_rec(rm_cur, &rm_rec)) == 1) { error = rmap_lookup(bt_cur, &rm_rec, &tmp, &have); if (error) { do_warn( _("Could not read reverse-mapping record for (%u/%u).\n"), - agno, rm_rec.rm_startblock); - goto err_cur; + group, + rm_rec.rm_startblock); + return error; } /* @@ -1283,15 +1266,15 @@ _("Could not read reverse-mapping record for (%u/%u).\n"), if (error) { do_warn( _("Could not read reverse-mapping record for (%u/%u).\n"), - agno, rm_rec.rm_startblock); - goto err_cur; + group, rm_rec.rm_startblock); + return error; } } if (!have) { do_warn( _("Missing reverse-mapping record for (%u/%u) %slen %u owner %"PRId64" \ %s%soff %"PRIu64"\n"), - agno, rm_rec.rm_startblock, + group, rm_rec.rm_startblock, (rm_rec.rm_flags & XFS_RMAP_UNWRITTEN) ? _("unwritten ") : "", rm_rec.rm_blockcount, @@ -1304,12 +1287,12 @@ _("Missing reverse-mapping record for (%u/%u) %slen %u owner %"PRId64" \ continue; } - /* Compare each refcount observation against the btree's */ + /* Compare each rmap observation against the btree's */ if (!rmap_is_good(&rm_rec, &tmp)) { do_warn( _("Incorrect reverse-mapping: saw (%u/%u) %slen %u owner %"PRId64" %s%soff \ %"PRIu64"; should be (%u/%u) %slen %u owner %"PRId64" %s%soff %"PRIu64"\n"), - agno, tmp.rm_startblock, + group, tmp.rm_startblock, (tmp.rm_flags & XFS_RMAP_UNWRITTEN) ? _("unwritten ") : "", tmp.rm_blockcount, @@ -1319,7 +1302,7 @@ _("Incorrect reverse-mapping: saw (%u/%u) %slen %u owner %"PRId64" %s%soff \ (tmp.rm_flags & XFS_RMAP_BMBT_BLOCK) ? _("bmbt ") : "", tmp.rm_offset, - agno, rm_rec.rm_startblock, + group, rm_rec.rm_startblock, (rm_rec.rm_flags & XFS_RMAP_UNWRITTEN) ? _("unwritten ") : "", rm_rec.rm_blockcount, @@ -1332,8 +1315,61 @@ _("Incorrect reverse-mapping: saw (%u/%u) %slen %u owner %"PRId64" %s%soff \ } } + return error; +} + +/* + * Compare the observed reverse mappings against what's in the ag btree. + */ +void +rmaps_verify_btree( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + struct xfs_btree_cur *rm_cur; + struct xfs_btree_cur *bt_cur = NULL; + struct xfs_buf *agbp = NULL; + struct xfs_perag *pag = NULL; + int error; + + if (!xfs_has_rmapbt(mp)) + return; + if (rmapbt_suspect) { + if (no_modify && agno == 0) + do_warn(_("would rebuild corrupt rmap btrees.\n")); + return; + } + + /* Create cursors to rmap structures */ + error = rmap_init_mem_cursor(mp, NULL, false, agno, &rm_cur); + if (error) { + do_warn(_("Not enough memory to check reverse mappings.\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 rmap 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_rmapbt_init_cursor(mp, NULL, agbp, pag); + if (!bt_cur) { + do_warn(_("Not enough memory to check reverse mappings.\n")); + goto err_agf; + } + + error = rmap_compare_records(rm_cur, bt_cur, agno); + if (error) + goto err_cur; + err_cur: - libxfs_btree_del_cursor(bt_cur, XFS_BTREE_NOERROR); + libxfs_btree_del_cursor(bt_cur, error); err_agf: libxfs_buf_relse(agbp); err_pag: @@ -1341,6 +1377,88 @@ _("Incorrect reverse-mapping: saw (%u/%u) %slen %u owner %"PRId64" %s%soff \ libxfs_btree_del_cursor(rm_cur, error); } +/* + * Compare the observed reverse mappings against what's in the rtgroup btree. + */ +void +rtrmaps_verify_btree( + struct xfs_mount *mp, + xfs_rgnumber_t rgno) +{ + struct xfs_btree_cur *rm_cur; + struct xfs_btree_cur *bt_cur = NULL; + struct xfs_rtgroup *rtg = NULL; + struct xfs_inode *ip = NULL; + int error; + + if (!xfs_has_rmapbt(mp)) + return; + if (rmapbt_suspect) { + if (no_modify && rgno == 0) + do_warn(_("would rebuild corrupt rmap btrees.\n")); + return; + } + + /* Create cursors to rmap structures */ + error = rmap_init_mem_cursor(mp, NULL, true, rgno, &rm_cur); + if (error) { + do_warn(_("Not enough memory to check reverse mappings.\n")); + return; + } + + rtg = libxfs_rtgroup_get(mp, rgno); + if (!rtg) { + do_warn(_("Could not load rtgroup %u.\n"), rgno); + goto err_rcur; + } + + ip = rtg_rmap(rtg); + if (!ip) { + do_warn(_("Could not find rtgroup %u rmap inode.\n"), rgno); + goto err_rtg; + } + + if (ip->i_df.if_format != XFS_DINODE_FMT_META_BTREE) { + do_warn( +_("rtgroup %u rmap 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_RTRMAP) { + do_warn( +_("rtgroup %u rmap inode has wrong metatype 0x%x, expected 0x%x\n"), + rgno, ip->i_df.if_format, + XFS_METAFILE_RTRMAP); + goto err_rtg; + } + + if (xfs_inode_has_attr_fork(ip) && + !(xfs_has_metadir(mp) && xfs_has_parent(mp))) { + do_warn( +_("rtgroup %u rmap inode should not have extended attributes\n"), rgno); + goto err_rtg; + } + + bt_cur = libxfs_rtrmapbt_init_cursor(NULL, rtg); + if (!bt_cur) { + do_warn(_("Not enough memory to check reverse mappings.\n")); + goto err_rtg; + } + + error = rmap_compare_records(rm_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: + libxfs_btree_del_cursor(rm_cur, error); +} + /* * Compare the key fields of two rmap records -- positive if key1 > key2, * negative if key1 < key2, and zero if equal. diff --git a/repair/rmap.h b/repair/rmap.h index b5c8b4f0bef794..ebda561e59bc8f 100644 --- a/repair/rmap.h +++ b/repair/rmap.h @@ -21,6 +21,7 @@ void rmap_add_bmbt_rec(struct xfs_mount *mp, xfs_ino_t ino, int whichfork, bool rmaps_are_mergeable(struct xfs_rmap_irec *r1, struct xfs_rmap_irec *r2); void rmap_add_fixed_ag_rec(struct xfs_mount *mp, xfs_agnumber_t agno); +void rmap_add_fixed_rtgroup_rec(struct xfs_mount *mp, xfs_rgnumber_t rgno); int rmap_add_agbtree_mapping(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, uint64_t owner); @@ -30,6 +31,7 @@ uint64_t rmap_record_count(struct xfs_mount *mp, bool isrt, xfs_agnumber_t agno); extern void rmap_avoid_check(struct xfs_mount *mp); void rmaps_verify_btree(struct xfs_mount *mp, xfs_agnumber_t agno); +void rtrmaps_verify_btree(struct xfs_mount *mp, xfs_rgnumber_t rgno); extern int64_t rmap_diffkeys(struct xfs_rmap_irec *kp1, struct xfs_rmap_irec *kp2); From patchwork Thu Feb 6 22:54: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: 13964043 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 E955C2417C2 for ; Thu, 6 Feb 2025 22:54:57 +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=1738882498; cv=none; b=oJA83QuYDNQ3kDnF+I3JmFe6wemmBvri0HTBz4YWjbIIiec54j8zHFKyGWNdT7Zzj7s6OCbok/JFd83nimzSmnn/i+dzXlJnImx/zAZ26+tnJPSurT0ictsPGfr2cnlD9IovwPVdMiJtuGsyfJKogRlVWPmbqF6ZRUu3nyPdq+g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882498; c=relaxed/simple; bh=T4IRVvUEz1rZ0YAIgzMnpO03ZTyzG8EqjiuTsbgobbI=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=thDwQOaZiyKR5Xd65ItBzudKbKf+lsf+ptCLQrFe4hOT0RgrN3ZjAdtHQRridNehmxmoZhfDARGJMtf/5SfyQ3QwrRwlhUmtMIvdUp4l1OVn3L+2/3KNByVcPjUoUDyGxHFxVlfnCyuzEk3FyRjBtD739cyv9Ao8w8WPHDX/yV8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jcYP03iB; 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="jcYP03iB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6147AC4CEDF; Thu, 6 Feb 2025 22:54:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882497; bh=T4IRVvUEz1rZ0YAIgzMnpO03ZTyzG8EqjiuTsbgobbI=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=jcYP03iBRvY0iy4SNkjMk3Bt4W0LUutag+GF3KQi0kksRSJKztd77sB4V6SjvxIx0 +K/hIAc40sUWwnMjKVeHcbH6QBAHIdDCZeP8A32lPGj1rnjN7xvt0JywvXQZls3ICV 3k1YLFxo0wSv8qB4RnTXRkfobppGcXhdqrl3MTcsPDcNjgE8ZdV73Epwwqldt+m8EL F9Scrw3nxQdKUq2cf98G/1rMayJHNKpW/5/BvQeizvJrBUU9VAYgFxUuA1gc20OQCu 6+zhz34EoGPnmG6zURbkz55v7jV+WifHHl/x6xs9Hrlknnpm1jnrXpdqoKpuBjhizy mGT6CD4xGgB1g== Date: Thu, 06 Feb 2025 14:54:56 -0800 Subject: [PATCH 20/27] xfs_repair: always check realtime file mappings against incore info From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088402.2741033.16711596957542694304.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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 Curiously, the xfs_repair code that processes data fork mappings of realtime files doesn't actually compare the mappings against the incore state map during the !check_dups phase (aka phase 3). As a result, we lose the opportunity to clear damaged realtime data forks before we get to crosslinked file checking in phase 4, which results in ondisk metadata errors calling do_error, which aborts repair. Split the process_rt_rec_state code into two functions: one to check the mapping, and another to update the incore state. The first one can be called to help us decide if we're going to zap the fork, and the second one updates the incore state if we decide to keep the fork. We already do this for regular data files. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- repair/dinode.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 84 insertions(+), 11 deletions(-) diff --git a/repair/dinode.c b/repair/dinode.c index 58691b196bc4cb..3995584a364771 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -253,7 +253,7 @@ _("data fork in rt ino %" PRIu64 " claims dup rt extent," return 0; } -static int +static void process_rt_rec_state( struct xfs_mount *mp, xfs_ino_t ino, @@ -297,11 +297,78 @@ _("data fork in rt inode %" PRIu64 " found invalid rt extent %"PRIu64" state %d set_rtbmap(ext, zap_metadata ? XR_E_METADATA : XR_E_INUSE); break; + case XR_E_BAD_STATE: + do_error( +_("bad state in rt extent map %" PRIu64 "\n"), + ext); case XR_E_METADATA: + case XR_E_FS_MAP: + case XR_E_INO: + case XR_E_INUSE_FS: + break; + case XR_E_INUSE: + case XR_E_MULT: + set_rtbmap(ext, XR_E_MULT); + break; + case XR_E_FREE1: + default: do_error( +_("illegal state %d in rt extent %" PRIu64 "\n"), + state, ext); + } + b += mp->m_sb.sb_rextsize; + } while (b < irec->br_startblock + irec->br_blockcount); +} + +/* + * Checks the realtime file's data mapping against in-core extent info, and + * complains if there are discrepancies. Returns 0 if good, 1 if bad. + */ +static int +check_rt_rec_state( + struct xfs_mount *mp, + xfs_ino_t ino, + struct xfs_bmbt_irec *irec) +{ + xfs_fsblock_t b = irec->br_startblock; + xfs_rtblock_t ext; + int state; + + do { + ext = (xfs_rtblock_t)b / mp->m_sb.sb_rextsize; + state = get_rtbmap(ext); + + if ((b % mp->m_sb.sb_rextsize) != 0) { + /* + * We are midway through a partially written extent. + * If we don't find the state that gets set in the + * other clause of this loop body, then we have a + * partially *mapped* rt extent and should complain. + */ + if (state != XR_E_INUSE && state != XR_E_FREE) { + do_warn( +_("data fork in rt inode %" PRIu64 " found invalid rt extent %"PRIu64" state %d at rt block %"PRIu64"\n"), + ino, ext, state, b); + return 1; + } + + b = roundup(b, mp->m_sb.sb_rextsize); + continue; + } + + /* + * This is the start of an rt extent. Complain if there are + * conflicting states. We'll set the state elsewhere. + */ + switch (state) { + case XR_E_FREE: + case XR_E_UNKNOWN: + break; + case XR_E_METADATA: + do_warn( _("data fork in rt inode %" PRIu64 " found metadata file block %" PRIu64 " in rt bmap\n"), ino, ext); - break; + return 1; case XR_E_BAD_STATE: do_error( _("bad state in rt extent map %" PRIu64 "\n"), @@ -309,12 +376,12 @@ _("bad state in rt extent map %" PRIu64 "\n"), case XR_E_FS_MAP: case XR_E_INO: case XR_E_INUSE_FS: - do_error( + do_warn( _("data fork in rt inode %" PRIu64 " found rt metadata extent %" PRIu64 " in rt bmap\n"), ino, ext); + return 1; case XR_E_INUSE: case XR_E_MULT: - set_rtbmap(ext, XR_E_MULT); do_warn( _("data fork in rt inode %" PRIu64 " claims used rt extent %" PRIu64 "\n"), ino, b); @@ -376,20 +443,26 @@ _("inode %" PRIu64 " - bad rt extent overflows - start %" PRIu64 ", " } pthread_mutex_lock(&rt_lock); - if (check_dups) - bad = process_rt_rec_dups(mp, ino, irec); - else - bad = process_rt_rec_state(mp, ino, zap_metadata, irec); - pthread_mutex_unlock(&rt_lock); + bad = check_rt_rec_state(mp, ino, irec); if (bad) - return bad; + goto out_unlock; + + if (check_dups) { + bad = process_rt_rec_dups(mp, ino, irec); + if (bad) + goto out_unlock; + } else { + process_rt_rec_state(mp, ino, zap_metadata, irec); + } /* * bump up the block counter */ *tot += irec->br_blockcount; - return 0; +out_unlock: + pthread_mutex_unlock(&rt_lock); + return bad; } /* From patchwork Thu Feb 6 22:55:12 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: 13964044 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 1D6862417C8 for ; Thu, 6 Feb 2025 22:55:13 +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=1738882513; cv=none; b=fZJULqlI9/UXLIpALI1uJkOdLqtWChNzFRjxOnngAZiIuoUbsMzxlQmr9WGm/KrKMXa4oTAe/vOoI+lmsX455XsMODQ5RfC03U/t7Rc9SU/9MAMMs+pT5Gxt6tATC4s/9TE0Wul1dq1l7BKwXlh0QdLEpikN4W+HHaoB/i6tSB4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882513; c=relaxed/simple; bh=1A/LinvrIjdLccyR/Pk4gOrrIQyfcZOCOhZYuxkc2zc=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=uL1X6NU2JLs4dTImyVw7kmBmW4I/MGv42GD0g6Ei0G5wGeZLZemS0qp4RQx+nBVMDi7Dkowx+ROyj6avp5d15k5XrosQKFhmSZ7tujWmxY0BEhS6JqhTKOawV/LM8l4paThR1fGT0viTltkFPr4RU4kfPQ2CB6paMd5QOYgEcOM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=A9agdovR; 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="A9agdovR" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E93CBC4CEDF; Thu, 6 Feb 2025 22:55:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882513; bh=1A/LinvrIjdLccyR/Pk4gOrrIQyfcZOCOhZYuxkc2zc=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=A9agdovR+1TVjMQBLAVfZKLnsRkigHSdEl7OkrJvwNu7Jv+B2wtu4vUr5yfW5gZgW EE3TXqEAuIiv+jqmmaBQVyAnDjIfybbPg2JF590PtTsH6hqApfktHrlzahrMAlBZsy kBllMbx9iGAHYNqMqUH8HV6VxERqG3tJ6d16A+jIPtcYD4EzpL801D969VkC47jomh AD8IEdrD3h3bOqpDOD9ioVn1dFoa7+8QWer0e24YfXnG5PpjQ725Ug1pjHbVjackRV qmxVfTavT8sHbhlWW217JLoW5hOSbd6h1MW8pz4ZWpDWl6Ht8KwIj/MgC2y3fDuOEn w8p7oNcog0+nA== Date: Thu, 06 Feb 2025 14:55:12 -0800 Subject: [PATCH 21/27] xfs_repair: rebuild the realtime rmap btree From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088417.2741033.9023081378772193251.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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 Rebuild the realtime rmap btree file from the reverse mapping records we gathered from walking the inodes. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- libxfs/libxfs_api_defs.h | 8 + repair/Makefile | 1 repair/bulkload.c | 41 +++++++ repair/bulkload.h | 2 repair/phase6.c | 21 ++++ repair/rmap.c | 26 +++++ repair/rmap.h | 1 repair/rtrmap_repair.c | 265 ++++++++++++++++++++++++++++++++++++++++++++++ repair/xfs_repair.c | 8 + 9 files changed, 371 insertions(+), 2 deletions(-) create mode 100644 repair/rtrmap_repair.c diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index b62efad757470b..193b1eeaa7537e 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -278,6 +278,7 @@ #define xfs_rmap_irec_offset_unpack libxfs_rmap_irec_offset_unpack #define xfs_rmap_lookup_le libxfs_rmap_lookup_le #define xfs_rmap_lookup_le_range libxfs_rmap_lookup_le_range +#define xfs_rmap_map_extent libxfs_rmap_map_extent #define xfs_rmap_map_raw libxfs_rmap_map_raw #define xfs_rmap_query_all libxfs_rmap_query_all #define xfs_rmap_query_range libxfs_rmap_query_range @@ -295,9 +296,12 @@ #define xfs_rtginode_name libxfs_rtginode_name #define xfs_rtsummary_create libxfs_rtsummary_create +#define xfs_rtginode_create libxfs_rtginode_create #define xfs_rtginode_irele libxfs_rtginode_irele #define xfs_rtginode_load libxfs_rtginode_load #define xfs_rtginode_load_parent libxfs_rtginode_load_parent +#define xfs_rtginode_mkdir_parent libxfs_rtginode_mkdir_parent +#define xfs_rtginode_name libxfs_rtginode_name #define xfs_rtgroup_alloc libxfs_rtgroup_alloc #define xfs_rtgroup_extents libxfs_rtgroup_extents #define xfs_rtgroup_grab libxfs_rtgroup_grab @@ -314,12 +318,16 @@ #define xfs_rtgroup_get libxfs_rtgroup_get #define xfs_rtgroup_put libxfs_rtgroup_put #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 +#define xfs_rtrmapbt_create libxfs_rtrmapbt_create #define xfs_rtrmapbt_droot_maxrecs libxfs_rtrmapbt_droot_maxrecs #define xfs_rtrmapbt_maxlevels_ondisk libxfs_rtrmapbt_maxlevels_ondisk #define xfs_rtrmapbt_init_cursor libxfs_rtrmapbt_init_cursor #define xfs_rtrmapbt_maxrecs libxfs_rtrmapbt_maxrecs #define xfs_rtrmapbt_mem_init libxfs_rtrmapbt_mem_init #define xfs_rtrmapbt_mem_cursor libxfs_rtrmapbt_mem_cursor +#define xfs_rtrmapbt_stage_cursor libxfs_rtrmapbt_stage_cursor #define xfs_sb_from_disk libxfs_sb_from_disk #define xfs_sb_mount_rextsize libxfs_sb_mount_rextsize diff --git a/repair/Makefile b/repair/Makefile index a36a95e353a504..6f4ec3b3a9c4dc 100644 --- a/repair/Makefile +++ b/repair/Makefile @@ -73,6 +73,7 @@ CFILES = \ rcbag.c \ rmap.c \ rt.c \ + rtrmap_repair.c \ sb.c \ scan.c \ slab.c \ diff --git a/repair/bulkload.c b/repair/bulkload.c index aada5bbae579f8..a9e51de0a24c17 100644 --- a/repair/bulkload.c +++ b/repair/bulkload.c @@ -361,3 +361,44 @@ bulkload_estimate_ag_slack( if (bload->node_slack < 0) bload->node_slack = 2; } + +/* + * Estimate proper slack values for a btree that's being reloaded. + * + * Under most circumstances, we'll take whatever default loading value the + * btree bulk loading code calculates for us. However, there are some + * exceptions to this rule: + * + * (1) If someone turned one of the debug knobs. + * (2) The FS has less than ~9% space free. + * + * Note that we actually use 3/32 for the comparison to avoid division. + */ +void +bulkload_estimate_inode_slack( + struct xfs_mount *mp, + struct xfs_btree_bload *bload, + unsigned long long free) +{ + /* + * The global values are set to -1 (i.e. take the bload defaults) + * unless someone has set them otherwise, so we just pull the values + * here. + */ + bload->leaf_slack = bload_leaf_slack; + bload->node_slack = bload_node_slack; + + /* No further changes if there's more than 3/32ths space left. */ + if (free >= ((mp->m_sb.sb_dblocks * 3) >> 5)) + return; + + /* + * We're low on space; load the btrees as tightly as possible. Leave + * a couple of open slots in each btree block so that we don't end up + * splitting the btrees like crazy right after mount. + */ + if (bload->leaf_slack < 0) + bload->leaf_slack = 2; + if (bload->node_slack < 0) + bload->node_slack = 2; +} diff --git a/repair/bulkload.h b/repair/bulkload.h index a88aafaa678a3a..842121b15190e7 100644 --- a/repair/bulkload.h +++ b/repair/bulkload.h @@ -78,5 +78,7 @@ void bulkload_cancel(struct bulkload *bkl); int bulkload_commit(struct bulkload *bkl); void bulkload_estimate_ag_slack(struct repair_ctx *sc, struct xfs_btree_bload *bload, unsigned int free); +void bulkload_estimate_inode_slack(struct xfs_mount *mp, + struct xfs_btree_bload *bload, unsigned long long free); #endif /* __XFS_REPAIR_BULKLOAD_H__ */ diff --git a/repair/phase6.c b/repair/phase6.c index 7d2e0554594265..cae9d970481840 100644 --- a/repair/phase6.c +++ b/repair/phase6.c @@ -21,6 +21,8 @@ #include "repair/pptr.h" #include "repair/rt.h" #include "repair/quotacheck.h" +#include "repair/slab.h" +#include "repair/rmap.h" static xfs_ino_t orphanage_ino; @@ -685,6 +687,15 @@ ensure_rtgroup_summary( fill_rtsummary(rtg); } +static void +ensure_rtgroup_rmapbt( + struct xfs_rtgroup *rtg, + xfs_filblks_t est_fdblocks) +{ + if (ensure_rtgroup_file(rtg, XFS_RTGI_RMAP)) + populate_rtgroup_rmapbt(rtg, est_fdblocks); +} + /* Initialize a root directory. */ static int init_fs_root_dir( @@ -3365,6 +3376,8 @@ reset_rt_metadir_inodes( struct xfs_mount *mp) { struct xfs_rtgroup *rtg = NULL; + xfs_filblks_t metadata_blocks = 0; + xfs_filblks_t est_fdblocks = 0; int error; /* @@ -3386,6 +3399,13 @@ reset_rt_metadir_inodes( mark_ino_metadata(mp, mp->m_rtdirip->i_ino); } + /* Estimate how much free space will be left after building btrees */ + while ((rtg = xfs_rtgroup_next(mp, rtg))) + metadata_blocks += estimate_rtrmapbt_blocks(rtg); + + if (mp->m_sb.sb_fdblocks > metadata_blocks) + est_fdblocks = mp->m_sb.sb_fdblocks - metadata_blocks; + /* * This isn't the whole story, but it keeps the message that we've had * for years and which is expected in xfstests and more. @@ -3400,6 +3420,7 @@ _(" - resetting contents of realtime bitmap and summary inodes\n")); while ((rtg = xfs_rtgroup_next(mp, rtg))) { ensure_rtgroup_bitmap(rtg); ensure_rtgroup_summary(rtg); + ensure_rtgroup_rmapbt(rtg, est_fdblocks); } } diff --git a/repair/rmap.c b/repair/rmap.c index a40851b4d0dc69..85a65048db9afc 100644 --- a/repair/rmap.c +++ b/repair/rmap.c @@ -1940,3 +1940,29 @@ estimate_refcountbt_blocks( return libxfs_refcountbt_calc_size(mp, slab_count(x->ar_refcount_items)); } + +/* Estimate the size of the ondisk rtrmapbt from the incore tree. */ +xfs_filblks_t +estimate_rtrmapbt_blocks( + struct xfs_rtgroup *rtg) +{ + struct xfs_mount *mp = rtg_mount(rtg); + struct xfs_ag_rmap *x; + unsigned long long nr_recs; + + if (!rmap_needs_work(mp) || !xfs_has_rtrmapbt(mp)) + return 0; + + /* + * Overestimate the amount of space needed by pretending that every + * byte in the incore tree is used to store rtrmapbt records. This + * means we can use SEEK_DATA/HOLE on the xfile, which is faster than + * walking the entire btree. + */ + x = &rg_rmaps[rtg_rgno(rtg)]; + if (!rmaps_has_observations(x)) + return 0; + + nr_recs = xmbuf_bytes(x->ar_xmbtp) / sizeof(struct xfs_rmap_rec); + return libxfs_rtrmapbt_calc_size(mp, nr_recs); +} diff --git a/repair/rmap.h b/repair/rmap.h index ebda561e59bc8f..23859bf6c2ad42 100644 --- a/repair/rmap.h +++ b/repair/rmap.h @@ -60,5 +60,6 @@ int rmap_get_mem_rec(struct xfs_btree_cur *rmcur, struct xfs_rmap_irec *irec); void populate_rtgroup_rmapbt(struct xfs_rtgroup *rtg, xfs_filblks_t est_fdblocks); +xfs_filblks_t estimate_rtrmapbt_blocks(struct xfs_rtgroup *rtg); #endif /* RMAP_H_ */ diff --git a/repair/rtrmap_repair.c b/repair/rtrmap_repair.c new file mode 100644 index 00000000000000..2b07e8943e591d --- /dev/null +++ b/repair/rtrmap_repair.c @@ -0,0 +1,265 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2019-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" + +/* Ported routines from fs/xfs/scrub/rtrmap_repair.c */ + +/* + * Realtime Reverse Mapping (RTRMAPBT) Repair + * ========================================== + * + * Gather all the rmap records for the inode and fork we're fixing, reset the + * incore fork, then recreate the btree. + */ +struct xrep_rtrmap { + struct xfs_btree_cur *btree_cursor; + + /* New fork. */ + struct bulkload new_fork_info; + struct xfs_btree_bload rtrmap_bload; + + struct repair_ctx *sc; + struct xfs_rtgroup *rtg; + + /* Estimated free space after building all rt btrees */ + xfs_filblks_t est_fdblocks; +}; + +/* Retrieve rtrmapbt data for bulk load. */ +STATIC int +xrep_rtrmap_get_records( + struct xfs_btree_cur *cur, + unsigned int idx, + struct xfs_btree_block *block, + unsigned int nr_wanted, + void *priv) +{ + struct xrep_rtrmap *rr = priv; + union xfs_btree_rec *block_rec; + unsigned int loaded; + int ret; + + for (loaded = 0; loaded < nr_wanted; loaded++, idx++) { + ret = rmap_get_mem_rec(rr->btree_cursor, &cur->bc_rec.r); + if (ret < 0) + return ret; + if (ret == 0) + do_error( + _("ran out of records while rebuilding rt rmap btree\n")); + + 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_rtrmap_claim_block( + struct xfs_btree_cur *cur, + union xfs_btree_ptr *ptr, + void *priv) +{ + struct xrep_rtrmap *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_rtrmap_iroot_size( + struct xfs_btree_cur *cur, + unsigned int level, + unsigned int nr_this_level, + void *priv) +{ + return xfs_rtrmap_broot_space_calc(cur->bc_mp, level, nr_this_level); +} + +/* Reserve new btree blocks and bulk load all the rtrmap records. */ +STATIC int +xrep_rtrmap_btree_load( + struct xrep_rtrmap *rr, + struct xfs_btree_cur *rtrmap_cur) +{ + struct repair_ctx *sc = rr->sc; + int error; + + rr->rtrmap_bload.get_records = xrep_rtrmap_get_records; + rr->rtrmap_bload.claim_block = xrep_rtrmap_claim_block; + rr->rtrmap_bload.iroot_size = xrep_rtrmap_iroot_size; + bulkload_estimate_inode_slack(sc->mp, &rr->rtrmap_bload, + rr->est_fdblocks); + + /* Compute how many blocks we'll need. */ + error = -libxfs_btree_bload_compute_geometry(rtrmap_cur, + &rr->rtrmap_bload, + rmap_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 rtrmap + * 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->rtrmap_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->rtrmap_bload.nr_blocks); + if (error) + return error; + + /* Add all observed rtrmap records. */ + error = rmap_init_mem_cursor(rr->sc->mp, sc->tp, true, + rtg_rgno(rr->rtg), &rr->btree_cursor); + if (error) + return error; + error = -libxfs_btree_bload(rtrmap_cur, &rr->rtrmap_bload, rr); + libxfs_btree_del_cursor(rr->btree_cursor, error); + return error; +} + +/* Update the inode counters. */ +STATIC int +xrep_rtrmap_reset_counters( + struct xrep_rtrmap *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 rmap 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_rtrmap_build_new_tree( + struct xrep_rtrmap *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_rtrmapbt_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_rtrmap_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_rtrmapbt_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_rtrmap_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 reverse-mappings in the rtrmapbt. */ +void +populate_rtgroup_rmapbt( + struct xfs_rtgroup *rtg, + xfs_filblks_t est_fdblocks) +{ + struct xfs_mount *mp = rtg_mount(rtg); + struct xfs_inode *ip = rtg_rmap(rtg); + struct repair_ctx sc = { + .mp = mp, + .ip = ip, + }; + struct xrep_rtrmap rr = { + .sc = &sc, + .rtg = rtg, + .est_fdblocks = est_fdblocks, + }; + int error; + + if (!xfs_has_rtrmapbt(mp)) + return; + + error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, + &sc.tp); + if (error) + goto out; + + error = xrep_rtrmap_build_new_tree(&rr); + if (error) { + libxfs_trans_cancel(sc.tp); + goto out; + } + + error = -libxfs_trans_commit(sc.tp); +out: + if (error) + do_error( + _("rtgroup %u rmap btree could not be rebuilt, error %d\n"), + rtg_rgno(rtg), error); +} diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c index 9509f04685c870..eeaaf643468941 100644 --- a/repair/xfs_repair.c +++ b/repair/xfs_repair.c @@ -1385,15 +1385,19 @@ main(int argc, char **argv) rcbagbt_destroy_cur_cache(); /* - * Done with the block usage maps, toss them... + * Done with the block usage maps, toss them. Realtime metadata aren't + * rebuilt until phase 6, so we have to keep them around. */ - rmaps_free(mp); + if (mp->m_sb.sb_rblocks == 0) + rmaps_free(mp); free_bmaps(mp); if (!bad_ino_btree) { phase6(mp); phase_end(mp, 6); + if (mp->m_sb.sb_rblocks != 0) + rmaps_free(mp); free_rtgroup_inodes(); phase7(mp, phase2_threads); From patchwork Thu Feb 6 22:55:28 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: 13964045 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 2B4242417CB for ; Thu, 6 Feb 2025 22:55: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=1738882529; cv=none; b=uW/OJVDFkH09+xnPjvU7agFEYeq9LPo/RFYCh1izaPqRxGnod1RcyluMnuHz9eQEfZlfNC+WEZ5vqSBwOFTSOjv7JaX/hNi5+SkloW/AOeHaZrOcDCukaCnVauo4HwKbIDzwXCaQuKuCI9sFxDv7z+8d/l3+THvTvy5F0GRV3ao= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882529; c=relaxed/simple; bh=xrUchvP9TfMHuwj5Jp4BwvNt7L7NflK8tBjQycwpV18=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Yxi41z1s6X1QutLxmRLhwEOi90NomtGaDMq8KXIXcMSB1X12RG6GT5GAovTfYwdhihsmv0z96LoiOCrAtlsGs2dXe2wT/hJkCrO8sk2864qkVlcCofDcdwGcB1gLrRJMoVUB5cHxK83mqWgaCms5q2GqAOdOLjr+8UIOXYxzdSQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bnN+DLUA; 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="bnN+DLUA" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 96BDEC4CEDD; Thu, 6 Feb 2025 22:55:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882528; bh=xrUchvP9TfMHuwj5Jp4BwvNt7L7NflK8tBjQycwpV18=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=bnN+DLUA38TLcSd4RHDBtqAL2E5QWzh3XFOOPuTAbGiBlvMsOXn8DO4/o2SMk/nfk xMjXxgdQfQGFgi1L2ZXIGpETaXplF0M/Di5faNqmvUIb30rpzff8c9t7jwlpEYjFcC kXDMC4J8B4fMIHGvRyGI7h0IQS/B1fxnmk76H5cu/ZXwvAYh5EyIQqMUbt6EPfUSpj AIOtud8zjITeSRsTppxkp5LVLkGRy/WvRRa5p2wztpTF8VvJ8V/nkmYTO5RmFY+ohM qPN9oTjMUweXaEZd29lE++IES0hkBji4W5+QPFXQX3BA3Iv0RBohSsZ5ji3hQNIUwN 4uk/r6gHSSNLw== Date: Thu, 06 Feb 2025 14:55:28 -0800 Subject: [PATCH 22/27] xfs_repair: check for global free space concerns with default btree slack levels From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088433.2741033.15187806936982398424.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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 It's possible that before repair was started, the filesystem might have been nearly full, and its metadata btree blocks could all have been nearly full. If we then rebuild the btrees with blocks that are only 75% full, that expansion might be enough to run out of free space. The solution to this is to pack the new blocks completely full if we fear running out of space. Previously, we only had to check and decide that on a per-AG basis. However, now that XFS can have filesystems with metadata btrees rooted in inodes, we have a global free space concern because there might be enough space in each AG to regenerate the AG btrees at 75%, but that might not leave enough space to regenerate the inode btrees, even if we fill those blocks to 100%. Hence we need to precompute the worst case space usage for all btrees in the filesystem and compare /that/ against the global free space to decide if we're going to pack the btrees maximally to conserve space. That decision can override the per-AG determination. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- repair/globals.c | 6 +++ repair/globals.h | 2 + repair/phase5.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- repair/phase6.c | 16 +++++--- 4 files changed, 129 insertions(+), 9 deletions(-) diff --git a/repair/globals.c b/repair/globals.c index 99291d6afd61b9..143b4a8beb53f4 100644 --- a/repair/globals.c +++ b/repair/globals.c @@ -114,6 +114,12 @@ int thread_count; /* If nonzero, simulate failure after this phase. */ int fail_after_phase; +/* + * Do we think we're going to be so low on disk space that we need to pack + * all rebuilt btree blocks completely full to avoid running out of space? + */ +bool need_packed_btrees; + /* quota inode numbers */ enum quotino_state { QI_STATE_UNKNOWN, diff --git a/repair/globals.h b/repair/globals.h index b23a06af6cc81b..8bb9bbaeca4fb0 100644 --- a/repair/globals.h +++ b/repair/globals.h @@ -159,6 +159,8 @@ extern int fail_after_phase; extern struct libxfs_init x; +extern bool need_packed_btrees; + void set_quota_inode(xfs_dqtype_t type, xfs_ino_t); void lose_quota_inode(xfs_dqtype_t type); void clear_quota_inode(xfs_dqtype_t type); diff --git a/repair/phase5.c b/repair/phase5.c index ac5f04697b7110..cacaf74dda3a60 100644 --- a/repair/phase5.c +++ b/repair/phase5.c @@ -481,11 +481,14 @@ _("unable to rebuild AG %u. Not enough free space in on-disk AG.\n"), /* * Estimate the number of free blocks in this AG after rebuilding - * all btrees. + * all btrees, unless we already decided that we need to pack all + * btree blocks maximally. */ - total_btblocks = estimate_agbtree_blocks(pag, num_extents); - if (num_freeblocks > total_btblocks) - est_agfreeblocks = num_freeblocks - total_btblocks; + if (!need_packed_btrees) { + total_btblocks = estimate_agbtree_blocks(pag, num_extents); + if (num_freeblocks > total_btblocks) + est_agfreeblocks = num_freeblocks - total_btblocks; + } init_ino_cursors(&sc, pag, est_agfreeblocks, &sb_icount_ag[agno], &sb_ifree_ag[agno], &btr_ino, &btr_fino); @@ -632,6 +635,107 @@ check_rtmetadata( check_rtsummary(mp); } +/* + * Estimate the amount of free space used by the perag metadata without + * building the incore tree. This is only necessary if realtime btrees are + * enabled. + */ +static xfs_extlen_t +estimate_agbtree_blocks_early( + struct xfs_perag *pag, + unsigned int *num_freeblocks) +{ + struct xfs_mount *mp = pag_mount(pag); + xfs_agblock_t agbno; + xfs_agblock_t ag_end; + xfs_extlen_t extent_len; + xfs_extlen_t blen; + unsigned int num_extents = 0; + int bstate; + bool in_extent = false; + + /* Find the number of free space extents. */ + ag_end = libxfs_ag_block_count(mp, pag_agno(pag)); + for (agbno = 0; agbno < ag_end; agbno += blen) { + bstate = get_bmap_ext(pag_agno(pag), agbno, ag_end, &blen, + false); + if (bstate < XR_E_INUSE) { + if (!in_extent) { + /* + * found the start of a free extent + */ + in_extent = true; + num_extents++; + extent_len = blen; + } else { + extent_len += blen; + } + } else { + if (in_extent) { + /* + * free extent ends here + */ + in_extent = false; + *num_freeblocks += extent_len; + } + } + } + if (in_extent) + *num_freeblocks += extent_len; + + return estimate_agbtree_blocks(pag, num_extents); +} + +/* + * Decide if we need to pack every new btree block completely full to conserve + * disk space. Normally we rebuild btree blocks to be 75% full, but we don't + * want to start rebuilding AG btrees that way only to discover that there + * isn't enough space left in the data volume to rebuild inode-based btrees. + */ +static bool +are_packed_btrees_needed( + struct xfs_mount *mp) +{ + struct xfs_perag *pag = NULL; + struct xfs_rtgroup *rtg = NULL; + unsigned long long metadata_blocks = 0; + unsigned long long fdblocks = 0; + + /* + * 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)) + return false; + + while ((pag = xfs_perag_next(mp, pag))) { + unsigned int ag_fdblocks = 0; + + metadata_blocks += estimate_agbtree_blocks_early(pag, + &ag_fdblocks); + fdblocks += ag_fdblocks; + } + + while ((rtg = xfs_rtgroup_next(mp, rtg))) + metadata_blocks += estimate_rtrmapbt_blocks(rtg); + + /* + * If we think we'll have more metadata blocks than free space, then + * pack the btree blocks. + */ + if (metadata_blocks > fdblocks) + return true; + + /* + * If the amount of free space after building btrees is less than 9% + * of the data volume, pack the btree blocks. + */ + fdblocks -= metadata_blocks; + if (fdblocks < ((mp->m_sb.sb_dblocks * 3) >> 5)) + return true; + return false; +} + void phase5(xfs_mount_t *mp) { @@ -683,6 +787,8 @@ phase5(xfs_mount_t *mp) if (error) do_error(_("cannot alloc lost block bitmap\n")); + need_packed_btrees = are_packed_btrees_needed(mp); + while ((pag = xfs_perag_next(mp, pag))) phase5_func(mp, pag, lost_blocks); diff --git a/repair/phase6.c b/repair/phase6.c index cae9d970481840..2ddfd0526767e0 100644 --- a/repair/phase6.c +++ b/repair/phase6.c @@ -3399,12 +3399,18 @@ reset_rt_metadir_inodes( mark_ino_metadata(mp, mp->m_rtdirip->i_ino); } - /* Estimate how much free space will be left after building btrees */ - while ((rtg = xfs_rtgroup_next(mp, rtg))) - metadata_blocks += estimate_rtrmapbt_blocks(rtg); + /* + * Estimate how much free space will be left after building btrees + * unless we already decided that we needed to pack all new blocks + * maximally. + */ + if (!need_packed_btrees) { + while ((rtg = xfs_rtgroup_next(mp, rtg))) + metadata_blocks += estimate_rtrmapbt_blocks(rtg); - if (mp->m_sb.sb_fdblocks > metadata_blocks) - est_fdblocks = mp->m_sb.sb_fdblocks - metadata_blocks; + if (mp->m_sb.sb_fdblocks > metadata_blocks) + est_fdblocks = mp->m_sb.sb_fdblocks - metadata_blocks; + } /* * This isn't the whole story, but it keeps the message that we've had From patchwork Thu Feb 6 22:55: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: 13964046 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 B6D232417C2 for ; Thu, 6 Feb 2025 22:55:44 +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=1738882544; cv=none; b=uTKTyPm3Lfb09zsutzmalzhyONBFGhl8jGOqrfhQUw4uDeoSZmLTIeSrzKxO4DYZCuLSFneZLeTexphDlmTml83r6ZsFwxDYecAS0OlB7iu9X27iNcDDOeMIKWlDP8QyKQQ52hYKkDf/UcuxRGn84H7pceKXCV3LCFZ0QynYEbw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882544; c=relaxed/simple; bh=d/2NK6Ngfr/vCc7VVdpTnnSK+BFmPYQWGUEIJakjkL4=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=vC94emfvdpv1l5tL2nGBWeRXmtisIEzBpK/aOD7nDZOioQkwHDbVUVKIcjyKpm0ypLa9N2t+zK93bqIQTVQcMvXr+K4n6mAOwVHfVDRW1NmDn/32Ht2cXm6auHSi1IpQxsMSn2jR983JhS8dVz2cdpLnZWxFneDVYLS8KIPKbi4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=PIiXcWsG; 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="PIiXcWsG" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3B332C4CEDD; Thu, 6 Feb 2025 22:55:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882544; bh=d/2NK6Ngfr/vCc7VVdpTnnSK+BFmPYQWGUEIJakjkL4=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=PIiXcWsGRHilSw60NmWl4WDQUvLXdOA/n3IPhfqSpMvVsx/36j9L6RgrEZYqmk6nt 78fCkv+lyz2S06aY/2KScCYKd6KEJRTr8YM8ufJtJVIaRsKIO41tic1u209FwwNsI1 TAw6FIWlnACHt13yrGuQ7hh6XmID4J2U6QKwYd2hsCJnyo5bTn+8yVvOPQFgG9pmxg tAR9P25bfRFozYPXQ5rABgBgm/lmO2gFMdyG0W+A/JSY6EAFKQBDtZosbszHaxk87b W/AwGT4Un7LXDQsdaHxHWr5YU44+tXK3eXbYs9QelubT2YO3yah9GmOvzMwsq6gmTW jZ9wRPoePFMBg== Date: Thu, 06 Feb 2025 14:55:43 -0800 Subject: [PATCH 23/27] xfs_repair: rebuild the bmap btree for realtime files From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088448.2741033.9119599638346403244.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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 rmap btree information to rebuild an inode's data fork when appropriate. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- repair/bmap_repair.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 105 insertions(+), 4 deletions(-) diff --git a/repair/bmap_repair.c b/repair/bmap_repair.c index 7e7c2a39f5724b..5d1f639be81ff4 100644 --- a/repair/bmap_repair.c +++ b/repair/bmap_repair.c @@ -209,6 +209,101 @@ xrep_bmap_scan_ag( return error; } +/* Check for any obvious errors or conflicts in the file mapping. */ +STATIC int +xrep_bmap_check_rtfork_rmap( + struct repair_ctx *sc, + struct xfs_btree_cur *cur, + const struct xfs_rmap_irec *rec) +{ + /* xattr extents are never stored on realtime devices */ + if (rec->rm_flags & XFS_RMAP_ATTR_FORK) + return EFSCORRUPTED; + + /* bmbt blocks are never stored on realtime devices */ + if (rec->rm_flags & XFS_RMAP_BMBT_BLOCK) + return EFSCORRUPTED; + + /* Data extents for non-rt files are never stored on the rt device. */ + if (!XFS_IS_REALTIME_INODE(sc->ip)) + return EFSCORRUPTED; + + /* Check the file offsets and physical extents. */ + if (!xfs_verify_fileext(sc->mp, rec->rm_offset, rec->rm_blockcount)) + return EFSCORRUPTED; + + /* Check that this fits in the rt volume. */ + if (!xfs_verify_rgbext(to_rtg(cur->bc_group), rec->rm_startblock, + rec->rm_blockcount)) + return EFSCORRUPTED; + + return 0; +} + +/* Record realtime extents that belong to this inode's fork. */ +STATIC int +xrep_bmap_walk_rtrmap( + struct xfs_btree_cur *cur, + const struct xfs_rmap_irec *rec, + void *priv) +{ + struct xrep_bmap *rb = priv; + int error = 0; + + /* Skip extents which are not owned by this inode and fork. */ + if (rec->rm_owner != rb->sc->ip->i_ino) + return 0; + + error = xrep_bmap_check_rtfork_rmap(rb->sc, cur, rec); + if (error) + return error; + + /* + * Record all blocks allocated to this file even if the extent isn't + * for the fork we're rebuilding so that we can reset di_nblocks later. + */ + rb->nblocks += rec->rm_blockcount; + + /* If this rmap isn't for the fork we want, we're done. */ + if (rb->whichfork == XFS_DATA_FORK && + (rec->rm_flags & XFS_RMAP_ATTR_FORK)) + return 0; + if (rb->whichfork == XFS_ATTR_FORK && + !(rec->rm_flags & XFS_RMAP_ATTR_FORK)) + return 0; + + return xrep_bmap_from_rmap(rb, rec->rm_offset, rec->rm_startblock, + rec->rm_blockcount, + rec->rm_flags & XFS_RMAP_UNWRITTEN); +} + +/* + * Scan the realtime reverse mappings to build the new extent map. The rt rmap + * inodes must be loaded from disk explicitly here, since we have not yet + * validated the metadata directory tree but do not wish to throw away user + * data unnecessarily. + */ +STATIC int +xrep_bmap_scan_rt( + struct xrep_bmap *rb, + struct xfs_rtgroup *rtg) +{ + struct repair_ctx *sc = rb->sc; + struct xfs_mount *mp = sc->mp; + struct xfs_inode *ip = rtg_rmap(rtg); + struct xfs_btree_cur *cur; + int error; + + /* failed to load the rtdir inode? */ + if (!xfs_has_rtrmapbt(mp) || !ip) + return ENOENT; + + cur = libxfs_rtrmapbt_init_cursor(sc->tp, rtg); + error = -libxfs_rmap_query_all(cur, xrep_bmap_walk_rtrmap, rb); + libxfs_btree_del_cursor(cur, error); + return error; +} + /* * Collect block mappings for this fork of this inode and decide if we have * enough space to rebuild. Caller is responsible for cleaning up the list if @@ -219,8 +314,18 @@ xrep_bmap_find_mappings( struct xrep_bmap *rb) { struct xfs_perag *pag = NULL; + struct xfs_rtgroup *rtg = NULL; int error; + /* Iterate the rtrmaps for extents. */ + while ((rtg = xfs_rtgroup_next(rb->sc->mp, rtg))) { + error = xrep_bmap_scan_rt(rb, rtg); + if (error) { + libxfs_rtgroup_put(rtg); + return error; + } + } + /* Iterate the rmaps for extents. */ while ((pag = xfs_perag_next(rb->sc->mp, pag))) { error = xrep_bmap_scan_ag(rb, pag); @@ -570,10 +675,6 @@ xrep_bmap_check_inputs( return EINVAL; } - /* Don't know how to rebuild realtime data forks. */ - if (XFS_IS_REALTIME_INODE(sc->ip)) - return EOPNOTSUPP; - return 0; } From patchwork Thu Feb 6 22:55:59 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: 13964047 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 F30222417C2 for ; Thu, 6 Feb 2025 22:55: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=1738882560; cv=none; b=PLbEETfpoDE7GXyniu5Izm7ND4xJ4DFYdZWYXOytRymD2QWMSE7Ff/k6upAWAA76duJmmhZqlgzchm8wubJODpo5jmCWGP2lBJhBhh1a9jc1MfKj1dFsQIXt/NIkCyL/86NEEv1ANC240YlM13wLFXZ61YmlAUty2SXLFG8es4M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882560; c=relaxed/simple; bh=JQpTnQQ1o3qvsJwOG8Dd6fzx2wR/t3VHQMW0Cqxi33o=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=aYAFfevGtIFnulNoFdgyhyN+v9KrDQgBCKofXkObWLYA20TVZNtl2ZTj1YcC1i1mPjNEycrY6IHijZaH7voAjLpmDaGFlOsA7Iqzk7fJcNeLR4Ef6U6io6gXfN/7k8BzmtZjfWbBisBYsbid2qKqw4ZmPCJav6cyBtdDVeJL/Fs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=AwmC3qkt; 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="AwmC3qkt" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D1DDEC4CEDF; Thu, 6 Feb 2025 22:55:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882559; bh=JQpTnQQ1o3qvsJwOG8Dd6fzx2wR/t3VHQMW0Cqxi33o=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=AwmC3qktp7yufBElr2S5tZK8alazC4/sAfaMWmfpxhKs3AHt50ewcZ1ZLuwylqEDt 8guZgnsLRcBDJWp1C9HAgGVYt+3itTDaAhGV2CS04z3CiVWidoifhzozKLuzkcH0TT i/dxP0tKXYI7CGqfW6IVx4itSkZz4kJdhMuTppSacZw7BoJ6Xpo9bDEmhZeUrFmSfV y4GweIfKB0ohvH3xc2BXcGfDkqSdAthUsZLFDDOiafj31CMlzX8h2h8axIZ5U1VlxQ xa9ct4+L0dw+L7DfN5CeZGYia3OrUtHXXD9zTXUVVfCqgG7sNUKbGT4+OHhrTN8JAd hKKQE2abNCwYw== Date: Thu, 06 Feb 2025 14:55:59 -0800 Subject: [PATCH 24/27] xfs_repair: reserve per-AG space while rebuilding rt metadata From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088464.2741033.2066305894736213498.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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 Realtime metadata btrees can consume quite a bit of space on a full filesystem. Since the metadata are just regular files, we need to make the per-AG reservations to avoid overfilling any of the AGs while rebuilding metadata. This avoids the situation where a filesystem comes straight from repair and immediately trips over not having enough space in an AG. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- include/libxfs.h | 1 + repair/phase6.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/include/libxfs.h b/include/libxfs.h index 79f8e1ff03d3f5..82b34b9d81c3a7 100644 --- a/include/libxfs.h +++ b/include/libxfs.h @@ -101,6 +101,7 @@ struct iomap; #include "xfs_rtgroup.h" #include "xfs_rtbitmap.h" #include "xfs_rtrmap_btree.h" +#include "xfs_ag_resv.h" #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) diff --git a/repair/phase6.c b/repair/phase6.c index 2ddfd0526767e0..30ea19fda9fd87 100644 --- a/repair/phase6.c +++ b/repair/phase6.c @@ -3540,10 +3540,41 @@ reset_quota_metadir_inodes( libxfs_irele(dp); } +static int +reserve_ag_blocks( + struct xfs_mount *mp) +{ + struct xfs_perag *pag = NULL; + int error = 0; + int err2; + + mp->m_finobt_nores = false; + + while ((pag = xfs_perag_next(mp, pag))) { + err2 = -libxfs_ag_resv_init(pag, NULL); + if (err2 && !error) + error = err2; + } + + return error; +} + +static void +unreserve_ag_blocks( + struct xfs_mount *mp) +{ + struct xfs_perag *pag = NULL; + + while ((pag = xfs_perag_next(mp, pag))) + libxfs_ag_resv_free(pag); +} + void phase6(xfs_mount_t *mp) { ino_tree_node_t *irec; + bool reserve_perag; + int error; int i; parent_ptr_init(mp); @@ -3588,6 +3619,17 @@ phase6(xfs_mount_t *mp) do_warn(_("would reinitialize metadata root directory\n")); } + reserve_perag = xfs_has_realtime(mp) && !no_modify; + if (reserve_perag) { + error = reserve_ag_blocks(mp); + if (error) { + if (error != ENOSPC) + do_warn( + _("could not reserve per-AG space to rebuild realtime metadata")); + reserve_perag = false; + } + } + if (xfs_has_rtgroups(mp)) reset_rt_metadir_inodes(mp); else @@ -3596,6 +3638,9 @@ phase6(xfs_mount_t *mp) if (xfs_has_metadir(mp) && xfs_has_quota(mp) && !no_modify) reset_quota_metadir_inodes(mp); + if (reserve_perag) + unreserve_ag_blocks(mp); + mark_standalone_inodes(mp); do_log(_(" - traversing filesystem ...\n")); From patchwork Thu Feb 6 22:56:15 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: 13964048 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 089AB2417C2 for ; Thu, 6 Feb 2025 22:56: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=1738882577; cv=none; b=RWNMy+OmklPWY+zmgQxZuDj1nmf6WduZLUlTZ7IMXCbVP1QalmRxjtAIkZ8l7LEJamFWs0YS8ANdqp/YO5j40HdzRewKsYi1Cf/MyqkmWb2YGd1Xj5WYzt2ixPM8O20yigoK9IE7NwX9zleoJVaasNTzHNZvzz283S3nDwjFR10= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882577; c=relaxed/simple; bh=CyuAJ9CPsPHyGwUH/7oXh2nQiXX1a/48gMByVJTDrXw=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=jjO6sKHD/ob7k7kdLbWJoQYrKsFzzvRBLQr+goWzwC+KNfU28nn64sr+hlNTt4/uad9MZ/nkfLlexkOU5S2lkcUd8XDJbhd+gk+DMuzufkwW2N+WkGF/3asGZ203i7H5PGcC+PplsO+EddhoJA3vOnotP38mmqGojrnOr17R9IQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=TWuTNHAA; 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="TWuTNHAA" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6F717C4CEDD; Thu, 6 Feb 2025 22:56:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882575; bh=CyuAJ9CPsPHyGwUH/7oXh2nQiXX1a/48gMByVJTDrXw=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=TWuTNHAABB0ioEM9QzNtPgJ9iQ1tnDbz/mjLVsdSReaXaMM8buH16vT8hu4j1QyjN W6pagrHGCu0UkTaD+2aZKlQaxjTeueB5+oZfGcT7ng386MTXR7jD1UBaVmNwyquBMx t0or7jbX3MTXy7Q0mN1XujUwiCi2R9Wlsgjq726Rr/F6Sze3yfottbI3/KeW49w8TC Of0lj94/55PiR26uMm6ABzuJ+VCSGYGqSqNtE+hAzkKYo65XL7pBcP54nEUfYF7h/u xxmPi5WwbqFrjS5pcfi3cQ41R1wPItAwcDzG/QcOswKB3Wnb+eujYhIbVE6fCM8Wuu F3fnVV6fgwrYQ== Date: Thu, 06 Feb 2025 14:56:15 -0800 Subject: [PATCH 25/27] xfs_logprint: report realtime RUIs From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088479.2741033.18274174802899432825.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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 RUI format just enough to report if an RUI targets the realtime device or not. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig 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 8336f26e093310..aaa9598616a308 100644 --- a/logprint/log_misc.c +++ b/logprint/log_misc.c @@ -1014,12 +1014,14 @@ xlog_print_record( be32_to_cpu(op_head->oh_len)); break; } + case XFS_LI_RUI_RT: case XFS_LI_RUI: { skip = xlog_print_trans_rui(&ptr, be32_to_cpu(op_head->oh_len), continued); break; } + case XFS_LI_RUD_RT: case XFS_LI_RUD: { skip = xlog_print_trans_rud(&ptr, be32_to_cpu(op_head->oh_len)); diff --git a/logprint/log_print_all.c b/logprint/log_print_all.c index ed5f234975ccad..56e765d64f2df4 100644 --- a/logprint/log_print_all.c +++ b/logprint/log_print_all.c @@ -422,9 +422,11 @@ xlog_recover_print_logitem( case XFS_LI_ATTRI: xlog_recover_print_attri(item); break; + case XFS_LI_RUD_RT: case XFS_LI_RUD: xlog_recover_print_rud(item); break; + case XFS_LI_RUI_RT: case XFS_LI_RUI: xlog_recover_print_rui(item); break; @@ -498,6 +500,12 @@ xlog_recover_print_item( case XFS_LI_RUI: printf("RUI"); break; + case XFS_LI_RUD_RT: + printf("RUD_RT"); + break; + case XFS_LI_RUI_RT: + printf("RUI_RT"); + break; case XFS_LI_CUD: printf("CUD"); break; diff --git a/logprint/log_redo.c b/logprint/log_redo.c index 41e7c94a52dc21..a0cc558499ae0b 100644 --- a/logprint/log_redo.c +++ b/logprint/log_redo.c @@ -274,6 +274,7 @@ xlog_print_trans_rui( uint src_len, int continued) { + const char *item_name = "RUI?"; struct xfs_rui_log_format *src_f, *f = NULL; uint dst_len; uint nextents; @@ -318,8 +319,14 @@ xlog_print_trans_rui( goto error; } - printf(_("RUI: #regs: %d num_extents: %d id: 0x%llx\n"), - f->rui_size, f->rui_nextents, (unsigned long long)f->rui_id); + switch (f->rui_type) { + case XFS_LI_RUI: item_name = "RUI"; break; + case XFS_LI_RUI_RT: item_name = "RUI_RT"; break; + } + + printf(_("%s: #regs: %d num_extents: %d id: 0x%llx\n"), + item_name, f->rui_size, f->rui_nextents, + (unsigned long long)f->rui_id); if (continued) { printf(_("RUI extent data skipped (CONTINUE set, no space)\n")); @@ -359,6 +366,7 @@ xlog_print_trans_rud( char **ptr, uint len) { + const char *item_name = "RUD?"; struct xfs_rud_log_format *f; struct xfs_rud_log_format lbuf; @@ -371,11 +379,17 @@ xlog_print_trans_rud( */ memmove(&lbuf, *ptr, min(core_size, len)); f = &lbuf; + + switch (f->rud_type) { + case XFS_LI_RUD: item_name = "RUD"; break; + case XFS_LI_RUD_RT: item_name = "RUD_RT"; break; + } + *ptr += len; if (len >= core_size) { - printf(_("RUD: #regs: %d id: 0x%llx\n"), - f->rud_size, - (unsigned long long)f->rud_rui_id); + printf(_("%s: #regs: %d id: 0x%llx\n"), + item_name, f->rud_size, + (unsigned long long)f->rud_rui_id); /* don't print extents as they are not used */ From patchwork Thu Feb 6 22:56: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: 13964049 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 A175E2417C2 for ; Thu, 6 Feb 2025 22:56:31 +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=1738882592; cv=none; b=d4qPUTI6OT9BFDg23nUImaW+chPFONuc+b7cmqfauo5m88+U7IEjxZGfmANflOLPjOUx7wjobFNxAngtE/poPSvOSL2nHWXusbwnrRQQPR/EDQeSzh3oYikuqMqPm+moYYWrbl8n7nHCkPYJHWbGUg4lKgF7GtmqB3C4A8KWIC0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882592; c=relaxed/simple; bh=1IjVNNHFDasAHSsnEVIJ5AfPZwiBO2ycdpgMQRCWosc=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=dBsfEvxH3APnXkVm+uYSjtJ0PDtEJUkb9DgoggZ3w+TbZgW/huBDe4WaDbMkKk9Xe3XAu+N7Fp5c91ByGA7DmP6tiFulNodVl4JWl8FLDNfkWrxEgtvfgirW0A2VRgfFaxCYMoDnD4mNKcr6wDUEMgfoUZCucAwjtl8Lpmlt6FU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KeBqCCgR; 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="KeBqCCgR" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 13664C4CEDD; Thu, 6 Feb 2025 22:56:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882591; bh=1IjVNNHFDasAHSsnEVIJ5AfPZwiBO2ycdpgMQRCWosc=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=KeBqCCgRaq0HmJA04EbAeGxMSWDMY3a7F+U20NmzYzu5HnXmtcUT4+hkq1OJfgV0J oKcMBajHOK4iDnp47reXuD2hY9/4Q6i2nZslu4cNDWfYAcn2I0DSC/FLzClERVKzk4 p99djyUILQn429Yzqftg58t3M4uZDWiH+yH4C3VVcEMZn3r4A34jv+5xM5piU+HuT+ Zj4jD9Jk9eBnri7Z95E0uz7bDJCQ7r1O+9nmHTauDhhrgHNo0TyLSuTpRYqIO7uoxw J024Kkn24sKxPaf4DxlPhvifaThDvghyrcaD+6H5n2L8YL3kglrWOwMFZ+6Kf8YCaC 8YGGjvd2sPJdg== Date: Thu, 06 Feb 2025 14:56:30 -0800 Subject: [PATCH 26/27] mkfs: add some rtgroup inode helpers From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088495.2741033.10645836020741372245.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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 Create some simple helpers to reduce the amount of typing whenever we access rtgroup inodes. Conversion was done with this spatch and some minor reformatting: @@ expression rtg; @@ - rtg->rtg_inodes[XFS_RTGI_BITMAP] + rtg_bitmap(rtg) @@ expression rtg; @@ - rtg->rtg_inodes[XFS_RTGI_SUMMARY] + rtg_summary(rtg) and the CLI command: $ spatch --sp-file /tmp/moo.cocci --dir fs/xfs/ --use-gitgrep --in-place Signed-off-by: "Darrick J. Wong" --- mkfs/proto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkfs/proto.c b/mkfs/proto.c index 6dd3a2005b15b3..60e5c7d02713d0 100644 --- a/mkfs/proto.c +++ b/mkfs/proto.c @@ -1057,7 +1057,7 @@ rtfreesp_init( if (error) res_failed(error); - libxfs_trans_ijoin(tp, rtg->rtg_inodes[XFS_RTGI_BITMAP], 0); + libxfs_trans_ijoin(tp, rtg_bitmap(rtg), 0); error = -libxfs_rtfree_extent(tp, rtg, start_rtx, nr); if (error) { fprintf(stderr, From patchwork Thu Feb 6 22:56:46 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: 13964050 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 43C9A2417CD for ; Thu, 6 Feb 2025 22:56:46 +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=1738882607; cv=none; b=aNgwzzwu0N/93uId/wndxaxsqFNTHnh0OUCItln+lCjl3CDaS7wUQl8XSJrdYYtTKhCDOIrABFRSfewzGoh69VANE7y67h0Xhv1XXxzfmVDYR9hlemucTqC9tdrPnbS/EnDqJBYy/eUCz0OsB560uxOQSGADotAPVB6vT++T7V0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738882607; c=relaxed/simple; bh=T/uWJUxjIWqcuJEDzjPqfkI7nUy63Odqwek1TFIZX/E=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=C31tGha+MkzwE2JrNSt5GPQSQH+NInhC2bwp4bWVigPx28rDwQkFgJ3ddrweIFqZcjNzg66nwniMwBuzWKgFZsAIqbdZ9uJN4G3TewObmyEZ+dahrLttPOO/fBo/+fWNC5JtViJRq9jDUovNkpGAYYBKyrIR+XjqhdXunb5IHVc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=so0Ubjte; 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="so0Ubjte" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A7B00C4CEDF; Thu, 6 Feb 2025 22:56:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738882606; bh=T/uWJUxjIWqcuJEDzjPqfkI7nUy63Odqwek1TFIZX/E=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=so0Ubjtes7ydaeveHIutzpVmS4srFPCQmAF23xpgPV33xIoq/r6Ps9d8jIv8OhuNz Rkpb80VMTssnvQCSxdTqOTV0+kcdbqkAa6PpATip7911jUFqUeaO42F0qn81jJ3ZVm eWBXK/pcDqq6L4/A79Rn2nnZJsSXjyLk/wRB9laKfvaQ/qhhAgE31hdxKIf8yxCIJv 4V8kAhj/YW7X4EDoNZ0sbn/cVMNRMrpYj8oCU4ojJ8l5qa+rzCrq/QlJEwCY+scigP mS5bo6CknG9elckQyIBg9fRpPiEwGGvqxaYL4zTo/YStMf1yJN1lOa8tKjX3KtZeq9 92kA7+6Dd67FQ== Date: Thu, 06 Feb 2025 14:56:46 -0800 Subject: [PATCH 27/27] mkfs: create the realtime rmap inode From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173888088511.2741033.12591731083152285550.stgit@frogsfrogsfrogs> In-Reply-To: <173888088056.2741033.17433872323468891160.stgit@frogsfrogsfrogs> References: <173888088056.2741033.17433872323468891160.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 Create a realtime rmapbt inode if we format the fs with realtime and rmap. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- libxfs/init.c | 7 ---- libxfs/libxfs_api_defs.h | 3 ++ mkfs/proto.c | 29 +++++++++++++++ mkfs/xfs_mkfs.c | 87 +++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 114 insertions(+), 12 deletions(-) diff --git a/libxfs/init.c b/libxfs/init.c index 02a4cfdf38b198..f92805620c33f1 100644 --- a/libxfs/init.c +++ b/libxfs/init.c @@ -312,13 +312,6 @@ rtmount_init( return -1; } - if (xfs_has_rmapbt(mp)) { - fprintf(stderr, - _("%s: Reverse mapping btree not compatible with realtime device. Please try a newer xfsprogs.\n"), - progname); - return -1; - } - if (mp->m_rtdev_targp->bt_bdev == 0 && !xfs_is_debugger(mp)) { fprintf(stderr, _("%s: filesystem has a realtime subvolume\n"), progname); diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index 193b1eeaa7537e..df24f36f0d2874 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -224,6 +224,8 @@ #define xfs_metafile_iget libxfs_metafile_iget #define xfs_trans_metafile_iget libxfs_trans_metafile_iget +#define xfs_metafile_resv_free libxfs_metafile_resv_free +#define xfs_metafile_resv_init libxfs_metafile_resv_init #define xfs_metafile_set_iflag libxfs_metafile_set_iflag #define xfs_metadir_cancel libxfs_metadir_cancel #define xfs_metadir_commit libxfs_metadir_commit @@ -324,6 +326,7 @@ #define xfs_rtrmapbt_droot_maxrecs libxfs_rtrmapbt_droot_maxrecs #define xfs_rtrmapbt_maxlevels_ondisk libxfs_rtrmapbt_maxlevels_ondisk #define xfs_rtrmapbt_init_cursor libxfs_rtrmapbt_init_cursor +#define xfs_rtrmapbt_init_rtsb libxfs_rtrmapbt_init_rtsb #define xfs_rtrmapbt_maxrecs libxfs_rtrmapbt_maxrecs #define xfs_rtrmapbt_mem_init libxfs_rtrmapbt_mem_init #define xfs_rtrmapbt_mem_cursor libxfs_rtrmapbt_mem_cursor diff --git a/mkfs/proto.c b/mkfs/proto.c index 60e5c7d02713d0..2c453480271666 100644 --- a/mkfs/proto.c +++ b/mkfs/proto.c @@ -1095,6 +1095,28 @@ rtinit_nogroups( } } +static int +init_rtrmap_for_rtsb( + struct xfs_rtgroup *rtg) +{ + struct xfs_mount *mp = rtg_mount(rtg); + struct xfs_trans *tp; + int error; + + error = -libxfs_trans_alloc_inode(rtg_rmap(rtg), + &M_RES(mp)->tr_itruncate, 0, 0, false, &tp); + if (error) + return error; + + error = -libxfs_rtrmapbt_init_rtsb(mp, rtg, tp); + if (error) { + libxfs_trans_cancel(tp); + return error; + } + + return -libxfs_trans_commit(tp); +} + static void rtinit_groups( struct xfs_mount *mp) @@ -1115,6 +1137,13 @@ rtinit_groups( error); } + if (xfs_has_rtsb(mp) && xfs_has_rtrmapbt(mp) && + rtg_rgno(rtg) == 0) { + error = init_rtrmap_for_rtsb(rtg); + if (error) + fail(_("rtrmap rtsb init failed"), error); + } + rtfreesp_init(rtg); } } diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index f5556fcc4040ed..c8042261328171 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -2678,12 +2678,18 @@ _("reflink not supported with realtime devices\n")); } cli->sb_feat.reflink = false; - if (cli->sb_feat.rmapbt && cli_opt_set(&mopts, M_RMAPBT)) { - fprintf(stderr, -_("rmapbt not supported with realtime devices\n")); - usage(); + if (!cli->sb_feat.metadir && cli->sb_feat.rmapbt) { + if (cli_opt_set(&mopts, M_RMAPBT) && + cli_opt_set(&mopts, M_METADIR)) { + fprintf(stderr, +_("rmapbt not supported on realtime devices without metadir feature\n")); + usage(); + } else if (cli_opt_set(&mopts, M_RMAPBT)) { + cli->sb_feat.metadir = true; + } else { + cli->sb_feat.rmapbt = false; + } } - cli->sb_feat.rmapbt = false; } if ((cli->fsx.fsx_xflags & FS_XFLAG_COWEXTSIZE) && @@ -5006,6 +5012,74 @@ write_rtsb( libxfs_buf_relse(sb_bp); } +static inline void +prealloc_fail( + struct xfs_mount *mp, + int error, + xfs_filblks_t ask, + const char *tag) +{ + if (error == ENOSPC) + fprintf(stderr, + _("%s: cannot handle expansion of %s; need %llu free blocks, have %llu\n"), + progname, tag, (unsigned long long)ask, + (unsigned long long)mp->m_sb.sb_fdblocks); + else + fprintf(stderr, + _("%s: error %d while checking free space for %s\n"), + progname, error, tag); + exit(1); +} + +/* + * Make sure there's enough space on the data device to handle realtime + * metadata btree expansions. + */ +static void +check_rt_meta_prealloc( + struct xfs_mount *mp) +{ + struct xfs_perag *pag = NULL; + struct xfs_rtgroup *rtg = NULL; + xfs_filblks_t ask; + int error; + + /* + * First create all the per-AG reservations, since they take from the + * free block count. Each AG should start with enough free space for + * the per-AG reservation. + */ + mp->m_finobt_nores = false; + + while ((pag = xfs_perag_next(mp, pag))) { + error = -libxfs_ag_resv_init(pag, NULL); + if (error && error != ENOSPC) { + fprintf(stderr, + _("%s: error %d while checking AG free space for realtime metadata\n"), + progname, error); + exit(1); + } + } + + /* Realtime metadata btree inode */ + while ((rtg = xfs_rtgroup_next(mp, rtg))) { + ask = libxfs_rtrmapbt_calc_reserves(mp); + error = -libxfs_metafile_resv_init(rtg_rmap(rtg), ask); + if (error) + prealloc_fail(mp, error, ask, _("realtime rmap btree")); + } + + /* Unreserve the realtime metadata reservations. */ + while ((rtg = xfs_rtgroup_next(mp, rtg))) + libxfs_metafile_resv_free(rtg_rmap(rtg)); + + /* Unreserve the per-AG reservations. */ + while ((pag = xfs_perag_next(mp, pag))) + libxfs_ag_resv_free(pag); + + mp->m_finobt_nores = false; +} + int main( int argc, @@ -5343,6 +5417,9 @@ main( */ check_root_ino(mp); + /* Make sure we can handle space preallocations of rt metadata btrees */ + check_rt_meta_prealloc(mp); + /* * Re-write multiple secondary superblocks with rootinode field set */