From patchwork Sun Dec 31 21:15:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507597 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 54B13BA2B for ; Sun, 31 Dec 2023 21:15:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="QzyPH40+" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D4960C433C8; Sun, 31 Dec 2023 21:15:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704057352; bh=6gYhs78HbM8RJ74hPLsn6uYLIK8JwaOGxp10HbV1K3A=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=QzyPH40+3jkTBuAO4RPY+ctsU/7ajbI9Rtuca6fofZz6X1kO1izyzuPJY+lAutXF8 L+43dbHw0SmWFNUuGfDqCTyii+JkSiWXudSZ1VfFCXugpEiZWZolrOL4hixK+FpmNc 4lG0AO5CG8SWa93/2+bWs9xjxlzMlasrgsIFb0xi6OrJHbRhxjJqeWPhGuBmi4N+iP jZ4EfmXsXDSa5giQ9jHzx8o3F/j9Ea1NWKKD7D0Q8yz3IWuUWqn0EqI5ycwcEUxYi/ dtDJ11OPV3749dp8FLQREHyvGlTlB18nDfO6sXq6CIBhwNNzJ0RxwvZiMqs8ZvBZsK 103WT7PaGy+tg== Date: Sun, 31 Dec 2023 13:15:52 -0800 Subject: [PATCH 01/24] xfs: create incore realtime group structures From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404846257.1763124.13866237693545815043.stgit@frogsfrogsfrogs> In-Reply-To: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> References: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 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 an incore object that will contain information about a realtime allocation group. This will eventually enable us to shard the realtime section in a similar manner to how we shard the data section. Signed-off-by: Darrick J. Wong --- fs/xfs/Makefile | 1 fs/xfs/libxfs/xfs_format.h | 8 + fs/xfs/libxfs/xfs_rtgroup.c | 251 +++++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_rtgroup.h | 132 +++++++++++++++++++++++ fs/xfs/libxfs/xfs_sb.c | 5 + fs/xfs/libxfs/xfs_types.h | 4 + fs/xfs/xfs_log_recover.c | 6 + fs/xfs/xfs_mount.c | 12 ++ fs/xfs/xfs_mount.h | 6 + fs/xfs/xfs_rtalloc.c | 8 + fs/xfs/xfs_super.c | 2 fs/xfs/xfs_trace.c | 1 fs/xfs/xfs_trace.h | 38 +++++++ 13 files changed, 473 insertions(+), 1 deletion(-) create mode 100644 fs/xfs/libxfs/xfs_rtgroup.c create mode 100644 fs/xfs/libxfs/xfs_rtgroup.h diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 5362a0fb56d77..500dea292a9d6 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -59,6 +59,7 @@ xfs-y += $(addprefix libxfs/, \ # xfs_rtbitmap is shared with libxfs xfs-$(CONFIG_XFS_RT) += $(addprefix libxfs/, \ xfs_rtbitmap.o \ + xfs_rtgroup.o \ ) # highlevel code diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index 0636ca97622dd..3bd93c01bf4bf 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -184,6 +184,14 @@ typedef struct xfs_sb { */ xfs_ino_t sb_metadirino; + /* + * Realtime group geometry information. On disk these fields live in + * the rsumino slot, but we cache them separately in the in-core super + * for easy access. + */ + xfs_rgblock_t sb_rgblocks; /* size of a realtime group */ + xfs_rgnumber_t sb_rgcount; /* number of realtime groups */ + /* must be padded to 64 bit alignment */ } xfs_sb_t; diff --git a/fs/xfs/libxfs/xfs_rtgroup.c b/fs/xfs/libxfs/xfs_rtgroup.c new file mode 100644 index 0000000000000..caa82c4813038 --- /dev/null +++ b/fs/xfs/libxfs/xfs_rtgroup.c @@ -0,0 +1,251 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022-2024 Oracle. All Rights Reserved. + * Author: Darrick J. Wong + */ +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_trans_resv.h" +#include "xfs_bit.h" +#include "xfs_sb.h" +#include "xfs_mount.h" +#include "xfs_btree.h" +#include "xfs_alloc_btree.h" +#include "xfs_rmap_btree.h" +#include "xfs_alloc.h" +#include "xfs_ialloc.h" +#include "xfs_rmap.h" +#include "xfs_ag.h" +#include "xfs_ag_resv.h" +#include "xfs_health.h" +#include "xfs_error.h" +#include "xfs_bmap.h" +#include "xfs_defer.h" +#include "xfs_log_format.h" +#include "xfs_trans.h" +#include "xfs_trace.h" +#include "xfs_inode.h" +#include "xfs_icache.h" +#include "xfs_rtgroup.h" +#include "xfs_rtbitmap.h" + +/* + * Passive reference counting access wrappers to the rtgroup structures. If + * the rtgroup structure is to be freed, the freeing code is responsible for + * cleaning up objects with passive references before freeing the structure. + */ +struct xfs_rtgroup * +xfs_rtgroup_get( + struct xfs_mount *mp, + xfs_rgnumber_t rgno) +{ + struct xfs_rtgroup *rtg; + + rcu_read_lock(); + rtg = radix_tree_lookup(&mp->m_rtgroup_tree, rgno); + if (rtg) { + trace_xfs_rtgroup_get(rtg, _RET_IP_); + ASSERT(atomic_read(&rtg->rtg_ref) >= 0); + atomic_inc(&rtg->rtg_ref); + } + rcu_read_unlock(); + return rtg; +} + +/* Get a passive reference to the given rtgroup. */ +struct xfs_rtgroup * +xfs_rtgroup_hold( + struct xfs_rtgroup *rtg) +{ + ASSERT(atomic_read(&rtg->rtg_ref) > 0 || + atomic_read(&rtg->rtg_active_ref) > 0); + + trace_xfs_rtgroup_hold(rtg, _RET_IP_); + atomic_inc(&rtg->rtg_ref); + return rtg; +} + +void +xfs_rtgroup_put( + struct xfs_rtgroup *rtg) +{ + trace_xfs_rtgroup_put(rtg, _RET_IP_); + ASSERT(atomic_read(&rtg->rtg_ref) > 0); + atomic_dec(&rtg->rtg_ref); +} + +/* + * Active references for rtgroup structures. This is for short term access to + * the rtgroup structures for walking trees or accessing state. If an rtgroup + * is being shrunk or is offline, then this will fail to find that group and + * return NULL instead. + */ +struct xfs_rtgroup * +xfs_rtgroup_grab( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + struct xfs_rtgroup *rtg; + + rcu_read_lock(); + rtg = radix_tree_lookup(&mp->m_rtgroup_tree, agno); + if (rtg) { + trace_xfs_rtgroup_grab(rtg, _RET_IP_); + if (!atomic_inc_not_zero(&rtg->rtg_active_ref)) + rtg = NULL; + } + rcu_read_unlock(); + return rtg; +} + +void +xfs_rtgroup_rele( + struct xfs_rtgroup *rtg) +{ + trace_xfs_rtgroup_rele(rtg, _RET_IP_); + if (atomic_dec_and_test(&rtg->rtg_active_ref)) + wake_up(&rtg->rtg_active_wq); +} + +int +xfs_initialize_rtgroups( + struct xfs_mount *mp, + xfs_rgnumber_t rgcount) +{ + struct xfs_rtgroup *rtg; + xfs_rgnumber_t index; + xfs_rgnumber_t first_initialised = NULLRGNUMBER; + int error; + + if (!xfs_has_rtgroups(mp)) + return 0; + + /* + * Walk the current rtgroup tree so we don't try to initialise rt + * groups that already exist (growfs case). Allocate and insert all the + * rtgroups we don't find ready for initialisation. + */ + for (index = 0; index < rgcount; index++) { + rtg = xfs_rtgroup_get(mp, index); + if (rtg) { + xfs_rtgroup_put(rtg); + continue; + } + + rtg = kmem_zalloc(sizeof(struct xfs_rtgroup), KM_MAYFAIL); + if (!rtg) { + error = -ENOMEM; + goto out_unwind_new_rtgs; + } + rtg->rtg_rgno = index; + rtg->rtg_mount = mp; + + error = radix_tree_preload(GFP_NOFS); + if (error) + goto out_free_rtg; + + spin_lock(&mp->m_rtgroup_lock); + if (radix_tree_insert(&mp->m_rtgroup_tree, index, rtg)) { + WARN_ON_ONCE(1); + spin_unlock(&mp->m_rtgroup_lock); + radix_tree_preload_end(); + error = -EEXIST; + goto out_free_rtg; + } + spin_unlock(&mp->m_rtgroup_lock); + radix_tree_preload_end(); + +#ifdef __KERNEL__ + /* Place kernel structure only init below this point. */ + spin_lock_init(&rtg->rtg_state_lock); + init_waitqueue_head(&rtg->rtg_active_wq); +#endif /* __KERNEL__ */ + + /* Active ref owned by mount indicates rtgroup is online. */ + atomic_set(&rtg->rtg_active_ref, 1); + + /* first new rtg is fully initialized */ + if (first_initialised == NULLRGNUMBER) + first_initialised = index; + } + + return 0; + +out_free_rtg: + kmem_free(rtg); +out_unwind_new_rtgs: + /* unwind any prior newly initialized rtgs */ + for (index = first_initialised; index < rgcount; index++) { + rtg = radix_tree_delete(&mp->m_rtgroup_tree, index); + if (!rtg) + break; + kmem_free(rtg); + } + return error; +} + +STATIC void +__xfs_free_rtgroups( + struct rcu_head *head) +{ + struct xfs_rtgroup *rtg; + + rtg = container_of(head, struct xfs_rtgroup, rcu_head); + kmem_free(rtg); +} + +/* + * Free up the rtgroup resources associated with the mount structure. + */ +void +xfs_free_rtgroups( + struct xfs_mount *mp) +{ + struct xfs_rtgroup *rtg; + xfs_rgnumber_t rgno; + + if (!xfs_has_rtgroups(mp)) + return; + + for (rgno = 0; rgno < mp->m_sb.sb_rgcount; rgno++) { + spin_lock(&mp->m_rtgroup_lock); + rtg = radix_tree_delete(&mp->m_rtgroup_tree, rgno); + spin_unlock(&mp->m_rtgroup_lock); + ASSERT(rtg); + XFS_IS_CORRUPT(mp, atomic_read(&rtg->rtg_ref) != 0); + + /* drop the mount's active reference */ + xfs_rtgroup_rele(rtg); + XFS_IS_CORRUPT(mp, atomic_read(&rtg->rtg_active_ref) != 0); + + call_rcu(&rtg->rcu_head, __xfs_free_rtgroups); + } +} + +/* Find the size of the rtgroup, in blocks. */ +static xfs_rgblock_t +__xfs_rtgroup_block_count( + struct xfs_mount *mp, + xfs_rgnumber_t rgno, + xfs_rgnumber_t rgcount, + xfs_rfsblock_t rblocks) +{ + ASSERT(rgno < rgcount); + + if (rgno < rgcount - 1) + return mp->m_sb.sb_rgblocks; + return xfs_rtb_rounddown_rtx(mp, + rblocks - (rgno * mp->m_sb.sb_rgblocks)); +} + +/* Compute the number of blocks in this realtime group. */ +xfs_rgblock_t +xfs_rtgroup_block_count( + struct xfs_mount *mp, + xfs_rgnumber_t rgno) +{ + return __xfs_rtgroup_block_count(mp, rgno, mp->m_sb.sb_rgcount, + mp->m_sb.sb_rblocks); +} diff --git a/fs/xfs/libxfs/xfs_rtgroup.h b/fs/xfs/libxfs/xfs_rtgroup.h new file mode 100644 index 0000000000000..2f0a670217c48 --- /dev/null +++ b/fs/xfs/libxfs/xfs_rtgroup.h @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2022-2024 Oracle. All Rights Reserved. + * Author: Darrick J. Wong + */ +#ifndef __LIBXFS_RTGROUP_H +#define __LIBXFS_RTGROUP_H 1 + +struct xfs_mount; +struct xfs_trans; + +/* + * Realtime group incore structure, similar to the per-AG structure. + */ +struct xfs_rtgroup { + struct xfs_mount *rtg_mount; + xfs_rgnumber_t rtg_rgno; + atomic_t rtg_ref; /* passive reference count */ + atomic_t rtg_active_ref; /* active reference count */ + wait_queue_head_t rtg_active_wq;/* woken active_ref falls to zero */ + + /* for rcu-safe freeing */ + struct rcu_head rcu_head; + + /* Number of blocks in this group */ + xfs_rgblock_t rtg_blockcount; + +#ifdef __KERNEL__ + /* -- kernel only structures below this line -- */ + spinlock_t rtg_state_lock; +#endif /* __KERNEL__ */ +}; + +#ifdef CONFIG_XFS_RT +/* Passive rtgroup references */ +struct xfs_rtgroup *xfs_rtgroup_get(struct xfs_mount *mp, xfs_rgnumber_t rgno); +struct xfs_rtgroup *xfs_rtgroup_hold(struct xfs_rtgroup *rtg); +void xfs_rtgroup_put(struct xfs_rtgroup *rtg); + +/* Active rtgroup references */ +struct xfs_rtgroup *xfs_rtgroup_grab(struct xfs_mount *mp, xfs_rgnumber_t rgno); +void xfs_rtgroup_rele(struct xfs_rtgroup *rtg); + +int xfs_initialize_rtgroups(struct xfs_mount *mp, xfs_rgnumber_t rgcount); +void xfs_free_rtgroups(struct xfs_mount *mp); +#else +static inline struct xfs_rtgroup * +xfs_rtgroup_get( + struct xfs_mount *mp, + xfs_rgnumber_t rgno) +{ + return NULL; +} +static inline struct xfs_rtgroup * +xfs_rtgroup_hold(struct xfs_rtgroup *rtg) +{ + ASSERT(rtg == NULL); + return NULL; +} +# define xfs_rtgroup_grab xfs_rtgroup_get +# define xfs_rtgroup_put(rtg) ((void)0) +# define xfs_rtgroup_rele(rtg) ((void)0) +# define xfs_initialize_rtgroups(mp, rgcount) (0) +# define xfs_free_rtgroups(mp) ((void)0) +#endif /* CONFIG_XFS_RT */ + +/* + * rt group iteration APIs + */ +static inline struct xfs_rtgroup * +xfs_rtgroup_next( + struct xfs_rtgroup *rtg, + xfs_rgnumber_t *rgno, + xfs_rgnumber_t end_rgno) +{ + struct xfs_mount *mp = rtg->rtg_mount; + + *rgno = rtg->rtg_rgno + 1; + xfs_rtgroup_rele(rtg); + if (*rgno > end_rgno) + return NULL; + return xfs_rtgroup_grab(mp, *rgno); +} + +#define for_each_rtgroup_range(mp, rgno, end_rgno, rtg) \ + for ((rtg) = xfs_rtgroup_grab((mp), (rgno)); \ + (rtg) != NULL; \ + (rtg) = xfs_rtgroup_next((rtg), &(rgno), (end_rgno))) + +#define for_each_rtgroup_from(mp, rgno, rtg) \ + for_each_rtgroup_range((mp), (rgno), (mp)->m_sb.sb_rgcount - 1, (rtg)) + + +#define for_each_rtgroup(mp, rgno, rtg) \ + (rgno) = 0; \ + for_each_rtgroup_from((mp), (rgno), (rtg)) + +static inline bool +xfs_verify_rgbno( + struct xfs_rtgroup *rtg, + xfs_rgblock_t rgbno) +{ + if (rgbno >= rtg->rtg_blockcount) + return false; + if (rgbno < rtg->rtg_mount->m_sb.sb_rextsize) + return false; + return true; +} + +static inline bool +xfs_verify_rgbext( + struct xfs_rtgroup *rtg, + xfs_rgblock_t rgbno, + xfs_rgblock_t len) +{ + if (rgbno + len <= rgbno) + return false; + + if (!xfs_verify_rgbno(rtg, rgbno)) + return false; + + return xfs_verify_rgbno(rtg, rgbno + len - 1); +} + +#ifdef CONFIG_XFS_RT +xfs_rgblock_t xfs_rtgroup_block_count(struct xfs_mount *mp, + xfs_rgnumber_t rgno); +#else +# define xfs_rtgroup_block_count(mp, rgno) (0) +#endif /* CONFIG_XFS_RT */ + +#endif /* __LIBXFS_RTGROUP_H */ diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index 7a20b9b4bccb3..88402cb4a6879 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -701,6 +701,9 @@ __xfs_sb_from_disk( to->sb_gquotino = NULLFSINO; to->sb_pquotino = NULLFSINO; } + + to->sb_rgcount = 0; + to->sb_rgblocks = 0; } void @@ -1015,6 +1018,8 @@ xfs_sb_mount_common( mp->m_blockwmask = mp->m_blockwsize - 1; mp->m_rtxblklog = log2_if_power2(sbp->sb_rextsize); mp->m_rtxblkmask = mask64_if_power2(sbp->sb_rextsize); + mp->m_rgblklog = 0; + mp->m_rgblkmask = 0; mp->m_alloc_mxr[0] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 1); mp->m_alloc_mxr[1] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 0); diff --git a/fs/xfs/libxfs/xfs_types.h b/fs/xfs/libxfs/xfs_types.h index 5556615a2ff9c..195471c438599 100644 --- a/fs/xfs/libxfs/xfs_types.h +++ b/fs/xfs/libxfs/xfs_types.h @@ -9,10 +9,12 @@ typedef uint32_t prid_t; /* project ID */ typedef uint32_t xfs_agblock_t; /* blockno in alloc. group */ +typedef uint32_t xfs_rgblock_t; /* blockno in realtime group */ typedef uint32_t xfs_agino_t; /* inode # within allocation grp */ typedef uint32_t xfs_extlen_t; /* extent length in blocks */ typedef uint32_t xfs_rtxlen_t; /* file extent length in rtextents */ typedef uint32_t xfs_agnumber_t; /* allocation group number */ +typedef uint32_t xfs_rgnumber_t; /* realtime group number */ typedef uint64_t xfs_extnum_t; /* # of extents in a file */ typedef uint32_t xfs_aextnum_t; /* # extents in an attribute fork */ typedef int64_t xfs_fsize_t; /* bytes in a file */ @@ -54,7 +56,9 @@ typedef void * xfs_failaddr_t; #define NULLRTEXTNO ((xfs_rtxnum_t)-1) #define NULLAGBLOCK ((xfs_agblock_t)-1) +#define NULLRGBLOCK ((xfs_rgblock_t)-1) #define NULLAGNUMBER ((xfs_agnumber_t)-1) +#define NULLRGNUMBER ((xfs_rgnumber_t)-1) #define NULLCOMMITLSN ((xfs_lsn_t)-1) diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 628d7915120b0..5e9562f37dc89 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -28,6 +28,7 @@ #include "xfs_ag.h" #include "xfs_quota.h" #include "xfs_reflink.h" +#include "xfs_rtgroup.h" #define BLK_AVG(blk1, blk2) ((blk1+blk2) >> 1) @@ -3347,6 +3348,11 @@ xlog_do_recover( xfs_warn(mp, "Failed post-recovery per-ag init: %d", error); return error; } + error = xfs_initialize_rtgroups(mp, sbp->sb_rgcount); + if (error) { + xfs_warn(mp, "Failed post-recovery rtgroup init: %d", error); + return error; + } mp->m_alloc_set_aside = xfs_alloc_set_aside(mp); /* Normal transactions can now occur */ diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 8b61b8c51cd16..ba6c77e7e265d 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -35,6 +35,7 @@ #include "xfs_trace.h" #include "xfs_ag.h" #include "xfs_imeta.h" +#include "xfs_rtgroup.h" #include "scrub/stats.h" static DEFINE_MUTEX(xfs_uuid_table_mutex); @@ -842,10 +843,16 @@ xfs_mountfs( goto out_free_dir; } + error = xfs_initialize_rtgroups(mp, sbp->sb_rgcount); + if (error) { + xfs_warn(mp, "Failed rtgroup init: %d", error); + goto out_free_perag; + } + if (XFS_IS_CORRUPT(mp, !sbp->sb_logblocks)) { xfs_warn(mp, "no log defined"); error = -EFSCORRUPTED; - goto out_free_perag; + goto out_free_rtgroup; } error = xfs_inodegc_register_shrinker(mp); @@ -1070,6 +1077,8 @@ xfs_mountfs( if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp) xfs_buftarg_drain(mp->m_logdev_targp); xfs_buftarg_drain(mp->m_ddev_targp); + out_free_rtgroup: + xfs_free_rtgroups(mp); out_free_perag: xfs_free_perag(mp); out_free_dir: @@ -1151,6 +1160,7 @@ xfs_unmountfs( xfs_errortag_clearall(mp); #endif shrinker_free(mp->m_inodegc_shrinker); + xfs_free_rtgroups(mp); xfs_free_perag(mp); xfs_errortag_del(mp); diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index b45a4f4a8503e..52976a133cec9 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -121,6 +121,7 @@ typedef struct xfs_mount { uint8_t m_agno_log; /* log #ag's */ uint8_t m_sectbb_log; /* sectlog - BBSHIFT */ int8_t m_rtxblklog; /* log2 of rextsize, if possible */ + int8_t m_rgblklog; /* log2 of rt group sz if possible */ uint m_blockmask; /* sb_blocksize-1 */ uint m_blockwsize; /* sb_blocksize in words */ uint m_blockwmask; /* blockwsize-1 */ @@ -155,6 +156,7 @@ typedef struct xfs_mount { uint64_t m_low_space[XFS_LOWSP_MAX]; uint64_t m_low_rtexts[XFS_LOWSP_MAX]; uint64_t m_rtxblkmask; /* rt extent block mask */ + uint64_t m_rgblkmask; /* rt group block mask */ struct xfs_ino_geometry m_ino_geo; /* inode geometry */ struct xfs_trans_resv m_resv; /* precomputed res values */ /* low free space thresholds */ @@ -203,6 +205,8 @@ typedef struct xfs_mount { */ atomic64_t m_allocbt_blks; + struct radix_tree_root m_rtgroup_tree; /* per-rt group info */ + spinlock_t m_rtgroup_lock; /* lock for m_rtgroup_tree */ struct radix_tree_root m_perag_tree; /* per-ag accounting info */ spinlock_t m_perag_lock; /* lock for m_perag_tree */ uint64_t m_resblks; /* total reserved blocks */ @@ -294,6 +298,7 @@ typedef struct xfs_mount { #define XFS_FEAT_NEEDSREPAIR (1ULL << 25) /* needs xfs_repair */ #define XFS_FEAT_NREXT64 (1ULL << 26) /* large extent counters */ #define XFS_FEAT_METADIR (1ULL << 27) /* metadata directory tree */ +#define XFS_FEAT_RTGROUPS (1ULL << 28) /* realtime groups */ /* Mount features */ #define XFS_FEAT_NOATTR2 (1ULL << 48) /* disable attr2 creation */ @@ -358,6 +363,7 @@ __XFS_HAS_FEAT(bigtime, BIGTIME) __XFS_HAS_FEAT(needsrepair, NEEDSREPAIR) __XFS_HAS_FEAT(large_extent_counts, NREXT64) __XFS_HAS_FEAT(metadir, METADIR) +__XFS_HAS_FEAT(rtgroups, RTGROUPS) /* * Mount features diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index f76ecb9a19b51..59ded74c9007e 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -24,6 +24,7 @@ #include "xfs_health.h" #include "xfs_da_format.h" #include "xfs_imeta.h" +#include "xfs_rtgroup.h" /* * Realtime metadata files are not quite regular files because userspace can't @@ -1396,6 +1397,8 @@ xfs_rtmount_inodes( { struct xfs_trans *tp; struct xfs_sb *sbp = &mp->m_sb; + struct xfs_rtgroup *rtg; + xfs_rgnumber_t rgno; int error; error = xfs_trans_alloc_empty(mp, &tp); @@ -1426,6 +1429,11 @@ xfs_rtmount_inodes( if (error) goto out_rele_summary; + for_each_rtgroup(mp, rgno, rtg) { + rtg->rtg_blockcount = xfs_rtgroup_block_count(mp, + rtg->rtg_rgno); + } + xfs_alloc_rsum_cache(mp, sbp->sb_rbmblocks); xfs_trans_cancel(tp); return 0; diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 998fa006af5bb..c154e2cb7a18e 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -2002,6 +2002,8 @@ static int xfs_init_fs_context( spin_lock_init(&mp->m_sb_lock); INIT_RADIX_TREE(&mp->m_perag_tree, GFP_ATOMIC); spin_lock_init(&mp->m_perag_lock); + INIT_RADIX_TREE(&mp->m_rtgroup_tree, GFP_ATOMIC); + spin_lock_init(&mp->m_rtgroup_lock); mutex_init(&mp->m_growlock); INIT_WORK(&mp->m_flush_inodes_work, xfs_flush_inodes_worker); INIT_DELAYED_WORK(&mp->m_reclaim_work, xfs_reclaim_worker); diff --git a/fs/xfs/xfs_trace.c b/fs/xfs/xfs_trace.c index 453cf7ffdea03..21f55b0125fc4 100644 --- a/fs/xfs/xfs_trace.c +++ b/fs/xfs/xfs_trace.c @@ -44,6 +44,7 @@ #include "xfs_xchgrange.h" #include "xfs_parent.h" #include "xfs_imeta.h" +#include "xfs_rtgroup.h" /* * We include this last to have the helpers above available for the trace diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 17f364e1b9613..81c21000d4fea 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -87,6 +87,7 @@ struct xfs_getparents; struct xfs_parent_name_irec; struct xfs_attrlist_cursor_kern; struct xfs_imeta_update; +struct xfs_rtgroup; #define XFS_ATTR_FILTER_FLAGS \ { XFS_ATTR_ROOT, "ROOT" }, \ @@ -216,6 +217,43 @@ DEFINE_PERAG_REF_EVENT(xfs_perag_rele); DEFINE_PERAG_REF_EVENT(xfs_perag_set_inode_tag); DEFINE_PERAG_REF_EVENT(xfs_perag_clear_inode_tag); +#ifdef CONFIG_XFS_RT +DECLARE_EVENT_CLASS(xfs_rtgroup_class, + TP_PROTO(struct xfs_rtgroup *rtg, unsigned long caller_ip), + TP_ARGS(rtg, caller_ip), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_rgnumber_t, rgno) + __field(int, refcount) + __field(int, active_refcount) + __field(unsigned long, caller_ip) + ), + TP_fast_assign( + __entry->dev = rtg->rtg_mount->m_super->s_dev; + __entry->rgno = rtg->rtg_rgno; + __entry->refcount = atomic_read(&rtg->rtg_ref); + __entry->active_refcount = atomic_read(&rtg->rtg_active_ref); + __entry->caller_ip = caller_ip; + ), + TP_printk("dev %d:%d rgno 0x%x passive refs %d active refs %d caller %pS", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->rgno, + __entry->refcount, + __entry->active_refcount, + (char *)__entry->caller_ip) +); + +#define DEFINE_RTGROUP_REF_EVENT(name) \ +DEFINE_EVENT(xfs_rtgroup_class, name, \ + TP_PROTO(struct xfs_rtgroup *rtg, unsigned long caller_ip), \ + TP_ARGS(rtg, caller_ip)) +DEFINE_RTGROUP_REF_EVENT(xfs_rtgroup_get); +DEFINE_RTGROUP_REF_EVENT(xfs_rtgroup_hold); +DEFINE_RTGROUP_REF_EVENT(xfs_rtgroup_put); +DEFINE_RTGROUP_REF_EVENT(xfs_rtgroup_grab); +DEFINE_RTGROUP_REF_EVENT(xfs_rtgroup_rele); +#endif /* CONFIG_XFS_RT */ + TRACE_EVENT(xfs_inodegc_worker, TP_PROTO(struct xfs_mount *mp, unsigned int shrinker_hits), TP_ARGS(mp, shrinker_hits), From patchwork Sun Dec 31 21:16:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507598 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 B76F6BA22 for ; Sun, 31 Dec 2023 21:16:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="F00fmvL/" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7E516C433C7; Sun, 31 Dec 2023 21:16:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704057368; bh=7NthETXwYqJ3xi4zCJ2GKeS+oauegPfCKEDhRhHiLMM=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=F00fmvL/atVzSsfVefeQ9xzkyo6EIHeNqr03VKCLJxzGuMC9G8v6aL9tqCzWd2viJ SP7vSHSsVWUMZVbbdlqGILBeMSHOxxB7cu8fUMW+ckjOtC+IgJJM7VbmpDIn7gjLfq pFpKWk0JDm9bQESKKSDu0IcZaedC0KW3wVvcDrM0sSE5nZk+V6tWazbai/P6XoaKVW fqRQ3qotwL2Uuz2zwAKA9JTbhSvAocYwZtSlIjpiVM76yaEMGp9qQEkMGG8g7igO/L YfoAxpvtSTXKIwydO4XDJZrKNuU41oksFAnzRkgV2plx3SEJJ9QowtSOoSFFX0CpeF 7IN+kwaVFGT8g== Date: Sun, 31 Dec 2023 13:16:08 -0800 Subject: [PATCH 02/24] xfs: define the format of rt groups From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404846274.1763124.9559567871299782407.stgit@frogsfrogsfrogs> In-Reply-To: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> References: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Define the ondisk format of realtime group metadata. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_format.h | 62 +++++++++++++++++++++++++++- fs/xfs/libxfs/xfs_ondisk.h | 1 fs/xfs/libxfs/xfs_rtgroup.c | 96 +++++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_rtgroup.h | 83 +++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_sb.c | 86 +++++++++++++++++++++++++++++++++++++-- fs/xfs/libxfs/xfs_shared.h | 1 6 files changed, 324 insertions(+), 5 deletions(-) diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index 3bd93c01bf4bf..8debe92571692 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -216,7 +216,17 @@ struct xfs_dsb { * pointers are no longer used. */ __be64 sb_rbmino; - __be64 sb_rsumino; /* summary inode for rt bitmap */ + /* + * rtgroups requires metadir, so we reuse the rsumino space to hold + * the rg block count and shift values. + */ + union { + __be64 sb_rsumino; /* summary inode for rt bitmap */ + struct { + __be32 sb_rgcount; /* # of realtime groups */ + __be32 sb_rgblocks; /* rtblocks per group */ + }; + }; __be32 sb_rextsize; /* realtime extent size, blocks */ __be32 sb_agblocks; /* size of an allocation group */ __be32 sb_agcount; /* number of allocation groups */ @@ -398,6 +408,7 @@ xfs_sb_has_ro_compat_feature( #define XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR (1 << 4) /* needs xfs_repair */ #define XFS_SB_FEAT_INCOMPAT_NREXT64 (1 << 5) /* large extent counters */ #define XFS_SB_FEAT_INCOMPAT_PARENT (1 << 6) /* parent pointers */ +#define XFS_SB_FEAT_INCOMPAT_RTGROUPS (1U << 30) /* realtime groups */ #define XFS_SB_FEAT_INCOMPAT_METADIR (1U << 31) /* metadata dir tree */ #define XFS_SB_FEAT_INCOMPAT_ALL \ (XFS_SB_FEAT_INCOMPAT_FTYPE| \ @@ -752,6 +763,55 @@ union xfs_suminfo_raw { __u32 old; }; +/* + * Realtime allocation groups break the rt section into multiple pieces that + * could be locked independently. Realtime block group numbers are 32-bit + * quantities. Block numbers within a group are also 32-bit quantities, but + * the upper bit must never be set. + */ +#define XFS_MAX_RGBLOCKS ((xfs_rgblock_t)(1U << 31) - 1) +#define XFS_MAX_RGNUMBER ((xfs_rgnumber_t)(-1U)) + +#define XFS_RTSB_MAGIC 0x58524750 /* 'XRGP' */ + +/* + * Realtime superblock - on disk version. Must be padded to 64 bit alignment. + * The first block of each realtime group contains this superblock; this is + * how we avoid having file data extents cross a group boundary. + */ +struct xfs_rtsb { + __be32 rsb_magicnum; /* magic number == XFS_RTSB_MAGIC */ + __be32 rsb_blocksize; /* logical block size, bytes */ + __be64 rsb_rblocks; /* number of realtime blocks */ + + __be64 rsb_rextents; /* number of realtime extents */ + __be64 rsb_lsn; /* last write sequence */ + + __be32 rsb_rgcount; /* # of realtime groups */ + unsigned char rsb_fname[XFSLABEL_MAX]; /* rt volume name */ + + uuid_t rsb_uuid; /* user-visible file system unique id */ + + __be32 rsb_rextsize; /* realtime extent size, blocks */ + __be32 rsb_rbmblocks; /* number of rt bitmap blocks */ + + __be32 rsb_rgblocks; /* rt blocks per group */ + __u8 rsb_blocklog; /* log2 of sb_blocksize */ + __u8 rsb_sectlog; /* log2 of sb_sectsize */ + __u8 rsb_rextslog; /* log2 of sb_rextents */ + __u8 rsb_pad; + + __le32 rsb_crc; /* superblock crc */ + __le32 rsb_pad2; + + uuid_t rsb_meta_uuid; /* metadata file system unique id */ + + /* must be padded to 64 bit alignment */ +}; + +#define XFS_RTSB_CRC_OFF offsetof(struct xfs_rtsb, rsb_crc) +#define XFS_RTSB_DADDR ((xfs_daddr_t)0) /* daddr in rt section */ + /* * XFS Timestamps * ============== diff --git a/fs/xfs/libxfs/xfs_ondisk.h b/fs/xfs/libxfs/xfs_ondisk.h index 832d96f0f3c54..65219d4cf99ca 100644 --- a/fs/xfs/libxfs/xfs_ondisk.h +++ b/fs/xfs/libxfs/xfs_ondisk.h @@ -53,6 +53,7 @@ xfs_check_ondisk_structs(void) XFS_CHECK_STRUCT_SIZE(xfs_inobt_ptr_t, 4); XFS_CHECK_STRUCT_SIZE(xfs_refcount_ptr_t, 4); XFS_CHECK_STRUCT_SIZE(xfs_rmap_ptr_t, 4); + XFS_CHECK_STRUCT_SIZE(struct xfs_rtsb, 104); /* dir/attr trees */ XFS_CHECK_STRUCT_SIZE(struct xfs_attr3_leaf_hdr, 80); diff --git a/fs/xfs/libxfs/xfs_rtgroup.c b/fs/xfs/libxfs/xfs_rtgroup.c index caa82c4813038..a82dd23cf0c79 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.c +++ b/fs/xfs/libxfs/xfs_rtgroup.c @@ -28,6 +28,7 @@ #include "xfs_trace.h" #include "xfs_inode.h" #include "xfs_icache.h" +#include "xfs_buf_item.h" #include "xfs_rtgroup.h" #include "xfs_rtbitmap.h" @@ -249,3 +250,98 @@ xfs_rtgroup_block_count( return __xfs_rtgroup_block_count(mp, rgno, mp->m_sb.sb_rgcount, mp->m_sb.sb_rblocks); } + +static xfs_failaddr_t +xfs_rtsb_verify( + struct xfs_buf *bp) +{ + struct xfs_mount *mp = bp->b_mount; + struct xfs_rtsb *rsb = bp->b_addr; + + if (!xfs_verify_magic(bp, rsb->rsb_magicnum)) + return __this_address; + if (be32_to_cpu(rsb->rsb_blocksize) != mp->m_sb.sb_blocksize) + return __this_address; + if (be64_to_cpu(rsb->rsb_rblocks) != mp->m_sb.sb_rblocks) + return __this_address; + + if (be64_to_cpu(rsb->rsb_rextents) != mp->m_sb.sb_rextents) + return __this_address; + + if (!uuid_equal(&rsb->rsb_uuid, &mp->m_sb.sb_uuid)) + return __this_address; + + if (be32_to_cpu(rsb->rsb_rgcount) != mp->m_sb.sb_rgcount) + return __this_address; + + if (be32_to_cpu(rsb->rsb_rextsize) != mp->m_sb.sb_rextsize) + return __this_address; + if (be32_to_cpu(rsb->rsb_rbmblocks) != mp->m_sb.sb_rbmblocks) + return __this_address; + + if (be32_to_cpu(rsb->rsb_rgblocks) != mp->m_sb.sb_rgblocks) + return __this_address; + if (rsb->rsb_blocklog != mp->m_sb.sb_blocklog) + return __this_address; + if (rsb->rsb_sectlog != mp->m_sb.sb_sectlog) + return __this_address; + if (rsb->rsb_rextslog != mp->m_sb.sb_rextslog) + return __this_address; + if (rsb->rsb_pad) + return __this_address; + + if (rsb->rsb_pad2) + return __this_address; + + if (!uuid_equal(&rsb->rsb_meta_uuid, &mp->m_sb.sb_meta_uuid)) + return __this_address; + + /* Everything to the end of the fs block must be zero */ + if (memchr_inv(rsb + 1, 0, BBTOB(bp->b_length) - sizeof(*rsb))) + return __this_address; + + return NULL; +} + +static void +xfs_rtsb_read_verify( + struct xfs_buf *bp) +{ + xfs_failaddr_t fa; + + if (!xfs_buf_verify_cksum(bp, XFS_RTSB_CRC_OFF)) + xfs_verifier_error(bp, -EFSBADCRC, __this_address); + else { + fa = xfs_rtsb_verify(bp); + if (fa) + xfs_verifier_error(bp, -EFSCORRUPTED, fa); + } +} + +static void +xfs_rtsb_write_verify( + struct xfs_buf *bp) +{ + struct xfs_rtsb *rsb = bp->b_addr; + struct xfs_buf_log_item *bip = bp->b_log_item; + xfs_failaddr_t fa; + + fa = xfs_rtsb_verify(bp); + if (fa) { + xfs_verifier_error(bp, -EFSCORRUPTED, fa); + return; + } + + if (bip) + rsb->rsb_lsn = cpu_to_be64(bip->bli_item.li_lsn); + + xfs_buf_update_cksum(bp, XFS_RTSB_CRC_OFF); +} + +const struct xfs_buf_ops xfs_rtsb_buf_ops = { + .name = "xfs_rtsb", + .magic = { 0, cpu_to_be32(XFS_RTSB_MAGIC) }, + .verify_read = xfs_rtsb_read_verify, + .verify_write = xfs_rtsb_write_verify, + .verify_struct = xfs_rtsb_verify, +}; diff --git a/fs/xfs/libxfs/xfs_rtgroup.h b/fs/xfs/libxfs/xfs_rtgroup.h index 2f0a670217c48..924c8c95acbc3 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.h +++ b/fs/xfs/libxfs/xfs_rtgroup.h @@ -122,6 +122,89 @@ xfs_verify_rgbext( return xfs_verify_rgbno(rtg, rgbno + len - 1); } +static inline xfs_rtblock_t +xfs_rgbno_to_rtb( + struct xfs_mount *mp, + xfs_rgnumber_t rgno, + xfs_rgblock_t rgbno) +{ + ASSERT(xfs_has_rtgroups(mp)); + + if (mp->m_rgblklog >= 0) + return ((xfs_rtblock_t)rgno << mp->m_rgblklog) | rgbno; + + return ((xfs_rtblock_t)rgno * mp->m_sb.sb_rgblocks) + rgbno; +} + +static inline xfs_rgnumber_t +xfs_rtb_to_rgno( + struct xfs_mount *mp, + xfs_rtblock_t rtbno) +{ + ASSERT(xfs_has_rtgroups(mp)); + + if (mp->m_rgblklog >= 0) + return rtbno >> mp->m_rgblklog; + + return div_u64(rtbno, mp->m_sb.sb_rgblocks); +} + +static inline xfs_rgblock_t +xfs_rtb_to_rgbno( + struct xfs_mount *mp, + xfs_rtblock_t rtbno, + xfs_rgnumber_t *rgno) +{ + uint32_t rem; + + ASSERT(xfs_has_rtgroups(mp)); + + if (mp->m_rgblklog >= 0) { + *rgno = rtbno >> mp->m_rgblklog; + return rtbno & mp->m_rgblkmask; + } + + *rgno = div_u64_rem(rtbno, mp->m_sb.sb_rgblocks, &rem); + return rem; +} + +static inline xfs_daddr_t +xfs_rtb_to_daddr( + struct xfs_mount *mp, + xfs_rtblock_t rtbno) +{ + return rtbno << mp->m_blkbb_log; +} + +static inline xfs_rtblock_t +xfs_daddr_to_rtb( + struct xfs_mount *mp, + xfs_daddr_t daddr) +{ + return daddr >> mp->m_blkbb_log; +} + +static inline xfs_rgnumber_t +xfs_daddr_to_rgno( + struct xfs_mount *mp, + xfs_daddr_t daddr) +{ + xfs_rtblock_t rtb = daddr >> mp->m_blkbb_log; + + return xfs_rtb_to_rgno(mp, rtb); +} + +static inline xfs_rgblock_t +xfs_daddr_to_rgbno( + struct xfs_mount *mp, + xfs_daddr_t daddr) +{ + xfs_rtblock_t rtb = daddr >> mp->m_blkbb_log; + xfs_rgnumber_t rgno; + + return xfs_rtb_to_rgbno(mp, rtb, &rgno); +} + #ifdef CONFIG_XFS_RT xfs_rgblock_t xfs_rtgroup_block_count(struct xfs_mount *mp, xfs_rgnumber_t rgno); diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index 88402cb4a6879..638de2f7c8dc1 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -180,6 +180,8 @@ xfs_sb_version_to_features( features |= XFS_FEAT_PARENT; if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR) features |= XFS_FEAT_METADIR; + if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_RTGROUPS) + features |= XFS_FEAT_RTGROUPS; return features; } @@ -307,6 +309,64 @@ xfs_validate_sb_write( return 0; } +static int +xfs_validate_sb_rtgroups( + struct xfs_mount *mp, + struct xfs_sb *sbp) +{ + uint64_t groups; + + if (!(sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR)) { + xfs_warn(mp, +"Realtime groups require metadata directory tree."); + return -EINVAL; + } + + if (sbp->sb_rgblocks > XFS_MAX_RGBLOCKS) { + xfs_warn(mp, +"Realtime group size (%u) must be less than %u.", + sbp->sb_rgblocks, XFS_MAX_RGBLOCKS); + return -EINVAL; + } + + if (sbp->sb_rextsize == 0) { + xfs_warn(mp, +"Realtime extent size must not be zero."); + return -EINVAL; + } + + if (sbp->sb_rgblocks % sbp->sb_rextsize != 0) { + xfs_warn(mp, +"Realtime group size (%u) must be an even multiple of extent size (%u).", + sbp->sb_rgblocks, sbp->sb_rextsize); + return -EINVAL; + } + + if (sbp->sb_rgblocks < (sbp->sb_rextsize << 1)) { + xfs_warn(mp, +"Realtime group size (%u) must be greater than 1 rt extent.", + sbp->sb_rgblocks); + return -EINVAL; + } + + if (sbp->sb_rgcount > XFS_MAX_RGNUMBER) { + xfs_warn(mp, +"Realtime groups (%u) must be less than %u.", + sbp->sb_rgcount, XFS_MAX_RGNUMBER); + return -EINVAL; + } + + groups = howmany_64(sbp->sb_rblocks, sbp->sb_rgblocks); + if (groups != sbp->sb_rgcount) { + xfs_warn(mp, +"Realtime groups (%u) do not cover the entire rt section; need (%llu) groups.", + sbp->sb_rgcount, groups); + return -EINVAL; + } + + return 0; +} + /* Check the validity of the SB. */ STATIC int xfs_validate_sb_common( @@ -318,6 +378,7 @@ xfs_validate_sb_common( uint32_t agcount = 0; uint32_t rem; bool has_dalign; + int error; if (!xfs_verify_magic(bp, dsb->sb_magicnum)) { xfs_warn(mp, @@ -367,6 +428,12 @@ xfs_validate_sb_common( return -EINVAL; } } + + if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_RTGROUPS) { + error = xfs_validate_sb_rtgroups(mp, sbp); + if (error) + return error; + } } else if (sbp->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD | XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD)) { xfs_notice(mp, @@ -702,8 +769,13 @@ __xfs_sb_from_disk( to->sb_pquotino = NULLFSINO; } - to->sb_rgcount = 0; - to->sb_rgblocks = 0; + if (to->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_RTGROUPS) { + to->sb_rgcount = be32_to_cpu(from->sb_rgcount); + to->sb_rgblocks = be32_to_cpu(from->sb_rgblocks); + } else { + to->sb_rgcount = 0; + to->sb_rgblocks = 0; + } } void @@ -863,6 +935,12 @@ xfs_sb_to_disk( to->sb_gquotino = cpu_to_be64(NULLFSINO); to->sb_pquotino = cpu_to_be64(NULLFSINO); } + + if (from->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_RTGROUPS) { + /* must come after setting to_rsumino */ + to->sb_rgcount = cpu_to_be32(from->sb_rgcount); + to->sb_rgblocks = cpu_to_be32(from->sb_rgblocks); + } } /* @@ -1018,8 +1096,8 @@ xfs_sb_mount_common( mp->m_blockwmask = mp->m_blockwsize - 1; mp->m_rtxblklog = log2_if_power2(sbp->sb_rextsize); mp->m_rtxblkmask = mask64_if_power2(sbp->sb_rextsize); - mp->m_rgblklog = 0; - mp->m_rgblkmask = 0; + mp->m_rgblklog = log2_if_power2(sbp->sb_rgblocks); + mp->m_rgblkmask = mask64_if_power2(sbp->sb_rgblocks); mp->m_alloc_mxr[0] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 1); mp->m_alloc_mxr[1] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 0); diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h index 2cecebe018814..f76d2789e1c2d 100644 --- a/fs/xfs/libxfs/xfs_shared.h +++ b/fs/xfs/libxfs/xfs_shared.h @@ -39,6 +39,7 @@ extern const struct xfs_buf_ops xfs_inode_buf_ra_ops; extern const struct xfs_buf_ops xfs_refcountbt_buf_ops; extern const struct xfs_buf_ops xfs_rmapbt_buf_ops; extern const struct xfs_buf_ops xfs_rtbuf_ops; +extern const struct xfs_buf_ops xfs_rtsb_buf_ops; extern const struct xfs_buf_ops xfs_sb_buf_ops; extern const struct xfs_buf_ops xfs_sb_quiet_buf_ops; extern const struct xfs_buf_ops xfs_symlink_buf_ops; From patchwork Sun Dec 31 21:16:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507599 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 668B9BA34 for ; Sun, 31 Dec 2023 21:16:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="FpZn8kaS" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 39D76C433C7; Sun, 31 Dec 2023 21:16:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704057384; bh=hTnBwbjAGPp3cUhG0nBI7bBdP1hH/Qzze5u5eXauiug=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=FpZn8kaSypib2sNdTL02eq60eeU/ND+AKnGC1PtDyBXEaHuYiZY2RaJh1dpEFpHRc cpILh39z4x13hZxJmC9uhVP6/Y4G1rI38IRQQ4iLv9RrtP+6d2b/yPIjXa+T+kK26N xazF69jezk7SxeNBMBfNunudJLpClCStqVWbKAQ8+nbSFEM8ywLzhtgH6WaEjrxHvI cM5CCqyJtXa3yZNAyLBBdaZnPJiST0RcWPnRp1Rv1OhEBBVrBSiUjulsCKucON+cpg o94uAkumZZQsh/Ic7YT1VDw7PYjDrI4iinyBHHvKktKWbdW1nl1Sr9VGHfwl1yRpgY UJIXQ8PJrjzuw== Date: Sun, 31 Dec 2023 13:16:23 -0800 Subject: [PATCH 03/24] xfs: reduce rt summary file levels for rtgroups filesystems From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404846290.1763124.4226770473396031658.stgit@frogsfrogsfrogs> In-Reply-To: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> References: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong The rt summary file is supposed to be large enough to track the number of log2(rtextentcount) free space extents that start in a given rt bitmap block. Prior to rt groups, there could be a single 2^52 block free extent, which implies a summary file with 53 levels. However, each rtgroup uses its first rt extent to hold a superblock, so there can't be any free extents longer than the length of a group. Groups are limited to 2^32-1 blocks, which means that the longest freespace will be counted in level 31. Hence we only need 32 levels. Adjust the rextslog computation to create smaller rt summary files for rtgroups filesystems. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_format.h | 2 +- fs/xfs/libxfs/xfs_rtbitmap.c | 11 +++++++++++ fs/xfs/libxfs/xfs_rtbitmap.h | 4 ++-- fs/xfs/libxfs/xfs_sb.c | 2 +- fs/xfs/scrub/rtbitmap.c | 2 +- fs/xfs/scrub/rtsummary.c | 2 +- fs/xfs/xfs_rtalloc.c | 5 +++-- 7 files changed, 20 insertions(+), 8 deletions(-) diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index 8debe92571692..43e66740e2aec 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -313,7 +313,7 @@ struct xfs_dsb { #define XFS_SB_VERSION_NUM(sbp) ((sbp)->sb_versionnum & XFS_SB_VERSION_NUMBITS) -static inline bool xfs_sb_is_v5(struct xfs_sb *sbp) +static inline bool xfs_sb_is_v5(const struct xfs_sb *sbp) { return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5; } diff --git a/fs/xfs/libxfs/xfs_rtbitmap.c b/fs/xfs/libxfs/xfs_rtbitmap.c index 795035556c4b4..a8e5c702a7515 100644 --- a/fs/xfs/libxfs/xfs_rtbitmap.c +++ b/fs/xfs/libxfs/xfs_rtbitmap.c @@ -1144,10 +1144,21 @@ xfs_rtbitmap_blockcount( */ uint8_t xfs_compute_rextslog( + const struct xfs_sb *sbp, xfs_rtbxlen_t rtextents) { if (!rtextents) return 0; + + /* + * Realtime groups are never larger than 2^32 extents and are never + * fully free, so we can use highbit32 on the number of rtextents per + * group. + */ + if (xfs_sb_is_v5(sbp) && + (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_RTGROUPS)) + return xfs_highbit32(sbp->sb_rgblocks / sbp->sb_rextsize); + return xfs_highbit64(rtextents); } diff --git a/fs/xfs/libxfs/xfs_rtbitmap.h b/fs/xfs/libxfs/xfs_rtbitmap.h index 6ac17f0195ea1..3de0ec2d24123 100644 --- a/fs/xfs/libxfs/xfs_rtbitmap.h +++ b/fs/xfs/libxfs/xfs_rtbitmap.h @@ -351,7 +351,7 @@ xfs_rtfree_extent( int xfs_rtfree_blocks(struct xfs_trans *tp, xfs_fsblock_t rtbno, xfs_filblks_t rtlen); -uint8_t xfs_compute_rextslog(xfs_rtbxlen_t rtextents); +uint8_t xfs_compute_rextslog(const struct xfs_sb *sbp, xfs_rtbxlen_t rtextents); /* Do we support an rt volume having this number of rtextents? */ static inline bool @@ -396,7 +396,7 @@ void xfs_rtbitmap_unlock_shared(struct xfs_mount *mp, # define xfs_rtsummary_read_buf(a,b) (-ENOSYS) # define xfs_rtbuf_cache_relse(a) (0) # define xfs_rtalloc_extent_is_free(m,t,s,l,i) (-ENOSYS) -# define xfs_compute_rextslog(rtx) (0) +# define xfs_compute_rextslog(sbp, rtx) (0) # define xfs_validate_rtextents(rtx) (false) static inline xfs_filblks_t xfs_rtbitmap_blockcount(struct xfs_mount *mp, xfs_rtbxlen_t rtextents) diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index 638de2f7c8dc1..6a6877c365ae9 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -583,7 +583,7 @@ xfs_validate_sb_common( if (!xfs_validate_rtextents(rexts) || sbp->sb_rextents != rexts || - sbp->sb_rextslog != xfs_compute_rextslog(rexts) || + sbp->sb_rextslog != xfs_compute_rextslog(sbp, rexts) || sbp->sb_rbmblocks != rbmblocks) { xfs_notice(mp, "realtime geometry sanity check failed"); diff --git a/fs/xfs/scrub/rtbitmap.c b/fs/xfs/scrub/rtbitmap.c index c018376256a86..7f910fed7de95 100644 --- a/fs/xfs/scrub/rtbitmap.c +++ b/fs/xfs/scrub/rtbitmap.c @@ -61,7 +61,7 @@ xchk_setup_rtbitmap( */ if (mp->m_sb.sb_rblocks) { rtb->rextents = xfs_rtb_to_rtx(mp, mp->m_sb.sb_rblocks); - rtb->rextslog = xfs_compute_rextslog(rtb->rextents); + rtb->rextslog = xfs_compute_rextslog(&mp->m_sb, rtb->rextents); rtb->rbmblocks = xfs_rtbitmap_blockcount(mp, rtb->rextents); } return 0; diff --git a/fs/xfs/scrub/rtsummary.c b/fs/xfs/scrub/rtsummary.c index 829036b50b0c1..df9aa29cb94c6 100644 --- a/fs/xfs/scrub/rtsummary.c +++ b/fs/xfs/scrub/rtsummary.c @@ -92,7 +92,7 @@ xchk_setup_rtsummary( int rextslog; rts->rextents = xfs_rtb_to_rtx(mp, mp->m_sb.sb_rblocks); - rextslog = xfs_compute_rextslog(rts->rextents); + rextslog = xfs_compute_rextslog(&mp->m_sb, rts->rextents); rts->rsumlevels = rextslog + 1; rts->rbmblocks = xfs_rtbitmap_blockcount(mp, rts->rextents); rsumblocks = xfs_rtsummary_blockcount(mp, rts->rsumlevels, diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 59ded74c9007e..ba9116b6e8de7 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -981,7 +981,7 @@ xfs_growfs_rt( if (!xfs_validate_rtextents(nrextents)) return -EINVAL; nrbmblocks = xfs_rtbitmap_blockcount(mp, nrextents); - nrextslog = xfs_compute_rextslog(nrextents); + nrextslog = xfs_compute_rextslog(&mp->m_sb, nrextents); nrsumlevels = nrextslog + 1; nrsumblocks = xfs_rtsummary_blockcount(mp, nrsumlevels, nrbmblocks); nrsumsize = XFS_FSB_TO_B(mp, nrsumblocks); @@ -1048,7 +1048,8 @@ xfs_growfs_rt( nsbp->sb_rblocks = min(nrblocks, nrblocks_step); nsbp->sb_rextents = xfs_rtb_to_rtx(nmp, nsbp->sb_rblocks); ASSERT(nsbp->sb_rextents != 0); - nsbp->sb_rextslog = xfs_compute_rextslog(nsbp->sb_rextents); + nsbp->sb_rextslog = xfs_compute_rextslog(&mp->m_sb, + nsbp->sb_rextents); nrsumlevels = nmp->m_rsumlevels = nsbp->sb_rextslog + 1; nrsumblocks = xfs_rtsummary_blockcount(mp, nrsumlevels, nsbp->sb_rbmblocks); From patchwork Sun Dec 31 21:16:39 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507600 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 6105DAD25 for ; Sun, 31 Dec 2023 21:16:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="FOnADMMf" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CE13CC433C7; Sun, 31 Dec 2023 21:16:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704057399; bh=/eOJZgW5kCYoIULdBdw7UOfx/TTiccdT7WXC7LMaF9s=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=FOnADMMf3xihcbzOHQ4xvAS1iqtph8WMBqLL5pbmDh58nIp6wuQH/n88aF87ADllm P9/Q6TRkPtZkanFFruiVVBzpjPc+02HuJk0/QPxflqovGyATs/SHIjFbnmh7Fyk1i4 0jb36OU2uekzsA5CNct9cchIkzBP2PJMoDZXqK/HP8cgRFeOAaTkoIDwKyhOt0+y3p EqoEOSuQfyfAyr/+phXk/HymHl9lVx9mr3khjAFQR7km8rHVQbCJANv/UudGA03f+Q vEhd81HSeZdR3hRdPmeyoLWUE7EBS1ba0XovVWV92NCE9WiaSgWv8M4nGWAVxxtfGb GEU+F708T0zIQ== Date: Sun, 31 Dec 2023 13:16:39 -0800 Subject: [PATCH 04/24] xfs: check the realtime superblock at mount time From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404846306.1763124.5318728014535151147.stgit@frogsfrogsfrogs> In-Reply-To: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> References: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Check the realtime superblock at mount time, to ensure that the label actually matches the primary superblock. If the rt superblock is good, attach it to the xfs_mount so that the log can use ordered buffers to keep this primary in sync with the primary super on the data device. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_mount.h | 1 + fs/xfs/xfs_rtalloc.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_rtalloc.h | 5 +++++ fs/xfs/xfs_super.c | 16 ++++++++++++++-- 4 files changed, 70 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 52976a133cec9..7e86aa137d1fa 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -85,6 +85,7 @@ typedef struct xfs_mount { struct super_block *m_super; struct xfs_ail *m_ail; /* fs active log item list */ struct xfs_buf *m_sb_bp; /* buffer for superblock */ + struct xfs_buf *m_rtsb_bp; /* realtime superblock */ char *m_rtname; /* realtime device name */ char *m_logname; /* external log device name */ struct xfs_da_geometry *m_dir_geo; /* directory block geometry */ diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index ba9116b6e8de7..430d63e5ba751 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -1252,6 +1252,56 @@ xfs_rtallocate_extent( return 0; } +/* Read the primary realtime group's superblock and attach it to the mount. */ +int +xfs_rtmount_readsb( + struct xfs_mount *mp) +{ + struct xfs_buf *bp; + int error; + + if (!xfs_has_rtgroups(mp)) + return 0; + if (mp->m_sb.sb_rblocks == 0) + return 0; + if (mp->m_rtdev_targp == NULL) { + xfs_warn(mp, + "Filesystem has a realtime volume, use rtdev=device option"); + return -ENODEV; + } + + /* m_blkbb_log is not set up yet */ + error = xfs_buf_read_uncached(mp->m_rtdev_targp, XFS_RTSB_DADDR, + mp->m_sb.sb_blocksize >> BBSHIFT, XBF_NO_IOACCT, &bp, + &xfs_rtsb_buf_ops); + if (error) { + xfs_warn(mp, "rt sb validate failed with error %d.", error); + /* bad CRC means corrupted metadata */ + if (error == -EFSBADCRC) + error = -EFSCORRUPTED; + return error; + } + + mp->m_rtsb_bp = bp; + xfs_buf_unlock(bp); + return 0; +} + +/* Detach the realtime superblock from the mount and free it. */ +void +xfs_rtmount_freesb( + struct xfs_mount *mp) +{ + struct xfs_buf *bp = mp->m_rtsb_bp; + + if (!bp) + return; + + xfs_buf_lock(bp); + mp->m_rtsb_bp = NULL; + xfs_buf_relse(bp); +} + /* * Initialize realtime fields in the mount structure. */ diff --git a/fs/xfs/xfs_rtalloc.h b/fs/xfs/xfs_rtalloc.h index f7cb9ffe51ca6..b982b97cf073f 100644 --- a/fs/xfs/xfs_rtalloc.h +++ b/fs/xfs/xfs_rtalloc.h @@ -33,6 +33,9 @@ xfs_rtallocate_extent( xfs_rtxnum_t *rtblock); /* out: start rtext allocated */ +int xfs_rtmount_readsb(struct xfs_mount *mp); +void xfs_rtmount_freesb(struct xfs_mount *mp); + /* * Initialize realtime fields in the mount structure. */ @@ -79,6 +82,8 @@ int xfs_rtalloc_reinit_frextents(struct xfs_mount *mp); # define xfs_rtpick_extent(m,t,l,rb) (-ENOSYS) # define xfs_growfs_rt(mp,in) (-ENOSYS) # define xfs_rtalloc_reinit_frextents(m) (0) +# define xfs_rtmount_readsb(mp) (0) +# define xfs_rtmount_freesb(mp) ((void)0) static inline int /* error */ xfs_rtmount_init( xfs_mount_t *mp) /* file system mount structure */ diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index c154e2cb7a18e..f3a5e194c535b 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -45,6 +45,7 @@ #include "xfs_rtbitmap.h" #include "xfs_swapext_item.h" #include "xfs_parent.h" +#include "xfs_rtalloc.h" #include "scrub/stats.h" #include "scrub/rcbag_btree.h" @@ -1152,6 +1153,7 @@ xfs_fs_put_super( xfs_filestream_unmount(mp); xfs_unmountfs(mp); + xfs_rtmount_freesb(mp); xfs_freesb(mp); xchk_mount_stats_free(mp); free_percpu(mp->m_stats.xs_stats); @@ -1671,9 +1673,13 @@ xfs_fs_fill_super( goto out_free_sb; } + error = xfs_rtmount_readsb(mp); + if (error) + goto out_free_sb; + error = xfs_filestream_mount(mp); if (error) - goto out_free_sb; + goto out_free_rtsb; /* * we must configure the block size in the superblock before we run the @@ -1717,6 +1723,10 @@ xfs_fs_fill_super( xfs_warn(mp, "EXPERIMENTAL metadata directory feature in use. Use at your own risk!"); + if (xfs_has_rtgroups(mp)) + xfs_warn(mp, +"EXPERIMENTAL realtime allocation group feature in use. Use at your own risk!"); + if (xfs_has_reflink(mp)) { if (mp->m_sb.sb_rblocks) { xfs_alert(mp, @@ -1761,6 +1771,8 @@ xfs_fs_fill_super( out_filestream_unmount: xfs_filestream_unmount(mp); + out_free_rtsb: + xfs_rtmount_freesb(mp); out_free_sb: xfs_freesb(mp); out_free_scrub_stats: @@ -1780,7 +1792,7 @@ xfs_fs_fill_super( out_unmount: xfs_filestream_unmount(mp); xfs_unmountfs(mp); - goto out_free_sb; + goto out_free_rtsb; } static int From patchwork Sun Dec 31 21:16:55 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507601 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 A429CBA22 for ; Sun, 31 Dec 2023 21:16:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="lsmgR3vR" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6FEC8C433C8; Sun, 31 Dec 2023 21:16:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704057415; bh=CyQ6xe168nReaTvfg3AY7d6MF7LiDCc7WIk2m7/lYHY=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=lsmgR3vR6QQnT32MHXlcb4yop+oynD2y7RcWXCwPSe6iJ7vkmKGaXSy3T333ApsrI JafyMUsoep0k8yBgXIKiIe8sDAStbISOW9VPVuFllzjIq323gCvygPvQnpotyAU7uS PB8hFm3sl+dAt1YvX3i0V0cJivMm7TTarnkcXn8wQgUAa6wt1EoCKPUp6qIyxRiXJQ YlQOEO7VUyVtiC98tas8gjRCmbtSJH972ChBCfLmAhIQjoAbtG1WvvxVk7b02fj/7s SaS5a2N2LAMcRBbB+rNN+taU1lbydhdkm1wASlCr/9Oz6OqN3CO4Cq7v1Bn1AVQ+oY WrrIzRO+Q3c2g== Date: Sun, 31 Dec 2023 13:16:55 -0800 Subject: [PATCH 05/24] xfs: update primary realtime super every time we update the primary fs super From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404846322.1763124.15754856029181407257.stgit@frogsfrogsfrogs> In-Reply-To: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> References: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Every time we update parts of the primary filesystem superblock that are echoed in the primary rt super, we should update that primary realtime super. Avoid an ondisk log format change by using ordered buffers to write the primary rt super. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_rtgroup.c | 74 +++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_rtgroup.h | 6 +++ fs/xfs/libxfs/xfs_sb.c | 13 +++++++ fs/xfs/xfs_buf_item_recover.c | 18 ++++++++++ fs/xfs/xfs_trans.c | 10 ++++++ fs/xfs/xfs_trans.h | 1 + fs/xfs/xfs_trans_buf.c | 25 +++++++++++--- 7 files changed, 142 insertions(+), 5 deletions(-) diff --git a/fs/xfs/libxfs/xfs_rtgroup.c b/fs/xfs/libxfs/xfs_rtgroup.c index a82dd23cf0c79..325e4eb8f8781 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.c +++ b/fs/xfs/libxfs/xfs_rtgroup.c @@ -345,3 +345,77 @@ const struct xfs_buf_ops xfs_rtsb_buf_ops = { .verify_write = xfs_rtsb_write_verify, .verify_struct = xfs_rtsb_verify, }; + +/* Update a realtime superblock from the primary fs super */ +void +xfs_rtgroup_update_super( + struct xfs_buf *rtsb_bp, + const struct xfs_buf *sb_bp) +{ + const struct xfs_dsb *dsb = sb_bp->b_addr; + struct xfs_rtsb *rsb = rtsb_bp->b_addr; + const uuid_t *meta_uuid; + + rsb->rsb_magicnum = cpu_to_be32(XFS_RTSB_MAGIC); + rsb->rsb_blocksize = dsb->sb_blocksize; + rsb->rsb_rblocks = dsb->sb_rblocks; + + rsb->rsb_rextents = dsb->sb_rextents; + rsb->rsb_lsn = 0; + + memcpy(&rsb->rsb_uuid, &dsb->sb_uuid, sizeof(rsb->rsb_uuid)); + + rsb->rsb_rgcount = dsb->sb_rgcount; + memcpy(&rsb->rsb_fname, &dsb->sb_fname, XFSLABEL_MAX); + + rsb->rsb_rextsize = dsb->sb_rextsize; + rsb->rsb_rbmblocks = dsb->sb_rbmblocks; + + rsb->rsb_rgblocks = dsb->sb_rgblocks; + rsb->rsb_blocklog = dsb->sb_blocklog; + rsb->rsb_sectlog = dsb->sb_sectlog; + rsb->rsb_rextslog = dsb->sb_rextslog; + rsb->rsb_pad = 0; + rsb->rsb_pad2 = 0; + + /* + * The metadata uuid is the fs uuid if the metauuid feature is not + * enabled. + */ + if (dsb->sb_features_incompat & + cpu_to_be32(XFS_SB_FEAT_INCOMPAT_META_UUID)) + meta_uuid = &dsb->sb_meta_uuid; + else + meta_uuid = &dsb->sb_uuid; + memcpy(&rsb->rsb_meta_uuid, meta_uuid, sizeof(rsb->rsb_meta_uuid)); +} + +/* + * Update the primary realtime superblock from a filesystem superblock and + * log it to the given transaction. + */ +void +xfs_rtgroup_log_super( + struct xfs_trans *tp, + const struct xfs_buf *sb_bp) +{ + struct xfs_buf *rtsb_bp; + + if (!xfs_has_rtgroups(tp->t_mountp)) + return; + + rtsb_bp = xfs_trans_getrtsb(tp); + if (!rtsb_bp) { + /* + * It's possible for the rtgroups feature to be enabled but + * there is no incore rt superblock buffer if the rt geometry + * was specified at mkfs time but the rt section has not yet + * been attached. In this case, rblocks must be zero. + */ + ASSERT(tp->t_mountp->m_sb.sb_rblocks == 0); + return; + } + + xfs_rtgroup_update_super(rtsb_bp, sb_bp); + xfs_trans_ordered_buf(tp, rtsb_bp); +} diff --git a/fs/xfs/libxfs/xfs_rtgroup.h b/fs/xfs/libxfs/xfs_rtgroup.h index 924c8c95acbc3..83bbd43f7271a 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.h +++ b/fs/xfs/libxfs/xfs_rtgroup.h @@ -208,8 +208,14 @@ xfs_daddr_to_rgbno( #ifdef CONFIG_XFS_RT xfs_rgblock_t xfs_rtgroup_block_count(struct xfs_mount *mp, xfs_rgnumber_t rgno); + +void xfs_rtgroup_update_super(struct xfs_buf *rtsb_bp, + const struct xfs_buf *sb_bp); +void xfs_rtgroup_log_super(struct xfs_trans *tp, const struct xfs_buf *sb_bp); #else # define xfs_rtgroup_block_count(mp, rgno) (0) +# define xfs_rtgroup_update_super(bp, sb_bp) ((void)0) +# define xfs_rtgroup_log_super(tp, sb_bp) ((void)0) #endif /* CONFIG_XFS_RT */ #endif /* __LIBXFS_RTGROUP_H */ diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index 6a6877c365ae9..b37924cf67a93 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -27,6 +27,7 @@ #include "xfs_ag.h" #include "xfs_rtbitmap.h" #include "xfs_swapext.h" +#include "xfs_rtgroup.h" /* * Physical superblock buffer manipulations. Shared with libxfs in userspace. @@ -1161,6 +1162,8 @@ xfs_log_sb( xfs_sb_to_disk(bp->b_addr, &mp->m_sb); xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF); xfs_trans_log_buf(tp, bp, 0, sizeof(struct xfs_dsb) - 1); + + xfs_rtgroup_log_super(tp, bp); } /* @@ -1277,6 +1280,7 @@ xfs_sync_sb_buf( { struct xfs_trans *tp; struct xfs_buf *bp; + struct xfs_buf *rtsb_bp = NULL; int error; error = xfs_trans_alloc(mp, &M_RES(mp)->tr_sb, 0, 0, 0, &tp); @@ -1286,6 +1290,11 @@ xfs_sync_sb_buf( bp = xfs_trans_getsb(tp); xfs_log_sb(tp); xfs_trans_bhold(tp, bp); + if (xfs_has_rtgroups(mp)) { + rtsb_bp = xfs_trans_getrtsb(tp); + if (rtsb_bp) + xfs_trans_bhold(tp, rtsb_bp); + } xfs_trans_set_sync(tp); error = xfs_trans_commit(tp); if (error) @@ -1294,7 +1303,11 @@ xfs_sync_sb_buf( * write out the sb buffer to get the changes to disk */ error = xfs_bwrite(bp); + if (!error && rtsb_bp) + error = xfs_bwrite(rtsb_bp); out: + if (rtsb_bp) + xfs_buf_relse(rtsb_bp); xfs_buf_relse(bp); return error; } diff --git a/fs/xfs/xfs_buf_item_recover.c b/fs/xfs/xfs_buf_item_recover.c index 43167f543afc3..4be9a384dc6f7 100644 --- a/fs/xfs/xfs_buf_item_recover.c +++ b/fs/xfs/xfs_buf_item_recover.c @@ -22,6 +22,7 @@ #include "xfs_inode.h" #include "xfs_dir2.h" #include "xfs_quota.h" +#include "xfs_rtgroup.h" /* * This is the number of entries in the l_buf_cancel_table used during @@ -995,6 +996,23 @@ xlog_recover_buf_commit_pass2( ASSERT(bp->b_mount == mp); bp->b_flags |= _XBF_LOGRECOVERY; xfs_buf_delwri_queue(bp, buffer_list); + + /* + * Update the primary rt super if we just recovered the primary + * fs super. + */ + if (xfs_has_rtgroups(mp) && bp->b_ops == &xfs_sb_buf_ops) { + struct xfs_buf *rtsb_bp = mp->m_rtsb_bp; + + if (rtsb_bp) { + xfs_buf_lock(rtsb_bp); + xfs_buf_hold(rtsb_bp); + xfs_rtgroup_update_super(rtsb_bp, bp); + rtsb_bp->b_flags |= _XBF_LOGRECOVERY; + xfs_buf_delwri_queue(rtsb_bp, buffer_list); + xfs_buf_relse(rtsb_bp); + } + } } out_release: diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 81337fdb89ab8..fab625f64189f 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -25,6 +25,7 @@ #include "xfs_dquot.h" #include "xfs_icache.h" #include "xfs_rtbitmap.h" +#include "xfs_rtgroup.h" struct kmem_cache *xfs_trans_cache; @@ -477,6 +478,7 @@ xfs_trans_apply_sb_deltas( { struct xfs_dsb *sbp; struct xfs_buf *bp; + bool update_rtsb = false; int whole = 0; bp = xfs_trans_getsb(tp); @@ -537,22 +539,27 @@ xfs_trans_apply_sb_deltas( if (tp->t_rextsize_delta) { be32_add_cpu(&sbp->sb_rextsize, tp->t_rextsize_delta); whole = 1; + update_rtsb = true; } if (tp->t_rbmblocks_delta) { be32_add_cpu(&sbp->sb_rbmblocks, tp->t_rbmblocks_delta); whole = 1; + update_rtsb = true; } if (tp->t_rblocks_delta) { be64_add_cpu(&sbp->sb_rblocks, tp->t_rblocks_delta); whole = 1; + update_rtsb = true; } if (tp->t_rextents_delta) { be64_add_cpu(&sbp->sb_rextents, tp->t_rextents_delta); whole = 1; + update_rtsb = true; } if (tp->t_rextslog_delta) { sbp->sb_rextslog += tp->t_rextslog_delta; whole = 1; + update_rtsb = true; } xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF); @@ -569,6 +576,9 @@ xfs_trans_apply_sb_deltas( xfs_trans_log_buf(tp, bp, offsetof(struct xfs_dsb, sb_icount), offsetof(struct xfs_dsb, sb_frextents) + sizeof(sbp->sb_frextents) - 1); + + if (update_rtsb) + xfs_rtgroup_log_super(tp, bp); } /* diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 3cffc3cb41814..f3ddb05f3bcc6 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -212,6 +212,7 @@ xfs_trans_read_buf( } struct xfs_buf *xfs_trans_getsb(struct xfs_trans *); +struct xfs_buf *xfs_trans_getrtsb(struct xfs_trans *tp); void xfs_trans_brelse(xfs_trans_t *, struct xfs_buf *); void xfs_trans_bjoin(xfs_trans_t *, struct xfs_buf *); diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index e28ab74af4f0e..8e886ecfd69a3 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c @@ -168,12 +168,11 @@ xfs_trans_get_buf_map( /* * Get and lock the superblock buffer for the given transaction. */ -struct xfs_buf * -xfs_trans_getsb( - struct xfs_trans *tp) +static struct xfs_buf * +__xfs_trans_getsb( + struct xfs_trans *tp, + struct xfs_buf *bp) { - struct xfs_buf *bp = tp->t_mountp->m_sb_bp; - /* * Just increment the lock recursion count if the buffer is already * attached to this transaction. @@ -197,6 +196,22 @@ xfs_trans_getsb( return bp; } +struct xfs_buf * +xfs_trans_getsb( + struct xfs_trans *tp) +{ + return __xfs_trans_getsb(tp, tp->t_mountp->m_sb_bp); +} + +struct xfs_buf * +xfs_trans_getrtsb( + struct xfs_trans *tp) +{ + if (!tp->t_mountp->m_rtsb_bp) + return NULL; + return __xfs_trans_getsb(tp, tp->t_mountp->m_rtsb_bp); +} + /* * Get and lock the buffer for the caller if it is not already * locked within the given transaction. If it has not yet been From patchwork Sun Dec 31 21:17:10 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507602 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 45CF1BA22 for ; Sun, 31 Dec 2023 21:17:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="s0woDowL" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 17FBFC433C7; Sun, 31 Dec 2023 21:17:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704057431; bh=4ul8+N48oPnBfqmSTe1PlrQkXMcQfb9UIE8FH7ykL60=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=s0woDowLYNMpTudGz3jDF+yCxWxPhkUzIwodyjPWcr5j3UFUKnouIQs1/YjLCZnga Gn2EFQ74soDEkNrbErTHh92mCftEVw4oD3NQUKYIgZ77osEgVkmpfbaYDETXOiL+gd hHLQQaJnKAnc08ySCj3m0TCWvVD+c0Z2OygTsFYUFduhPwqkXjY44hZB7ZBRonTp41 FFhm1ZqEF4sV4RXGucoslClYDi0mGZA0oHxxe1oTqNdjR3hTZB5zWENYAKswMuXzZm 9MHOKN2GTJnyMI8QGqoyY9F3aPekNu0tR4AvU8NZSzyBFkVq3shgpEc47vxzfPr8BK JxbW+s21TyYew== Date: Sun, 31 Dec 2023 13:17:10 -0800 Subject: [PATCH 06/24] xfs: write secondary realtime superblocks to disk From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404846338.1763124.14677859962621212096.stgit@frogsfrogsfrogs> In-Reply-To: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> References: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 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 library functions to make it easy to update all the secondary realtime superblocks on disk; this will be used by growfs, xfs_db, mkfs, and xfs_repair. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_rtgroup.c | 117 +++++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_rtgroup.h | 2 + 2 files changed, 119 insertions(+) diff --git a/fs/xfs/libxfs/xfs_rtgroup.c b/fs/xfs/libxfs/xfs_rtgroup.c index 325e4eb8f8781..173297f582e00 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.c +++ b/fs/xfs/libxfs/xfs_rtgroup.c @@ -419,3 +419,120 @@ xfs_rtgroup_log_super( xfs_rtgroup_update_super(rtsb_bp, sb_bp); xfs_trans_ordered_buf(tp, rtsb_bp); } + +/* Initialize a secondary realtime superblock. */ +static int +xfs_rtgroup_init_secondary_super( + struct xfs_mount *mp, + xfs_rgnumber_t rgno, + struct xfs_buf **bpp) +{ + struct xfs_buf *bp; + struct xfs_rtsb *rsb; + xfs_rtblock_t rtbno; + int error; + + ASSERT(rgno != 0); + + error = xfs_buf_get_uncached(mp->m_rtdev_targp, XFS_FSB_TO_BB(mp, 1), + 0, &bp); + if (error) + return error; + + rtbno = xfs_rgbno_to_rtb(mp, rgno, 0); + bp->b_maps[0].bm_bn = xfs_rtb_to_daddr(mp, rtbno); + bp->b_ops = &xfs_rtsb_buf_ops; + xfs_buf_zero(bp, 0, BBTOB(bp->b_length)); + + rsb = bp->b_addr; + rsb->rsb_magicnum = cpu_to_be32(XFS_RTSB_MAGIC); + rsb->rsb_blocksize = cpu_to_be32(mp->m_sb.sb_blocksize); + rsb->rsb_rblocks = cpu_to_be64(mp->m_sb.sb_rblocks); + + rsb->rsb_rextents = cpu_to_be64(mp->m_sb.sb_rextents); + + memcpy(&rsb->rsb_uuid, &mp->m_sb.sb_uuid, sizeof(rsb->rsb_uuid)); + + rsb->rsb_rgcount = cpu_to_be32(mp->m_sb.sb_rgcount); + memcpy(&rsb->rsb_fname, &mp->m_sb.sb_fname, XFSLABEL_MAX); + + rsb->rsb_rextsize = cpu_to_be32(mp->m_sb.sb_rextsize); + rsb->rsb_rbmblocks = cpu_to_be32(mp->m_sb.sb_rbmblocks); + + rsb->rsb_rgblocks = cpu_to_be32(mp->m_sb.sb_rgblocks); + rsb->rsb_blocklog = mp->m_sb.sb_blocklog; + rsb->rsb_sectlog = mp->m_sb.sb_sectlog; + rsb->rsb_rextslog = mp->m_sb.sb_rextslog; + + memcpy(&rsb->rsb_meta_uuid, &mp->m_sb.sb_meta_uuid, + sizeof(rsb->rsb_meta_uuid)); + + *bpp = bp; + return 0; +} + +/* + * Update all the realtime superblocks to match the new state of the primary. + * Because we are completely overwriting all the existing fields in the + * secondary superblock buffers, there is no need to read them in from disk. + * Just get a new buffer, stamp it and write it. + * + * The rt super buffers do not need to be kept them in memory once they are + * written so we mark them as a one-shot buffer. + */ +int +xfs_rtgroup_update_secondary_sbs( + struct xfs_mount *mp) +{ + LIST_HEAD (buffer_list); + struct xfs_rtgroup *rtg; + xfs_rgnumber_t start_rgno = 1; + int saved_error = 0; + int error = 0; + + for_each_rtgroup_from(mp, start_rgno, rtg) { + struct xfs_buf *bp; + + error = xfs_rtgroup_init_secondary_super(mp, rtg->rtg_rgno, + &bp); + /* + * If we get an error reading or writing alternate superblocks, + * continue. If we break early, we'll leave more superblocks + * un-updated than updated. + */ + if (error) { + xfs_warn(mp, + "error allocating secondary superblock for rt group %d", + rtg->rtg_rgno); + if (!saved_error) + saved_error = error; + continue; + } + + xfs_buf_oneshot(bp); + xfs_buf_delwri_queue(bp, &buffer_list); + xfs_buf_relse(bp); + + /* don't hold too many buffers at once */ + if (rtg->rtg_rgno % 16) + continue; + + error = xfs_buf_delwri_submit(&buffer_list); + if (error) { + xfs_warn(mp, + "write error %d updating a secondary superblock near rt group %u", + error, rtg->rtg_rgno); + if (!saved_error) + saved_error = error; + continue; + } + } + error = xfs_buf_delwri_submit(&buffer_list); + if (error) { + xfs_warn(mp, + "write error %d updating a secondary superblock near rt group %u", + error, start_rgno); + } + + return saved_error ? saved_error : error; +} diff --git a/fs/xfs/libxfs/xfs_rtgroup.h b/fs/xfs/libxfs/xfs_rtgroup.h index 83bbd43f7271a..2d0422c6712da 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.h +++ b/fs/xfs/libxfs/xfs_rtgroup.h @@ -212,10 +212,12 @@ xfs_rgblock_t xfs_rtgroup_block_count(struct xfs_mount *mp, void xfs_rtgroup_update_super(struct xfs_buf *rtsb_bp, const struct xfs_buf *sb_bp); void xfs_rtgroup_log_super(struct xfs_trans *tp, const struct xfs_buf *sb_bp); +int xfs_rtgroup_update_secondary_sbs(struct xfs_mount *mp); #else # define xfs_rtgroup_block_count(mp, rgno) (0) # define xfs_rtgroup_update_super(bp, sb_bp) ((void)0) # define xfs_rtgroup_log_super(tp, sb_bp) ((void)0) +# define xfs_rtgroup_update_secondary_sbs(mp) (0) #endif /* CONFIG_XFS_RT */ #endif /* __LIBXFS_RTGROUP_H */ From patchwork Sun Dec 31 21:17:26 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507603 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 5469FBA22 for ; Sun, 31 Dec 2023 21:17:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="r5qA56yt" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CBC13C433C7; Sun, 31 Dec 2023 21:17:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704057446; bh=ocFZXlM/xyYgtYZiF1K/P4uEfPCT/oYOA4/8oW1E+SI=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=r5qA56ytkzr5Tv8t/1plzvmR7kd/VY1xfnVZGwdsQKorM03yQRJaVHjTQlenC25Sj 2hRVmiSFccOydx5Og9EJi5Ulswb7iqjMP/FMHP+mkG/iGKf+wqMY2ufmMYpOPvpMXH gx/nrH6Fjpc18zZrAW58cKEkxKhayOdVQsXi9QdPy0MnjIF34siDFHmPzDAo84RH1s mmr2X37gd9gINmySkFRVMQ25T1VQPwVOgolYiBdOpxhuly10Pr4p5VkuEYzAZ85uLw bI492rIMnjOaR13uGMBYyW7MZQr2E6dsqp2w0HncrEwKq5Rr8maypVmbQeWGWnEaVb zOkbuE9rvuKgQ== Date: Sun, 31 Dec 2023 13:17:26 -0800 Subject: [PATCH 07/24] xfs: grow the realtime section when realtime groups are enabled From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404846354.1763124.8063727469645216799.stgit@frogsfrogsfrogs> In-Reply-To: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> References: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Enable growing the rt section when realtime groups are enabled. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_shared.h | 1 fs/xfs/xfs_rtalloc.c | 136 +++++++++++++++++++++++++++++++++++++++++++- fs/xfs/xfs_trans.c | 10 +++ fs/xfs/xfs_trans.h | 1 4 files changed, 144 insertions(+), 4 deletions(-) diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h index f76d2789e1c2d..65691af0488e7 100644 --- a/fs/xfs/libxfs/xfs_shared.h +++ b/fs/xfs/libxfs/xfs_shared.h @@ -111,6 +111,7 @@ void xfs_log_get_max_trans_res(struct xfs_mount *mp, #define XFS_TRANS_SB_RBLOCKS 0x00000800 #define XFS_TRANS_SB_REXTENTS 0x00001000 #define XFS_TRANS_SB_REXTSLOG 0x00002000 +#define XFS_TRANS_SB_RGCOUNT 0x00004000 /* * Here we centralize the specification of XFS meta-data buffer reference count diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 430d63e5ba751..23a15700d3596 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -902,6 +902,88 @@ xfs_alloc_rsum_cache( * Visible (exported) functions. */ +static int +xfs_growfs_rt_free_new( + struct xfs_mount *mp, + struct xfs_rtalloc_args *nargs, + xfs_rtbxlen_t *freed_rtx) +{ + struct xfs_mount *nmp = nargs->mp; + struct xfs_sb *sbp = &mp->m_sb; + struct xfs_sb *nsbp = &nmp->m_sb; + xfs_rtblock_t rtbno, next_rtbno; + int error = 0; + + if (!xfs_has_rtgroups(mp)) { + *freed_rtx = nsbp->sb_rextents - sbp->sb_rextents; + return xfs_rtfree_range(nargs, sbp->sb_rextents, *freed_rtx); + } + + *freed_rtx = 0; + + rtbno = xfs_rtx_to_rtb(nmp, sbp->sb_rextents); + next_rtbno = xfs_rtx_to_rtb(nmp, nsbp->sb_rextents); + while (rtbno < next_rtbno) { + xfs_rtxnum_t start_rtx, next_rtx; + xfs_rtblock_t next_free_rtbno; + xfs_rgnumber_t rgno; + xfs_rgblock_t rgbno; + + /* + * Compute the first new extent that we want to free, being + * careful to skip past a realtime superblock at the start of + * the new region. + */ + rgbno = xfs_rtb_to_rgbno(nmp, rtbno, &rgno); + if (rgbno == 0) { + rtbno += nsbp->sb_rextsize; + if (rtbno >= next_rtbno) + break; + } + + start_rtx = xfs_rtb_to_rtx(nmp, rtbno); + + /* + * Stop freeing either at the end of the new rt section or at + * the start of the next realtime group. + */ + next_free_rtbno = xfs_rgbno_to_rtb(nmp, rgno + 1, 0); + next_rtx = xfs_rtb_to_rtx(nmp, next_free_rtbno); + next_rtx = min(next_rtx, nsbp->sb_rextents); + + *freed_rtx += next_rtx - start_rtx; + error = xfs_rtfree_range(nargs, start_rtx, + next_rtx - start_rtx); + if (error) + break; + + rtbno = next_free_rtbno; + } + + return error; +} + +static int +xfs_growfs_rt_init_primary( + struct xfs_mount *mp) +{ + struct xfs_buf *rtsb_bp; + int error; + + error = xfs_buf_get_uncached(mp->m_rtdev_targp, XFS_FSB_TO_BB(mp, 1), + 0, &rtsb_bp); + if (error) + return error; + + rtsb_bp->b_maps[0].bm_bn = XFS_RTSB_DADDR; + rtsb_bp->b_ops = &xfs_rtsb_buf_ops; + + xfs_rtgroup_update_super(rtsb_bp, mp->m_sb_bp); + mp->m_rtsb_bp = rtsb_bp; + xfs_buf_unlock(rtsb_bp); + return 0; +} + /* * Grow the realtime area of the filesystem. */ @@ -992,6 +1074,35 @@ xfs_growfs_rt( */ if (nrsumblocks > (mp->m_sb.sb_logblocks >> 1)) return -EINVAL; + + /* Allocate the new rt group structures */ + if (xfs_has_rtgroups(mp)) { + uint64_t new_rgcount; + + new_rgcount = howmany_64(nrblocks, mp->m_sb.sb_rgblocks); + if (new_rgcount > XFS_MAX_RGNUMBER) + return -EINVAL; + + /* + * We don't support changing the group size to match the extent + * size, even if the size of the rt section is currently zero. + */ + if (mp->m_sb.sb_rgblocks % in->extsize != 0) + return -EOPNOTSUPP; + + if (mp->m_sb.sb_rblocks == 0) { + error = xfs_growfs_rt_init_primary(mp); + if (error) + return error; + } + + if (new_rgcount > mp->m_sb.sb_rgcount) { + error = xfs_initialize_rtgroups(mp, new_rgcount); + if (error) + return error; + } + } + /* * Get the old block counts for bitmap and summary inodes. * These can't change since other growfs callers are locked out. @@ -1033,7 +1144,10 @@ xfs_growfs_rt( .mp = nmp, }; struct xfs_trans *tp; + struct xfs_rtgroup *rtg; xfs_rfsblock_t nrblocks_step; + xfs_rtbxlen_t freed_rtx = 0; + xfs_rgnumber_t last_rgno = mp->m_sb.sb_rgcount - 1; *nmp = *mp; nsbp = &nmp->m_sb; @@ -1057,6 +1171,10 @@ xfs_growfs_rt( /* recompute growfsrt reservation from new rsumsize */ xfs_trans_resv_calc(nmp, &nmp->m_resv); + if (xfs_has_rtgroups(mp)) + nsbp->sb_rgcount = howmany_64(nsbp->sb_rblocks, + nsbp->sb_rgblocks); + /* * Start a transaction, get the log reservation. */ @@ -1099,6 +1217,7 @@ xfs_growfs_rt( if (error) goto error_cancel; } + /* * Update superblock fields. */ @@ -1117,11 +1236,13 @@ xfs_growfs_rt( if (nsbp->sb_rextslog != sbp->sb_rextslog) xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTSLOG, nsbp->sb_rextslog - sbp->sb_rextslog); + if (nsbp->sb_rgcount != sbp->sb_rgcount) + xfs_trans_mod_sb(tp, XFS_TRANS_SB_RGCOUNT, + nsbp->sb_rgcount - sbp->sb_rgcount); /* * Free new extent. */ - error = xfs_rtfree_range(&nargs, sbp->sb_rextents, - nsbp->sb_rextents - sbp->sb_rextents); + error = xfs_growfs_rt_free_new(mp, &nargs, &freed_rtx); xfs_rtbuf_cache_relse(&nargs); if (error) { error_cancel: @@ -1131,8 +1252,7 @@ xfs_growfs_rt( /* * Mark more blocks free in the superblock. */ - xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, - nsbp->sb_rextents - sbp->sb_rextents); + xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, freed_rtx); /* * Update mp values into the real mp structure. */ @@ -1145,6 +1265,10 @@ xfs_growfs_rt( if (error) break; + for_each_rtgroup_from(mp, last_rgno, rtg) + rtg->rtg_blockcount = xfs_rtgroup_block_count(mp, + rtg->rtg_rgno); + /* Ensure the mount RT feature flag is now set. */ mp->m_features |= XFS_FEAT_REALTIME; } @@ -1153,6 +1277,10 @@ xfs_growfs_rt( /* Update secondary superblocks now the physical grow has completed */ error = xfs_update_secondary_sbs(mp); + if (error) + goto out_free; + + error = xfs_rtgroup_update_secondary_sbs(mp); out_free: /* diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index fab625f64189f..1eaf32422bf66 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -456,6 +456,10 @@ xfs_trans_mod_sb( case XFS_TRANS_SB_REXTSLOG: tp->t_rextslog_delta += delta; break; + case XFS_TRANS_SB_RGCOUNT: + ASSERT(delta > 0); + tp->t_rgcount_delta += delta; + break; default: ASSERT(0); return; @@ -561,6 +565,11 @@ xfs_trans_apply_sb_deltas( whole = 1; update_rtsb = true; } + if (tp->t_rgcount_delta) { + be32_add_cpu(&sbp->sb_rgcount, tp->t_rgcount_delta); + whole = 1; + update_rtsb = true; + } xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF); if (whole) @@ -674,6 +683,7 @@ xfs_trans_unreserve_and_mod_sb( mp->m_sb.sb_rblocks += tp->t_rblocks_delta; mp->m_sb.sb_rextents += tp->t_rextents_delta; mp->m_sb.sb_rextslog += tp->t_rextslog_delta; + mp->m_sb.sb_rgcount += tp->t_rgcount_delta; spin_unlock(&mp->m_sb_lock); /* diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index f3ddb05f3bcc6..2046ee06fe88f 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -146,6 +146,7 @@ typedef struct xfs_trans { int64_t t_rblocks_delta;/* superblock rblocks change */ int64_t t_rextents_delta;/* superblocks rextents chg */ int64_t t_rextslog_delta;/* superblocks rextslog chg */ + int64_t t_rgcount_delta; /* realtime group count */ struct list_head t_items; /* log item descriptors */ struct list_head t_busy; /* list of busy extents */ struct list_head t_dfops; /* deferred operations */ From patchwork Sun Dec 31 21:17:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507604 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 02B2EBA2E for ; Sun, 31 Dec 2023 21:17:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hn5FE5Rp" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7B482C433C7; Sun, 31 Dec 2023 21:17:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704057462; bh=/TiEWYYItZwvncszQPXShr4QjodL6ZvOgMNItBghsvA=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=hn5FE5RpttY85FXclefjVzNRZNOtwRKB7BvK5GluBcC+kSwmDTkNuJ/EvDzxN/DGD TBuaMu+bp/V1T5tP4mnyFbcwAcFcyTOaLPeO7gQWOu2azXF8BRYlnWX/gxEmSYFtWd H+YEOuT63jHcwmz2lLzYKuJwnG/eOAidR2453nvl/MHYFnekKVNaP3qjOUuT94p48p +Ua9anTG/xYN1QFZRZ5Y79vwW1RJTLC1fqTSdShQNdflgwpYegx6h9yGjs0s+TrKhL GsV3YxwnhXGq2lvzKS+vcGNEIonZCV4urpnwJs/hqCpx3Mq//1Q8rXvQB5loge5Aum DQR/rAO09N+LA== Date: Sun, 31 Dec 2023 13:17:41 -0800 Subject: [PATCH 08/24] xfs: always update secondary rt supers when we update secondary fs supers From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404846370.1763124.5031203573820391747.stgit@frogsfrogsfrogs> In-Reply-To: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> References: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 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 any update to the secondary superblocks in the data section are also echoed to the secondary superblocks in the realtime section. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_fsops.c | 4 ++++ fs/xfs/xfs_ioctl.c | 3 +++ 2 files changed, 7 insertions(+) diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 80811d16dde00..84b311bd185af 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -21,6 +21,7 @@ #include "xfs_ag.h" #include "xfs_ag_resv.h" #include "xfs_trace.h" +#include "xfs_rtgroup.h" /* * Write new AG headers to disk. Non-transactional, but need to be @@ -319,6 +320,9 @@ xfs_growfs_data( /* Update secondary superblocks now the physical grow has completed */ error = xfs_update_secondary_sbs(mp); + if (error) + goto out_error; + error = xfs_rtgroup_update_secondary_sbs(mp); out_error: /* diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index a887c1d5d69fb..b140f7ed916c9 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -42,6 +42,7 @@ #include "xfs_rtbitmap.h" #include "xfs_xchgrange.h" #include "xfs_file.h" +#include "xfs_rtgroup.h" #include #include @@ -1874,6 +1875,8 @@ xfs_ioc_setlabel( */ mutex_lock(&mp->m_growlock); error = xfs_update_secondary_sbs(mp); + if (!error) + error = xfs_rtgroup_update_secondary_sbs(mp); mutex_unlock(&mp->m_growlock); invalidate_bdev(bdev); From patchwork Sun Dec 31 21:17:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507605 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 AC7BEBA22 for ; Sun, 31 Dec 2023 21:17:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="MpLeZXuW" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2CE51C433C7; Sun, 31 Dec 2023 21:17:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704057478; bh=Yb/y8uzEQq10qTquGSS8shy6v+pwFMRsesAUu7c20+Y=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=MpLeZXuWwykVbQgdBCct4NSNjEVqnksUJCYWaSpAUASi+etA0jRfzeQtzTxWCggxr 61ZSdvLXa5/xOnzfEiK/GVf6hmg7rFx8bm0QcImYblb6SYmkJuzCFZbdAVNOIMaBdk EYFFUt1heLmKOcYSqoHt80COroNChATtEtVhWcVJ/IhIPK7rdJH8BcAtHoaURYSoyU wcOP/Ysaeg5Hu5T5Xb6fgZFHkmrIinRNDIbIOiaQARswM/Bcg72ZGRn6b8/kLZ4KeP Dimm4Ya47XV1KYw4XSekSQHyR2163AA5p5zg4i/SD/a5kJNHAbGic0CALhspvwqfxj lVMc8Is01PqMg== Date: Sun, 31 Dec 2023 13:17:57 -0800 Subject: [PATCH 09/24] xfs: export realtime group geometry via XFS_FSOP_GEOM From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404846385.1763124.16362358589721884777.stgit@frogsfrogsfrogs> In-Reply-To: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> References: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Export the realtime geometry information so that userspace can query it. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_fs.h | 4 +++- fs/xfs/libxfs/xfs_sb.c | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index a0efcbde5ae60..bae9ef924bf59 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -186,7 +186,9 @@ struct xfs_fsop_geom { __u32 logsunit; /* log stripe unit, bytes */ uint32_t sick; /* o: unhealthy fs & rt metadata */ uint32_t checked; /* o: checked fs & rt metadata */ - __u64 reserved[17]; /* reserved space */ + __u32 rgblocks; /* rtblocks in a realtime group */ + __u32 rgcount; /* number of realtime groups */ + __u64 reserved[16]; /* reserved space */ }; #define XFS_FSOP_GEOM_SICK_COUNTERS (1 << 0) /* summary counters */ diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index b37924cf67a93..cf94417aa9faa 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -1411,6 +1411,11 @@ xfs_fs_geometry( return; geo->version = XFS_FSOP_GEOM_VERSION_V5; + + if (xfs_has_rtgroups(mp)) { + geo->rgcount = sbp->sb_rgcount; + geo->rgblocks = sbp->sb_rgblocks; + } } /* Read a secondary superblock. */ From patchwork Sun Dec 31 21:18:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507606 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 0C31DBA22 for ; Sun, 31 Dec 2023 21:18:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Ms8gpQov" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C7D34C433C8; Sun, 31 Dec 2023 21:18:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704057493; bh=Af8az1MLCxvemrSWEZ6nt+e/5KVZA0sD5MwWmAYUaRg=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=Ms8gpQovNSjaIMkuD2KrEF8FInEy+aFuOLXmMMfEP+D52TynAU94XyGUN3HX6YUeQ JoUssiDAtHRoYsg5/UmF2Drp8UlaDFeRtYMroONXuXy2tJ4+JjrzGKwoVTNOJ7r3UM aJeBsy2FyzUFZKemMqYTe5WwMjI3pSWHngwzaCQkxgQmcSqDW3G8zXcO+cnViLg8SX gsUCbqOWVpXsHjpr75IPa6IXvnzfuIT7haKWPu97w+CKGsgh1w8XFyTgQGQ06mU9nP esypf4dI74R9f8mSgWxvKwYfF6rqjqJy0w/GAtYOy582mB1SiEYbMM5d4EA+DEXvRa ARs/gKyVXYV1Q== Date: Sun, 31 Dec 2023 13:18:13 -0800 Subject: [PATCH 10/24] xfs: check that rtblock extents do not overlap with the rt group metadata From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404846401.1763124.10399457109318187719.stgit@frogsfrogsfrogs> In-Reply-To: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> References: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong The ondisk format specifies that the start of each realtime group must have a superblock so that rt space mappings never cross an rtgroup boundary. Check that rt block pointers obey this. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_types.c | 46 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/fs/xfs/libxfs/xfs_types.c b/fs/xfs/libxfs/xfs_types.c index b1fa715e5f398..34d02b2bfdd16 100644 --- a/fs/xfs/libxfs/xfs_types.c +++ b/fs/xfs/libxfs/xfs_types.c @@ -13,6 +13,8 @@ #include "xfs_mount.h" #include "xfs_ag.h" #include "xfs_imeta.h" +#include "xfs_rtbitmap.h" +#include "xfs_rtgroup.h" /* @@ -133,6 +135,26 @@ xfs_verify_dir_ino( return xfs_verify_ino(mp, ino); } +/* + * Verify that an rtgroup block number pointer neither points outside the + * rtgroup nor points at static metadata. + */ +static inline bool +xfs_verify_rgno_rgbno( + struct xfs_mount *mp, + xfs_rgnumber_t rgno, + xfs_rgblock_t rgbno) +{ + xfs_rgblock_t eorg; + + eorg = xfs_rtgroup_block_count(mp, rgno); + if (rgbno >= eorg) + return false; + if (rgbno < mp->m_sb.sb_rextsize) + return false; + return true; +} + /* * Verify that an realtime block number pointer doesn't point off the * end of the realtime device. @@ -142,7 +164,20 @@ xfs_verify_rtbno( struct xfs_mount *mp, xfs_rtblock_t rtbno) { - return rtbno < mp->m_sb.sb_rblocks; + xfs_rgnumber_t rgno; + xfs_rgblock_t rgbno; + + if (rtbno >= mp->m_sb.sb_rblocks) + return false; + + if (!xfs_has_rtgroups(mp)) + return true; + + rgbno = xfs_rtb_to_rgbno(mp, rtbno, &rgno); + if (rgno >= mp->m_sb.sb_rgcount) + return false; + + return xfs_verify_rgno_rgbno(mp, rgno, rgbno); } /* Verify that a realtime device extent is fully contained inside the volume. */ @@ -158,7 +193,14 @@ xfs_verify_rtbext( if (!xfs_verify_rtbno(mp, rtbno)) return false; - return xfs_verify_rtbno(mp, rtbno + len - 1); + if (!xfs_verify_rtbno(mp, rtbno + len - 1)) + return false; + + if (xfs_has_rtgroups(mp) && + xfs_rtb_to_rgno(mp, rtbno) != xfs_rtb_to_rgno(mp, rtbno + len - 1)) + return false; + + return true; } /* Calculate the range of valid icount values. */ From patchwork Sun Dec 31 21:18:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507607 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 B3E17BA2B for ; Sun, 31 Dec 2023 21:18:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="DDeaSkIZ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7F4C9C433C7; Sun, 31 Dec 2023 21:18:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704057509; bh=SnOyY19T959CG09L7R9Nip3ljHw5aPePNAVvannmheo=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=DDeaSkIZeCBXs894pP9/+kTb3MA7Z76Qdv+hX8WLr0JxFBivijqICztXlzzXd4ynf z1IYnAJ74QX7Fu87B/gxqg+/vVd4i43OvRZiDvtSiqmPDNMBVBr9Z8yKgbpRtYe/uM SJWTk/mM60sfbP5GPKAOnk4Oc/w5trREuNXH0K2kYbXZt4GTUoZCUnXNYPiBBdA29A kg/T/AbeLD/j67ns7WiRSBXL8CYKK1iQGNO4SBJNCJc3+lYfTY5usth9YvJ3KQCWWQ IqBtqnntoxoiPiSn77H6zdGyIXzl67VHDvX/sHDBeZbf/dh/7+bFQcfci4yLsKLKa2 PLRkZ4zKuts3Q== Date: Sun, 31 Dec 2023 13:18:29 -0800 Subject: [PATCH 11/24] xfs: add frextents to the lazysbcounters when rtgroups enabled From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404846417.1763124.7673702968469339561.stgit@frogsfrogsfrogs> In-Reply-To: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> References: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 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 the free rt extent count a part of the lazy sb counters when the realtime groups feature is enabled. This is possible because the patch to recompute frextents from the rtbitmap during log recovery predates the code adding rtgroup support, hence we know that the value will always be correct during runtime. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_sb.c | 5 +++++ fs/xfs/xfs_trans.c | 18 +++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index cf94417aa9faa..da20189bbe199 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -1150,6 +1150,9 @@ xfs_log_sb( * sb counters, despite having a percpu counter. It is always kept * consistent with the ondisk rtbitmap by xfs_trans_apply_sb_deltas() * and hence we don't need have to update it here. + * + * sb_frextents was added to the lazy sb counters when the rt groups + * feature was introduced. */ if (xfs_has_lazysbcount(mp)) { mp->m_sb.sb_icount = percpu_counter_sum(&mp->m_icount); @@ -1158,6 +1161,8 @@ xfs_log_sb( mp->m_sb.sb_icount); mp->m_sb.sb_fdblocks = percpu_counter_sum(&mp->m_fdblocks); } + if (xfs_has_rtgroups(mp)) + mp->m_sb.sb_frextents = percpu_counter_sum(&mp->m_frextents); xfs_sb_to_disk(bp->b_addr, &mp->m_sb); xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF); diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 1eaf32422bf66..d4952be8f2498 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -421,6 +421,8 @@ xfs_trans_mod_sb( ASSERT(tp->t_rtx_res_used <= tp->t_rtx_res); } tp->t_frextents_delta += delta; + if (xfs_has_rtgroups(mp)) + flags &= ~XFS_TRANS_SB_DIRTY; break; case XFS_TRANS_SB_RES_FREXTENTS: /* @@ -515,8 +517,14 @@ xfs_trans_apply_sb_deltas( * * Don't touch m_frextents because it includes incore reservations, * and those are handled by the unreserve function. + * + * sb_frextents was added to the lazy sb counters when the rt groups + * feature was introduced. This is possible because we know that all + * kernels supporting rtgroups will also recompute frextents from the + * realtime bitmap. */ - if (tp->t_frextents_delta || tp->t_res_frextents_delta) { + if ((tp->t_frextents_delta || tp->t_res_frextents_delta) && + !xfs_has_rtgroups(tp->t_mountp)) { struct xfs_mount *mp = tp->t_mountp; int64_t rtxdelta; @@ -630,7 +638,8 @@ xfs_trans_unreserve_and_mod_sb( if (tp->t_rtx_res > 0) rtxdelta = tp->t_rtx_res; if ((tp->t_frextents_delta != 0) && - (tp->t_flags & XFS_TRANS_SB_DIRTY)) + (xfs_has_rtgroups(mp) || + (tp->t_flags & XFS_TRANS_SB_DIRTY))) rtxdelta += tp->t_frextents_delta; if (xfs_has_lazysbcount(mp) || @@ -669,8 +678,11 @@ xfs_trans_unreserve_and_mod_sb( * Do not touch sb_frextents here because we are dealing with incore * reservation. sb_frextents is not part of the lazy sb counters so it * must be consistent with the ondisk rtbitmap and must never include - * incore reservations. + * incore reservations. sb_frextents was added to the lazy sb counters + * when the realtime groups feature was introduced. */ + if (xfs_has_rtgroups(mp)) + mp->m_sb.sb_frextents += rtxdelta; mp->m_sb.sb_dblocks += tp->t_dblocks_delta; mp->m_sb.sb_agcount += tp->t_agcount_delta; mp->m_sb.sb_imax_pct += tp->t_imaxpct_delta; From patchwork Sun Dec 31 21:18:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507608 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 614F6BA2B for ; Sun, 31 Dec 2023 21:18:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="jHjbNSCX" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2E83EC433C8; Sun, 31 Dec 2023 21:18:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704057525; bh=HNd/hE4iYzNpHP6mDwbkWFjS4bHwx7bRu2NRqNSnA+Q=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=jHjbNSCXbiSiqOKzxNPzcwi1UQC6uuw2lbbZNC6agtXe+PiJ5DFoJYFKaMTaIsRzY +8OpTj9BJz42I9Vop3vqJEom+EwN9z2FZo1NB3UtGPJFeiUwfVfWNQuWZ+NNcWy3yO Yr64Xr3kgBNw8mOIb2eaM2sZNWUm+/sVfzYAnc0TJNf/A13+KPFr50fPIrwdZw2OWa yygYavDApejRZeHBWNaqBASoGLIhO1TKSRHNSKU5cRjbgtMUA6BSzQV/6gSK/qufDK BtH8GSAeM+ll/FZT5sl2FAGVS5tv/TrnPhIv7afDTJcMErQHNzXrUhfPpXqs1uGXjv AvG0ZShx818aQ== Date: Sun, 31 Dec 2023 13:18:44 -0800 Subject: [PATCH 12/24] xfs: record rt group superblock errors in the health system From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404846432.1763124.13705528400720269212.stgit@frogsfrogsfrogs> In-Reply-To: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> References: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Record the state of per-rtgroup metadata sickness in the rtgroup structure for later reporting. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_health.h | 28 ++++++++++++++ fs/xfs/libxfs/xfs_rtgroup.h | 8 ++++ fs/xfs/scrub/health.c | 24 ++++++++++++ fs/xfs/xfs_health.c | 86 +++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_trace.h | 25 +++++++++++++ 5 files changed, 170 insertions(+), 1 deletion(-) diff --git a/fs/xfs/libxfs/xfs_health.h b/fs/xfs/libxfs/xfs_health.h index 1816c67351ac8..f5449a804c6c8 100644 --- a/fs/xfs/libxfs/xfs_health.h +++ b/fs/xfs/libxfs/xfs_health.h @@ -52,6 +52,7 @@ struct xfs_inode; struct xfs_fsop_geom; struct xfs_btree_cur; struct xfs_da_args; +struct xfs_rtgroup; /* Observable health issues for metadata spanning the entire filesystem. */ #define XFS_SICK_FS_COUNTERS (1 << 0) /* summary counters */ @@ -66,6 +67,7 @@ struct xfs_da_args; /* Observable health issues for realtime volume metadata. */ #define XFS_SICK_RT_BITMAP (1 << 0) /* realtime bitmap */ #define XFS_SICK_RT_SUMMARY (1 << 1) /* realtime summary */ +#define XFS_SICK_RT_SUPER (1 << 2) /* rt group superblock */ /* Observable health issues for AG metadata. */ #define XFS_SICK_AG_SB (1 << 0) /* superblock */ @@ -110,7 +112,8 @@ struct xfs_da_args; XFS_SICK_FS_METAPATH) #define XFS_SICK_RT_PRIMARY (XFS_SICK_RT_BITMAP | \ - XFS_SICK_RT_SUMMARY) + XFS_SICK_RT_SUMMARY | \ + XFS_SICK_RT_SUPER) #define XFS_SICK_AG_PRIMARY (XFS_SICK_AG_SB | \ XFS_SICK_AG_AGF | \ @@ -192,6 +195,14 @@ void xfs_rt_mark_healthy(struct xfs_mount *mp, unsigned int mask); void xfs_rt_measure_sickness(struct xfs_mount *mp, unsigned int *sick, unsigned int *checked); +void xfs_rgno_mark_sick(struct xfs_mount *mp, xfs_rgnumber_t rgno, + unsigned int mask); +void xfs_rtgroup_mark_sick(struct xfs_rtgroup *rtg, unsigned int mask); +void xfs_rtgroup_mark_checked(struct xfs_rtgroup *rtg, unsigned int mask); +void xfs_rtgroup_mark_healthy(struct xfs_rtgroup *rtg, unsigned int mask); +void xfs_rtgroup_measure_sickness(struct xfs_rtgroup *rtg, unsigned int *sick, + unsigned int *checked); + void xfs_agno_mark_sick(struct xfs_mount *mp, xfs_agnumber_t agno, unsigned int mask); void xfs_ag_mark_sick(struct xfs_perag *pag, unsigned int mask); @@ -241,6 +252,15 @@ xfs_ag_has_sickness(struct xfs_perag *pag, unsigned int mask) return sick & mask; } +static inline bool +xfs_rtgroup_has_sickness(struct xfs_rtgroup *rtg, unsigned int mask) +{ + unsigned int sick, checked; + + xfs_rtgroup_measure_sickness(rtg, &sick, &checked); + return sick & mask; +} + static inline bool xfs_inode_has_sickness(struct xfs_inode *ip, unsigned int mask) { @@ -262,6 +282,12 @@ xfs_rt_is_healthy(struct xfs_mount *mp) return !xfs_rt_has_sickness(mp, -1U); } +static inline bool +xfs_rtgroup_is_healthy(struct xfs_rtgroup *rtg) +{ + return !xfs_rtgroup_has_sickness(rtg, -1U); +} + static inline bool xfs_ag_is_healthy(struct xfs_perag *pag) { diff --git a/fs/xfs/libxfs/xfs_rtgroup.h b/fs/xfs/libxfs/xfs_rtgroup.h index 2d0422c6712da..c3f4f644ea56b 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.h +++ b/fs/xfs/libxfs/xfs_rtgroup.h @@ -25,6 +25,14 @@ struct xfs_rtgroup { /* Number of blocks in this group */ xfs_rgblock_t rtg_blockcount; + /* + * Bitsets of per-rtgroup metadata that have been checked and/or are + * sick. Callers should hold rtg_state_lock before accessing this + * field. + */ + uint16_t rtg_checked; + uint16_t rtg_sick; + #ifdef __KERNEL__ /* -- kernel only structures below this line -- */ spinlock_t rtg_state_lock; diff --git a/fs/xfs/scrub/health.c b/fs/xfs/scrub/health.c index 4aae9a594cce5..063176c1f35eb 100644 --- a/fs/xfs/scrub/health.c +++ b/fs/xfs/scrub/health.c @@ -14,6 +14,7 @@ #include "xfs_mount.h" #include "xfs_ag.h" #include "xfs_health.h" +#include "xfs_rtgroup.h" #include "scrub/scrub.h" #include "scrub/health.h" #include "scrub/common.h" @@ -76,6 +77,7 @@ enum xchk_health_group { XHG_RT, XHG_AG, XHG_INO, + XHG_RTGROUP, }; struct xchk_health_map { @@ -164,12 +166,16 @@ xchk_mark_all_healthy( struct xfs_mount *mp) { struct xfs_perag *pag; + struct xfs_rtgroup *rtg; xfs_agnumber_t agno; + xfs_rgnumber_t rgno; xfs_fs_mark_healthy(mp, XFS_SICK_FS_INDIRECT); xfs_rt_mark_healthy(mp, XFS_SICK_RT_INDIRECT); for_each_perag(mp, agno, pag) xfs_ag_mark_healthy(pag, XFS_SICK_AG_INDIRECT); + for_each_rtgroup(mp, rgno, rtg) + xfs_rtgroup_mark_healthy(rtg, XFS_SICK_RT_INDIRECT); } /* @@ -187,6 +193,7 @@ xchk_update_health( struct xfs_scrub *sc) { struct xfs_perag *pag; + struct xfs_rtgroup *rtg; bool bad; /* @@ -249,6 +256,15 @@ xchk_update_health( } else xfs_rt_mark_healthy(sc->mp, sc->sick_mask); break; + case XHG_RTGROUP: + rtg = xfs_rtgroup_get(sc->mp, sc->sm->sm_agno); + if (bad) { + xfs_rtgroup_mark_sick(rtg, sc->sick_mask); + xfs_rtgroup_mark_checked(rtg, sc->sick_mask); + } else + xfs_rtgroup_mark_healthy(rtg, sc->sick_mask); + xfs_rtgroup_put(rtg); + break; default: ASSERT(0); break; @@ -336,7 +352,9 @@ xchk_health_record( { struct xfs_mount *mp = sc->mp; struct xfs_perag *pag; + struct xfs_rtgroup *rtg; xfs_agnumber_t agno; + xfs_rgnumber_t rgno; unsigned int sick; unsigned int checked; @@ -355,5 +373,11 @@ xchk_health_record( xchk_set_corrupt(sc); } + for_each_rtgroup(mp, rgno, rtg) { + xfs_rtgroup_measure_sickness(rtg, &sick, &checked); + if (sick & XFS_SICK_RT_PRIMARY) + xchk_set_corrupt(sc); + } + return 0; } diff --git a/fs/xfs/xfs_health.c b/fs/xfs/xfs_health.c index b7aa33a4c9e06..1ec015663a6aa 100644 --- a/fs/xfs/xfs_health.c +++ b/fs/xfs/xfs_health.c @@ -18,6 +18,7 @@ #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_quota_defs.h" +#include "xfs_rtgroup.h" /* * Warn about metadata corruption that we detected but haven't fixed, and @@ -29,7 +30,9 @@ xfs_health_unmount( struct xfs_mount *mp) { struct xfs_perag *pag; + struct xfs_rtgroup *rtg; xfs_agnumber_t agno; + xfs_rgnumber_t rgno; unsigned int sick = 0; unsigned int checked = 0; bool warn = false; @@ -46,6 +49,15 @@ xfs_health_unmount( } } + /* Measure realtime group corruption levels. */ + for_each_rtgroup(mp, rgno, rtg) { + xfs_rtgroup_measure_sickness(rtg, &sick, &checked); + if (sick) { + trace_xfs_rtgroup_unfixed_corruption(rtg, sick); + warn = true; + } + } + /* Measure realtime volume corruption levels. */ xfs_rt_measure_sickness(mp, &sick, &checked); if (sick) { @@ -280,6 +292,80 @@ xfs_ag_measure_sickness( spin_unlock(&pag->pag_state_lock); } +/* Mark unhealthy per-rtgroup metadata given a raw rt group number. */ +void +xfs_rgno_mark_sick( + struct xfs_mount *mp, + xfs_rgnumber_t rgno, + unsigned int mask) +{ + struct xfs_rtgroup *rtg = xfs_rtgroup_get(mp, rgno); + + /* per-rtgroup structure not set up yet? */ + if (!rtg) + return; + + xfs_rtgroup_mark_sick(rtg, mask); + xfs_rtgroup_put(rtg); +} + +/* Mark unhealthy per-rtgroup metadata. */ +void +xfs_rtgroup_mark_sick( + struct xfs_rtgroup *rtg, + unsigned int mask) +{ + ASSERT(!(mask & ~XFS_SICK_RT_ALL)); + trace_xfs_rtgroup_mark_sick(rtg, mask); + + spin_lock(&rtg->rtg_state_lock); + rtg->rtg_sick |= mask; + spin_unlock(&rtg->rtg_state_lock); +} + +/* Mark per-rtgroup metadata as having been checked. */ +void +xfs_rtgroup_mark_checked( + struct xfs_rtgroup *rtg, + unsigned int mask) +{ + ASSERT(!(mask & ~XFS_SICK_RT_PRIMARY)); + + spin_lock(&rtg->rtg_state_lock); + rtg->rtg_checked |= mask; + spin_unlock(&rtg->rtg_state_lock); +} + +/* Mark per-rtgroup metadata ok. */ +void +xfs_rtgroup_mark_healthy( + struct xfs_rtgroup *rtg, + unsigned int mask) +{ + ASSERT(!(mask & ~XFS_SICK_RT_ALL)); + trace_xfs_rtgroup_mark_healthy(rtg, mask); + + spin_lock(&rtg->rtg_state_lock); + rtg->rtg_sick &= ~mask; + if (!(rtg->rtg_sick & XFS_SICK_RT_PRIMARY)) + rtg->rtg_sick &= ~XFS_SICK_RT_SECONDARY; + rtg->rtg_checked |= mask; + spin_unlock(&rtg->rtg_state_lock); +} + +/* Sample which per-rtgroup metadata are unhealthy. */ +void +xfs_rtgroup_measure_sickness( + struct xfs_rtgroup *rtg, + unsigned int *sick, + unsigned int *checked) +{ + spin_lock(&rtg->rtg_state_lock); + *sick = rtg->rtg_sick; + *checked = rtg->rtg_checked; + spin_unlock(&rtg->rtg_state_lock); +} + /* Mark the unhealthy parts of an inode. */ void xfs_inode_mark_sick( diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 81c21000d4fea..d23566e841cba 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -4307,6 +4307,31 @@ DEFINE_AG_CORRUPT_EVENT(xfs_ag_mark_sick); DEFINE_AG_CORRUPT_EVENT(xfs_ag_mark_healthy); DEFINE_AG_CORRUPT_EVENT(xfs_ag_unfixed_corruption); +DECLARE_EVENT_CLASS(xfs_rtgroup_corrupt_class, + TP_PROTO(struct xfs_rtgroup *rtg, unsigned int flags), + TP_ARGS(rtg, flags), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_rgnumber_t, rgno) + __field(unsigned int, flags) + ), + TP_fast_assign( + __entry->dev = rtg->rtg_mount->m_super->s_dev; + __entry->rgno = rtg->rtg_rgno; + __entry->flags = flags; + ), + TP_printk("dev %d:%d rgno 0x%x flags 0x%x", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->rgno, __entry->flags) +); +#define DEFINE_RTGROUP_CORRUPT_EVENT(name) \ +DEFINE_EVENT(xfs_rtgroup_corrupt_class, name, \ + TP_PROTO(struct xfs_rtgroup *rtg, unsigned int flags), \ + TP_ARGS(rtg, flags)) +DEFINE_RTGROUP_CORRUPT_EVENT(xfs_rtgroup_mark_sick); +DEFINE_RTGROUP_CORRUPT_EVENT(xfs_rtgroup_mark_healthy); +DEFINE_RTGROUP_CORRUPT_EVENT(xfs_rtgroup_unfixed_corruption); + DECLARE_EVENT_CLASS(xfs_inode_corrupt_class, TP_PROTO(struct xfs_inode *ip, unsigned int flags), TP_ARGS(ip, flags), From patchwork Sun Dec 31 21:19:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507609 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 0D751BA22 for ; Sun, 31 Dec 2023 21:19:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="q6Pq/FTp" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D1FDFC433C8; Sun, 31 Dec 2023 21:19:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704057540; bh=XT0juCSkHRRgbipNTzoAXFELKfL4HhjItYseWK18n4Q=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=q6Pq/FTpF2xH2V5bNupJbOaF1M/IecoWVKpGKbDdfnn3HcBOoV1HrAzX/E1kcH84g j8cpEoGKJz5QFaAKzh6laMz9P3+1G6/ptK22L3gkSh/b1kzj0tiYfs9goHqPM694+R ZNNbOKd+YLZFagC7mvGMXe8/j0RXxNoh7xarqW5Recm2wsS1HNBCRG5jI/lSca6yOX gIijUODW27oTFplKyZSZNitKsD826kPAQKpGq+9F4kQXWDehvpo76gBNCwExI0Kw/k j77uqyLM0xKH82WjoPn9pDjY/mY+N+E3XJzM3qJNjTQHKqzpDx3H8M3yc2JsX1Thw0 7SXxm68RmASAA== Date: Sun, 31 Dec 2023 13:19:00 -0800 Subject: [PATCH 13/24] xfs: define locking primitives for realtime groups From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404846449.1763124.7733896504887006856.stgit@frogsfrogsfrogs> In-Reply-To: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> References: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Define helper functions to lock all metadata inodes related to a realtime group. There's not much to look at now, but this will become important when we add per-rtgroup metadata files and online fsck code for them. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_rtgroup.c | 33 +++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_rtgroup.h | 14 ++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/fs/xfs/libxfs/xfs_rtgroup.c b/fs/xfs/libxfs/xfs_rtgroup.c index 173297f582e00..3c86a560adfe3 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.c +++ b/fs/xfs/libxfs/xfs_rtgroup.c @@ -536,3 +536,36 @@ xfs_rtgroup_update_secondary_sbs( return saved_error ? saved_error : error; } + +/* Lock metadata inodes associated with this rt group. */ +void +xfs_rtgroup_lock( + struct xfs_trans *tp, + struct xfs_rtgroup *rtg, + unsigned int rtglock_flags) +{ + ASSERT(!(rtglock_flags & ~XFS_RTGLOCK_ALL_FLAGS)); + ASSERT(!(rtglock_flags & XFS_RTGLOCK_BITMAP_SHARED) || + !(rtglock_flags & XFS_RTGLOCK_BITMAP)); + + if (rtglock_flags & XFS_RTGLOCK_BITMAP) + xfs_rtbitmap_lock(tp, rtg->rtg_mount); + else if (rtglock_flags & XFS_RTGLOCK_BITMAP_SHARED) + xfs_rtbitmap_lock_shared(rtg->rtg_mount, XFS_RBMLOCK_BITMAP); +} + +/* Unlock metadata inodes associated with this rt group. */ +void +xfs_rtgroup_unlock( + struct xfs_rtgroup *rtg, + unsigned int rtglock_flags) +{ + ASSERT(!(rtglock_flags & ~XFS_RTGLOCK_ALL_FLAGS)); + ASSERT(!(rtglock_flags & XFS_RTGLOCK_BITMAP_SHARED) || + !(rtglock_flags & XFS_RTGLOCK_BITMAP)); + + if (rtglock_flags & XFS_RTGLOCK_BITMAP) + xfs_rtbitmap_unlock(rtg->rtg_mount); + else if (rtglock_flags & XFS_RTGLOCK_BITMAP_SHARED) + xfs_rtbitmap_unlock_shared(rtg->rtg_mount, XFS_RBMLOCK_BITMAP); +} diff --git a/fs/xfs/libxfs/xfs_rtgroup.h b/fs/xfs/libxfs/xfs_rtgroup.h index c3f4f644ea56b..70968cf700fab 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.h +++ b/fs/xfs/libxfs/xfs_rtgroup.h @@ -221,11 +221,25 @@ void xfs_rtgroup_update_super(struct xfs_buf *rtsb_bp, const struct xfs_buf *sb_bp); void xfs_rtgroup_log_super(struct xfs_trans *tp, const struct xfs_buf *sb_bp); int xfs_rtgroup_update_secondary_sbs(struct xfs_mount *mp); + +/* Lock the rt bitmap inode in exclusive mode */ +#define XFS_RTGLOCK_BITMAP (1U << 0) +/* Lock the rt bitmap inode in shared mode */ +#define XFS_RTGLOCK_BITMAP_SHARED (1U << 1) + +#define XFS_RTGLOCK_ALL_FLAGS (XFS_RTGLOCK_BITMAP | \ + XFS_RTGLOCK_BITMAP_SHARED) + +void xfs_rtgroup_lock(struct xfs_trans *tp, struct xfs_rtgroup *rtg, + unsigned int rtglock_flags); +void xfs_rtgroup_unlock(struct xfs_rtgroup *rtg, unsigned int rtglock_flags); #else # define xfs_rtgroup_block_count(mp, rgno) (0) # define xfs_rtgroup_update_super(bp, sb_bp) ((void)0) # define xfs_rtgroup_log_super(tp, sb_bp) ((void)0) # define xfs_rtgroup_update_secondary_sbs(mp) (0) +# define xfs_rtgroup_lock(tp, rtg, gf) ((void)0) +# define xfs_rtgroup_unlock(rtg, gf) ((void)0) #endif /* CONFIG_XFS_RT */ #endif /* __LIBXFS_RTGROUP_H */ From patchwork Sun Dec 31 21:19:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507610 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 B6019BA2B for ; Sun, 31 Dec 2023 21:19:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="m61tUBq7" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 84CAEC433C8; Sun, 31 Dec 2023 21:19:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704057556; bh=Wx63+yfNOlY/RD84hnRTYOp35JMes955sIDw9nNdGsM=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=m61tUBq7ILsPnTmZXzvT+Otn2Krx14bqcs+w1Com/abgfQvObGvhfJFkJAOkM8GzK OXmxfuzNh/POnjzf4n3bP9zJQdckK58W0CWi2dbWvOgXzQBs6PCeEfI+kf5HN9qSfp im7EsTxDPgaf1r8ngPrY49AQM7UqXaHXm7ghQhspRLAK3lhbN95TiZTebTM76x8izu BM4ZMUv8oH9pi96QykBhMbZ0lzHYVSN2mY5d+RI7N6a0GHVrseiqjTj4ApaXTkpfJG wXBYuIZY9ej/sAcpf1W+RyExPVbsWHfterz+e1jZAUCUxbIhvjEBMTNH8QC0miYfns JZS0GrnUNPlhQ== Date: Sun, 31 Dec 2023 13:19:16 -0800 Subject: [PATCH 14/24] xfs: export the geometry of realtime groups to userspace From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404846464.1763124.5701999725639143419.stgit@frogsfrogsfrogs> In-Reply-To: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> References: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 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 an ioctl so that the kernel can report the status of realtime groups to userspace. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_fs.h | 1 + fs/xfs/libxfs/xfs_fs_staging.h | 17 +++++++++++++++++ fs/xfs/libxfs/xfs_health.h | 2 ++ fs/xfs/libxfs/xfs_rtgroup.c | 14 ++++++++++++++ fs/xfs/libxfs/xfs_rtgroup.h | 4 ++++ fs/xfs/xfs_health.c | 28 ++++++++++++++++++++++++++++ fs/xfs/xfs_ioctl.c | 32 ++++++++++++++++++++++++++++++++ 7 files changed, 98 insertions(+) diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index bae9ef924bf59..c5bf53c6a43ca 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -852,6 +852,7 @@ struct xfs_scrub_metadata { /* XFS_IOC_SCRUBV_METADATA -- staging 60 */ #define XFS_IOC_AG_GEOMETRY _IOWR('X', 61, struct xfs_ag_geometry) /* XFS_IOC_GETPARENTS ---- staging 62 */ +/* XFS_IOC_RTGROUP_GEOMETRY - staging 63 */ /* * ioctl commands that replace IRIX syssgi()'s diff --git a/fs/xfs/libxfs/xfs_fs_staging.h b/fs/xfs/libxfs/xfs_fs_staging.h index 69d29f213af3a..1f57331487791 100644 --- a/fs/xfs/libxfs/xfs_fs_staging.h +++ b/fs/xfs/libxfs/xfs_fs_staging.h @@ -202,4 +202,21 @@ static inline size_t sizeof_xfs_scrub_vec(unsigned int nr) #define XFS_IOC_SCRUBV_METADATA _IOWR('X', 60, struct xfs_scrub_vec_head) +/* + * Output for XFS_IOC_RTGROUP_GEOMETRY + */ +struct xfs_rtgroup_geometry { + __u32 rg_number; /* i/o: rtgroup number */ + __u32 rg_length; /* o: length in blocks */ + __u32 rg_sick; /* o: sick things in ag */ + __u32 rg_checked; /* o: checked metadata in ag */ + __u32 rg_flags; /* i/o: flags for this ag */ + __u32 rg_pad; /* o: zero */ + __u64 rg_reserved[13]; /* o: zero */ +}; +#define XFS_RTGROUP_GEOM_SICK_SUPER (1 << 0) /* superblock */ +#define XFS_RTGROUP_GEOM_SICK_BITMAP (1 << 1) /* rtbitmap for this group */ + +#define XFS_IOC_RTGROUP_GEOMETRY _IOWR('X', 63, struct xfs_rtgroup_geometry) + #endif /* __XFS_FS_STAGING_H__ */ diff --git a/fs/xfs/libxfs/xfs_health.h b/fs/xfs/libxfs/xfs_health.h index f5449a804c6c8..1e9938a417b42 100644 --- a/fs/xfs/libxfs/xfs_health.h +++ b/fs/xfs/libxfs/xfs_health.h @@ -302,6 +302,8 @@ xfs_inode_is_healthy(struct xfs_inode *ip) void xfs_fsop_geom_health(struct xfs_mount *mp, struct xfs_fsop_geom *geo); void xfs_ag_geom_health(struct xfs_perag *pag, struct xfs_ag_geometry *ageo); +void xfs_rtgroup_geom_health(struct xfs_rtgroup *rtg, + struct xfs_rtgroup_geometry *rgeo); void xfs_bulkstat_health(struct xfs_inode *ip, struct xfs_bulkstat *bs); #define xfs_metadata_is_sick(error) \ diff --git a/fs/xfs/libxfs/xfs_rtgroup.c b/fs/xfs/libxfs/xfs_rtgroup.c index 3c86a560adfe3..ed4f8aa67b158 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.c +++ b/fs/xfs/libxfs/xfs_rtgroup.c @@ -569,3 +569,17 @@ xfs_rtgroup_unlock( else if (rtglock_flags & XFS_RTGLOCK_BITMAP_SHARED) xfs_rtbitmap_unlock_shared(rtg->rtg_mount, XFS_RBMLOCK_BITMAP); } + +/* Retrieve rt group geometry. */ +int +xfs_rtgroup_get_geometry( + struct xfs_rtgroup *rtg, + struct xfs_rtgroup_geometry *rgeo) +{ + /* Fill out form. */ + memset(rgeo, 0, sizeof(*rgeo)); + rgeo->rg_number = rtg->rtg_rgno; + rgeo->rg_length = rtg->rtg_blockcount; + xfs_rtgroup_geom_health(rtg, rgeo); + return 0; +} diff --git a/fs/xfs/libxfs/xfs_rtgroup.h b/fs/xfs/libxfs/xfs_rtgroup.h index 70968cf700fab..e6d60425faa4d 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.h +++ b/fs/xfs/libxfs/xfs_rtgroup.h @@ -233,6 +233,9 @@ int xfs_rtgroup_update_secondary_sbs(struct xfs_mount *mp); void xfs_rtgroup_lock(struct xfs_trans *tp, struct xfs_rtgroup *rtg, unsigned int rtglock_flags); void xfs_rtgroup_unlock(struct xfs_rtgroup *rtg, unsigned int rtglock_flags); + +int xfs_rtgroup_get_geometry(struct xfs_rtgroup *rtg, + struct xfs_rtgroup_geometry *rgeo); #else # define xfs_rtgroup_block_count(mp, rgno) (0) # define xfs_rtgroup_update_super(bp, sb_bp) ((void)0) @@ -240,6 +243,7 @@ void xfs_rtgroup_unlock(struct xfs_rtgroup *rtg, unsigned int rtglock_flags); # define xfs_rtgroup_update_secondary_sbs(mp) (0) # define xfs_rtgroup_lock(tp, rtg, gf) ((void)0) # define xfs_rtgroup_unlock(rtg, gf) ((void)0) +# define xfs_rtgroup_get_geometry(rtg, rgeo) (-EOPNOTSUPP) #endif /* CONFIG_XFS_RT */ #endif /* __LIBXFS_RTGROUP_H */ diff --git a/fs/xfs/xfs_health.c b/fs/xfs/xfs_health.c index 1ec015663a6aa..b53ef95a37a54 100644 --- a/fs/xfs/xfs_health.c +++ b/fs/xfs/xfs_health.c @@ -529,6 +529,34 @@ xfs_ag_geom_health( } } +static const struct ioctl_sick_map rtgroup_map[] = { + { XFS_SICK_RT_SUPER, XFS_RTGROUP_GEOM_SICK_SUPER }, + { XFS_SICK_RT_BITMAP, XFS_RTGROUP_GEOM_SICK_BITMAP }, + { 0, 0 }, +}; + +/* Fill out rtgroup geometry health info. */ +void +xfs_rtgroup_geom_health( + struct xfs_rtgroup *rtg, + struct xfs_rtgroup_geometry *rgeo) +{ + const struct ioctl_sick_map *m; + unsigned int sick; + unsigned int checked; + + rgeo->rg_sick = 0; + rgeo->rg_checked = 0; + + xfs_rtgroup_measure_sickness(rtg, &sick, &checked); + for (m = rtgroup_map; m->sick_mask; m++) { + if (checked & m->sick_mask) + rgeo->rg_checked |= m->ioctl_mask; + if (sick & m->sick_mask) + rgeo->rg_sick |= m->ioctl_mask; + } +} + static const struct ioctl_sick_map ino_map[] = { { XFS_SICK_INO_CORE, XFS_BS_SICK_INODE }, { XFS_SICK_INO_BMBTD, XFS_BS_SICK_BMBTD }, diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index b140f7ed916c9..32a52799ae826 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -995,6 +995,36 @@ xfs_ioc_ag_geometry( return 0; } +STATIC int +xfs_ioc_rtgroup_geometry( + struct xfs_mount *mp, + void __user *arg) +{ + struct xfs_rtgroup *rtg; + struct xfs_rtgroup_geometry rgeo; + int error; + + if (copy_from_user(&rgeo, arg, sizeof(rgeo))) + return -EFAULT; + if (rgeo.rg_flags || rgeo.rg_pad) + return -EINVAL; + if (memchr_inv(&rgeo.rg_reserved, 0, sizeof(rgeo.rg_reserved))) + return -EINVAL; + + rtg = xfs_rtgroup_get(mp, rgeo.rg_number); + if (!rtg) + return -EINVAL; + + error = xfs_rtgroup_get_geometry(rtg, &rgeo); + xfs_rtgroup_put(rtg); + if (error) + return error; + + if (copy_to_user(arg, &rgeo, sizeof(rgeo))) + return -EFAULT; + return 0; +} + /* * Linux extended inode flags interface. */ @@ -2081,6 +2111,8 @@ xfs_file_ioctl( case XFS_IOC_AG_GEOMETRY: return xfs_ioc_ag_geometry(mp, arg); + case XFS_IOC_RTGROUP_GEOMETRY: + return xfs_ioc_rtgroup_geometry(mp, arg); case XFS_IOC_GETVERSION: return put_user(inode->i_generation, (int __user *)arg); From patchwork Sun Dec 31 21:19:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507611 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 9FF97BA2E for ; Sun, 31 Dec 2023 21:19:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="XKgUlVj8" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2A699C433C7; Sun, 31 Dec 2023 21:19:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704057572; bh=xRrn3Bq1WVJBRkc54a6tUtqIbL1g5J88Xw58MNmVsQs=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=XKgUlVj8XYAQitPFUt44UgoaYto66nQWs4SgY1WXDyafgkFppQgpQbD4QLxy3E1lI 09cB3vLcAdnJxNwuI67AGOGbHIJ9gX/bqvGmPdKY9PDdG+lmr5IX8QRI+SVxlsc+fa cBQeYPqSlEiXxSs7UeSFuUfdi0ZgO5JDotqbRYM8y0JUeSsqUPZZvB0Jzx8X2EMT2v fNRevDvavIsAY0PPzPYQM6v0pAdt2gOFTY8aP449R1gJEqpYjXBQf5vm7jtp6Rzxuo MRWR10dOKQrsXn5fl5Ik/c31kSuwpC4CA1j+cs/RJZp2iiLefnwYfUl1UmpWEvjcmR Xx8VCx0tUAVgw== Date: Sun, 31 Dec 2023 13:19:31 -0800 Subject: [PATCH 15/24] xfs: add block headers to realtime bitmap blocks From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404846480.1763124.1033850500766758011.stgit@frogsfrogsfrogs> In-Reply-To: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> References: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Upgrade rtbitmap blocks to have self describing metadata like most every other thing in XFS. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_format.h | 14 +++++ fs/xfs/libxfs/xfs_ondisk.h | 1 fs/xfs/libxfs/xfs_rtbitmap.c | 108 ++++++++++++++++++++++++++++++++++++++--- fs/xfs/libxfs/xfs_rtbitmap.h | 33 ++++++++++++- fs/xfs/libxfs/xfs_sb.c | 18 +++++-- fs/xfs/libxfs/xfs_shared.h | 1 fs/xfs/xfs_buf_item_recover.c | 20 +++++++- fs/xfs/xfs_mount.h | 3 + fs/xfs/xfs_rtalloc.c | 60 ++++++++++++++++------- 9 files changed, 224 insertions(+), 34 deletions(-) diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index 43e66740e2aec..7178bd463c1c0 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -1300,6 +1300,20 @@ static inline bool xfs_dinode_has_large_extent_counts( /* * RT bit manipulation macros. */ +#define XFS_RTBITMAP_MAGIC 0x424D505A /* BMPZ */ + +struct xfs_rtbuf_blkinfo { + __be32 rt_magic; /* validity check on block */ + __be32 rt_crc; /* CRC of block */ + __be64 rt_owner; /* inode that owns the block */ + __be64 rt_blkno; /* first block of the buffer */ + __be64 rt_lsn; /* sequence number of last write */ + uuid_t rt_uuid; /* filesystem we belong to */ +}; + +#define XFS_RTBUF_CRC_OFF \ + offsetof(struct xfs_rtbuf_blkinfo, rt_crc) + #define XFS_RTMIN(a,b) ((a) < (b) ? (a) : (b)) #define XFS_RTMAX(a,b) ((a) > (b) ? (a) : (b)) diff --git a/fs/xfs/libxfs/xfs_ondisk.h b/fs/xfs/libxfs/xfs_ondisk.h index 65219d4cf99ca..70b96efa26973 100644 --- a/fs/xfs/libxfs/xfs_ondisk.h +++ b/fs/xfs/libxfs/xfs_ondisk.h @@ -76,6 +76,7 @@ xfs_check_ondisk_structs(void) /* realtime structures */ XFS_CHECK_STRUCT_SIZE(union xfs_rtword_raw, 4); XFS_CHECK_STRUCT_SIZE(union xfs_suminfo_raw, 4); + XFS_CHECK_STRUCT_SIZE(struct xfs_rtbuf_blkinfo, 48); /* * m68k has problems with xfs_attr_leaf_name_remote_t, but we pad it to diff --git a/fs/xfs/libxfs/xfs_rtbitmap.c b/fs/xfs/libxfs/xfs_rtbitmap.c index a8e5c702a7515..4d85b8ea9a861 100644 --- a/fs/xfs/libxfs/xfs_rtbitmap.c +++ b/fs/xfs/libxfs/xfs_rtbitmap.c @@ -18,28 +18,84 @@ #include "xfs_error.h" #include "xfs_rtbitmap.h" #include "xfs_health.h" +#include "xfs_log.h" +#include "xfs_buf_item.h" /* * Realtime allocator bitmap functions shared with userspace. */ -/* - * Real time buffers need verifiers to avoid runtime warnings during IO. - * We don't have anything to verify, however, so these are just dummy - * operations. - */ +static xfs_failaddr_t +xfs_rtbuf_verify( + struct xfs_buf *bp) +{ + struct xfs_mount *mp = bp->b_mount; + struct xfs_rtbuf_blkinfo *hdr = bp->b_addr; + + if (!xfs_verify_magic(bp, hdr->rt_magic)) + return __this_address; + if (!xfs_has_rtgroups(mp)) + return __this_address; + if (!xfs_has_crc(mp)) + return __this_address; + if (!uuid_equal(&hdr->rt_uuid, &mp->m_sb.sb_meta_uuid)) + return __this_address; + if (hdr->rt_blkno != cpu_to_be64(xfs_buf_daddr(bp))) + return __this_address; + return NULL; +} + static void xfs_rtbuf_verify_read( - struct xfs_buf *bp) + struct xfs_buf *bp) { + struct xfs_mount *mp = bp->b_mount; + struct xfs_rtbuf_blkinfo *hdr = bp->b_addr; + xfs_failaddr_t fa; + + if (!xfs_has_rtgroups(mp) || bp->b_ops != &xfs_rtbitmap_buf_ops) + return; + + if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr->rt_lsn))) { + fa = __this_address; + goto fail; + } + + if (!xfs_buf_verify_cksum(bp, XFS_RTBUF_CRC_OFF)) { + fa = __this_address; + goto fail; + } + + fa = xfs_rtbuf_verify(bp); + if (fa) + goto fail; + return; +fail: + xfs_verifier_error(bp, -EFSCORRUPTED, fa); } static void xfs_rtbuf_verify_write( struct xfs_buf *bp) { - return; + struct xfs_mount *mp = bp->b_mount; + struct xfs_rtbuf_blkinfo *hdr = bp->b_addr; + struct xfs_buf_log_item *bip = bp->b_log_item; + xfs_failaddr_t fa; + + if (!xfs_has_rtgroups(mp) || bp->b_ops != &xfs_rtbitmap_buf_ops) + return; + + fa = xfs_rtbuf_verify(bp); + if (fa) { + xfs_verifier_error(bp, -EFSCORRUPTED, fa); + return; + } + + if (bip) + hdr->rt_lsn = cpu_to_be64(bip->bli_item.li_lsn); + xfs_buf_update_cksum(bp, XFS_RTBUF_CRC_OFF); } const struct xfs_buf_ops xfs_rtbuf_ops = { @@ -48,6 +104,14 @@ const struct xfs_buf_ops xfs_rtbuf_ops = { .verify_write = xfs_rtbuf_verify_write, }; +const struct xfs_buf_ops xfs_rtbitmap_buf_ops = { + .name = "xfs_rtbitmap", + .magic = { 0, cpu_to_be32(XFS_RTBITMAP_MAGIC) }, + .verify_read = xfs_rtbuf_verify_read, + .verify_write = xfs_rtbuf_verify_write, + .verify_struct = xfs_rtbuf_verify, +}; + /* Release cached rt bitmap and summary buffers. */ void xfs_rtbuf_cache_relse( @@ -125,13 +189,26 @@ xfs_rtbuf_get( ASSERT(map.br_startblock != NULLFSBLOCK); error = xfs_trans_read_buf(mp, args->tp, mp->m_ddev_targp, XFS_FSB_TO_DADDR(mp, map.br_startblock), - mp->m_bsize, 0, &bp, &xfs_rtbuf_ops); + mp->m_bsize, 0, &bp, + xfs_rtblock_ops(mp, issum)); if (xfs_metadata_is_sick(error)) xfs_rt_mark_sick(mp, issum ? XFS_SICK_RT_SUMMARY : XFS_SICK_RT_BITMAP); if (error) return error; + if (xfs_has_rtgroups(mp) && !issum) { + struct xfs_rtbuf_blkinfo *hdr = bp->b_addr; + + if (hdr->rt_owner != cpu_to_be64(ip->i_ino)) { + xfs_buf_mark_corrupt(bp); + xfs_trans_brelse(args->tp, bp); + xfs_rt_mark_sick(mp, issum ? XFS_SICK_RT_SUMMARY : + XFS_SICK_RT_BITMAP); + return -EFSCORRUPTED; + } + } + xfs_trans_buf_set_type(args->tp, bp, type); *cbpp = bp; *coffp = block; @@ -1125,6 +1202,19 @@ xfs_rtalloc_extent_is_free( return 0; } +/* Compute the number of rt extents tracked by a single bitmap block. */ +xfs_rtxnum_t +xfs_rtbitmap_rtx_per_rbmblock( + struct xfs_mount *mp) +{ + unsigned int rbmblock_bytes = mp->m_sb.sb_blocksize; + + if (xfs_has_rtgroups(mp)) + rbmblock_bytes -= sizeof(struct xfs_rtbuf_blkinfo); + + return rbmblock_bytes * NBBY; +} + /* * Compute the number of rtbitmap blocks needed to track the given number of rt * extents. @@ -1134,7 +1224,7 @@ xfs_rtbitmap_blockcount( struct xfs_mount *mp, xfs_rtbxlen_t rtextents) { - return howmany_64(rtextents, NBBY * mp->m_sb.sb_blocksize); + return howmany_64(rtextents, xfs_rtbitmap_rtx_per_rbmblock(mp)); } /* diff --git a/fs/xfs/libxfs/xfs_rtbitmap.h b/fs/xfs/libxfs/xfs_rtbitmap.h index 3de0ec2d24123..e1cf47d2a9281 100644 --- a/fs/xfs/libxfs/xfs_rtbitmap.h +++ b/fs/xfs/libxfs/xfs_rtbitmap.h @@ -148,6 +148,9 @@ xfs_rtx_to_rbmblock( struct xfs_mount *mp, xfs_rtxnum_t rtx) { + if (xfs_has_rtgroups(mp)) + return div_u64(rtx, mp->m_rtx_per_rbmblock); + return rtx >> mp->m_blkbit_log; } @@ -157,6 +160,13 @@ xfs_rtx_to_rbmword( struct xfs_mount *mp, xfs_rtxnum_t rtx) { + if (xfs_has_rtgroups(mp)) { + unsigned int mod; + + div_u64_rem(rtx >> XFS_NBWORDLOG, mp->m_blockwsize, &mod); + return mod; + } + return (rtx >> XFS_NBWORDLOG) & (mp->m_blockwsize - 1); } @@ -166,6 +176,9 @@ xfs_rbmblock_to_rtx( struct xfs_mount *mp, xfs_fileoff_t rbmoff) { + if (xfs_has_rtgroups(mp)) + return rbmoff * mp->m_rtx_per_rbmblock; + return rbmoff << mp->m_blkbit_log; } @@ -175,7 +188,14 @@ xfs_rbmblock_wordptr( struct xfs_rtalloc_args *args, unsigned int index) { - union xfs_rtword_raw *words = args->rbmbp->b_addr; + struct xfs_mount *mp = args->mp; + union xfs_rtword_raw *words; + struct xfs_rtbuf_blkinfo *hdr = args->rbmbp->b_addr; + + if (xfs_has_rtgroups(mp)) + words = (union xfs_rtword_raw *)(hdr + 1); + else + words = args->rbmbp->b_addr; return words + index; } @@ -277,6 +297,16 @@ xfs_suminfo_add( return info->old; } +static inline const struct xfs_buf_ops * +xfs_rtblock_ops( + struct xfs_mount *mp, + bool issum) +{ + if (xfs_has_rtgroups(mp) && !issum) + return &xfs_rtbitmap_buf_ops; + return &xfs_rtbuf_ops; +} + /* * Functions for walking free space rtextents in the realtime bitmap. */ @@ -365,6 +395,7 @@ xfs_validate_rtextents( return true; } +xfs_rtxnum_t xfs_rtbitmap_rtx_per_rbmblock(struct xfs_mount *mp); xfs_filblks_t xfs_rtbitmap_blockcount(struct xfs_mount *mp, xfs_rtbxlen_t rtextents); unsigned long long xfs_rtbitmap_wordcount(struct xfs_mount *mp, diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index da20189bbe199..8298334f4ee8d 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -577,10 +577,15 @@ xfs_validate_sb_common( } else { uint64_t rexts; uint64_t rbmblocks; + unsigned int rbmblock_bytes = sbp->sb_blocksize; rexts = div_u64(sbp->sb_rblocks, sbp->sb_rextsize); - rbmblocks = howmany_64(sbp->sb_rextents, - NBBY * sbp->sb_blocksize); + + if (xfs_sb_is_v5(sbp) && + (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_RTGROUPS)) + rbmblock_bytes -= sizeof(struct xfs_rtbuf_blkinfo); + + rbmblocks = howmany_64(sbp->sb_rextents, NBBY * rbmblock_bytes); if (!xfs_validate_rtextents(rexts) || sbp->sb_rextents != rexts || @@ -1093,8 +1098,13 @@ xfs_sb_mount_common( mp->m_sectbb_log = sbp->sb_sectlog - BBSHIFT; mp->m_agno_log = xfs_highbit32(sbp->sb_agcount - 1) + 1; mp->m_blockmask = sbp->sb_blocksize - 1; - mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG; - mp->m_blockwmask = mp->m_blockwsize - 1; + if (xfs_has_rtgroups(mp)) + mp->m_blockwsize = (sbp->sb_blocksize - + sizeof(struct xfs_rtbuf_blkinfo)) >> + XFS_WORDLOG; + else + mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG; + mp->m_rtx_per_rbmblock = mp->m_blockwsize << XFS_NBWORDLOG; mp->m_rtxblklog = log2_if_power2(sbp->sb_rextsize); mp->m_rtxblkmask = mask64_if_power2(sbp->sb_rextsize); mp->m_rgblklog = log2_if_power2(sbp->sb_rgblocks); diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h index 65691af0488e7..f57788164a702 100644 --- a/fs/xfs/libxfs/xfs_shared.h +++ b/fs/xfs/libxfs/xfs_shared.h @@ -38,6 +38,7 @@ extern const struct xfs_buf_ops xfs_inode_buf_ops; extern const struct xfs_buf_ops xfs_inode_buf_ra_ops; extern const struct xfs_buf_ops xfs_refcountbt_buf_ops; extern const struct xfs_buf_ops xfs_rmapbt_buf_ops; +extern const struct xfs_buf_ops xfs_rtbitmap_buf_ops; extern const struct xfs_buf_ops xfs_rtbuf_ops; extern const struct xfs_buf_ops xfs_rtsb_buf_ops; extern const struct xfs_buf_ops xfs_sb_buf_ops; diff --git a/fs/xfs/xfs_buf_item_recover.c b/fs/xfs/xfs_buf_item_recover.c index 4be9a384dc6f7..448df616e975e 100644 --- a/fs/xfs/xfs_buf_item_recover.c +++ b/fs/xfs/xfs_buf_item_recover.c @@ -23,6 +23,7 @@ #include "xfs_dir2.h" #include "xfs_quota.h" #include "xfs_rtgroup.h" +#include "xfs_rtbitmap.h" /* * This is the number of entries in the l_buf_cancel_table used during @@ -391,9 +392,15 @@ xlog_recover_validate_buf_type( break; #ifdef CONFIG_XFS_RT case XFS_BLFT_RTBITMAP_BUF: + if (xfs_has_rtgroups(mp) && magic32 != XFS_RTBITMAP_MAGIC) { + warnmsg = "Bad rtbitmap magic!"; + break; + } + bp->b_ops = xfs_rtblock_ops(mp, false); + break; case XFS_BLFT_RTSUMMARY_BUF: /* no magic numbers for verification of RT buffers */ - bp->b_ops = &xfs_rtbuf_ops; + bp->b_ops = xfs_rtblock_ops(mp, true); break; #endif /* CONFIG_XFS_RT */ default: @@ -728,11 +735,20 @@ xlog_recover_get_buf_lsn( * UUIDs, so we must recover them immediately. */ blft = xfs_blft_from_flags(buf_f); - if (blft == XFS_BLFT_RTBITMAP_BUF || blft == XFS_BLFT_RTSUMMARY_BUF) + if (!xfs_has_rtgroups(mp) && blft == XFS_BLFT_RTBITMAP_BUF) + goto recover_immediately; + if (blft == XFS_BLFT_RTSUMMARY_BUF) goto recover_immediately; magic32 = be32_to_cpu(*(__be32 *)blk); switch (magic32) { + case XFS_RTBITMAP_MAGIC: { + struct xfs_rtbuf_blkinfo *hdr = blk; + + lsn = be64_to_cpu(hdr->rt_lsn); + uuid = &hdr->rt_uuid; + break; + } case XFS_ABTB_CRC_MAGIC: case XFS_ABTC_CRC_MAGIC: case XFS_ABTB_MAGIC: diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 7e86aa137d1fa..14094b29ab6fe 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -125,7 +125,8 @@ typedef struct xfs_mount { int8_t m_rgblklog; /* log2 of rt group sz if possible */ uint m_blockmask; /* sb_blocksize-1 */ uint m_blockwsize; /* sb_blocksize in words */ - uint m_blockwmask; /* blockwsize-1 */ + /* number of rt extents per rt bitmap block if rtgroups enabled */ + unsigned int m_rtx_per_rbmblock; uint m_alloc_mxr[2]; /* max alloc btree records */ uint m_alloc_mnr[2]; /* min alloc btree records */ uint m_bmap_dmxr[2]; /* max bmap btree records */ diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 23a15700d3596..924266978ca27 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -761,6 +761,42 @@ xfs_rtallocate_extent_size( return 0; } +/* Get a buffer for the block. */ +static int +xfs_growfs_init_rtbuf( + struct xfs_trans *tp, + struct xfs_inode *ip, + xfs_fsblock_t fsbno, + enum xfs_blft buf_type) +{ + struct xfs_mount *mp = tp->t_mountp; + struct xfs_buf *bp; + xfs_daddr_t d; + int error; + + d = XFS_FSB_TO_DADDR(mp, fsbno); + error = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, 0, + &bp); + if (error) + return error; + + xfs_trans_buf_set_type(tp, bp, buf_type); + bp->b_ops = xfs_rtblock_ops(mp, buf_type == XFS_BLFT_RTSUMMARY_BUF); + memset(bp->b_addr, 0, mp->m_sb.sb_blocksize); + + if (xfs_has_rtgroups(mp) && buf_type == XFS_BLFT_RTBITMAP_BUF) { + struct xfs_rtbuf_blkinfo *hdr = bp->b_addr; + + hdr->rt_magic = cpu_to_be32(XFS_RTBITMAP_MAGIC); + hdr->rt_owner = cpu_to_be64(ip->i_ino); + hdr->rt_blkno = cpu_to_be64(d); + uuid_copy(&hdr->rt_uuid, &mp->m_sb.sb_meta_uuid); + } + + xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1); + return 0; +} + /* * Allocate space to the bitmap or summary file, and zero it, for growfs. */ @@ -772,8 +808,6 @@ xfs_growfs_rt_alloc( struct xfs_inode *ip) /* inode (bitmap/summary) */ { xfs_fileoff_t bno; /* block number in file */ - struct xfs_buf *bp; /* temporary buffer for zeroing */ - xfs_daddr_t d; /* disk block address */ int error; /* error return value */ xfs_fsblock_t fsbno; /* filesystem block for bno */ struct xfs_bmbt_irec map; /* block map output */ @@ -848,19 +882,11 @@ xfs_growfs_rt_alloc( */ xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); - /* - * Get a buffer for the block. - */ - d = XFS_FSB_TO_DADDR(mp, fsbno); - error = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, - mp->m_bsize, 0, &bp); + + error = xfs_growfs_init_rtbuf(tp, ip, fsbno, buf_type); if (error) goto out_trans_cancel; - xfs_trans_buf_set_type(tp, bp, buf_type); - bp->b_ops = &xfs_rtbuf_ops; - memset(bp->b_addr, 0, mp->m_sb.sb_blocksize); - xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1); /* * Commit the transaction. */ @@ -1133,10 +1159,10 @@ xfs_growfs_rt( * Skip the current block if it is exactly full. * This also deals with the case where there were no rtextents before. */ - for (bmbno = sbp->sb_rbmblocks - - ((sbp->sb_rextents & ((1 << mp->m_blkbit_log) - 1)) != 0); - bmbno < nrbmblocks; - bmbno++) { + bmbno = sbp->sb_rbmblocks; + if (xfs_rtx_to_rbmword(mp, sbp->sb_rextents) != 0) + bmbno--; + for (; bmbno < nrbmblocks; bmbno++) { struct xfs_rtalloc_args args = { .mp = mp, }; @@ -1157,7 +1183,7 @@ xfs_growfs_rt( nsbp->sb_rextsize = in->extsize; nmp->m_rtxblklog = -1; /* don't use shift or masking */ nsbp->sb_rbmblocks = bmbno + 1; - nrblocks_step = (bmbno + 1) * NBBY * nsbp->sb_blocksize * + nrblocks_step = (bmbno + 1) * mp->m_rtx_per_rbmblock * nsbp->sb_rextsize; nsbp->sb_rblocks = min(nrblocks, nrblocks_step); nsbp->sb_rextents = xfs_rtb_to_rtx(nmp, nsbp->sb_rblocks); From patchwork Sun Dec 31 21:19:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507612 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 E3E5FB67F for ; Sun, 31 Dec 2023 21:19:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="vCnYSwfK" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B70BFC433C7; Sun, 31 Dec 2023 21:19:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704057587; bh=9+b3UQ29MtamCja/XSHqjFRyedG+1c11tn/lKyuLVLI=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=vCnYSwfKl0xK97aq5wOxqsibRk1PhvECs19oFKcCa78zNBiuI8oQnGIKYsqindd1g CIGTu/On/MT5ardpJvsZAlnejkhyduu+Bd0OQwqqzIIGjtnjCLMC3XkUAVihM7olvM 68Q8y6K0Pxz8E4KPJavxoJ7mNi+Zv9YAZy5zbn9a+jPD51ZLu2k3yv1N3Uw5Wh7fOA y8M5g3sG7858KXWxVLNnDp1bpEGH2TYnBuHNwybjYP1WjRZb9T2ZeLFjkMbpSK28TH 80RXOviaOrdZ64bYCPQD5e8GXuQ84z5tU6n2sOIB7wMXnM7OHt0WoxGu7H3FsA5rI0 1y1wrQUZVvl0g== Date: Sun, 31 Dec 2023 13:19:47 -0800 Subject: [PATCH 16/24] xfs: encode the rtbitmap in little endian format From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404846496.1763124.7029031511754234393.stgit@frogsfrogsfrogs> In-Reply-To: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> References: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Currently, the ondisk realtime bitmap file is accessed in units of 32-bit words. There's no endian translation of the contents of this file, which means that the Bad Things Happen(tm) if you go from (say) x86 to powerpc. Since we have a new feature flag, let's take the opportunity to enforce an endianness on the file. The natural format of a bitmap is (IMHO) little endian, because the byte offsets of the bitmap data should always increase in step with the information being indexed. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_format.h | 4 +++- fs/xfs/libxfs/xfs_rtbitmap.h | 7 ++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index 7178bd463c1c0..77422fbd3372e 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -749,10 +749,12 @@ struct xfs_agfl { /* * Realtime bitmap information is accessed by the word, which is currently - * stored in host-endian format. + * stored in host-endian format. Starting with the realtime groups feature, + * the words are stored in le32 ondisk. */ union xfs_rtword_raw { __u32 old; + __le32 rtg; }; /* diff --git a/fs/xfs/libxfs/xfs_rtbitmap.h b/fs/xfs/libxfs/xfs_rtbitmap.h index e1cf47d2a9281..588689e53ba39 100644 --- a/fs/xfs/libxfs/xfs_rtbitmap.h +++ b/fs/xfs/libxfs/xfs_rtbitmap.h @@ -208,6 +208,8 @@ xfs_rtbitmap_getword( { union xfs_rtword_raw *word = xfs_rbmblock_wordptr(args, index); + if (xfs_has_rtgroups(args->mp)) + return le32_to_cpu(word->rtg); return word->old; } @@ -220,7 +222,10 @@ xfs_rtbitmap_setword( { union xfs_rtword_raw *word = xfs_rbmblock_wordptr(args, index); - word->old = value; + if (xfs_has_rtgroups(args->mp)) + word->rtg = cpu_to_le32(value); + else + word->old = value; } /* From patchwork Sun Dec 31 21:20:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507613 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 868B0BE48 for ; Sun, 31 Dec 2023 21:20:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ljxUSdQW" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5325BC433C8; Sun, 31 Dec 2023 21:20:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704057603; bh=NMudRqQsATVukR8CZgrvUnd0IKc5A2hzlwaNRSauDQs=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=ljxUSdQWmeIsG1OPowzkV5Ei/uD6rVeVIAH9O3IgZIuO4Ex/MG4saHkJ1U0QKenC2 JPwRslaEkSrUfQp0Fd3PRqnV1J5jbIpdhWS8xHiq5I4SOhPZUwl6WPvxJbD79m+70w 3tTTtuUpNJfplMa27ZNpuN5L4xBRQN+V+ScBEkLhkjI6nSRNAjgtoQ/Crk71hq7J2S HEXOamc0+mjKmoJtYpd4WG26QvJNRS4KaE9CfhZAY+eJBRJl1+0TqfK2/wLJEQ2+uR 3X02Jdd5pewECUMr22567HQ/xZxqKULQSh5xTdub4gTDKP6eOOMxTfZOEL3UhJ6VtY LQ4wMBXpZLhdg== Date: Sun, 31 Dec 2023 13:20:02 -0800 Subject: [PATCH 17/24] xfs: add block headers to realtime summary blocks From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404846512.1763124.5719004400299158627.stgit@frogsfrogsfrogs> In-Reply-To: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> References: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Upgrade rtsummary blocks to have self describing metadata like most every other thing in XFS. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_format.h | 1 + fs/xfs/libxfs/xfs_rtbitmap.c | 18 +++++++++++++++--- fs/xfs/libxfs/xfs_rtbitmap.h | 19 +++++++++++++++++-- fs/xfs/libxfs/xfs_shared.h | 1 + fs/xfs/scrub/rtsummary_repair.c | 15 +++++++++++++-- fs/xfs/xfs_buf_item_recover.c | 11 +++++++---- fs/xfs/xfs_rtalloc.c | 7 +++++-- 7 files changed, 59 insertions(+), 13 deletions(-) diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index 77422fbd3372e..f2c70e1027ed7 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -1303,6 +1303,7 @@ static inline bool xfs_dinode_has_large_extent_counts( * RT bit manipulation macros. */ #define XFS_RTBITMAP_MAGIC 0x424D505A /* BMPZ */ +#define XFS_RTSUMMARY_MAGIC 0x53554D59 /* SUMY */ struct xfs_rtbuf_blkinfo { __be32 rt_magic; /* validity check on block */ diff --git a/fs/xfs/libxfs/xfs_rtbitmap.c b/fs/xfs/libxfs/xfs_rtbitmap.c index 4d85b8ea9a861..3530524b3fc2b 100644 --- a/fs/xfs/libxfs/xfs_rtbitmap.c +++ b/fs/xfs/libxfs/xfs_rtbitmap.c @@ -53,7 +53,7 @@ xfs_rtbuf_verify_read( struct xfs_rtbuf_blkinfo *hdr = bp->b_addr; xfs_failaddr_t fa; - if (!xfs_has_rtgroups(mp) || bp->b_ops != &xfs_rtbitmap_buf_ops) + if (!xfs_has_rtgroups(mp)) return; if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr->rt_lsn))) { @@ -84,7 +84,7 @@ xfs_rtbuf_verify_write( struct xfs_buf_log_item *bip = bp->b_log_item; xfs_failaddr_t fa; - if (!xfs_has_rtgroups(mp) || bp->b_ops != &xfs_rtbitmap_buf_ops) + if (!xfs_has_rtgroups(mp)) return; fa = xfs_rtbuf_verify(bp); @@ -112,6 +112,14 @@ const struct xfs_buf_ops xfs_rtbitmap_buf_ops = { .verify_struct = xfs_rtbuf_verify, }; +const struct xfs_buf_ops xfs_rtsummary_buf_ops = { + .name = "xfs_rtsummary", + .magic = { 0, cpu_to_be32(XFS_RTSUMMARY_MAGIC) }, + .verify_read = xfs_rtbuf_verify_read, + .verify_write = xfs_rtbuf_verify_write, + .verify_struct = xfs_rtbuf_verify, +}; + /* Release cached rt bitmap and summary buffers. */ void xfs_rtbuf_cache_relse( @@ -197,7 +205,7 @@ xfs_rtbuf_get( if (error) return error; - if (xfs_has_rtgroups(mp) && !issum) { + if (xfs_has_rtgroups(mp)) { struct xfs_rtbuf_blkinfo *hdr = bp->b_addr; if (hdr->rt_owner != cpu_to_be64(ip->i_ino)) { @@ -1277,6 +1285,10 @@ xfs_rtsummary_blockcount( unsigned long long rsumwords; rsumwords = (unsigned long long)rsumlevels * rbmblocks; + + if (xfs_has_rtgroups(mp)) + return howmany_64(rsumwords, mp->m_blockwsize); + return XFS_B_TO_FSB(mp, rsumwords << XFS_WORDLOG); } diff --git a/fs/xfs/libxfs/xfs_rtbitmap.h b/fs/xfs/libxfs/xfs_rtbitmap.h index 588689e53ba39..e8558db14b9b7 100644 --- a/fs/xfs/libxfs/xfs_rtbitmap.h +++ b/fs/xfs/libxfs/xfs_rtbitmap.h @@ -250,6 +250,9 @@ xfs_rtsumoffs_to_block( struct xfs_mount *mp, xfs_rtsumoff_t rsumoff) { + if (xfs_has_rtgroups(mp)) + return rsumoff / mp->m_blockwsize; + return XFS_B_TO_FSBT(mp, rsumoff * sizeof(xfs_suminfo_t)); } @@ -264,6 +267,9 @@ xfs_rtsumoffs_to_infoword( { unsigned int mask = mp->m_blockmask >> XFS_SUMINFOLOG; + if (xfs_has_rtgroups(mp)) + return rsumoff % mp->m_blockwsize; + return rsumoff & mask; } @@ -273,7 +279,13 @@ xfs_rsumblock_infoptr( struct xfs_rtalloc_args *args, unsigned int index) { - union xfs_suminfo_raw *info = args->sumbp->b_addr; + union xfs_suminfo_raw *info; + struct xfs_rtbuf_blkinfo *hdr = args->sumbp->b_addr; + + if (xfs_has_rtgroups(args->mp)) + info = (union xfs_suminfo_raw *)(hdr + 1); + else + info = args->sumbp->b_addr; return info + index; } @@ -307,8 +319,11 @@ xfs_rtblock_ops( struct xfs_mount *mp, bool issum) { - if (xfs_has_rtgroups(mp) && !issum) + if (xfs_has_rtgroups(mp)) { + if (issum) + return &xfs_rtsummary_buf_ops; return &xfs_rtbitmap_buf_ops; + } return &xfs_rtbuf_ops; } diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h index f57788164a702..8ad4b67d6febb 100644 --- a/fs/xfs/libxfs/xfs_shared.h +++ b/fs/xfs/libxfs/xfs_shared.h @@ -39,6 +39,7 @@ extern const struct xfs_buf_ops xfs_inode_buf_ra_ops; extern const struct xfs_buf_ops xfs_refcountbt_buf_ops; extern const struct xfs_buf_ops xfs_rmapbt_buf_ops; extern const struct xfs_buf_ops xfs_rtbitmap_buf_ops; +extern const struct xfs_buf_ops xfs_rtsummary_buf_ops; extern const struct xfs_buf_ops xfs_rtbuf_ops; extern const struct xfs_buf_ops xfs_rtsb_buf_ops; extern const struct xfs_buf_ops xfs_sb_buf_ops; diff --git a/fs/xfs/scrub/rtsummary_repair.c b/fs/xfs/scrub/rtsummary_repair.c index 058c5ebabf9a2..c66373eec436d 100644 --- a/fs/xfs/scrub/rtsummary_repair.c +++ b/fs/xfs/scrub/rtsummary_repair.c @@ -87,12 +87,23 @@ xrep_rtsummary_prep_buf( ondisk = xfs_rsumblock_infoptr(&rts->args, 0); rts->args.sumbp = NULL; - bp->b_ops = &xfs_rtbuf_ops; - error = xfsum_copyout(sc, rts->prep_wordoff, ondisk, mp->m_blockwsize); if (error) return error; + if (xfs_has_rtgroups(sc->mp)) { + struct xfs_rtbuf_blkinfo *hdr = bp->b_addr; + + hdr->rt_magic = cpu_to_be32(XFS_RTSUMMARY_MAGIC); + hdr->rt_owner = cpu_to_be64(sc->ip->i_ino); + hdr->rt_blkno = cpu_to_be64(xfs_buf_daddr(bp)); + hdr->rt_lsn = 0; + uuid_copy(&hdr->rt_uuid, &sc->mp->m_sb.sb_meta_uuid); + bp->b_ops = &xfs_rtsummary_buf_ops; + } else { + bp->b_ops = &xfs_rtbuf_ops; + } + rts->prep_wordoff += mp->m_blockwsize; xfs_trans_buf_set_type(sc->tp, bp, XFS_BLFT_RTSUMMARY_BUF); return 0; diff --git a/fs/xfs/xfs_buf_item_recover.c b/fs/xfs/xfs_buf_item_recover.c index 448df616e975e..2e617041161e0 100644 --- a/fs/xfs/xfs_buf_item_recover.c +++ b/fs/xfs/xfs_buf_item_recover.c @@ -399,7 +399,10 @@ xlog_recover_validate_buf_type( bp->b_ops = xfs_rtblock_ops(mp, false); break; case XFS_BLFT_RTSUMMARY_BUF: - /* no magic numbers for verification of RT buffers */ + if (xfs_has_rtgroups(mp) && magic32 != XFS_RTSUMMARY_MAGIC) { + warnmsg = "Bad rtsummary magic!"; + break; + } bp->b_ops = xfs_rtblock_ops(mp, true); break; #endif /* CONFIG_XFS_RT */ @@ -735,13 +738,13 @@ xlog_recover_get_buf_lsn( * UUIDs, so we must recover them immediately. */ blft = xfs_blft_from_flags(buf_f); - if (!xfs_has_rtgroups(mp) && blft == XFS_BLFT_RTBITMAP_BUF) - goto recover_immediately; - if (blft == XFS_BLFT_RTSUMMARY_BUF) + if (!xfs_has_rtgroups(mp) && (blft == XFS_BLFT_RTBITMAP_BUF || + blft == XFS_BLFT_RTSUMMARY_BUF)) goto recover_immediately; magic32 = be32_to_cpu(*(__be32 *)blk); switch (magic32) { + case XFS_RTSUMMARY_MAGIC: case XFS_RTBITMAP_MAGIC: { struct xfs_rtbuf_blkinfo *hdr = blk; diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 924266978ca27..ff08c1d997fdb 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -784,10 +784,13 @@ xfs_growfs_init_rtbuf( bp->b_ops = xfs_rtblock_ops(mp, buf_type == XFS_BLFT_RTSUMMARY_BUF); memset(bp->b_addr, 0, mp->m_sb.sb_blocksize); - if (xfs_has_rtgroups(mp) && buf_type == XFS_BLFT_RTBITMAP_BUF) { + if (xfs_has_rtgroups(mp)) { struct xfs_rtbuf_blkinfo *hdr = bp->b_addr; - hdr->rt_magic = cpu_to_be32(XFS_RTBITMAP_MAGIC); + if (buf_type == XFS_BLFT_RTBITMAP_BUF) + hdr->rt_magic = cpu_to_be32(XFS_RTBITMAP_MAGIC); + else + hdr->rt_magic = cpu_to_be32(XFS_RTSUMMARY_MAGIC); hdr->rt_owner = cpu_to_be64(ip->i_ino); hdr->rt_blkno = cpu_to_be64(d); uuid_copy(&hdr->rt_uuid, &mp->m_sb.sb_meta_uuid); From patchwork Sun Dec 31 21:20:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507614 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 72767BE47 for ; Sun, 31 Dec 2023 21:20:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="uQsQNKxU" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 07728C433C8; Sun, 31 Dec 2023 21:20:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704057619; bh=YBnL93N1sDtUjjwf2KxM+bGeZhbLzyufyZ+rKEkfWxo=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=uQsQNKxUWzEIuNCJzjrh+tJd0PtMO4xUI/8TeIghfQagbEuZgUoUsGtZ9Q/gfOcmg jexvacHnyzAeo4GOs0jjDlPIO2xuuV7xDCvjdxEZycOIcxb12ytylI2M4caCEvhXT7 Ze/DDUeAB0gYBVgfeaEZLHxbht40GwDFIGBYSCSOPnK5j3t3Ss6t6X45VNzNtSlYBY nwUSV+w26oUjTnABjaY6yvkJVHMJxoBDofB6reAid2JSXEYc9Fo31mtFPLuZMLuFve toT0EX7ZlcDepqfH9x1PSpyA57pSiOSADwLBT8tc5wgkkl2ImvL5iKaXufN4Ygncv2 uCwV52ojF2j0A== Date: Sun, 31 Dec 2023 13:20:18 -0800 Subject: [PATCH 18/24] xfs: encode the rtsummary in big endian format From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404846529.1763124.15100521804833298198.stgit@frogsfrogsfrogs> In-Reply-To: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> References: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Currently, the ondisk realtime summary file counters are accessed in units of 32-bit words. There's no endian translation of the contents of this file, which means that the Bad Things Happen(tm) if you go from (say) x86 to powerpc. Since we have a new feature flag, let's take the opportunity to enforce an endianness on the file. Encode the summary information in big endian format, like most of the rest of the filesystem. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_format.h | 4 +++- fs/xfs/libxfs/xfs_rtbitmap.h | 7 +++++++ fs/xfs/scrub/rtsummary.c | 5 +++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index f2c70e1027ed7..59ba13db53e7a 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -759,10 +759,12 @@ union xfs_rtword_raw { /* * Realtime summary counts are accessed by the word, which is currently - * stored in host-endian format. + * stored in host-endian format. Starting with the realtime groups feature, + * the words are stored in be32 ondisk. */ union xfs_suminfo_raw { __u32 old; + __be32 rtg; }; /* diff --git a/fs/xfs/libxfs/xfs_rtbitmap.h b/fs/xfs/libxfs/xfs_rtbitmap.h index e8558db14b9b7..0bb63f77ede82 100644 --- a/fs/xfs/libxfs/xfs_rtbitmap.h +++ b/fs/xfs/libxfs/xfs_rtbitmap.h @@ -298,6 +298,8 @@ xfs_suminfo_get( { union xfs_suminfo_raw *info = xfs_rsumblock_infoptr(args, index); + if (xfs_has_rtgroups(args->mp)) + return be32_to_cpu(info->rtg); return info->old; } @@ -310,6 +312,11 @@ xfs_suminfo_add( { union xfs_suminfo_raw *info = xfs_rsumblock_infoptr(args, index); + if (xfs_has_rtgroups(args->mp)) { + be32_add_cpu(&info->rtg, delta); + return be32_to_cpu(info->rtg); + } + info->old += delta; return info->old; } diff --git a/fs/xfs/scrub/rtsummary.c b/fs/xfs/scrub/rtsummary.c index df9aa29cb94c6..5107873775b7f 100644 --- a/fs/xfs/scrub/rtsummary.c +++ b/fs/xfs/scrub/rtsummary.c @@ -142,6 +142,11 @@ xchk_rtsum_inc( struct xfs_mount *mp, union xfs_suminfo_raw *v) { + if (xfs_has_rtgroups(mp)) { + be32_add_cpu(&v->rtg, 1); + return be32_to_cpu(v->rtg); + } + v->old += 1; return v->old; } From patchwork Sun Dec 31 21:20:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507615 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 D88C9BE4A for ; Sun, 31 Dec 2023 21:20:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="WwwBTEtG" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A5F38C433C7; Sun, 31 Dec 2023 21:20:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704057634; bh=5//ySmczwmtz2XgpwFe4TCs4eQeGTlsg3pu8hJVY7xs=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=WwwBTEtGvSWMkUwpTNQJ/qngOo0QhCg3blNXYobjLTAJB1RiCmnXZmrINfkQFYyGg fnEm/uHwU+UbRjAOSth/H9MArkWF8oM8EK/1oJHe/0RaEqMdKh4GdNjBAcj+AEP002 DS/LtpAYggY0nx/JZEpRYy8WBvM07zfn6wI0s+MAu3ZNkkC7vMQJfKF4M5OBj28xfL 4ttY2EOxNzehKhALNm5ezxCWuVstjc4yf9d1Zl5GkteIPxxj83EbaTD4mGl3PWed6L x4GTbvlW3POx/PeGIdYTFpZQHl3LTAgACCAMZly+W5vS9NT33gPsvbvi35sIiMdeoQ RAd8mVJ4T5XAA== Date: Sun, 31 Dec 2023 13:20:34 -0800 Subject: [PATCH 19/24] xfs: store rtgroup information with a bmap intent From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404846544.1763124.14189276181526727693.stgit@frogsfrogsfrogs> In-Reply-To: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> References: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 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 the bmap intent items take an active reference to the rtgroup containing the space that is being mapped or unmapped. We will need this functionality once we start enabling rmap and reflink on the rt volume. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_bmap.h | 5 ++++- fs/xfs/xfs_bmap_item.c | 18 ++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h index bd7f936262cc6..61c195198db43 100644 --- a/fs/xfs/libxfs/xfs_bmap.h +++ b/fs/xfs/libxfs/xfs_bmap.h @@ -246,7 +246,10 @@ struct xfs_bmap_intent { enum xfs_bmap_intent_type bi_type; int bi_whichfork; struct xfs_inode *bi_owner; - struct xfs_perag *bi_pag; + union { + struct xfs_perag *bi_pag; + struct xfs_rtgroup *bi_rtg; + }; struct xfs_bmbt_irec bi_bmap; }; diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c index 02b872a133104..234296a37b269 100644 --- a/fs/xfs/xfs_bmap_item.c +++ b/fs/xfs/xfs_bmap_item.c @@ -26,6 +26,7 @@ #include "xfs_log_recover.h" #include "xfs_ag.h" #include "xfs_trace.h" +#include "xfs_rtgroup.h" struct kmem_cache *xfs_bui_cache; struct kmem_cache *xfs_bud_cache; @@ -326,8 +327,18 @@ xfs_bmap_update_get_group( { xfs_agnumber_t agno; - if (xfs_ifork_is_realtime(bi->bi_owner, bi->bi_whichfork)) + if (xfs_ifork_is_realtime(bi->bi_owner, bi->bi_whichfork)) { + if (xfs_has_rtgroups(mp)) { + xfs_rgnumber_t rgno; + + rgno = xfs_rtb_to_rgno(mp, bi->bi_bmap.br_startblock); + bi->bi_rtg = xfs_rtgroup_get(mp, rgno); + } else { + bi->bi_rtg = NULL; + } + return; + } agno = XFS_FSB_TO_AGNO(mp, bi->bi_bmap.br_startblock); @@ -358,8 +369,11 @@ static inline void xfs_bmap_update_put_group( struct xfs_bmap_intent *bi) { - if (xfs_ifork_is_realtime(bi->bi_owner, bi->bi_whichfork)) + if (xfs_ifork_is_realtime(bi->bi_owner, bi->bi_whichfork)) { + if (xfs_has_rtgroups(bi->bi_owner->i_mount)) + xfs_rtgroup_put(bi->bi_rtg); return; + } xfs_perag_intent_put(bi->bi_pag); } From patchwork Sun Dec 31 21:20:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507616 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 7E980BE47 for ; Sun, 31 Dec 2023 21:20:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="gDuCOgYu" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 52A32C433C8; Sun, 31 Dec 2023 21:20:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704057650; bh=3mZoU9XTsVX45m6pqc1e/d18VzDo3r7ZepREwPb1iYk=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=gDuCOgYu4AadnkEHdVHWaDJ2l1FTesA0tUaP4UHtC4IYG73Dc8OP17S78Imc1BVGS YOvM0WxQbxC0ybDJP7IHMWEVU8zfyvIC856BYBqVp8tNDgtHYUdNkIe9uednvt44n+ gCn/OJaVbntQaUufhfEBZszt7mN3hy5tQSRRfVFZU+LGFSgkGLCE8JjzLe971zEIOU NjxWvhXzvkw7bqyvmDTpLN4yhw9ezjaLcCFc8uMcOeLrFERyqfCXWQ8bptoJIPCbyX 6r5tV7kQg2xT7XGo43C9Uf7aq1+eVM7GE/7T4xmlFbtV2r0FIprX6i7CKzVm1jo7di NDVi7tazCWsCg== Date: Sun, 31 Dec 2023 13:20:49 -0800 Subject: [PATCH 20/24] xfs: use an incore rtgroup rotor for rtpick From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404846560.1763124.10631906687948394801.stgit@frogsfrogsfrogs> In-Reply-To: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> References: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong During the 6.7 merge window, Linus noticed that the realtime allocator was doing some sketchy things trying to encode a u64 sequence counter into the rtbitmap file's atime. The sketchy casting of a struct pointer to a u64 pointer has subtly broken several times over the past decade as the codebase has transitioned to using the VFS i_atime field and that field has changed in size and layout over time. Since the goal of the rtpick code is to _suggest_ a starting place for new rt file allocations, the repeated breakage has not resulted in inconsistent metadata. IOWs, it's a hint. For rtgroups, we don't need this complex code to cut the rtextents space into fractions. Add an rtgroup rotor and use that for rtpick, similar to AG rotoring on the data device. The new rotor does not persist, which reduces the logging overhead slightly. Link: https://lore.kernel.org/linux-xfs/CAHk-=wj3oM3d-Hw2vvxys3KCZ9De+gBN7Gxr2jf96OTisL9udw@mail.gmail.com/ Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_rtbitmap.c | 12 ++++++++---- fs/xfs/xfs_mount.h | 1 + fs/xfs/xfs_rtalloc.c | 11 +++++++++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/fs/xfs/libxfs/xfs_rtbitmap.c b/fs/xfs/libxfs/xfs_rtbitmap.c index 3530524b3fc2b..0ef14157e8157 100644 --- a/fs/xfs/libxfs/xfs_rtbitmap.c +++ b/fs/xfs/libxfs/xfs_rtbitmap.c @@ -1064,10 +1064,14 @@ xfs_rtfree_extent( if (!(mp->m_rbmip->i_diflags & XFS_DIFLAG_NEWRTBM)) mp->m_rbmip->i_diflags |= XFS_DIFLAG_NEWRTBM; - atime = inode_get_atime(VFS_I(mp->m_rbmip)); - atime.tv_sec = 0; - inode_set_atime_to_ts(VFS_I(mp->m_rbmip), atime); - xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE); + if (xfs_has_rtgroups(mp)) { + mp->m_rtgrotor = 0; + } else { + atime = inode_get_atime(VFS_I(mp->m_rbmip)); + atime.tv_sec = 0; + inode_set_atime_to_ts(VFS_I(mp->m_rbmip), atime); + xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE); + } } error = 0; out: diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 14094b29ab6fe..a086b96b0a513 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -224,6 +224,7 @@ typedef struct xfs_mount { #ifdef CONFIG_XFS_ONLINE_SCRUB_STATS struct xchk_stats *m_scrub_stats; #endif + xfs_rgnumber_t m_rtgrotor; /* last rtgroup rtpicked */ xfs_agnumber_t m_agfrotor; /* last ag where space found */ atomic_t m_agirotor; /* last ag dir inode alloced */ diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index ff08c1d997fdb..6479bb04657ec 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -1688,6 +1688,17 @@ xfs_rtpick_extent( ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL)); + if (xfs_has_rtgroups(mp)) { + xfs_rtblock_t rtbno; + + /* Pick the first usable rtx of the group. */ + rtbno = xfs_rgbno_to_rtb(mp, mp->m_rtgrotor, 0); + *pick = xfs_rtb_to_rtx(mp, rtbno) + 1; + + mp->m_rtgrotor = (mp->m_rtgrotor + 1) % mp->m_sb.sb_rgcount; + return 0; + } + ts = inode_get_atime(VFS_I(mp->m_rbmip)); if (!(mp->m_rbmip->i_diflags & XFS_DIFLAG_NEWRTBM)) { mp->m_rbmip->i_diflags |= XFS_DIFLAG_NEWRTBM; From patchwork Sun Dec 31 21:21:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507617 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 3C109BA2B for ; Sun, 31 Dec 2023 21:21:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="it/mZKOC" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0A4C4C433C7; Sun, 31 Dec 2023 21:21:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704057666; bh=gZS+Di5Rdrc58RCqwPES7BV0rAEd9DXrWlJyM1xGvbk=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=it/mZKOCb8ppnyWX0OqbSM1pf9S/rwTERygcigWR6Oiecpx5C0gMA4jRvx802jQP5 XF2hRp2Hoa8Nd3nd3rMGgLRw9GsvZg82402hMB+pB4vgy1sdy+LJ6jYC4op/tcqjgi QXSQ5UHlxHan4CGb7vSYrKDgMzJw8yTK6dtk5w+r7JKgfp3DfTI+BDbxsRJN1KoiYi /z2SQ/txttzc0pWQsoPvMn7pVg1CgGFrLuRqW4VfgF6vO5v5mAmz+b8ZBE6AFWGCdk +oKQUWxz5gsexjl7U+dZazOqUNC8bInIquKFRi6SpjoKAyo1DQZDHu8B3GsDUYFsty X748SSsFuYjzQ== Date: Sun, 31 Dec 2023 13:21:05 -0800 Subject: [PATCH 21/24] xfs: scrub the realtime group superblock From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404846576.1763124.1964293867828384078.stgit@frogsfrogsfrogs> In-Reply-To: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> References: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Enable scrubbing of realtime group superblocks. Signed-off-by: Darrick J. Wong --- fs/xfs/Makefile | 1 + fs/xfs/libxfs/xfs_fs.h | 3 +- fs/xfs/scrub/common.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/scrub/common.h | 46 ++++++++++++++----------- fs/xfs/scrub/health.c | 1 + fs/xfs/scrub/rgsuper.c | 77 ++++++++++++++++++++++++++++++++++++++++++ fs/xfs/scrub/scrub.c | 20 ++++++++++- fs/xfs/scrub/scrub.h | 40 ++++++++++------------ fs/xfs/scrub/stats.c | 1 + fs/xfs/scrub/trace.h | 4 ++ 10 files changed, 237 insertions(+), 44 deletions(-) create mode 100644 fs/xfs/scrub/rgsuper.c diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 500dea292a9d6..7416ab9efc4d8 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -190,6 +190,7 @@ xfs-y += $(addprefix scrub/, \ xfs-$(CONFIG_XFS_ONLINE_SCRUB_STATS) += scrub/stats.o xfs-$(CONFIG_XFS_RT) += $(addprefix scrub/, \ + rgsuper.o \ rtbitmap.o \ rtsummary.o \ ) diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index c5bf53c6a43ca..237d13a500daf 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -735,9 +735,10 @@ struct xfs_scrub_metadata { #define XFS_SCRUB_TYPE_HEALTHY 27 /* everything checked out ok */ #define XFS_SCRUB_TYPE_DIRTREE 28 /* directory tree structure */ #define XFS_SCRUB_TYPE_METAPATH 29 /* metadata directory tree paths */ +#define XFS_SCRUB_TYPE_RGSUPER 30 /* realtime superblock */ /* Number of scrub subcommands. */ -#define XFS_SCRUB_TYPE_NR 30 +#define XFS_SCRUB_TYPE_NR 31 /* * This special type code only applies to the vectored scrub implementation. diff --git a/fs/xfs/scrub/common.c b/fs/xfs/scrub/common.c index e9294a933c3ab..3dee7d717073e 100644 --- a/fs/xfs/scrub/common.c +++ b/fs/xfs/scrub/common.c @@ -34,6 +34,7 @@ #include "xfs_quota.h" #include "xfs_swapext.h" #include "xfs_rtbitmap.h" +#include "xfs_rtgroup.h" #include "scrub/scrub.h" #include "scrub/common.h" #include "scrub/trace.h" @@ -121,6 +122,17 @@ xchk_process_error( XFS_SCRUB_OFLAG_CORRUPT, __return_address); } +bool +xchk_process_rt_error( + struct xfs_scrub *sc, + xfs_rgnumber_t rgno, + xfs_rgblock_t rgbno, + int *error) +{ + return __xchk_process_error(sc, rgno, rgbno, error, + XFS_SCRUB_OFLAG_CORRUPT, __return_address); +} + bool xchk_xref_process_error( struct xfs_scrub *sc, @@ -132,6 +144,17 @@ xchk_xref_process_error( XFS_SCRUB_OFLAG_XFAIL, __return_address); } +bool +xchk_xref_process_rt_error( + struct xfs_scrub *sc, + xfs_rgnumber_t rgno, + xfs_rgblock_t rgbno, + int *error) +{ + return __xchk_process_error(sc, rgno, rgbno, error, + XFS_SCRUB_OFLAG_XFAIL, __return_address); +} + /* Check for operational errors for a file offset. */ static bool __xchk_fblock_process_error( @@ -699,6 +722,7 @@ xchk_rt_init( XCHK_RTLOCK_BITMAP_SHARED)) < 2); ASSERT(hweight32(rtlock_flags & (XCHK_RTLOCK_SUMMARY | XCHK_RTLOCK_SUMMARY_SHARED)) < 2); + ASSERT(sr->rtg == NULL); if (rtlock_flags & XCHK_RTLOCK_BITMAP) xfs_ilock(sc->mp->m_rbmip, XFS_ILOCK_EXCL); @@ -722,6 +746,8 @@ xchk_rt_unlock( struct xfs_scrub *sc, struct xchk_rt *sr) { + ASSERT(sr->rtg == NULL); + if (!sr->rtlock_flags) return; @@ -749,6 +775,68 @@ xchk_rt_unlock_rtbitmap( sc->sr.rtlock_flags &= ~XCHK_RTLOCK_BITMAP_SHARED; } +#ifdef CONFIG_XFS_RT +/* + * For scrubbing a realtime group, grab all the in-core resources we'll need to + * check the metadata, which means taking the ILOCK of the realtime group's + * metadata inodes. Callers must not join these inodes to the transaction with + * non-zero lockflags or concurrency problems will result. The @rtglock_flags + * argument takes XFS_RTGLOCK_* flags. + */ +int +xchk_rtgroup_init( + struct xfs_scrub *sc, + xfs_rgnumber_t rgno, + struct xchk_rt *sr, + unsigned int rtglock_flags) +{ + ASSERT(sr->rtg == NULL); + ASSERT(sr->rtlock_flags == 0); + + sr->rtg = xfs_rtgroup_get(sc->mp, rgno); + if (!sr->rtg) + return -ENOENT; + + xfs_rtgroup_lock(NULL, sr->rtg, rtglock_flags); + sr->rtlock_flags = rtglock_flags; + return 0; +} + +/* + * Unlock the realtime group. This must be done /after/ committing (or + * cancelling) the scrub transaction. + */ +void +xchk_rtgroup_unlock( + struct xfs_scrub *sc, + struct xchk_rt *sr) +{ + ASSERT(sr->rtg != NULL); + + if (sr->rtlock_flags) { + xfs_rtgroup_unlock(sr->rtg, sr->rtlock_flags); + sr->rtlock_flags = 0; + } +} + +/* + * Unlock the realtime group and release its resources. This must be done + * /after/ committing (or cancelling) the scrub transaction. + */ +void +xchk_rtgroup_free( + struct xfs_scrub *sc, + struct xchk_rt *sr) +{ + ASSERT(sr->rtg != NULL); + + xchk_rtgroup_unlock(sc, sr); + + xfs_rtgroup_put(sr->rtg); + sr->rtg = NULL; +} +#endif /* CONFIG_XFS_RT */ + /* Per-scrubber setup functions */ void diff --git a/fs/xfs/scrub/common.h b/fs/xfs/scrub/common.h index 007d293a06d52..0edf67e697da3 100644 --- a/fs/xfs/scrub/common.h +++ b/fs/xfs/scrub/common.h @@ -12,11 +12,15 @@ void xchk_trans_cancel(struct xfs_scrub *sc); bool xchk_process_error(struct xfs_scrub *sc, xfs_agnumber_t agno, xfs_agblock_t bno, int *error); +bool xchk_process_rt_error(struct xfs_scrub *sc, xfs_rgnumber_t rgno, + xfs_rgblock_t rgbno, int *error); bool xchk_fblock_process_error(struct xfs_scrub *sc, int whichfork, xfs_fileoff_t offset, int *error); bool xchk_xref_process_error(struct xfs_scrub *sc, xfs_agnumber_t agno, xfs_agblock_t bno, int *error); +bool xchk_xref_process_rt_error(struct xfs_scrub *sc, + xfs_rgnumber_t rgno, xfs_rgblock_t rgbno, int *error); bool xchk_fblock_xref_process_error(struct xfs_scrub *sc, int whichfork, xfs_fileoff_t offset, int *error); @@ -53,6 +57,11 @@ int xchk_checkpoint_log(struct xfs_mount *mp); bool xchk_should_check_xref(struct xfs_scrub *sc, int *error, struct xfs_btree_cur **curpp); +static inline int xchk_setup_nothing(struct xfs_scrub *sc) +{ + return -ENOENT; +} + /* Setup functions */ int xchk_setup_agheader(struct xfs_scrub *sc); int xchk_setup_fs(struct xfs_scrub *sc); @@ -72,17 +81,11 @@ int xchk_setup_metapath(struct xfs_scrub *sc); #ifdef CONFIG_XFS_RT int xchk_setup_rtbitmap(struct xfs_scrub *sc); int xchk_setup_rtsummary(struct xfs_scrub *sc); +int xchk_setup_rgsuperblock(struct xfs_scrub *sc); #else -static inline int -xchk_setup_rtbitmap(struct xfs_scrub *sc) -{ - return -ENOENT; -} -static inline int -xchk_setup_rtsummary(struct xfs_scrub *sc) -{ - return -ENOENT; -} +# define xchk_setup_rtbitmap xchk_setup_nothing +# define xchk_setup_rtsummary xchk_setup_nothing +# define xchk_setup_rgsuperblock xchk_setup_nothing #endif #ifdef CONFIG_XFS_QUOTA int xchk_ino_dqattach(struct xfs_scrub *sc); @@ -94,16 +97,8 @@ xchk_ino_dqattach(struct xfs_scrub *sc) { return 0; } -static inline int -xchk_setup_quota(struct xfs_scrub *sc) -{ - return -ENOENT; -} -static inline int -xchk_setup_quotacheck(struct xfs_scrub *sc) -{ - return -ENOENT; -} +# define xchk_setup_quota xchk_setup_nothing +# define xchk_setup_quotacheck xchk_setup_nothing #endif int xchk_setup_fscounters(struct xfs_scrub *sc); int xchk_setup_nlinks(struct xfs_scrub *sc); @@ -147,6 +142,17 @@ void xchk_rt_init(struct xfs_scrub *sc, struct xchk_rt *sr, unsigned int xchk_rtlock_flags); void xchk_rt_unlock(struct xfs_scrub *sc, struct xchk_rt *sr); void xchk_rt_unlock_rtbitmap(struct xfs_scrub *sc); + +#ifdef CONFIG_XFS_RT +int xchk_rtgroup_init(struct xfs_scrub *sc, xfs_rgnumber_t rgno, + struct xchk_rt *sr, unsigned int rtglock_flags); +void xchk_rtgroup_unlock(struct xfs_scrub *sc, struct xchk_rt *sr); +void xchk_rtgroup_free(struct xfs_scrub *sc, struct xchk_rt *sr); +#else +# define xchk_rtgroup_init(sc, rgno, sr, lockflags) (-ENOSYS) +# define xchk_rtgroup_free(sc, sr) ((void)0) +#endif /* CONFIG_XFS_RT */ + int xchk_ag_read_headers(struct xfs_scrub *sc, xfs_agnumber_t agno, struct xchk_ag *sa); void xchk_ag_btcur_free(struct xchk_ag *sa); diff --git a/fs/xfs/scrub/health.c b/fs/xfs/scrub/health.c index 063176c1f35eb..7fccb1a03060a 100644 --- a/fs/xfs/scrub/health.c +++ b/fs/xfs/scrub/health.c @@ -114,6 +114,7 @@ static const struct xchk_health_map type_to_health_flag[XFS_SCRUB_TYPE_NR] = { [XFS_SCRUB_TYPE_NLINKS] = { XHG_FS, XFS_SICK_FS_NLINKS }, [XFS_SCRUB_TYPE_DIRTREE] = { XHG_INO, XFS_SICK_INO_DIRTREE }, [XFS_SCRUB_TYPE_METAPATH] = { XHG_FS, XFS_SICK_FS_METAPATH }, + [XFS_SCRUB_TYPE_RGSUPER] = { XHG_RTGROUP, XFS_SICK_RT_SUPER }, }; /* Return the health status mask for this scrub type. */ diff --git a/fs/xfs/scrub/rgsuper.c b/fs/xfs/scrub/rgsuper.c new file mode 100644 index 0000000000000..ae23609cdb900 --- /dev/null +++ b/fs/xfs/scrub/rgsuper.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022-2024 Oracle. All Rights Reserved. + * Author: Darrick J. Wong + */ +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_trans_resv.h" +#include "xfs_mount.h" +#include "xfs_rtgroup.h" +#include "scrub/scrub.h" +#include "scrub/common.h" + +/* Set us up with a transaction and an empty context. */ +int +xchk_setup_rgsuperblock( + struct xfs_scrub *sc) +{ + return xchk_trans_alloc(sc, 0); +} + +/* Cross-reference with the other rt metadata. */ +STATIC void +xchk_rgsuperblock_xref( + struct xfs_scrub *sc) +{ + struct xfs_mount *mp = sc->mp; + xfs_rgnumber_t rgno = sc->sr.rtg->rtg_rgno; + xfs_rtblock_t rtbno; + + if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) + return; + + rtbno = xfs_rgbno_to_rtb(mp, rgno, 0); + xchk_xref_is_used_rt_space(sc, rtbno, 1); +} + +int +xchk_rgsuperblock( + struct xfs_scrub *sc) +{ + struct xfs_buf *bp; + xfs_rgnumber_t rgno = sc->sm->sm_agno; + int error; + + /* + * Grab an active reference to the rtgroup structure. If we can't get + * it, we're racing with something that's tearing down the group, so + * signal that the group no longer exists. Take the rtbitmap in shared + * mode so that the group can't change while we're doing things. + */ + error = xchk_rtgroup_init(sc, rgno, &sc->sr, XFS_RTGLOCK_BITMAP_SHARED); + if (error) + return error; + + /* + * If this is the primary rtgroup superblock, we know it passed the + * verifier checks at mount time and do not need to load the buffer + * again. + */ + if (sc->sr.rtg->rtg_rgno == 0) { + xchk_rgsuperblock_xref(sc); + return 0; + } + + /* The secondary rt super is checked by the read verifier. */ + error = xfs_buf_read_uncached(sc->mp->m_rtdev_targp, XFS_RTSB_DADDR, + XFS_FSB_TO_BB(sc->mp, 1), 0, &bp, &xfs_rtsb_buf_ops); + if (!xchk_process_rt_error(sc, rgno, 0, &error)) + return error; + + xchk_rgsuperblock_xref(sc); + xfs_buf_relse(bp); + return 0; +} diff --git a/fs/xfs/scrub/scrub.c b/fs/xfs/scrub/scrub.c index 5d551433b3233..c1e226a9ac08d 100644 --- a/fs/xfs/scrub/scrub.c +++ b/fs/xfs/scrub/scrub.c @@ -230,7 +230,10 @@ xchk_teardown( xfs_trans_cancel(sc->tp); sc->tp = NULL; } - xchk_rt_unlock(sc, &sc->sr); + if (sc->sr.rtg) + xchk_rtgroup_free(sc, &sc->sr); + else + xchk_rt_unlock(sc, &sc->sr); if (sc->ip) { if (sc->ilock_flags) xchk_iunlock(sc, sc->ilock_flags); @@ -455,6 +458,13 @@ static const struct xchk_meta_ops meta_scrub_ops[] = { .has = xfs_has_metadir, .repair = xrep_metapath, }, + [XFS_SCRUB_TYPE_RGSUPER] = { /* realtime group superblock */ + .type = ST_RTGROUP, + .setup = xchk_setup_rgsuperblock, + .scrub = xchk_rgsuperblock, + .has = xfs_has_rtgroups, + .repair = xrep_notsupported, + }, }; static int @@ -504,6 +514,14 @@ xchk_validate_inputs( break; case ST_GENERIC: break; + case ST_RTGROUP: + if (sm->sm_ino || sm->sm_gen) + goto out; + if (!xfs_has_rtgroups(mp) && sm->sm_agno != 0) + goto out; + if (xfs_has_rtgroups(mp) && sm->sm_agno >= mp->m_sb.sb_rgcount) + goto out; + break; default: goto out; } diff --git a/fs/xfs/scrub/scrub.h b/fs/xfs/scrub/scrub.h index 1671b6aa48081..26d2731eddb99 100644 --- a/fs/xfs/scrub/scrub.h +++ b/fs/xfs/scrub/scrub.h @@ -67,6 +67,7 @@ enum xchk_type { ST_FS, /* per-FS metadata */ ST_INODE, /* per-inode metadata */ ST_GENERIC, /* determined by the scrubber */ + ST_RTGROUP, /* rtgroup metadata */ }; struct xchk_meta_ops { @@ -113,7 +114,13 @@ struct xchk_ag { /* Inode lock state for the RT volume. */ struct xchk_rt { - /* XCHK_RTLOCK_* lock state */ + /* incore rtgroup, if applicable */ + struct xfs_rtgroup *rtg; + + /* + * XCHK_RTLOCK_* lock state if rtg == NULL, or XFS_RTGLOCK_* lock state + * if rtg != NULL. + */ unsigned int rtlock_flags; }; @@ -241,6 +248,11 @@ xchk_should_terminate( return false; } +static inline int xchk_nothing(struct xfs_scrub *sc) +{ + return -ENOENT; +} + /* Metadata scrubbers */ int xchk_tester(struct xfs_scrub *sc); int xchk_superblock(struct xfs_scrub *sc); @@ -264,32 +276,18 @@ int xchk_metapath(struct xfs_scrub *sc); #ifdef CONFIG_XFS_RT int xchk_rtbitmap(struct xfs_scrub *sc); int xchk_rtsummary(struct xfs_scrub *sc); +int xchk_rgsuperblock(struct xfs_scrub *sc); #else -static inline int -xchk_rtbitmap(struct xfs_scrub *sc) -{ - return -ENOENT; -} -static inline int -xchk_rtsummary(struct xfs_scrub *sc) -{ - return -ENOENT; -} +# define xchk_rtbitmap xchk_nothing +# define xchk_rtsummary xchk_nothing +# define xchk_rgsuperblock xchk_nothing #endif #ifdef CONFIG_XFS_QUOTA int xchk_quota(struct xfs_scrub *sc); int xchk_quotacheck(struct xfs_scrub *sc); #else -static inline int -xchk_quota(struct xfs_scrub *sc) -{ - return -ENOENT; -} -static inline int -xchk_quotacheck(struct xfs_scrub *sc) -{ - return -ENOENT; -} +# define xchk_quota xchk_nothing +# define xchk_quotacheck xchk_nothing #endif int xchk_fscounters(struct xfs_scrub *sc); int xchk_nlinks(struct xfs_scrub *sc); diff --git a/fs/xfs/scrub/stats.c b/fs/xfs/scrub/stats.c index 2e576c601b7dc..c3f8ac37e5e03 100644 --- a/fs/xfs/scrub/stats.c +++ b/fs/xfs/scrub/stats.c @@ -81,6 +81,7 @@ static const char *name_map[XFS_SCRUB_TYPE_NR] = { [XFS_SCRUB_TYPE_NLINKS] = "nlinks", [XFS_SCRUB_TYPE_DIRTREE] = "dirtree", [XFS_SCRUB_TYPE_METAPATH] = "metapath", + [XFS_SCRUB_TYPE_RGSUPER] = "rgsuper", }; /* Format the scrub stats into a text buffer, similar to pcp style. */ diff --git a/fs/xfs/scrub/trace.h b/fs/xfs/scrub/trace.h index 038a4f8dda5a0..0bcd93bed07d6 100644 --- a/fs/xfs/scrub/trace.h +++ b/fs/xfs/scrub/trace.h @@ -83,6 +83,7 @@ TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_HEALTHY); TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_DIRTREE); TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_BARRIER); TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_METAPATH); +TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_RGSUPER); #define XFS_SCRUB_TYPE_STRINGS \ { XFS_SCRUB_TYPE_PROBE, "probe" }, \ @@ -115,7 +116,8 @@ TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_METAPATH); { XFS_SCRUB_TYPE_HEALTHY, "healthy" }, \ { XFS_SCRUB_TYPE_DIRTREE, "dirtree" }, \ { XFS_SCRUB_TYPE_BARRIER, "barrier" }, \ - { XFS_SCRUB_TYPE_METAPATH, "metapath" } + { XFS_SCRUB_TYPE_METAPATH, "metapath" }, \ + { XFS_SCRUB_TYPE_RGSUPER, "rgsuper" } #define XFS_SCRUB_FLAG_STRINGS \ { XFS_SCRUB_IFLAG_REPAIR, "repair" }, \ From patchwork Sun Dec 31 21:21:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507618 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 D5E32BA2E for ; Sun, 31 Dec 2023 21:21:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="H/LHQBG/" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9E6ABC433C8; Sun, 31 Dec 2023 21:21:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704057681; bh=QTL6aFdPgiAauDII8KHqSknp4QuqQbVlzFKVfzkf4MU=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=H/LHQBG/HLJWWTbUZeT05I610EFnQcnrskB+tJVuT0BmYRNOooTzcEudq3Kog/52C 0kUSv8DZSxjWaWsngNMPnKWlw70RBU+aMh4ZgJj9gj//RCT5ijl2OJV21MmUVqeO// InhJfZ+BSIWVl6sMigFKvjjVexxhG93VAUgy5ZHJ8l8Ngtmcup4htbZjmzXXXg5e2I n0ENgp1whNP0etkO9hrsZ87kQKhp++jfdhj5Ghnh98xF6q3iWLhNysBcbH8Sr7+ETW /+glZPYeiCjv1uB6yPF5jgI7zJ7CZ7j0Yr521nk1scHQX0p0/yxKSW31OYLlzMyLu1 1CEsFR4rqg4eg== Date: Sun, 31 Dec 2023 13:21:21 -0800 Subject: [PATCH 22/24] xfs: repair secondary realtime group superblocks From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404846593.1763124.10346346517283580350.stgit@frogsfrogsfrogs> In-Reply-To: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> References: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Repair secondary realtime group superblocks. They're not critical for anything, but some consistency would be a good idea. Signed-off-by: Darrick J. Wong --- fs/xfs/Makefile | 1 + fs/xfs/libxfs/xfs_rtgroup.c | 2 +- fs/xfs/libxfs/xfs_rtgroup.h | 3 +++ fs/xfs/scrub/repair.h | 3 +++ fs/xfs/scrub/rgsuper_repair.c | 48 +++++++++++++++++++++++++++++++++++++++++ fs/xfs/scrub/scrub.c | 2 +- 6 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 fs/xfs/scrub/rgsuper_repair.c diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 7416ab9efc4d8..6dc9e740f8ce5 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -231,6 +231,7 @@ xfs-y += $(addprefix scrub/, \ ) xfs-$(CONFIG_XFS_RT) += $(addprefix scrub/, \ + rgsuper_repair.o \ rtbitmap_repair.o \ rtsummary_repair.o \ ) diff --git a/fs/xfs/libxfs/xfs_rtgroup.c b/fs/xfs/libxfs/xfs_rtgroup.c index ed4f8aa67b158..7a45a16cbbab8 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.c +++ b/fs/xfs/libxfs/xfs_rtgroup.c @@ -421,7 +421,7 @@ xfs_rtgroup_log_super( } /* Initialize a secondary realtime superblock. */ -static int +int xfs_rtgroup_init_secondary_super( struct xfs_mount *mp, xfs_rgnumber_t rgno, diff --git a/fs/xfs/libxfs/xfs_rtgroup.h b/fs/xfs/libxfs/xfs_rtgroup.h index e6d60425faa4d..0a63f14b5aa0f 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.h +++ b/fs/xfs/libxfs/xfs_rtgroup.h @@ -221,6 +221,8 @@ void xfs_rtgroup_update_super(struct xfs_buf *rtsb_bp, const struct xfs_buf *sb_bp); void xfs_rtgroup_log_super(struct xfs_trans *tp, const struct xfs_buf *sb_bp); int xfs_rtgroup_update_secondary_sbs(struct xfs_mount *mp); +int xfs_rtgroup_init_secondary_super(struct xfs_mount *mp, xfs_rgnumber_t rgno, + struct xfs_buf **bpp); /* Lock the rt bitmap inode in exclusive mode */ #define XFS_RTGLOCK_BITMAP (1U << 0) @@ -241,6 +243,7 @@ int xfs_rtgroup_get_geometry(struct xfs_rtgroup *rtg, # define xfs_rtgroup_update_super(bp, sb_bp) ((void)0) # define xfs_rtgroup_log_super(tp, sb_bp) ((void)0) # define xfs_rtgroup_update_secondary_sbs(mp) (0) +# define xfs_rtgroup_init_secondary_super(mp, rgno, bpp) (-EOPNOTSUPP) # define xfs_rtgroup_lock(tp, rtg, gf) ((void)0) # define xfs_rtgroup_unlock(rtg, gf) ((void)0) # define xfs_rtgroup_get_geometry(rtg, rgeo) (-EOPNOTSUPP) diff --git a/fs/xfs/scrub/repair.h b/fs/xfs/scrub/repair.h index a0780ccdd9ab6..3d8ca12b2cc51 100644 --- a/fs/xfs/scrub/repair.h +++ b/fs/xfs/scrub/repair.h @@ -139,9 +139,11 @@ int xrep_metapath(struct xfs_scrub *sc); #ifdef CONFIG_XFS_RT int xrep_rtbitmap(struct xfs_scrub *sc); int xrep_rtsummary(struct xfs_scrub *sc); +int xrep_rgsuperblock(struct xfs_scrub *sc); #else # define xrep_rtbitmap xrep_notsupported # define xrep_rtsummary xrep_notsupported +# define xrep_rgsuperblock xrep_notsupported #endif /* CONFIG_XFS_RT */ #ifdef CONFIG_XFS_QUOTA @@ -246,6 +248,7 @@ static inline int xrep_setup_symlink(struct xfs_scrub *sc, unsigned int *x) #define xrep_symlink xrep_notsupported #define xrep_dirtree xrep_notsupported #define xrep_metapath xrep_notsupported +#define xrep_rgsuperblock xrep_notsupported #endif /* CONFIG_XFS_ONLINE_REPAIR */ diff --git a/fs/xfs/scrub/rgsuper_repair.c b/fs/xfs/scrub/rgsuper_repair.c new file mode 100644 index 0000000000000..61961764a6cf9 --- /dev/null +++ b/fs/xfs/scrub/rgsuper_repair.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022-2024 Oracle. All Rights Reserved. + * Author: Darrick J. Wong + */ +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_trans_resv.h" +#include "xfs_mount.h" +#include "xfs_defer.h" +#include "xfs_btree.h" +#include "xfs_inode.h" +#include "xfs_bit.h" +#include "xfs_log_format.h" +#include "xfs_trans.h" +#include "xfs_rtgroup.h" +#include "xfs_sb.h" +#include "scrub/scrub.h" +#include "scrub/repair.h" + +int +xrep_rgsuperblock( + struct xfs_scrub *sc) +{ + struct xfs_buf *bp; + int error; + + /* + * If this is the primary rtgroup superblock, log a superblock update + * to force both to disk. + */ + if (sc->sr.rtg->rtg_rgno == 0) { + xfs_log_sb(sc->tp); + return 0; + } + + /* Otherwise just write a new secondary to disk directly. */ + error = xfs_rtgroup_init_secondary_super(sc->mp, sc->sr.rtg->rtg_rgno, + &bp); + if (error) + return error; + + error = xfs_bwrite(bp); + xfs_buf_relse(bp); + return error; +} diff --git a/fs/xfs/scrub/scrub.c b/fs/xfs/scrub/scrub.c index c1e226a9ac08d..c9acc10209ddb 100644 --- a/fs/xfs/scrub/scrub.c +++ b/fs/xfs/scrub/scrub.c @@ -463,7 +463,7 @@ static const struct xchk_meta_ops meta_scrub_ops[] = { .setup = xchk_setup_rgsuperblock, .scrub = xchk_rgsuperblock, .has = xfs_has_rtgroups, - .repair = xrep_notsupported, + .repair = xrep_rgsuperblock, }, }; From patchwork Sun Dec 31 21:21:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507619 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 7FDE3BA2B for ; Sun, 31 Dec 2023 21:21:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="iueehF27" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4DF7AC433C7; Sun, 31 Dec 2023 21:21:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704057697; bh=cnEwhY3fO67SXke7cblo1KV4dxsoshG1f0MkMMoyf90=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=iueehF273zmgGtNP7CKiOHTnAlivlwhwIlGyVx0ceD3qYRH1YWrtg4oGDs2MLSJ3d /pfdaxXmYp0oIKtHd0ZKEm940SDKcXSnVp9/n10dYBzJZxvi2YPNbpVZwXbTRxeB07 V6GihCjPVTPua3n9i+rS2DTMsbpPiL+M3Kpu1TUhV8zQxDvKCCFMiBeKp3XhChg7wq 7i8rKOOrL/WyxjuXMMJXH4O+0a9ycjrXrWZIwRGzp4g9+brlSRe15zx4p5g9+VBniJ iX5061FeJN4i6zDrMe3sgjgYuMdx8tLwMckjoWxVqQ83RmdqLogm11qM9de1BVEa3G kLwGuDTT183AA== Date: Sun, 31 Dec 2023 13:21:36 -0800 Subject: [PATCH 23/24] xfs: scrub each rtgroup's portion of the rtbitmap separately From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404846609.1763124.17143188488189530626.stgit@frogsfrogsfrogs> In-Reply-To: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> References: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 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 new scrub type code so that userspace can scrub each rtgroup's portion of the rtbitmap file separately. This reduces the long tail latency that results from scanning the entire bitmap all at once, and prepares us for future patchsets, wherein we'll need to be able to lock a specific rtgroup so that we can rebuild that rtgroup's part of the rtbitmap contents from the rtgroup's rmap btree. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_fs.h | 3 + fs/xfs/scrub/common.h | 6 ++ fs/xfs/scrub/rtbitmap.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++- fs/xfs/scrub/rtbitmap.h | 6 ++ fs/xfs/scrub/scrub.c | 7 +++ fs/xfs/scrub/scrub.h | 2 + fs/xfs/scrub/stats.c | 1 fs/xfs/scrub/trace.h | 4 + 8 files changed, 150 insertions(+), 6 deletions(-) diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index 237d13a500daf..102b927336057 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -736,9 +736,10 @@ struct xfs_scrub_metadata { #define XFS_SCRUB_TYPE_DIRTREE 28 /* directory tree structure */ #define XFS_SCRUB_TYPE_METAPATH 29 /* metadata directory tree paths */ #define XFS_SCRUB_TYPE_RGSUPER 30 /* realtime superblock */ +#define XFS_SCRUB_TYPE_RGBITMAP 31 /* realtime group bitmap */ /* Number of scrub subcommands. */ -#define XFS_SCRUB_TYPE_NR 31 +#define XFS_SCRUB_TYPE_NR 32 /* * This special type code only applies to the vectored scrub implementation. diff --git a/fs/xfs/scrub/common.h b/fs/xfs/scrub/common.h index 0edf67e697da3..f96dd658feab9 100644 --- a/fs/xfs/scrub/common.h +++ b/fs/xfs/scrub/common.h @@ -82,10 +82,12 @@ int xchk_setup_metapath(struct xfs_scrub *sc); int xchk_setup_rtbitmap(struct xfs_scrub *sc); int xchk_setup_rtsummary(struct xfs_scrub *sc); int xchk_setup_rgsuperblock(struct xfs_scrub *sc); +int xchk_setup_rgbitmap(struct xfs_scrub *sc); #else # define xchk_setup_rtbitmap xchk_setup_nothing # define xchk_setup_rtsummary xchk_setup_nothing # define xchk_setup_rgsuperblock xchk_setup_nothing +# define xchk_setup_rgbitmap xchk_setup_nothing #endif #ifdef CONFIG_XFS_QUOTA int xchk_ino_dqattach(struct xfs_scrub *sc); @@ -144,6 +146,10 @@ void xchk_rt_unlock(struct xfs_scrub *sc, struct xchk_rt *sr); void xchk_rt_unlock_rtbitmap(struct xfs_scrub *sc); #ifdef CONFIG_XFS_RT + +/* All the locks we need to check an rtgroup. */ +#define XCHK_RTGLOCK_ALL (XFS_RTGLOCK_BITMAP_SHARED) + int xchk_rtgroup_init(struct xfs_scrub *sc, xfs_rgnumber_t rgno, struct xchk_rt *sr, unsigned int rtglock_flags); void xchk_rtgroup_unlock(struct xfs_scrub *sc, struct xchk_rt *sr); diff --git a/fs/xfs/scrub/rtbitmap.c b/fs/xfs/scrub/rtbitmap.c index 7f910fed7de95..aae8b0e6ff281 100644 --- a/fs/xfs/scrub/rtbitmap.c +++ b/fs/xfs/scrub/rtbitmap.c @@ -15,11 +15,66 @@ #include "xfs_inode.h" #include "xfs_bmap.h" #include "xfs_bit.h" +#include "xfs_rtgroup.h" #include "scrub/scrub.h" #include "scrub/common.h" #include "scrub/repair.h" #include "scrub/rtbitmap.h" +static inline void +xchk_rtbitmap_compute_geometry( + struct xfs_mount *mp, + struct xchk_rtbitmap *rtb) +{ + if (mp->m_sb.sb_rblocks == 0) + return; + + rtb->rextents = xfs_rtb_to_rtx(mp, mp->m_sb.sb_rblocks); + rtb->rextslog = xfs_compute_rextslog(&mp->m_sb, rtb->rextents); + rtb->rbmblocks = xfs_rtbitmap_blockcount(mp, rtb->rextents); +} + +/* Set us up with the realtime group metadata locked. */ +int +xchk_setup_rgbitmap( + struct xfs_scrub *sc) +{ + struct xfs_mount *mp = sc->mp; + struct xchk_rgbitmap *rgb; + int error; + + rgb = kzalloc(sizeof(struct xchk_rgbitmap), XCHK_GFP_FLAGS); + if (!rgb) + return -ENOMEM; + rgb->sc = sc; + sc->buf = rgb; + + error = xchk_trans_alloc(sc, 0); + if (error) + return error; + + error = xchk_install_live_inode(sc, mp->m_rbmip); + if (error) + return error; + + error = xchk_ino_dqattach(sc); + if (error) + return error; + + error = xchk_rtgroup_init(sc, sc->sm->sm_agno, &sc->sr, + XCHK_RTGLOCK_ALL); + if (error) + return error; + + /* + * Now that we've locked the rtbitmap, we can't race with growfsrt + * trying to expand the bitmap or change the size of the rt volume. + * Hence it is safe to compute and check the geometry values. + */ + xchk_rtbitmap_compute_geometry(mp, &rgb->rtb); + return 0; +} + /* Set us up with the realtime metadata locked. */ int xchk_setup_rtbitmap( @@ -59,11 +114,68 @@ xchk_setup_rtbitmap( * trying to expand the bitmap or change the size of the rt volume. * Hence it is safe to compute and check the geometry values. */ - if (mp->m_sb.sb_rblocks) { - rtb->rextents = xfs_rtb_to_rtx(mp, mp->m_sb.sb_rblocks); - rtb->rextslog = xfs_compute_rextslog(&mp->m_sb, rtb->rextents); - rtb->rbmblocks = xfs_rtbitmap_blockcount(mp, rtb->rextents); + xchk_rtbitmap_compute_geometry(mp, rtb); + return 0; +} + +/* Per-rtgroup bitmap contents. */ + +/* Scrub a free extent record from the realtime bitmap. */ +STATIC int +xchk_rgbitmap_rec( + struct xfs_mount *mp, + struct xfs_trans *tp, + const struct xfs_rtalloc_rec *rec, + void *priv) +{ + struct xchk_rgbitmap *rgb = priv; + struct xfs_scrub *sc = rgb->sc; + xfs_rtblock_t startblock; + xfs_filblks_t blockcount; + + startblock = xfs_rtx_to_rtb(mp, rec->ar_startext); + blockcount = xfs_rtx_to_rtb(mp, rec->ar_extcount); + + if (!xfs_verify_rtbext(mp, startblock, blockcount)) + xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0); + return 0; +} + +/* Scrub this group's realtime bitmap. */ +int +xchk_rgbitmap( + struct xfs_scrub *sc) +{ + struct xfs_rtalloc_rec keys[2]; + struct xfs_mount *mp = sc->mp; + struct xfs_rtgroup *rtg = sc->sr.rtg; + struct xchk_rgbitmap *rgb = sc->buf; + xfs_rtblock_t rtbno; + xfs_rgblock_t last_rgbno = rtg->rtg_blockcount - 1; + int error; + + /* Sanity check the realtime bitmap size. */ + if (sc->ip->i_disk_size < XFS_FSB_TO_B(mp, rgb->rtb.rbmblocks)) { + xchk_ino_set_corrupt(sc, sc->ip->i_ino); + return 0; } + + /* + * Check only the portion of the rtbitmap that corresponds to this + * realtime group. + */ + rtbno = xfs_rgbno_to_rtb(mp, rtg->rtg_rgno, 0); + keys[0].ar_startext = xfs_rtb_to_rtx(mp, rtbno); + + rtbno = xfs_rgbno_to_rtb(mp, rtg->rtg_rgno, last_rgbno); + keys[1].ar_startext = xfs_rtb_to_rtx(mp, rtbno); + keys[0].ar_extcount = keys[1].ar_extcount = 0; + + error = xfs_rtalloc_query_range(mp, sc->tp, &keys[0], &keys[1], + xchk_rgbitmap_rec, rgb); + if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error)) + return error; + return 0; } @@ -192,6 +304,13 @@ xchk_rtbitmap( if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) return error; + /* + * Each rtgroup checks its portion of the rt bitmap, so if we don't + * have that feature, we have to check the bitmap contents now. + */ + if (xfs_has_rtgroups(mp)) + return 0; + error = xfs_rtalloc_query_all(mp, sc->tp, xchk_rtbitmap_rec, sc); if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error)) return error; diff --git a/fs/xfs/scrub/rtbitmap.h b/fs/xfs/scrub/rtbitmap.h index 85304ff019e1d..f659f0e76b4fa 100644 --- a/fs/xfs/scrub/rtbitmap.h +++ b/fs/xfs/scrub/rtbitmap.h @@ -13,6 +13,12 @@ struct xchk_rtbitmap { unsigned int resblks; }; +struct xchk_rgbitmap { + struct xfs_scrub *sc; + + struct xchk_rtbitmap rtb; +}; + #ifdef CONFIG_XFS_ONLINE_REPAIR int xrep_setup_rtbitmap(struct xfs_scrub *sc, struct xchk_rtbitmap *rtb); #else diff --git a/fs/xfs/scrub/scrub.c b/fs/xfs/scrub/scrub.c index c9acc10209ddb..a6b7b57fc1df7 100644 --- a/fs/xfs/scrub/scrub.c +++ b/fs/xfs/scrub/scrub.c @@ -465,6 +465,13 @@ static const struct xchk_meta_ops meta_scrub_ops[] = { .has = xfs_has_rtgroups, .repair = xrep_rgsuperblock, }, + [XFS_SCRUB_TYPE_RGBITMAP] = { /* realtime group bitmap */ + .type = ST_RTGROUP, + .setup = xchk_setup_rgbitmap, + .scrub = xchk_rgbitmap, + .has = xfs_has_rtgroups, + .repair = xrep_notsupported, + }, }; static int diff --git a/fs/xfs/scrub/scrub.h b/fs/xfs/scrub/scrub.h index 26d2731eddb99..76eca41a8995a 100644 --- a/fs/xfs/scrub/scrub.h +++ b/fs/xfs/scrub/scrub.h @@ -277,10 +277,12 @@ int xchk_metapath(struct xfs_scrub *sc); int xchk_rtbitmap(struct xfs_scrub *sc); int xchk_rtsummary(struct xfs_scrub *sc); int xchk_rgsuperblock(struct xfs_scrub *sc); +int xchk_rgbitmap(struct xfs_scrub *sc); #else # define xchk_rtbitmap xchk_nothing # define xchk_rtsummary xchk_nothing # define xchk_rgsuperblock xchk_nothing +# define xchk_rgbitmap xchk_nothing #endif #ifdef CONFIG_XFS_QUOTA int xchk_quota(struct xfs_scrub *sc); diff --git a/fs/xfs/scrub/stats.c b/fs/xfs/scrub/stats.c index c3f8ac37e5e03..4bdff9a19dd6c 100644 --- a/fs/xfs/scrub/stats.c +++ b/fs/xfs/scrub/stats.c @@ -82,6 +82,7 @@ static const char *name_map[XFS_SCRUB_TYPE_NR] = { [XFS_SCRUB_TYPE_DIRTREE] = "dirtree", [XFS_SCRUB_TYPE_METAPATH] = "metapath", [XFS_SCRUB_TYPE_RGSUPER] = "rgsuper", + [XFS_SCRUB_TYPE_RGBITMAP] = "rgbitmap", }; /* Format the scrub stats into a text buffer, similar to pcp style. */ diff --git a/fs/xfs/scrub/trace.h b/fs/xfs/scrub/trace.h index 0bcd93bed07d6..dd809042a6041 100644 --- a/fs/xfs/scrub/trace.h +++ b/fs/xfs/scrub/trace.h @@ -84,6 +84,7 @@ TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_DIRTREE); TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_BARRIER); TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_METAPATH); TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_RGSUPER); +TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_RGBITMAP); #define XFS_SCRUB_TYPE_STRINGS \ { XFS_SCRUB_TYPE_PROBE, "probe" }, \ @@ -117,7 +118,8 @@ TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_RGSUPER); { XFS_SCRUB_TYPE_DIRTREE, "dirtree" }, \ { XFS_SCRUB_TYPE_BARRIER, "barrier" }, \ { XFS_SCRUB_TYPE_METAPATH, "metapath" }, \ - { XFS_SCRUB_TYPE_RGSUPER, "rgsuper" } + { XFS_SCRUB_TYPE_RGSUPER, "rgsuper" }, \ + { XFS_SCRUB_TYPE_RGBITMAP, "rgbitmap" } #define XFS_SCRUB_FLAG_STRINGS \ { XFS_SCRUB_IFLAG_REPAIR, "repair" }, \ From patchwork Sun Dec 31 21:21:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507620 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 2A53DBA22 for ; Sun, 31 Dec 2023 21:21:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="eI9anHEL" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E89F2C433C7; Sun, 31 Dec 2023 21:21:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704057713; bh=X7n9SWwYGRwa5po6HtUXNRsjtSSlzHfcOIO1+qpZxKI=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=eI9anHELra8cjk0ollIMvqTuaAQweebcP6+717dF2FYRs5yFTPtVhI26UNRDSWvd1 4dGu9gwHuaRSFjRaoHRpnBAhYpOm1xS+rf/yKd/vOV8cT5wXabq2UlZZyFEZ3p+oq/ MJxGar3Jx6e/0TRUoT/pqiF/upTmukSQ0tZch7LbRztYP9NeLtbIfSu7jjWzVJSHRc ozNTDtzH0/g6/klNJiTliynqZRXOLOjwRhjWHAyh0bPVljGQmj8oTvOfz1xzVdR2lH BfIWXgqB/g8+Z0sQ+sdpWsY17mnOxM8NIwQ3bGbSu+wjQoYegcXdYLzQC7re+0wpXh SNNimoJiB70fQ== Date: Sun, 31 Dec 2023 13:21:52 -0800 Subject: [PATCH 24/24] xfs: enable realtime group feature From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404846626.1763124.11828497045934905103.stgit@frogsfrogsfrogs> In-Reply-To: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> References: <170404846187.1763124.7316400597964398308.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_format.h | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index 59ba13db53e7a..87476c6bb6c64 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -418,6 +418,7 @@ xfs_sb_has_ro_compat_feature( XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR| \ XFS_SB_FEAT_INCOMPAT_NREXT64| \ XFS_SB_FEAT_INCOMPAT_PARENT | \ + XFS_SB_FEAT_INCOMPAT_RTGROUPS | \ XFS_SB_FEAT_INCOMPAT_METADIR) #define XFS_SB_FEAT_INCOMPAT_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_ALL