From patchwork Thu Oct 17 19:04:00 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840705 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 DBF511DED44 for ; Thu, 17 Oct 2024 19:04:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191841; cv=none; b=duJdXti1LeGjM2wfV03XQkzHK8dgybNybk3bLVI2XJ6qpr6wGaXz20GKba7S0wGpiL3Lo2oMxkvpgX/uOcHbbkYYEpiDwaa4yQlSNrZCk0NdBBqny84tWbowdBri8uPqqoShF/gL9CTXUYsCcWnMnF94wc1cYMrfWjmAf+A7M9U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191841; c=relaxed/simple; bh=8HDDYUvS56kuffQrPOfbZDZutHnDERMp2k/H/sLoMCA=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=p8RCRXKwq2B9TI+K2gIduGgkDnW6YHFC7WDZ+DI7y9nesmwurqZKOJBHn0JQAEKYjCYedgzGrVnjhSgv2VcP10DjyvhbP7+FfYw3ZygEdsgf0/UMlKO71HD2YngUC2f1wbItPR/SR2avkoNRNMfGOMbNtCoaxlW2P5yeAwNmou4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=f1k88/ix; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="f1k88/ix" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6EA62C4CEC3; Thu, 17 Oct 2024 19:04:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729191841; bh=8HDDYUvS56kuffQrPOfbZDZutHnDERMp2k/H/sLoMCA=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=f1k88/ixTZWbTcdLnaOB5rscXX599rztRKmfAWulMZ2nQeOz8LYFnKJxxJ2eYDYX8 5U0rKHpT2BmHbm9QDQIXv5gkpca9geTO8neKCkUqbXE1E0c9j2250cCwz5FQpY/Pi5 zCmHbvWDp7LoxLLr3DT2l0BggEgiq3PHo+09uhXjKbxHztHUBtETUiOM3ecQISGuDt Luu/JzXnzJYdqVRRC28z7do94yEfnGg8Eer6RvPU5j11YysGbMalqPw+PMQLEADHZR ARqNbQ24luFNhOsBO9DrgtN4CmdwtGCVqF9wbFMxQTzP2C2w6ZG/DPpaZpaJ249wIV OV/+R06eotWhQ== Date: Thu, 17 Oct 2024 12:04:00 -0700 Subject: [PATCH 01/34] xfs: define the format of rt groups From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919071681.3453179.2361469423447590163.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Define the ondisk format of realtime group metadata, and a superblock for realtime volumes. rt supers are conditionally enabled by a predicate function so that they can be disabled if we ever implement zoned storage support for the realtime volume. For rt group enabled file systems there is a separate bitmap and summary file for each group and thus the number of bitmap and summary blocks needs to be calculated differently. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_format.h | 42 +++++++++++++++++- fs/xfs/libxfs/xfs_ondisk.h | 3 + fs/xfs/libxfs/xfs_rtbitmap.c | 20 +++++++- fs/xfs/libxfs/xfs_rtgroup.c | 82 ++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_sb.c | 100 +++++++++++++++++++++++++++++++++++++----- fs/xfs/libxfs/xfs_shared.h | 1 fs/xfs/xfs_mount.h | 6 ++- fs/xfs/xfs_rtalloc.c | 30 +++++++++++-- 8 files changed, 262 insertions(+), 22 deletions(-) diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index 867060d60e8583..3cf044a2d5f2a9 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -265,8 +265,15 @@ struct xfs_dsb { uuid_t sb_meta_uuid; /* metadata file system unique id */ __be64 sb_metadirino; /* metadata directory tree root */ + __be32 sb_rgcount; /* # of realtime groups */ + __be32 sb_rgextents; /* size of rtgroup in rtx */ - /* must be padded to 64 bit alignment */ + /* + * The size of this structure must be padded to 64 bit alignment. + * + * NOTE: Don't forget to update secondary_sb_whack in xfs_repair when + * adding new fields here. + */ }; #define XFS_SB_CRC_OFF offsetof(struct xfs_dsb, sb_crc) @@ -716,6 +723,39 @@ 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. rtgroup 0 might have a superblock in it, + * so the minimum size of an rtgroup is 2 rtx. + */ +#define XFS_MAX_RGBLOCKS ((xfs_rgblock_t)(1U << 31) - 1) +#define XFS_MIN_RGEXTENTS ((xfs_rtxlen_t)2) +#define XFS_MAX_RGNUMBER ((xfs_rgnumber_t)(-1U)) + +#define XFS_RTSB_MAGIC 0x46726F67 /* 'Frog' */ + +/* + * Realtime superblock - on disk version. Must be padded to 64 bit alignment. + * The first block of the realtime volume contains this superblock. + */ +struct xfs_rtsb { + __be32 rsb_magicnum; /* magic number == XFS_RTSB_MAGIC */ + __le32 rsb_crc; /* superblock crc */ + + __be32 rsb_pad; /* zero */ + unsigned char rsb_fname[XFSLABEL_MAX]; /* file system name */ + + uuid_t rsb_uuid; /* user-visible file system unique id */ + 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 8bca86e350fdc1..38b314113d8f24 100644 --- a/fs/xfs/libxfs/xfs_ondisk.h +++ b/fs/xfs/libxfs/xfs_ondisk.h @@ -37,7 +37,7 @@ xfs_check_ondisk_structs(void) XFS_CHECK_STRUCT_SIZE(struct xfs_dinode, 176); XFS_CHECK_STRUCT_SIZE(struct xfs_disk_dquot, 104); XFS_CHECK_STRUCT_SIZE(struct xfs_dqblk, 136); - XFS_CHECK_STRUCT_SIZE(struct xfs_dsb, 272); + XFS_CHECK_STRUCT_SIZE(struct xfs_dsb, 280); XFS_CHECK_STRUCT_SIZE(struct xfs_dsymlink_hdr, 56); XFS_CHECK_STRUCT_SIZE(struct xfs_inobt_key, 4); XFS_CHECK_STRUCT_SIZE(struct xfs_inobt_rec, 16); @@ -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, 56); /* dir/attr trees */ XFS_CHECK_STRUCT_SIZE(struct xfs_attr3_leaf_hdr, 80); diff --git a/fs/xfs/libxfs/xfs_rtbitmap.c b/fs/xfs/libxfs/xfs_rtbitmap.c index 54079edfe10feb..416bbcd92af2ad 100644 --- a/fs/xfs/libxfs/xfs_rtbitmap.c +++ b/fs/xfs/libxfs/xfs_rtbitmap.c @@ -1157,6 +1157,21 @@ xfs_rtbitmap_blockcount_len( return howmany_64(rtextents, NBBY * mp->m_sb.sb_blocksize); } +/* How many rt extents does each rtbitmap file track? */ +static inline xfs_rtbxlen_t +xfs_rtbitmap_bitcount( + struct xfs_mount *mp) +{ + if (!mp->m_sb.sb_rextents) + return 0; + + /* rtgroup size can be nonzero even if rextents is zero */ + if (xfs_has_rtgroups(mp)) + return mp->m_sb.sb_rgextents; + + return mp->m_sb.sb_rextents; +} + /* * Compute the number of rtbitmap blocks used for a given file system. */ @@ -1164,7 +1179,7 @@ xfs_filblks_t xfs_rtbitmap_blockcount( struct xfs_mount *mp) { - return xfs_rtbitmap_blockcount_len(mp, mp->m_sb.sb_rextents); + return xfs_rtbitmap_blockcount_len(mp, xfs_rtbitmap_bitcount(mp)); } /* @@ -1178,8 +1193,7 @@ xfs_rtsummary_blockcount( { unsigned long long rsumwords; - *rsumlevels = xfs_compute_rextslog(mp->m_sb.sb_rextents) + 1; - + *rsumlevels = xfs_compute_rextslog(xfs_rtbitmap_bitcount(mp)) + 1; rsumwords = xfs_rtbitmap_blockcount(mp) * (*rsumlevels); return XFS_B_TO_FSB(mp, rsumwords << XFS_WORDLOG); } diff --git a/fs/xfs/libxfs/xfs_rtgroup.c b/fs/xfs/libxfs/xfs_rtgroup.c index da29f41e51f1e1..9e2ca61559f45e 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" #include "xfs_metafile.h" @@ -482,3 +483,84 @@ xfs_rtginode_load_parent( return xfs_metadir_load(tp, mp->m_metadirip, "rtgroups", XFS_METAFILE_DIR, &mp->m_rtdirip); } + +/* Check superblock fields for a read or a write. */ +static xfs_failaddr_t +xfs_rtsb_verify_common( + struct xfs_buf *bp) +{ + struct xfs_rtsb *rsb = bp->b_addr; + + if (!xfs_verify_magic(bp, rsb->rsb_magicnum)) + return __this_address; + if (rsb->rsb_pad) + 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; +} + +/* Check superblock fields for a read or revalidation. */ +static inline xfs_failaddr_t +xfs_rtsb_verify_all( + struct xfs_buf *bp) +{ + struct xfs_rtsb *rsb = bp->b_addr; + struct xfs_mount *mp = bp->b_mount; + xfs_failaddr_t fa; + + fa = xfs_rtsb_verify_common(bp); + if (fa) + return fa; + + if (memcmp(&rsb->rsb_fname, &mp->m_sb.sb_fname, XFSLABEL_MAX)) + return __this_address; + if (!uuid_equal(&rsb->rsb_uuid, &mp->m_sb.sb_uuid)) + return __this_address; + if (!uuid_equal(&rsb->rsb_meta_uuid, &mp->m_sb.sb_meta_uuid)) + 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); + return; + } + + fa = xfs_rtsb_verify_all(bp); + if (fa) + xfs_verifier_error(bp, -EFSCORRUPTED, fa); +} + +static void +xfs_rtsb_write_verify( + struct xfs_buf *bp) +{ + xfs_failaddr_t fa; + + fa = xfs_rtsb_verify_common(bp); + if (fa) { + xfs_verifier_error(bp, -EFSCORRUPTED, fa); + return; + } + + 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_all, +}; diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index 21891aa10ada02..b5f798d01dba05 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -234,11 +234,22 @@ xfs_validate_sb_read( return 0; } +/* Return the number of extents covered by a single rt bitmap file */ +static xfs_rtbxlen_t +xfs_extents_per_rbm( + struct xfs_sb *sbp) +{ + if (xfs_sb_is_v5(sbp) && + (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR)) + return sbp->sb_rgextents; + return sbp->sb_rextents; +} + static uint64_t -xfs_sb_calc_rbmblocks( +xfs_expected_rbmblocks( struct xfs_sb *sbp) { - return howmany_64(sbp->sb_rextents, NBBY * sbp->sb_blocksize); + return howmany_64(xfs_extents_per_rbm(sbp), NBBY * sbp->sb_blocksize); } /* Validate the realtime geometry */ @@ -260,7 +271,7 @@ xfs_validate_rt_geometry( if (sbp->sb_rextents == 0 || sbp->sb_rextents != div_u64(sbp->sb_rblocks, sbp->sb_rextsize) || sbp->sb_rextslog != xfs_compute_rextslog(sbp->sb_rextents) || - sbp->sb_rbmblocks != xfs_sb_calc_rbmblocks(sbp)) + sbp->sb_rbmblocks != xfs_expected_rbmblocks(sbp)) return false; return true; @@ -341,6 +352,59 @@ 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_rextsize == 0) { + xfs_warn(mp, +"Realtime extent size must not be zero."); + return -EINVAL; + } + + if (sbp->sb_rgextents > XFS_MAX_RGBLOCKS / sbp->sb_rextsize) { + xfs_warn(mp, +"Realtime group size (%u) must be less than %u rt extents.", + sbp->sb_rgextents, + XFS_MAX_RGBLOCKS / sbp->sb_rextsize); + return -EINVAL; + } + + if (sbp->sb_rgextents < XFS_MIN_RGEXTENTS) { + xfs_warn(mp, +"Realtime group size (%u) must be at least %u rt extents.", + sbp->sb_rgextents, XFS_MIN_RGEXTENTS); + 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_rextents, sbp->sb_rgextents); + 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; + } + + /* Exchange-range is required for fsr to work on realtime files */ + if (!(sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_EXCHRANGE)) { + xfs_warn(mp, +"Realtime groups feature requires exchange-range support."); + return -EINVAL; + } + + return 0; +} + /* Check the validity of the SB. */ STATIC int xfs_validate_sb_common( @@ -352,6 +416,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, @@ -401,6 +466,12 @@ xfs_validate_sb_common( return -EINVAL; } } + + if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR) { + 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, @@ -692,13 +763,15 @@ __xfs_sb_from_disk( if (convert_xquota) xfs_sb_quota_from_disk(to); - if (to->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR) + if (to->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR) { to->sb_metadirino = be64_to_cpu(from->sb_metadirino); - else + to->sb_rgcount = be32_to_cpu(from->sb_rgcount); + to->sb_rgextents = be32_to_cpu(from->sb_rgextents); + } else { to->sb_metadirino = NULLFSINO; - - to->sb_rgcount = 1; - to->sb_rgextents = 0; + to->sb_rgcount = 1; + to->sb_rgextents = 0; + } } void @@ -847,8 +920,11 @@ xfs_sb_to_disk( if (from->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_META_UUID) uuid_copy(&to->sb_meta_uuid, &from->sb_meta_uuid); - if (from->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR) + if (from->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR) { to->sb_metadirino = cpu_to_be64(from->sb_metadirino); + to->sb_rgcount = cpu_to_be32(from->sb_rgcount); + to->sb_rgextents = cpu_to_be32(from->sb_rgextents); + } } /* @@ -988,9 +1064,9 @@ xfs_mount_sb_set_rextsize( mp->m_rtxblklog = log2_if_power2(sbp->sb_rextsize); mp->m_rtxblkmask = mask64_if_power2(sbp->sb_rextsize); - mp->m_rgblocks = 0; - mp->m_rgblklog = 0; - mp->m_rgblkmask = (uint64_t)-1; + mp->m_rgblocks = sbp->sb_rgextents * sbp->sb_rextsize; + mp->m_rgblklog = log2_if_power2(mp->m_rgblocks); + mp->m_rgblkmask = mask64_if_power2(mp->m_rgblocks); rgs->blocks = 0; rgs->blklog = 0; diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h index 33b84a3a83ff63..552365d212ea26 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; diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 2795dd83c23b3f..eca206140d4b0c 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -387,12 +387,14 @@ __XFS_HAS_FEAT(metadir, METADIR) static inline bool xfs_has_rtgroups(struct xfs_mount *mp) { - return false; + /* all metadir file systems also allow rtgroups */ + return xfs_has_metadir(mp); } static inline bool xfs_has_rtsb(struct xfs_mount *mp) { - return false; + /* all rtgroups filesystems with an rt section have an rtsb */ + return xfs_has_rtgroups(mp) && xfs_has_realtime(mp); } /* diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index a5e3f7be81ffa8..866274a66d4d28 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -751,6 +751,11 @@ xfs_growfs_rt_alloc_fake_mount( nmp->m_sb.sb_rextents = xfs_blen_to_rtbxlen(nmp, nmp->m_sb.sb_rblocks); nmp->m_sb.sb_rbmblocks = xfs_rtbitmap_blockcount(nmp); nmp->m_sb.sb_rextslog = xfs_compute_rextslog(nmp->m_sb.sb_rextents); + if (xfs_has_rtgroups(nmp)) + nmp->m_sb.sb_rgcount = howmany_64(nmp->m_sb.sb_rextents, + nmp->m_sb.sb_rgextents); + else + nmp->m_sb.sb_rgcount = 1; nmp->m_rsumblocks = xfs_rtsummary_blockcount(nmp, &nmp->m_rsumlevels); if (rblocks > 0) @@ -761,6 +766,26 @@ xfs_growfs_rt_alloc_fake_mount( return nmp; } +static xfs_rfsblock_t +xfs_growfs_rt_nrblocks( + struct xfs_rtgroup *rtg, + xfs_rfsblock_t nrblocks, + xfs_agblock_t rextsize, + xfs_fileoff_t bmbno) +{ + struct xfs_mount *mp = rtg_mount(rtg); + xfs_rfsblock_t step; + + step = (bmbno + 1) * NBBY * mp->m_sb.sb_blocksize * rextsize; + if (xfs_has_rtgroups(mp)) { + xfs_rfsblock_t rgblocks = mp->m_sb.sb_rgextents * rextsize; + + step = min(rgblocks, step) + rgblocks * rtg_rgno(rtg); + } + + return min(nrblocks, step); +} + static int xfs_growfs_rt_bmblock( struct xfs_rtgroup *rtg, @@ -779,16 +804,15 @@ xfs_growfs_rt_bmblock( .rtg = rtg, }; struct xfs_mount *nmp; - xfs_rfsblock_t nrblocks_step; xfs_rtbxlen_t freed_rtx; int error; /* * Calculate new sb and mount fields for this round. */ - nrblocks_step = (bmbno + 1) * NBBY * mp->m_sb.sb_blocksize * rextsize; nmp = nargs.mp = xfs_growfs_rt_alloc_fake_mount(mp, - min(nrblocks, nrblocks_step), rextsize); + xfs_growfs_rt_nrblocks(rtg, nrblocks, rextsize, bmbno), + rextsize); if (!nmp) return -ENOMEM; From patchwork Thu Oct 17 19:04:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840706 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 319F721B42B for ; Thu, 17 Oct 2024 19:04:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191852; cv=none; b=dFPCtAX99UQfSnfkSTzHiU8zuy1g2TtHVIEgf0PxbqCx+vOZYOTRKdu2ZALJIu5ZTfdoM4IsjR41wfZvfHD7D6/DHbCcQlpFxiSsXQCle3VoqorYR6h/632yz8STnQD5zYl8/ZWGpOrvwPlGiN3Lut4rpv2kvewlwXZPMFfCHRQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191852; c=relaxed/simple; bh=ubx+jHgJxj6Q8aJ0jJF5hZsXzXbTF+6lZvGlcG+oSA0=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=hiucSOQnw9YJ34qkjfmfKVMGAWQUV9AyfrS5SF7u0onjQWgi61RkeUja6dbNvIxCPoo/93OxqNKFD9wqTiGphh7q7k9CGlmBrdVz2ljQqQWBWl+R92KHDtvZ/oq724OfcDBcpwMgt+M7LD5cOGadm7EQze5yxDbBYnRoP3iZI5E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Ueenfda8; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Ueenfda8" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1172DC4CECD; Thu, 17 Oct 2024 19:04:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729191852; bh=ubx+jHgJxj6Q8aJ0jJF5hZsXzXbTF+6lZvGlcG+oSA0=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=Ueenfda8kAEveVHRe6Y94POL967xCssl55QPsz6kLqPwLwH4QGcVU3BYDFhBBE6ty U+QKuDFYfO30R90kR5dz+C/o5vRUbNe1uQaqQMSLRMiv4biaEuEyegnx2ZBuggC9yE j25Wth2B7+Wd7Z5Fq7VH9pVwAikZYS0Ps3xLymL07+n5++OATktIvQATZP2XgzwOfr 8DnOeazaFkTURgwevY1JyKobGBNPU5+GiG/mYha7IvhL6GJ1GdMQ+0oH4FKLWphpua v8Rz38EXU7xTpb6+t6UGNzCCzwiHzADRfe9aE4ga9haHaI6PAMlsilCRV2UWC/9KOp 4P8mLVojSRxIw== Date: Thu, 17 Oct 2024 12:04:11 -0700 Subject: [PATCH 02/34] xfs: check the realtime superblock at mount time From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919071700.3453179.14138350794383351571.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Check the realtime superblock at mount time, to ensure that the label and uuids actually match the primary superblock on the data device. 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 Reviewed-by: Christoph Hellwig --- fs/xfs/xfs_mount.h | 1 + fs/xfs/xfs_rtalloc.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_rtalloc.h | 6 ++++++ fs/xfs/xfs_super.c | 12 ++++++++++-- 4 files changed, 67 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index eca206140d4b0c..06d67089b91f33 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -119,6 +119,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 866274a66d4d28..27186fcfdcde73 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -1152,6 +1152,56 @@ xfs_growfs_rt( return error; } +/* Read the realtime superblock and attach it to the mount. */ +int +xfs_rtmount_readsb( + struct xfs_mount *mp) +{ + struct xfs_buf *bp; + int error; + + if (!xfs_has_rtsb(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 a6836da9bebef5..8e2a07b8174b74 100644 --- a/fs/xfs/xfs_rtalloc.h +++ b/fs/xfs/xfs_rtalloc.h @@ -12,6 +12,10 @@ struct xfs_mount; struct xfs_trans; #ifdef CONFIG_XFS_RT +/* rtgroup superblock initialization */ +int xfs_rtmount_readsb(struct xfs_mount *mp); +void xfs_rtmount_freesb(struct xfs_mount *mp); + /* * Initialize realtime fields in the mount structure. */ @@ -42,6 +46,8 @@ int xfs_rtalloc_reinit_frextents(struct xfs_mount *mp); #else # 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 9ae352dfdd6c57..3afeab6844680a 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -45,6 +45,7 @@ #include "xfs_rtbitmap.h" #include "xfs_exchmaps_item.h" #include "xfs_parent.h" +#include "xfs_rtalloc.h" #include "scrub/stats.h" #include "scrub/rcbag_btree.h" @@ -1145,6 +1146,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); @@ -1690,9 +1692,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 @@ -1781,6 +1787,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: @@ -1800,7 +1808,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 Thu Oct 17 19:04:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840707 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 BFC211DED44 for ; Thu, 17 Oct 2024 19:04:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191862; cv=none; b=DeP2w+KBcE4v4uprQYsZCyoqYOOdQvGXYT3HiTuenmXdkzlzLObmEwHcv3clOd/iE1JSblbh9RntZrb0EGl2vDCQRxQfzZn0bgeADFMha0XARbSrYFBySDMmTVAom87rMVK9m6eyufWNE+VJoNYJPvOH8iiTEYdR/Xp5PYt2K98= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191862; c=relaxed/simple; bh=mdoBhgjnn/xi7i5ZqZ7pgDn8VWoW+7cWdcTU5bQigo0=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=gkQORGmpUTNTAqu1D7qwAD01eJw5voJcIcWMz1neOHePSFqI42K1QmuwK4JXEKWGFSprz8NytU2ranU8rEUhmgJIaf/XQ8u0U85lkWAChjt1TT+A9Gvq8hZUXv56WZxQHgTRghiEOJPqgFuNd+r7JLM+ZiHfjFw2ifBHOXW1WLI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WR8BEyer; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="WR8BEyer" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9C4D2C4CEC3; Thu, 17 Oct 2024 19:04:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729191862; bh=mdoBhgjnn/xi7i5ZqZ7pgDn8VWoW+7cWdcTU5bQigo0=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=WR8BEyer2ceosz485EZdKLtWmR6Z67zvTpAYxejiREF+MlTtHvB+TShbBpqU+pEtG sIxiHuMmv7KsRGbESzfOl1NmjbBdTFIQpl+9Q/uvYSe9jWm5oCV7aOexoXWDvDqZ78 y6MQAVmT6Y4a9xS1PCJDxKkSLcaMMPxS/5F2qS8WhuAntMjFaCDkP2jWgaSL3TfL8a mOtj0EaF5iMtAMRTzIbyzHSQqsHQacW2rRD+TP2PQlHyNHlNXJwG4MqjqN9dzZYRnX PgBNWaHF9g5t/GXF+LAZa2zOfX7I/GiJcTzdWFYDSdztnf8T1tFr8lkLUXEllODTB8 JI2f5zKuoGr1Q== Date: Thu, 17 Oct 2024 12:04:22 -0700 Subject: [PATCH 03/34] xfs: update realtime super every time we update the primary fs super From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919071717.3453179.11185815904810320065.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Every time we update parts of the primary filesystem superblock that are echoed in the rt superblock, we must update the rt super. Avoid changing the log to support logging to the rt device by using ordered buffers. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_rtgroup.c | 60 +++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_rtgroup.h | 7 +++++ fs/xfs/libxfs/xfs_sb.c | 14 +++++++++- fs/xfs/libxfs/xfs_sb.h | 2 + fs/xfs/xfs_buf_item_recover.c | 12 ++++++++ fs/xfs/xfs_ioctl.c | 4 ++- fs/xfs/xfs_trans.c | 1 + fs/xfs/xfs_trans.h | 1 + fs/xfs/xfs_trans_buf.c | 25 ++++++++++++++--- 9 files changed, 118 insertions(+), 8 deletions(-) diff --git a/fs/xfs/libxfs/xfs_rtgroup.c b/fs/xfs/libxfs/xfs_rtgroup.c index 9e2ca61559f45e..470260c911c8d1 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.c +++ b/fs/xfs/libxfs/xfs_rtgroup.c @@ -564,3 +564,63 @@ const struct xfs_buf_ops xfs_rtsb_buf_ops = { .verify_write = xfs_rtsb_write_verify, .verify_struct = xfs_rtsb_verify_all, }; + +/* Update a realtime superblock from the primary fs super */ +void +xfs_update_rtsb( + 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_pad = 0; + memcpy(&rsb->rsb_fname, &dsb->sb_fname, XFSLABEL_MAX); + + memcpy(&rsb->rsb_uuid, &dsb->sb_uuid, sizeof(rsb->rsb_uuid)); + + /* + * 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 realtime superblock from a filesystem superblock and log it to + * the given transaction. + */ +struct xfs_buf * +xfs_log_rtsb( + struct xfs_trans *tp, + const struct xfs_buf *sb_bp) +{ + struct xfs_buf *rtsb_bp; + + if (!xfs_has_rtsb(tp->t_mountp)) + return NULL; + + 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 NULL; + } + + xfs_update_rtsb(rtsb_bp, sb_bp); + xfs_trans_ordered_buf(tp, rtsb_bp); + return rtsb_bp; +} diff --git a/fs/xfs/libxfs/xfs_rtgroup.h b/fs/xfs/libxfs/xfs_rtgroup.h index 6ccf31bb6bc7a7..e7679fafff8ce7 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.h +++ b/fs/xfs/libxfs/xfs_rtgroup.h @@ -251,6 +251,11 @@ static inline const char *xfs_rtginode_path(xfs_rgnumber_t rgno, { return kasprintf(GFP_KERNEL, "%u.%s", rgno, xfs_rtginode_name(type)); } + +void xfs_update_rtsb(struct xfs_buf *rtsb_bp, + const struct xfs_buf *sb_bp); +struct xfs_buf *xfs_log_rtsb(struct xfs_trans *tp, + const struct xfs_buf *sb_bp); #else static inline void xfs_free_rtgroups(struct xfs_mount *mp, xfs_rgnumber_t first_rgno, xfs_rgnumber_t end_rgno) @@ -269,6 +274,8 @@ static inline int xfs_initialize_rtgroups(struct xfs_mount *mp, # define xfs_rtgroup_lock(rtg, gf) ((void)0) # define xfs_rtgroup_unlock(rtg, gf) ((void)0) # define xfs_rtgroup_trans_join(tp, rtg, gf) ((void)0) +# define xfs_update_rtsb(bp, sb_bp) ((void)0) +# define xfs_log_rtsb(tp, sb_bp) (NULL) #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 b5f798d01dba05..6b0757d60cf3af 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_exchrange.h" +#include "xfs_rtgroup.h" /* * Physical superblock buffer manipulations. Shared with libxfs in userspace. @@ -1276,10 +1277,12 @@ xfs_update_secondary_sbs( */ int xfs_sync_sb_buf( - struct xfs_mount *mp) + struct xfs_mount *mp, + bool update_rtsb) { 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); @@ -1289,6 +1292,11 @@ xfs_sync_sb_buf( bp = xfs_trans_getsb(tp); xfs_log_sb(tp); xfs_trans_bhold(tp, bp); + if (update_rtsb) { + rtsb_bp = xfs_log_rtsb(tp, bp); + if (rtsb_bp) + xfs_trans_bhold(tp, rtsb_bp); + } xfs_trans_set_sync(tp); error = xfs_trans_commit(tp); if (error) @@ -1297,7 +1305,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/libxfs/xfs_sb.h b/fs/xfs/libxfs/xfs_sb.h index 885c837559914d..999dcfccdaf960 100644 --- a/fs/xfs/libxfs/xfs_sb.h +++ b/fs/xfs/libxfs/xfs_sb.h @@ -15,7 +15,7 @@ struct xfs_perag; extern void xfs_log_sb(struct xfs_trans *tp); extern int xfs_sync_sb(struct xfs_mount *mp, bool wait); -extern int xfs_sync_sb_buf(struct xfs_mount *mp); +extern int xfs_sync_sb_buf(struct xfs_mount *mp, bool update_rtsb); extern void xfs_sb_mount_common(struct xfs_mount *mp, struct xfs_sb *sbp); void xfs_mount_sb_set_rextsize(struct xfs_mount *mp, struct xfs_sb *sbp); diff --git a/fs/xfs/xfs_buf_item_recover.c b/fs/xfs/xfs_buf_item_recover.c index c8259ee482fd86..feb3db2e891614 100644 --- a/fs/xfs/xfs_buf_item_recover.c +++ b/fs/xfs/xfs_buf_item_recover.c @@ -1061,6 +1061,18 @@ xlog_recover_buf_commit_pass2( current_lsn); if (error) goto out_release; + + /* Update the rt superblock if we have one. */ + if (xfs_has_rtsb(mp) && mp->m_rtsb_bp) { + struct xfs_buf *rtsb_bp = mp->m_rtsb_bp; + + xfs_buf_lock(rtsb_bp); + xfs_buf_hold(rtsb_bp); + xfs_update_rtsb(rtsb_bp, bp); + rtsb_bp->b_flags |= _XBF_LOGRECOVERY; + xfs_buf_delwri_queue(rtsb_bp, buffer_list); + xfs_buf_relse(rtsb_bp); + } } else { xlog_recover_do_reg_buffer(mp, item, bp, buf_f, current_lsn); } diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index ce4851e2800a3f..4d5df6593af5fd 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -1028,7 +1028,7 @@ xfs_ioc_setlabel( * buffered reads from userspace (i.e. from blkid) are invalidated, * and userspace will see the newly-written label. */ - error = xfs_sync_sb_buf(mp); + error = xfs_sync_sb_buf(mp, true); if (error) goto out; /* @@ -1039,6 +1039,8 @@ xfs_ioc_setlabel( mutex_unlock(&mp->m_growlock); invalidate_bdev(mp->m_ddev_targp->bt_bdev); + if (xfs_has_rtsb(mp) && mp->m_rtdev_targp) + invalidate_bdev(mp->m_rtdev_targp->bt_bdev); out: mnt_drop_write_file(filp); diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index cee7f0564409bd..118d31e11127be 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; diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index f06cc0f41665ad..f97e5c416efad1 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -214,6 +214,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 e28ab74af4f0e1..8e886ecfd69a3b 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 Thu Oct 17 19:04:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840708 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 9A91F21C18B for ; Thu, 17 Oct 2024 19:04:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191873; cv=none; b=aS1pWuo3KgWUCcNCeceLQgIg1DveVPWyvYm8upkr+HZqXWqG+hoKAVidAADki5qAe0MZVXkEGHmWtply+Ff4xxcM0x2lkla3fopwsqe9yCm9G+EHxe8MTpNkqf4mis3aCHZgo+ub4V7l+DzuUvR1ZQJkZK49w4osz21mV+zjb8Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191873; c=relaxed/simple; bh=3MhcNq9E7Zhfb3Wl3p4T7RJv8Gs3D/NgwmzTCH7Qs7Q=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=CPLuZguWCNbjpeUxM+kg6bx2fLUxh7PngAEXwUJoHgTys0B5fOz+e0rthWhdlHAi2M3K9dn7bjJRwwQe9+DWvhKwpKevpHpDm3qHP41Tk5VUnoeMXwRVQwC8OtsknZhQy/OWAgS9ClVYkfCQ62pXkei3Sv5yEIp2jyrPdL7B8Hk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=sCVaWB9F; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="sCVaWB9F" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 34CEBC4CEC3; Thu, 17 Oct 2024 19:04:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729191873; bh=3MhcNq9E7Zhfb3Wl3p4T7RJv8Gs3D/NgwmzTCH7Qs7Q=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=sCVaWB9F5dLKzB/E7UIXwLVxHlDghysRlktIjjaYuEiDuxqD7mwpoKVgFideAf8xx KVw76/hrPDzHlTswdCEtqEs/YAodX13NfbwzipwdpfAk8Pj48GyHwurieX53FelOod dx1MJFrCLOV6hUNSx193ENaeVZ54LSsqRAMbb8dCiIjiEdI3CKn2cj75wTGHKkSTM1 E7GpqDweQSWqxZg/SlkK/1t23IzEwzoQop6zLu6Fjf/XuFsyHt2/1K+DNvCWEc2tEh hiY1SAzF/guH5Kh3ISuV7TGASA6SGBEvDUz9G3B2W3cd34xPQFqyeqYQ7fXW+coFM4 2+8YrzkF6eqUA== Date: Thu, 17 Oct 2024 12:04:32 -0700 Subject: [PATCH 04/34] xfs: export realtime group geometry via XFS_FSOP_GEOM From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919071735.3453179.3805342059369104132.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Export the realtime geometry information so that userspace can query it. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- 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 faa38a7d1eb019..5c224d03270ce9 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -187,7 +187,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 rgextents; /* rt extents 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 6b0757d60cf3af..b1e12c7e7dbe23 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -1413,6 +1413,11 @@ xfs_fs_geometry( return; geo->version = XFS_FSOP_GEOM_VERSION_V5; + + if (xfs_has_rtgroups(mp)) { + geo->rgcount = sbp->sb_rgcount; + geo->rgextents = sbp->sb_rgextents; + } } /* Read a secondary superblock. */ From patchwork Thu Oct 17 19:04:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840709 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 436A421B43F for ; Thu, 17 Oct 2024 19:04:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191884; cv=none; b=BAa3qM1faQkOI1ZmA+b3TnMqji0aO6UatD7AA7E1xWrjstfyK7Il9n/v2SbVZyP/bshE78wDYkGtKcvMC0l5tCRJJNfrDzCJnLP3m9er3wr98/mOK9QOWNf3c7XM9c8bzw+wtqcutyU09cbXW3CAAi3ZTX+qVaSmdBDOAKqHPf4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191884; c=relaxed/simple; bh=8rfE2xWxsXbpSJoXBy6jSHY1KBlfKjhVUcFamUAByi0=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=bH+QSvwBsyca8ijDGuIrEa40/bg8rwNJL04rlEnLfQ0BltXEAKBuuXSYELg5HNvUFcY6mNiigxe7gZ1IJZAm/TDVmBd7ewUs1onweMmmMVgx6F2xP7CoZ/eGP6j5uNuCF/W3IPF64vXhL30eaF4p8kQe+wMq4fpNMjZOQ3CQOBM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KFMiR9a/; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="KFMiR9a/" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D36E2C4CEC3; Thu, 17 Oct 2024 19:04:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729191883; bh=8rfE2xWxsXbpSJoXBy6jSHY1KBlfKjhVUcFamUAByi0=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=KFMiR9a/J4SwN+KX8fe/c81BvFy07WEchCSGj87iYMKW8xHdpxoty8biuTl8Xa0gQ hlA3pcXr3ABJRn06rfnpv+datFKt/dYdEGFIIu5QDP2KNLUqE6aU2LZQNpC8atXkpx EBTVYDRUixdfP0RvENo12tsXKssDo1SDKRb+nZhVp3k/CMROJgih5G9VE2ao7LXMGJ A5RzLvL4nOcTKPPx+E/E/HnYDL+gjTcgFb6/WHdGZUHV2185m1LSB4hSvhxtewEGJF gurTYd2McULM3Ihws8EIGUMmO/nK5bmarBEu6woY8/izJNVTLGGF/KxWJDEc7anvJJ +jPq+v5h4eQvQ== Date: Thu, 17 Oct 2024 12:04:43 -0700 Subject: [PATCH 05/34] xfs: check that rtblock extents do not break rtsupers or rtgroups From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919071752.3453179.5275357148266525178.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Check that rt block pointers do not point to the realtime superblock and that allocated rt space extents do not cross rtgroup boundaries. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_types.c | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/fs/xfs/libxfs/xfs_types.c b/fs/xfs/libxfs/xfs_types.c index 1cbfe57e971d5c..a4c30844d42be1 100644 --- a/fs/xfs/libxfs/xfs_types.c +++ b/fs/xfs/libxfs/xfs_types.c @@ -12,6 +12,8 @@ #include "xfs_bit.h" #include "xfs_mount.h" #include "xfs_ag.h" +#include "xfs_rtbitmap.h" +#include "xfs_rtgroup.h" /* @@ -135,18 +137,37 @@ xfs_verify_dir_ino( } /* - * Verify that an realtime block number pointer doesn't point off the - * end of the realtime device. + * Verify that a realtime block number pointer neither points outside the + * allocatable areas of the rtgroup nor off the end of the realtime + * device. */ inline bool xfs_verify_rtbno( struct xfs_mount *mp, xfs_rtblock_t rtbno) { - return rtbno < mp->m_sb.sb_rblocks; + if (rtbno >= mp->m_sb.sb_rblocks) + return false; + + if (xfs_has_rtgroups(mp)) { + xfs_rgnumber_t rgno = xfs_rtb_to_rgno(mp, rtbno); + xfs_rtxnum_t rtx = xfs_rtb_to_rtx(mp, rtbno); + + if (rgno >= mp->m_sb.sb_rgcount) + return false; + if (rtx >= xfs_rtgroup_extents(mp, rgno)) + return false; + if (xfs_has_rtsb(mp) && rgno == 0 && rtx == 0) + return false; + } + return true; } -/* Verify that a realtime device extent is fully contained inside the volume. */ +/* + * Verify that an allocated realtime device extent neither points outside + * allocatable areas of the rtgroup, across an rtgroup boundary, nor off the + * end of the realtime device. + */ bool xfs_verify_rtbext( struct xfs_mount *mp, @@ -159,7 +180,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 Thu Oct 17 19:04:54 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840710 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 E728F21B43F for ; Thu, 17 Oct 2024 19:04:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191895; cv=none; b=pwP9ehwLhI9slcXKAnrQm4Ma3Qk9hS7t8l0+KDGkAFGqBT+rjLPwi1xKJrr2+RedWykhqODo10M1h/wp8m0+U4NnM3CV0gbs0/Cd5nGWRkUHgCMoKm4rPUkmZ8j9iefpMapKlsASwyRlLcJJOOYJuP/XibvU6QFe6xSyg2TchxQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191895; c=relaxed/simple; bh=CGzLs+wLBxbCVotl/MPY8RAwxOm2ol+utwrM6SlqLYw=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=oYU9CCNx3gISfPtMLus1m+eGlreLiYFBULdzlVX0k5oFZrjrvrqrJHpIcTFtX3mFZfv4tdEC/I3nlLetb8TP2XhfWn3ZXf96RzzZ5hBKR3lTlbiItK8jH5uegUCWPYNVs1kj+q41daclblBVFttq3bQS9NX0+A+UvNcXiCVtxeM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=P9lLap8Q; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="P9lLap8Q" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6C320C4CEC3; Thu, 17 Oct 2024 19:04:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729191894; bh=CGzLs+wLBxbCVotl/MPY8RAwxOm2ol+utwrM6SlqLYw=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=P9lLap8Q1rjPPeULEY8iGdH7XQzo14vmToo15oPf1eiM4Gj1dbuY/7bIYZg9KGwSn DREhSdYngThWbjyKGUHZPzpv/pf66rUd/+UpG85UuWoof329zgOFgh+slxFP+oThhz DGaY/hWR4pCKuZLqtM+vGijM1sHAhB9KDOuHTMLYuctgHfNbTTmEf3EoI3SekzxMqr yiTQGCkosJFWJJSAJyAbUbkx9Rd/pj1ZjCvdoVzLlTeggjEcEhHVoQ0DXdV94LuHQS DQiflwvBSEIbK87uecmFgJIDxI5wSLFbkHurLOUgumI5hG5/q4G+U3fUek08G50xhq n6KYE1dvr5TMA== Date: Thu, 17 Oct 2024 12:04:54 -0700 Subject: [PATCH 06/34] xfs: add a helper to prevent bmap merges across rtgroup boundaries From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919071769.3453179.4018870121067601287.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Christoph Hellwig Except for the rt superblock, realtime groups do not store any metadata at the start (or end) of the group. There is nothing to prevent the bmap code from merging allocations from multiple groups into a single bmap record. Add a helper to check for this case. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong [djwong: massage the commit message after pulling this into rtgroups] Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_bmap.c | 56 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 9bfa8247854d41..482b4c0cd6b193 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -40,6 +40,7 @@ #include "xfs_bmap_item.h" #include "xfs_symlink_remote.h" #include "xfs_inode_util.h" +#include "xfs_rtgroup.h" struct kmem_cache *xfs_bmap_intent_cache; @@ -1426,6 +1427,24 @@ xfs_bmap_last_offset( * Extent tree manipulation functions used during allocation. */ +static inline bool +xfs_bmap_same_rtgroup( + struct xfs_inode *ip, + int whichfork, + struct xfs_bmbt_irec *left, + struct xfs_bmbt_irec *right) +{ + struct xfs_mount *mp = ip->i_mount; + + if (xfs_ifork_is_realtime(ip, whichfork) && xfs_has_rtgroups(mp)) { + if (xfs_rtb_to_rgno(mp, left->br_startblock) != + xfs_rtb_to_rgno(mp, right->br_startblock)) + return false; + } + + return true; +} + /* * Convert a delayed allocation to a real allocation. */ @@ -1495,7 +1514,8 @@ xfs_bmap_add_extent_delay_real( LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff && LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock && LEFT.br_state == new->br_state && - LEFT.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN) + LEFT.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN && + xfs_bmap_same_rtgroup(bma->ip, whichfork, &LEFT, new)) state |= BMAP_LEFT_CONTIG; /* @@ -1519,7 +1539,8 @@ xfs_bmap_add_extent_delay_real( (BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING) || LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount - <= XFS_MAX_BMBT_EXTLEN)) + <= XFS_MAX_BMBT_EXTLEN) && + xfs_bmap_same_rtgroup(bma->ip, whichfork, new, &RIGHT)) state |= BMAP_RIGHT_CONTIG; error = 0; @@ -2064,7 +2085,8 @@ xfs_bmap_add_extent_unwritten_real( LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff && LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock && LEFT.br_state == new->br_state && - LEFT.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN) + LEFT.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN && + xfs_bmap_same_rtgroup(ip, whichfork, &LEFT, new)) state |= BMAP_LEFT_CONTIG; /* @@ -2088,7 +2110,8 @@ xfs_bmap_add_extent_unwritten_real( (BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING) || LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount - <= XFS_MAX_BMBT_EXTLEN)) + <= XFS_MAX_BMBT_EXTLEN) && + xfs_bmap_same_rtgroup(ip, whichfork, new, &RIGHT)) state |= BMAP_RIGHT_CONTIG; /* @@ -2597,7 +2620,8 @@ xfs_bmap_add_extent_hole_delay( */ if ((state & BMAP_LEFT_VALID) && (state & BMAP_LEFT_DELAY) && left.br_startoff + left.br_blockcount == new->br_startoff && - left.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN) + left.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN && + xfs_bmap_same_rtgroup(ip, whichfork, &left, new)) state |= BMAP_LEFT_CONTIG; if ((state & BMAP_RIGHT_VALID) && (state & BMAP_RIGHT_DELAY) && @@ -2605,7 +2629,8 @@ xfs_bmap_add_extent_hole_delay( new->br_blockcount + right.br_blockcount <= XFS_MAX_BMBT_EXTLEN && (!(state & BMAP_LEFT_CONTIG) || (left.br_blockcount + new->br_blockcount + - right.br_blockcount <= XFS_MAX_BMBT_EXTLEN))) + right.br_blockcount <= XFS_MAX_BMBT_EXTLEN)) && + xfs_bmap_same_rtgroup(ip, whichfork, new, &right)) state |= BMAP_RIGHT_CONTIG; /* @@ -2748,7 +2773,8 @@ xfs_bmap_add_extent_hole_real( left.br_startoff + left.br_blockcount == new->br_startoff && left.br_startblock + left.br_blockcount == new->br_startblock && left.br_state == new->br_state && - left.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN) + left.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN && + xfs_bmap_same_rtgroup(ip, whichfork, &left, new)) state |= BMAP_LEFT_CONTIG; if ((state & BMAP_RIGHT_VALID) && !(state & BMAP_RIGHT_DELAY) && @@ -2758,7 +2784,8 @@ xfs_bmap_add_extent_hole_real( new->br_blockcount + right.br_blockcount <= XFS_MAX_BMBT_EXTLEN && (!(state & BMAP_LEFT_CONTIG) || left.br_blockcount + new->br_blockcount + - right.br_blockcount <= XFS_MAX_BMBT_EXTLEN)) + right.br_blockcount <= XFS_MAX_BMBT_EXTLEN) && + xfs_bmap_same_rtgroup(ip, whichfork, new, &right)) state |= BMAP_RIGHT_CONTIG; error = 0; @@ -5715,6 +5742,8 @@ xfs_bunmapi( */ STATIC bool xfs_bmse_can_merge( + struct xfs_inode *ip, + int whichfork, struct xfs_bmbt_irec *left, /* preceding extent */ struct xfs_bmbt_irec *got, /* current extent to shift */ xfs_fileoff_t shift) /* shift fsb */ @@ -5730,7 +5759,8 @@ xfs_bmse_can_merge( if ((left->br_startoff + left->br_blockcount != startoff) || (left->br_startblock + left->br_blockcount != got->br_startblock) || (left->br_state != got->br_state) || - (left->br_blockcount + got->br_blockcount > XFS_MAX_BMBT_EXTLEN)) + (left->br_blockcount + got->br_blockcount > XFS_MAX_BMBT_EXTLEN) || + !xfs_bmap_same_rtgroup(ip, whichfork, left, got)) return false; return true; @@ -5766,7 +5796,7 @@ xfs_bmse_merge( blockcount = left->br_blockcount + got->br_blockcount; xfs_assert_ilocked(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); - ASSERT(xfs_bmse_can_merge(left, got, shift)); + ASSERT(xfs_bmse_can_merge(ip, whichfork, left, got, shift)); new = *left; new.br_blockcount = blockcount; @@ -5928,7 +5958,8 @@ xfs_bmap_collapse_extents( goto del_cursor; } - if (xfs_bmse_can_merge(&prev, &got, offset_shift_fsb)) { + if (xfs_bmse_can_merge(ip, whichfork, &prev, &got, + offset_shift_fsb)) { error = xfs_bmse_merge(tp, ip, whichfork, offset_shift_fsb, &icur, &got, &prev, cur, &logflags); @@ -6064,7 +6095,8 @@ xfs_bmap_insert_extents( * never find mergeable extents in this scenario. Check anyways * and warn if we encounter two extents that could be one. */ - if (xfs_bmse_can_merge(&got, &next, offset_shift_fsb)) + if (xfs_bmse_can_merge(ip, whichfork, &got, &next, + offset_shift_fsb)) WARN_ON_ONCE(1); } From patchwork Thu Oct 17 19:05:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840711 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 8130C219CA6 for ; Thu, 17 Oct 2024 19:05:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191905; cv=none; b=tW8R5XDj8XgPnecnnO96o7Rc7Ng9ySYp4xDX5xYNdBIhLug8QJdkG1yIgYRO5xE0XdlnuEAlJaMgOyvRIDJUU8BV/jpvy3Rozxx9bxBjmU51bTIqTji64qhOuEK1STM8DTHN0/grTDpN7BQHJTRgQQ29FKv5YcibWW8tPEIZZGQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191905; c=relaxed/simple; bh=Kf4OGCBwEryZinaVODl+gy8LCKsEetfQ/nDiw2Jr15M=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=UeUeEW075pNVbTlPYNF6BQpBl3b9cO8b+yNiXn55pUys7XevsTwCKhhnijxM3S9HkGZohFbTN8Bevbj61mlOWX6H55QjY2wGn7e2Ca3kxa2pqkRIT34IuKgH94/VxPjJFCndox5h2Hct8zbKBVJYJi4St70C2fUPakMrkzkpDr0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=aj5kwcLs; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="aj5kwcLs" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0ED17C4CEC3; Thu, 17 Oct 2024 19:05:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729191905; bh=Kf4OGCBwEryZinaVODl+gy8LCKsEetfQ/nDiw2Jr15M=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=aj5kwcLs2zInkX4zKDgCpN3LvPqpwdD5qvNYTZMIyiLD4rwZSEKrE/7wDwUmuZ4sj ktqCA/Q4M98WeBbDAyT7fbXCRwnRnIKkw3qOCyEVSxJBplJj+knVnyIsBnJOmgTk+i CuN+gjBy4428TkuslHnlLFgl9HwyVIl0exqpSNnP+bNX7PO1+fEobPH+mwpbXsmnUo jngnK9wgB5bWrWjv0ZFLF4FY4EWcW0W0PpVRNXjjeEn3Ltd/rltv9ucGwK8XNxRVGM i9F+XiCfmoCS5So+pHnc22mvQVjJOLuUuRcjpF8oYwn2jgNZVJTzsff+QwUQutIfLl 9f8bnNvYaltLw== Date: Thu, 17 Oct 2024 12:05:04 -0700 Subject: [PATCH 07/34] xfs: add frextents to the lazysbcounters when rtgroups enabled From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919071787.3453179.10280926363632024087.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Make 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 Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_sb.c | 15 ++++++++++----- fs/xfs/scrub/fscounters_repair.c | 9 +++++---- fs/xfs/xfs_trans.c | 33 +++++++++++++++++++-------------- 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index b1e12c7e7dbe23..d5bf886e18ab9e 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -1152,11 +1152,6 @@ xfs_log_sb( * reservations that have been taken out percpu counters. If we have an * unclean shutdown, this will be corrected by log recovery rebuilding * the counters from the AGF block counts. - * - * Do not update sb_frextents here because it is not part of the lazy - * 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. */ if (xfs_has_lazysbcount(mp)) { mp->m_sb.sb_icount = percpu_counter_sum_positive(&mp->m_icount); @@ -1167,6 +1162,16 @@ xfs_log_sb( percpu_counter_sum_positive(&mp->m_fdblocks); } + /* + * sb_frextents was added to the lazy sb counters when the rt groups + * feature was introduced. This counter can go negative due to the way + * we handle nearly-lockless reservations, so we must use the _positive + * variant here to avoid writing out nonsense frextents. + */ + if (xfs_has_rtgroups(mp)) + mp->m_sb.sb_frextents = + percpu_counter_sum_positive(&mp->m_frextents); + 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); diff --git a/fs/xfs/scrub/fscounters_repair.c b/fs/xfs/scrub/fscounters_repair.c index 469bf645dbea52..cda13447a373e1 100644 --- a/fs/xfs/scrub/fscounters_repair.c +++ b/fs/xfs/scrub/fscounters_repair.c @@ -68,15 +68,16 @@ xrep_fscounters( /* * Online repair is only supported on v5 file systems, which require - * lazy sb counters and thus no update of sb_fdblocks here. But as of - * now we don't support lazy counting sb_frextents yet, and thus need - * to also update it directly here. And for that we need to keep + * lazy sb counters and thus no update of sb_fdblocks here. But + * sb_frextents only uses a lazy counter with rtgroups, and thus needs + * to be updated directly here otherwise. And for that we need to keep * track of the delalloc reservations separately, as they are are * subtracted from m_frextents, but not included in sb_frextents. */ percpu_counter_set(&mp->m_frextents, fsc->frextents - fsc->frextents_delayed); - mp->m_sb.sb_frextents = fsc->frextents; + if (!xfs_has_rtgroups(mp)) + mp->m_sb.sb_frextents = fsc->frextents; return 0; } diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 118d31e11127be..01b5f5b32af467 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: /* @@ -430,6 +432,8 @@ xfs_trans_mod_sb( */ ASSERT(delta < 0); tp->t_res_frextents_delta += delta; + if (xfs_has_rtgroups(mp)) + flags &= ~XFS_TRANS_SB_DIRTY; break; case XFS_TRANS_SB_DBLOCKS: tp->t_dblocks_delta += delta; @@ -498,20 +502,22 @@ xfs_trans_apply_sb_deltas( } /* - * Updating frextents requires careful handling because it does not - * behave like the lazysb counters because we cannot rely on log - * recovery in older kenels to recompute the value from the rtbitmap. - * This means that the ondisk frextents must be consistent with the - * rtbitmap. + * 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. + * + * For older file systems, updating frextents requires careful handling + * because we cannot rely on log recovery in older kernels to recompute + * the value from the rtbitmap. This means that the ondisk frextents + * must be consistent with the rtbitmap. * * Therefore, log the frextents change to the ondisk superblock and * update the incore superblock so that future calls to xfs_log_sb * write the correct value ondisk. - * - * Don't touch m_frextents because it includes incore reservations, - * and those are handled by the unreserve function. */ - 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; @@ -619,7 +625,7 @@ xfs_trans_unreserve_and_mod_sb( } ASSERT(tp->t_rtx_res || tp->t_frextents_delta >= 0); - if (tp->t_flags & XFS_TRANS_SB_DIRTY) { + if (xfs_has_rtgroups(mp) || (tp->t_flags & XFS_TRANS_SB_DIRTY)) { rtxdelta += tp->t_frextents_delta; ASSERT(rtxdelta >= 0); } @@ -652,10 +658,9 @@ xfs_trans_unreserve_and_mod_sb( mp->m_sb.sb_icount += idelta; mp->m_sb.sb_ifree += ifreedelta; /* - * 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. + * Do not touch sb_frextents here because it is handled in + * xfs_trans_apply_sb_deltas for file systems where it isn't a lazy + * counter anyway. */ mp->m_sb.sb_dblocks += tp->t_dblocks_delta; mp->m_sb.sb_agcount += tp->t_agcount_delta; From patchwork Thu Oct 17 19:05:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840712 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 260EE1E0DC3 for ; Thu, 17 Oct 2024 19:05:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191916; cv=none; b=TxBKGLVzWlq2bpFckC/iTtqmwPzBl4Zcm3vznSbSjCOIIaLvUgoe94WHKtevhNTwLgFfT+VeAq0UR/Fv33ddcXFtecWk/ry/u2rHyIvhQ6Hr9S9BvABACu9ADa6WR6UsczzxpEjSfqXTuwnPj76AKyw7AY8wPmdmI+ymc14asOw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191916; c=relaxed/simple; bh=6gPCd9Jmuq8gyKFLwPLZN9HRZN0IGiOcoQGeu4VcV9Y=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Xorw67O1XQkc2lMVm0gtOUDzjZ9RR64MsvwGYBpOI6CUUqst+l1dEKdfGqno/Jqq5PfA/sVSHDGjEyVmQ0YP0sbtW+kF2NDKfhtgPFIEZ7/XwZrJ2Sk3/3wkItfst0hA1eUmWuhgTqJ7AxfkklXc+1MsGhSRWrmmNcZOjPCypR4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=vHW7+Jl4; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="vHW7+Jl4" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9DC40C4CEC3; Thu, 17 Oct 2024 19:05:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729191915; bh=6gPCd9Jmuq8gyKFLwPLZN9HRZN0IGiOcoQGeu4VcV9Y=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=vHW7+Jl4emwqpFx9siLI02rj/AJMGPIZSr/kJv9A3/iReSkwm9PWwF+mDBzPlEUdY Ic1ECLr4eKSAIQWe1p5arR6t9i3v4u7rUpYcC0bDa0jeNl7R8V6p1bC73M8QsEMUK5 KDEhtpfowFByrvbOM8bazxaL1JILKv2rkiVezDUlv/LHVbaG2OxaW+3QKiphbyXfe1 7k98B4Lm20S88kHFuPtgR6XoD2DSL4OCGQpCiGNKX4hFC6F5GeI2vxISNq8F7GfaO7 3y/S205NCI/rVhA7DA4kPxmsyFEeChruDbjhiyILX3h9C+ql4lTVl/p0993gzVKs0Y biHgM7WgtFwCg== Date: Thu, 17 Oct 2024 12:05:15 -0700 Subject: [PATCH 08/34] xfs: convert sick_map loops to use ARRAY_SIZE From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919071804.3453179.15009254087430418401.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Convert these arrays to use ARRAY_SIZE insteead of requiring an empty sentinel array element at the end. This saves memory and would have avoided a bug that worked its way into the next patch. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/xfs_health.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/fs/xfs/xfs_health.c b/fs/xfs/xfs_health.c index e5663e2ac9b853..b0d0c6bd9fa29c 100644 --- a/fs/xfs/xfs_health.c +++ b/fs/xfs/xfs_health.c @@ -373,6 +373,9 @@ struct ioctl_sick_map { unsigned int ioctl_mask; }; +#define for_each_sick_map(map, m) \ + for ((m) = (map); (m) < (map) + ARRAY_SIZE(map); (m)++) + static const struct ioctl_sick_map fs_map[] = { { XFS_SICK_FS_COUNTERS, XFS_FSOP_GEOM_SICK_COUNTERS}, { XFS_SICK_FS_UQUOTA, XFS_FSOP_GEOM_SICK_UQUOTA }, @@ -382,13 +385,11 @@ static const struct ioctl_sick_map fs_map[] = { { XFS_SICK_FS_NLINKS, XFS_FSOP_GEOM_SICK_NLINKS }, { XFS_SICK_FS_METADIR, XFS_FSOP_GEOM_SICK_METADIR }, { XFS_SICK_FS_METAPATH, XFS_FSOP_GEOM_SICK_METAPATH }, - { 0, 0 }, }; static const struct ioctl_sick_map rt_map[] = { { XFS_SICK_RT_BITMAP, XFS_FSOP_GEOM_SICK_RT_BITMAP }, { XFS_SICK_RT_SUMMARY, XFS_FSOP_GEOM_SICK_RT_SUMMARY }, - { 0, 0 }, }; static inline void @@ -418,11 +419,11 @@ xfs_fsop_geom_health( geo->checked = 0; xfs_fs_measure_sickness(mp, &sick, &checked); - for (m = fs_map; m->sick_mask; m++) + for_each_sick_map(fs_map, m) xfgeo_health_tick(geo, sick, checked, m); xfs_rt_measure_sickness(mp, &sick, &checked); - for (m = rt_map; m->sick_mask; m++) + for_each_sick_map(rt_map, m) xfgeo_health_tick(geo, sick, checked, m); } @@ -438,7 +439,6 @@ static const struct ioctl_sick_map ag_map[] = { { XFS_SICK_AG_RMAPBT, XFS_AG_GEOM_SICK_RMAPBT }, { XFS_SICK_AG_REFCNTBT, XFS_AG_GEOM_SICK_REFCNTBT }, { XFS_SICK_AG_INODES, XFS_AG_GEOM_SICK_INODES }, - { 0, 0 }, }; /* Fill out ag geometry health info. */ @@ -455,7 +455,7 @@ xfs_ag_geom_health( ageo->ag_checked = 0; xfs_group_measure_sickness(pag_group(pag), &sick, &checked); - for (m = ag_map; m->sick_mask; m++) { + for_each_sick_map(ag_map, m) { if (checked & m->sick_mask) ageo->ag_checked |= m->ioctl_mask; if (sick & m->sick_mask) @@ -477,7 +477,6 @@ static const struct ioctl_sick_map ino_map[] = { { XFS_SICK_INO_DIR_ZAPPED, XFS_BS_SICK_DIR }, { XFS_SICK_INO_SYMLINK_ZAPPED, XFS_BS_SICK_SYMLINK }, { XFS_SICK_INO_DIRTREE, XFS_BS_SICK_DIRTREE }, - { 0, 0 }, }; /* Fill out bulkstat health info. */ @@ -494,7 +493,7 @@ xfs_bulkstat_health( bs->bs_checked = 0; xfs_inode_measure_sickness(ip, &sick, &checked); - for (m = ino_map; m->sick_mask; m++) { + for_each_sick_map(ino_map, m) { if (checked & m->sick_mask) bs->bs_checked |= m->ioctl_mask; if (sick & m->sick_mask) From patchwork Thu Oct 17 19:05:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840713 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 6479F1E0DC3 for ; Thu, 17 Oct 2024 19:05:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191926; cv=none; b=dP9v54v1xmzMShV5uRCYUU6AmF0BMFe8x6Gypaiv0WFjl5oIUudXvbCPUcPp3Z6zgVlHXJZw/nw4e+6MzitjgNCr6cPMVjk5A8Ts+7nO3sJbnNMaE4yQCzj/8plCmRJ8npTXqZXToc1hti8IenD8lTYLCxHZzP3lr520PukqjME= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191926; c=relaxed/simple; bh=1w766CjaGHxOrJtq+n4hseE/F1DBzdJrMPO7p4A8npo=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=uR5hgx5QkZUdo0eUU0JKCPZQTukEbVa1HTBJAlF/SL5Eu9k7scw1frfXrVy+LiAwimq6l/e4c0PqXK+2KIBhcIX5pslEE9UQvCLLAppyoxbj3cZTc0/noFisioKKQR8HVAU/BBgO/ap96KYDlJtmUQeDzRQOzma0dICfwyCUQJI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IGHexQhK; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="IGHexQhK" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3D1D2C4CEC3; Thu, 17 Oct 2024 19:05:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729191926; bh=1w766CjaGHxOrJtq+n4hseE/F1DBzdJrMPO7p4A8npo=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=IGHexQhKw9ysrvDqC/en9Eyp6qDIdfRSFcbgj5XKGtCi86X4ittTvV6GUPdaSing9 wNnsi3T1fnv61CE4Sf/id2apC7x/S67Ra/wqa1VPW1Kq/SofLjNSYpmrZnfA1T1DvF hh7qXq/9c8HTTPROZEIr+b2aBVNW6lwpoBGpZ5Bw6GUE+mu5+/j+gzpxds3G8I7fu+ AfMR//0ZHScpsRCNIat1pGqSsLqvO7Adqc7W4pWBFkqHvrWiPytltCqx/45myBt4hn tJpeb0oFHKhKO9nDSSK6LvcXBBaFPqr4TOsJTJ2aSA+rGzpJ74Pzq9hrteCTaRmdfp QmwtQbfW90UyQ== Date: Thu, 17 Oct 2024 12:05:25 -0700 Subject: [PATCH 09/34] xfs: record rt group metadata errors in the health system From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919071821.3453179.18387264040007267965.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Record the state of per-rtgroup metadata sickness in the rtgroup structure for later reporting. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_health.h | 40 +++++++----- fs/xfs/libxfs/xfs_rtbitmap.c | 37 ++++++----- fs/xfs/libxfs/xfs_rtgroup.c | 38 ++++++++++- fs/xfs/libxfs/xfs_rtgroup.h | 1 fs/xfs/scrub/health.c | 31 ++++++--- fs/xfs/xfs_health.c | 142 ++++++++++++++++++------------------------ fs/xfs/xfs_trace.h | 4 - 7 files changed, 157 insertions(+), 136 deletions(-) diff --git a/fs/xfs/libxfs/xfs_health.h b/fs/xfs/libxfs/xfs_health.h index a23df94319e5fb..3d93b57cf57143 100644 --- a/fs/xfs/libxfs/xfs_health.h +++ b/fs/xfs/libxfs/xfs_health.h @@ -54,6 +54,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 */ @@ -65,9 +66,10 @@ struct xfs_da_args; #define XFS_SICK_FS_METADIR (1 << 6) /* metadata directory tree */ #define XFS_SICK_FS_METAPATH (1 << 7) /* metadata directory tree path */ -/* 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 */ +/* Observable health issues for realtime group metadata. */ +#define XFS_SICK_RG_SUPER (1 << 0) /* rt group superblock */ +#define XFS_SICK_RG_BITMAP (1 << 1) /* rt group bitmap */ +#define XFS_SICK_RG_SUMMARY (1 << 2) /* rt groups summary */ /* Observable health issues for AG metadata. */ #define XFS_SICK_AG_SB (1 << 0) /* superblock */ @@ -111,8 +113,9 @@ struct xfs_da_args; XFS_SICK_FS_METADIR | \ XFS_SICK_FS_METAPATH) -#define XFS_SICK_RT_PRIMARY (XFS_SICK_RT_BITMAP | \ - XFS_SICK_RT_SUMMARY) +#define XFS_SICK_RG_PRIMARY (XFS_SICK_RG_SUPER | \ + XFS_SICK_RG_BITMAP | \ + XFS_SICK_RG_SUMMARY) #define XFS_SICK_AG_PRIMARY (XFS_SICK_AG_SB | \ XFS_SICK_AG_AGF | \ @@ -142,26 +145,26 @@ struct xfs_da_args; /* Secondary state related to (but not primary evidence of) health problems. */ #define XFS_SICK_FS_SECONDARY (0) -#define XFS_SICK_RT_SECONDARY (0) +#define XFS_SICK_RG_SECONDARY (0) #define XFS_SICK_AG_SECONDARY (0) #define XFS_SICK_INO_SECONDARY (XFS_SICK_INO_FORGET) /* Evidence of health problems elsewhere. */ #define XFS_SICK_FS_INDIRECT (0) -#define XFS_SICK_RT_INDIRECT (0) +#define XFS_SICK_RG_INDIRECT (0) #define XFS_SICK_AG_INDIRECT (XFS_SICK_AG_INODES) #define XFS_SICK_INO_INDIRECT (0) /* All health masks. */ -#define XFS_SICK_FS_ALL (XFS_SICK_FS_PRIMARY | \ +#define XFS_SICK_FS_ALL (XFS_SICK_FS_PRIMARY | \ XFS_SICK_FS_SECONDARY | \ XFS_SICK_FS_INDIRECT) -#define XFS_SICK_RT_ALL (XFS_SICK_RT_PRIMARY | \ - XFS_SICK_RT_SECONDARY | \ - XFS_SICK_RT_INDIRECT) +#define XFS_SICK_RG_ALL (XFS_SICK_RG_PRIMARY | \ + XFS_SICK_RG_SECONDARY | \ + XFS_SICK_RG_INDIRECT) -#define XFS_SICK_AG_ALL (XFS_SICK_AG_PRIMARY | \ +#define XFS_SICK_AG_ALL (XFS_SICK_AG_PRIMARY | \ XFS_SICK_AG_SECONDARY | \ XFS_SICK_AG_INDIRECT) @@ -195,11 +198,8 @@ void xfs_fs_mark_healthy(struct xfs_mount *mp, unsigned int mask); void xfs_fs_measure_sickness(struct xfs_mount *mp, unsigned int *sick, unsigned int *checked); -void xfs_rt_mark_sick(struct xfs_mount *mp, unsigned int mask); -void xfs_rt_mark_corrupt(struct xfs_mount *mp, unsigned int mask); -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_agno_mark_sick(struct xfs_mount *mp, xfs_agnumber_t agno, unsigned int mask); @@ -244,11 +244,17 @@ xfs_group_has_sickness( xfs_group_measure_sickness(xg, &sick, &checked); return sick & mask; } + #define xfs_ag_has_sickness(pag, mask) \ xfs_group_has_sickness(pag_group(pag), (mask)) #define xfs_ag_is_healthy(pag) \ (!xfs_ag_has_sickness((pag), UINT_MAX)) +#define xfs_rtgroup_has_sickness(rtg, mask) \ + xfs_group_has_sickness(rtg_group(rtg), (mask)) +#define xfs_rtgroup_is_healthy(rtg) \ + (!xfs_rtgroup_has_sickness((rtg), UINT_MAX)) + static inline bool xfs_inode_has_sickness(struct xfs_inode *ip, unsigned int mask) { diff --git a/fs/xfs/libxfs/xfs_rtbitmap.c b/fs/xfs/libxfs/xfs_rtbitmap.c index 416bbcd92af2ad..e201064764d489 100644 --- a/fs/xfs/libxfs/xfs_rtbitmap.c +++ b/fs/xfs/libxfs/xfs_rtbitmap.c @@ -76,28 +76,31 @@ static int xfs_rtbuf_get( struct xfs_rtalloc_args *args, xfs_fileoff_t block, /* block number in bitmap or summary */ - int issum) /* is summary not bitmap */ + enum xfs_rtg_inodes type) { + struct xfs_inode *ip = args->rtg->rtg_inodes[type]; struct xfs_mount *mp = args->mp; struct xfs_buf **cbpp; /* cached block buffer */ xfs_fileoff_t *coffp; /* cached block number */ struct xfs_buf *bp; /* block buffer, result */ - struct xfs_inode *ip; /* bitmap or summary inode */ struct xfs_bmbt_irec map; - enum xfs_blft type; + enum xfs_blft buf_type; int nmap = 1; int error; - if (issum) { + switch (type) { + case XFS_RTGI_SUMMARY: cbpp = &args->sumbp; coffp = &args->sumoff; - ip = args->rtg->rtg_inodes[XFS_RTGI_SUMMARY]; - type = XFS_BLFT_RTSUMMARY_BUF; - } else { + buf_type = XFS_BLFT_RTSUMMARY_BUF; + break; + case XFS_RTGI_BITMAP: cbpp = &args->rbmbp; coffp = &args->rbmoff; - ip = args->rtg->rtg_inodes[XFS_RTGI_BITMAP]; - type = XFS_BLFT_RTBITMAP_BUF; + buf_type = XFS_BLFT_RTBITMAP_BUF; + break; + default: + return -EINVAL; } /* @@ -120,8 +123,7 @@ xfs_rtbuf_get( return error; if (XFS_IS_CORRUPT(mp, nmap == 0 || !xfs_bmap_is_written_extent(&map))) { - xfs_rt_mark_sick(mp, issum ? XFS_SICK_RT_SUMMARY : - XFS_SICK_RT_BITMAP); + xfs_rtginode_mark_sick(args->rtg, type); return -EFSCORRUPTED; } @@ -130,12 +132,11 @@ xfs_rtbuf_get( XFS_FSB_TO_DADDR(mp, map.br_startblock), mp->m_bsize, 0, &bp, &xfs_rtbuf_ops); if (xfs_metadata_is_sick(error)) - xfs_rt_mark_sick(mp, issum ? XFS_SICK_RT_SUMMARY : - XFS_SICK_RT_BITMAP); + xfs_rtginode_mark_sick(args->rtg, type); if (error) return error; - xfs_trans_buf_set_type(args->tp, bp, type); + xfs_trans_buf_set_type(args->tp, bp, buf_type); *cbpp = bp; *coffp = block; return 0; @@ -149,11 +150,11 @@ xfs_rtbitmap_read_buf( struct xfs_mount *mp = args->mp; if (XFS_IS_CORRUPT(mp, block >= mp->m_sb.sb_rbmblocks)) { - xfs_rt_mark_sick(mp, XFS_SICK_RT_BITMAP); + xfs_rtginode_mark_sick(args->rtg, XFS_RTGI_BITMAP); return -EFSCORRUPTED; } - return xfs_rtbuf_get(args, block, 0); + return xfs_rtbuf_get(args, block, XFS_RTGI_BITMAP); } int @@ -164,10 +165,10 @@ xfs_rtsummary_read_buf( struct xfs_mount *mp = args->mp; if (XFS_IS_CORRUPT(mp, block >= mp->m_rsumblocks)) { - xfs_rt_mark_sick(args->mp, XFS_SICK_RT_SUMMARY); + xfs_rtginode_mark_sick(args->rtg, XFS_RTGI_SUMMARY); return -EFSCORRUPTED; } - return xfs_rtbuf_get(args, block, 1); + return xfs_rtbuf_get(args, block, XFS_RTGI_SUMMARY); } /* diff --git a/fs/xfs/libxfs/xfs_rtgroup.c b/fs/xfs/libxfs/xfs_rtgroup.c index 470260c911c8d1..790a0b8c137fc8 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.c +++ b/fs/xfs/libxfs/xfs_rtgroup.c @@ -271,6 +271,8 @@ struct xfs_rtginode_ops { enum xfs_metafile_type metafile_type; + unsigned int sick; /* rtgroup sickness flag */ + /* Does the fs have this feature? */ bool (*enabled)(struct xfs_mount *mp); @@ -285,11 +287,13 @@ static const struct xfs_rtginode_ops xfs_rtginode_ops[XFS_RTGI_MAX] = { [XFS_RTGI_BITMAP] = { .name = "bitmap", .metafile_type = XFS_METAFILE_RTBITMAP, + .sick = XFS_SICK_RG_BITMAP, .create = xfs_rtbitmap_create, }, [XFS_RTGI_SUMMARY] = { .name = "summary", .metafile_type = XFS_METAFILE_RTSUMMARY, + .sick = XFS_SICK_RG_SUMMARY, .create = xfs_rtsummary_create, }, }; @@ -323,6 +327,17 @@ xfs_rtginode_enabled( return ops->enabled(rtg_mount(rtg)); } +/* Mark an rtgroup inode sick */ +void +xfs_rtginode_mark_sick( + struct xfs_rtgroup *rtg, + enum xfs_rtg_inodes type) +{ + const struct xfs_rtginode_ops *ops = &xfs_rtginode_ops[type]; + + xfs_group_mark_sick(rtg_group(rtg), ops->sick); +} + /* Load and existing rtgroup inode into the rtgroup structure. */ int xfs_rtginode_load( @@ -358,8 +373,10 @@ xfs_rtginode_load( } else { const char *path; - if (!mp->m_rtdirip) + if (!mp->m_rtdirip) { + xfs_fs_mark_sick(mp, XFS_SICK_FS_METADIR); return -EFSCORRUPTED; + } path = xfs_rtginode_path(rtg_rgno(rtg), type); if (!path) @@ -369,17 +386,22 @@ xfs_rtginode_load( kfree(path); } - if (error) + if (error) { + if (xfs_metadata_is_sick(error)) + xfs_rtginode_mark_sick(rtg, type); return error; + } if (XFS_IS_CORRUPT(mp, ip->i_df.if_format != XFS_DINODE_FMT_EXTENTS && ip->i_df.if_format != XFS_DINODE_FMT_BTREE)) { xfs_irele(ip); + xfs_rtginode_mark_sick(rtg, type); return -EFSCORRUPTED; } if (XFS_IS_CORRUPT(mp, ip->i_projid != rtg_rgno(rtg))) { xfs_irele(ip); + xfs_rtginode_mark_sick(rtg, type); return -EFSCORRUPTED; } @@ -416,8 +438,10 @@ xfs_rtginode_create( if (!xfs_rtginode_enabled(rtg, type)) return 0; - if (!mp->m_rtdirip) + if (!mp->m_rtdirip) { + xfs_fs_mark_sick(mp, XFS_SICK_FS_METADIR); return -EFSCORRUPTED; + } upd.path = xfs_rtginode_path(rtg_rgno(rtg), type); if (!upd.path) @@ -464,8 +488,10 @@ int xfs_rtginode_mkdir_parent( struct xfs_mount *mp) { - if (!mp->m_metadirip) + if (!mp->m_metadirip) { + xfs_fs_mark_sick(mp, XFS_SICK_FS_METADIR); return -EFSCORRUPTED; + } return xfs_metadir_mkdir(mp->m_metadirip, "rtgroups", &mp->m_rtdirip); } @@ -477,8 +503,10 @@ xfs_rtginode_load_parent( { struct xfs_mount *mp = tp->t_mountp; - if (!mp->m_metadirip) + if (!mp->m_metadirip) { + xfs_fs_mark_sick(mp, XFS_SICK_FS_METADIR); return -EFSCORRUPTED; + } return xfs_metadir_load(tp, mp->m_metadirip, "rtgroups", XFS_METAFILE_DIR, &mp->m_rtdirip); diff --git a/fs/xfs/libxfs/xfs_rtgroup.h b/fs/xfs/libxfs/xfs_rtgroup.h index e7679fafff8ce7..fba62b26912a89 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.h +++ b/fs/xfs/libxfs/xfs_rtgroup.h @@ -240,6 +240,7 @@ int xfs_rtginode_load_parent(struct xfs_trans *tp); const char *xfs_rtginode_name(enum xfs_rtg_inodes type); enum xfs_metafile_type xfs_rtginode_metafile_type(enum xfs_rtg_inodes type); bool xfs_rtginode_enabled(struct xfs_rtgroup *rtg, enum xfs_rtg_inodes type); +void xfs_rtginode_mark_sick(struct xfs_rtgroup *rtg, enum xfs_rtg_inodes type); int xfs_rtginode_load(struct xfs_rtgroup *rtg, enum xfs_rtg_inodes type, struct xfs_trans *tp); int xfs_rtginode_create(struct xfs_rtgroup *rtg, enum xfs_rtg_inodes type, diff --git a/fs/xfs/scrub/health.c b/fs/xfs/scrub/health.c index b8b92ff3a573a1..7547fb5bcd7272 100644 --- a/fs/xfs/scrub/health.c +++ b/fs/xfs/scrub/health.c @@ -12,6 +12,7 @@ #include "xfs_btree.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" @@ -71,9 +72,9 @@ enum xchk_health_group { XHG_FS = 1, - XHG_RT, XHG_AG, XHG_INO, + XHG_RTGROUP, }; struct xchk_health_map { @@ -100,8 +101,8 @@ static const struct xchk_health_map type_to_health_flag[XFS_SCRUB_TYPE_NR] = { [XFS_SCRUB_TYPE_XATTR] = { XHG_INO, XFS_SICK_INO_XATTR }, [XFS_SCRUB_TYPE_SYMLINK] = { XHG_INO, XFS_SICK_INO_SYMLINK }, [XFS_SCRUB_TYPE_PARENT] = { XHG_INO, XFS_SICK_INO_PARENT }, - [XFS_SCRUB_TYPE_RTBITMAP] = { XHG_RT, XFS_SICK_RT_BITMAP }, - [XFS_SCRUB_TYPE_RTSUM] = { XHG_RT, XFS_SICK_RT_SUMMARY }, + [XFS_SCRUB_TYPE_RTBITMAP] = { XHG_RTGROUP, XFS_SICK_RG_BITMAP }, + [XFS_SCRUB_TYPE_RTSUM] = { XHG_RTGROUP, XFS_SICK_RG_SUMMARY }, [XFS_SCRUB_TYPE_UQUOTA] = { XHG_FS, XFS_SICK_FS_UQUOTA }, [XFS_SCRUB_TYPE_GQUOTA] = { XHG_FS, XFS_SICK_FS_GQUOTA }, [XFS_SCRUB_TYPE_PQUOTA] = { XHG_FS, XFS_SICK_FS_PQUOTA }, @@ -162,11 +163,13 @@ xchk_mark_all_healthy( struct xfs_mount *mp) { struct xfs_perag *pag = NULL; + struct xfs_rtgroup *rtg = NULL; xfs_fs_mark_healthy(mp, XFS_SICK_FS_INDIRECT); - xfs_rt_mark_healthy(mp, XFS_SICK_RT_INDIRECT); while ((pag = xfs_perag_next(mp, pag))) xfs_group_mark_healthy(pag_group(pag), XFS_SICK_AG_INDIRECT); + while ((rtg = xfs_rtgroup_next(mp, rtg))) + xfs_group_mark_healthy(rtg_group(rtg), XFS_SICK_RG_INDIRECT); } /* @@ -184,6 +187,7 @@ xchk_update_health( struct xfs_scrub *sc) { struct xfs_perag *pag; + struct xfs_rtgroup *rtg; bool bad; /* @@ -236,11 +240,13 @@ xchk_update_health( else xfs_fs_mark_healthy(sc->mp, sc->sick_mask); break; - case XHG_RT: + case XHG_RTGROUP: + rtg = xfs_rtgroup_get(sc->mp, sc->sm->sm_agno); if (bad) - xfs_rt_mark_corrupt(sc->mp, sc->sick_mask); + xfs_group_mark_corrupt(rtg_group(rtg), sc->sick_mask); else - xfs_rt_mark_healthy(sc->mp, sc->sick_mask); + xfs_group_mark_healthy(rtg_group(rtg), sc->sick_mask); + xfs_rtgroup_put(rtg); break; default: ASSERT(0); @@ -295,6 +301,7 @@ xchk_health_record( { struct xfs_mount *mp = sc->mp; struct xfs_perag *pag = NULL; + struct xfs_rtgroup *rtg = NULL; unsigned int sick; unsigned int checked; @@ -302,15 +309,17 @@ xchk_health_record( if (sick & XFS_SICK_FS_PRIMARY) xchk_set_corrupt(sc); - xfs_rt_measure_sickness(mp, &sick, &checked); - if (sick & XFS_SICK_RT_PRIMARY) - xchk_set_corrupt(sc); - while ((pag = xfs_perag_next(mp, pag))) { xfs_group_measure_sickness(pag_group(pag), &sick, &checked); if (sick & XFS_SICK_AG_PRIMARY) xchk_set_corrupt(sc); } + while ((rtg = xfs_rtgroup_next(mp, rtg))) { + xfs_group_measure_sickness(rtg_group(rtg), &sick, &checked); + if (sick & XFS_SICK_RG_PRIMARY) + xchk_set_corrupt(sc); + } + return 0; } diff --git a/fs/xfs/xfs_health.c b/fs/xfs/xfs_health.c index b0d0c6bd9fa29c..9d8ee01cd163ef 100644 --- a/fs/xfs/xfs_health.c +++ b/fs/xfs/xfs_health.c @@ -18,6 +18,22 @@ #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_quota_defs.h" +#include "xfs_rtgroup.h" + +static void +xfs_health_unmount_group( + struct xfs_group *xg, + bool *warn) +{ + unsigned int sick = 0; + unsigned int checked = 0; + + xfs_group_measure_sickness(xg, &sick, &checked); + if (sick) { + trace_xfs_group_unfixed_corruption(xg, sick); + *warn = true; + } +} /* * Warn about metadata corruption that we detected but haven't fixed, and @@ -29,6 +45,7 @@ xfs_health_unmount( struct xfs_mount *mp) { struct xfs_perag *pag = NULL; + struct xfs_rtgroup *rtg = NULL; unsigned int sick = 0; unsigned int checked = 0; bool warn = false; @@ -37,21 +54,12 @@ xfs_health_unmount( return; /* Measure AG corruption levels. */ - while ((pag = xfs_perag_next(mp, pag))) { - xfs_group_measure_sickness(pag_group(pag), &sick, &checked); - if (sick) { - trace_xfs_group_unfixed_corruption(pag_group(pag), - sick); - warn = true; - } - } + while ((pag = xfs_perag_next(mp, pag))) + xfs_health_unmount_group(pag_group(pag), &warn); - /* Measure realtime volume corruption levels. */ - xfs_rt_measure_sickness(mp, &sick, &checked); - if (sick) { - trace_xfs_rt_unfixed_corruption(mp, sick); - warn = true; - } + /* Measure realtime group corruption levels. */ + while ((rtg = xfs_rtgroup_next(mp, rtg))) + xfs_health_unmount_group(rtg_group(rtg), &warn); /* * Measure fs corruption and keep the sample around for the warning. @@ -150,65 +158,6 @@ xfs_fs_measure_sickness( spin_unlock(&mp->m_sb_lock); } -/* Mark unhealthy realtime metadata. */ -void -xfs_rt_mark_sick( - struct xfs_mount *mp, - unsigned int mask) -{ - ASSERT(!(mask & ~XFS_SICK_RT_ALL)); - trace_xfs_rt_mark_sick(mp, mask); - - spin_lock(&mp->m_sb_lock); - mp->m_rt_sick |= mask; - spin_unlock(&mp->m_sb_lock); -} - -/* Mark realtime metadata as having been checked and found unhealthy by fsck. */ -void -xfs_rt_mark_corrupt( - struct xfs_mount *mp, - unsigned int mask) -{ - ASSERT(!(mask & ~XFS_SICK_RT_ALL)); - trace_xfs_rt_mark_corrupt(mp, mask); - - spin_lock(&mp->m_sb_lock); - mp->m_rt_sick |= mask; - mp->m_rt_checked |= mask; - spin_unlock(&mp->m_sb_lock); -} - -/* Mark a realtime metadata healed. */ -void -xfs_rt_mark_healthy( - struct xfs_mount *mp, - unsigned int mask) -{ - ASSERT(!(mask & ~XFS_SICK_RT_ALL)); - trace_xfs_rt_mark_healthy(mp, mask); - - spin_lock(&mp->m_sb_lock); - mp->m_rt_sick &= ~mask; - if (!(mp->m_rt_sick & XFS_SICK_RT_PRIMARY)) - mp->m_rt_sick &= ~XFS_SICK_RT_SECONDARY; - mp->m_rt_checked |= mask; - spin_unlock(&mp->m_sb_lock); -} - -/* Sample which realtime metadata are unhealthy. */ -void -xfs_rt_measure_sickness( - struct xfs_mount *mp, - unsigned int *sick, - unsigned int *checked) -{ - spin_lock(&mp->m_sb_lock); - *sick = mp->m_rt_sick; - *checked = mp->m_rt_checked; - spin_unlock(&mp->m_sb_lock); -} - /* Mark unhealthy per-ag metadata given a raw AG number. */ void xfs_agno_mark_sick( @@ -226,13 +175,24 @@ xfs_agno_mark_sick( xfs_perag_put(pag); } +static inline void +xfs_group_check_mask( + struct xfs_group *xg, + unsigned int mask) +{ + if (xg->xg_type == XG_TYPE_AG) + ASSERT(!(mask & ~XFS_SICK_AG_ALL)); + else + ASSERT(!(mask & ~XFS_SICK_RG_ALL)); +} + /* Mark unhealthy per-ag metadata. */ void xfs_group_mark_sick( struct xfs_group *xg, unsigned int mask) { - ASSERT(!(mask & ~XFS_SICK_AG_ALL)); + xfs_group_check_mask(xg, mask); trace_xfs_group_mark_sick(xg, mask); spin_lock(&xg->xg_state_lock); @@ -248,7 +208,7 @@ xfs_group_mark_corrupt( struct xfs_group *xg, unsigned int mask) { - ASSERT(!(mask & ~XFS_SICK_AG_ALL)); + xfs_group_check_mask(xg, mask); trace_xfs_group_mark_corrupt(xg, mask); spin_lock(&xg->xg_state_lock); @@ -265,7 +225,7 @@ xfs_group_mark_healthy( struct xfs_group *xg, unsigned int mask) { - ASSERT(!(mask & ~XFS_SICK_AG_ALL)); + xfs_group_check_mask(xg, mask); trace_xfs_group_mark_healthy(xg, mask); spin_lock(&xg->xg_state_lock); @@ -289,6 +249,23 @@ xfs_group_measure_sickness( spin_unlock(&xg->xg_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_group_mark_sick(rtg_group(rtg), mask); + xfs_rtgroup_put(rtg); +} + /* Mark the unhealthy parts of an inode. */ void xfs_inode_mark_sick( @@ -388,8 +365,8 @@ static const struct ioctl_sick_map fs_map[] = { }; static const struct ioctl_sick_map rt_map[] = { - { XFS_SICK_RT_BITMAP, XFS_FSOP_GEOM_SICK_RT_BITMAP }, - { XFS_SICK_RT_SUMMARY, XFS_FSOP_GEOM_SICK_RT_SUMMARY }, + { XFS_SICK_RG_BITMAP, XFS_FSOP_GEOM_SICK_RT_BITMAP }, + { XFS_SICK_RG_SUMMARY, XFS_FSOP_GEOM_SICK_RT_SUMMARY }, }; static inline void @@ -411,6 +388,7 @@ xfs_fsop_geom_health( struct xfs_mount *mp, struct xfs_fsop_geom *geo) { + struct xfs_rtgroup *rtg = NULL; const struct ioctl_sick_map *m; unsigned int sick; unsigned int checked; @@ -422,9 +400,11 @@ xfs_fsop_geom_health( for_each_sick_map(fs_map, m) xfgeo_health_tick(geo, sick, checked, m); - xfs_rt_measure_sickness(mp, &sick, &checked); - for_each_sick_map(rt_map, m) - xfgeo_health_tick(geo, sick, checked, m); + while ((rtg = xfs_rtgroup_next(mp, rtg))) { + xfs_group_measure_sickness(rtg_group(rtg), &sick, &checked); + for_each_sick_map(rt_map, m) + xfgeo_health_tick(geo, sick, checked, m); + } } static const struct ioctl_sick_map ag_map[] = { diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 818e9992ce5692..33b1dda6e7cefd 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -4260,10 +4260,6 @@ DEFINE_FS_CORRUPT_EVENT(xfs_fs_mark_sick); DEFINE_FS_CORRUPT_EVENT(xfs_fs_mark_corrupt); DEFINE_FS_CORRUPT_EVENT(xfs_fs_mark_healthy); DEFINE_FS_CORRUPT_EVENT(xfs_fs_unfixed_corruption); -DEFINE_FS_CORRUPT_EVENT(xfs_rt_mark_sick); -DEFINE_FS_CORRUPT_EVENT(xfs_rt_mark_corrupt); -DEFINE_FS_CORRUPT_EVENT(xfs_rt_mark_healthy); -DEFINE_FS_CORRUPT_EVENT(xfs_rt_unfixed_corruption); DECLARE_EVENT_CLASS(xfs_group_corrupt_class, TP_PROTO(const struct xfs_group *xg, unsigned int flags), From patchwork Thu Oct 17 19:05:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840714 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 0C62B1E0DC3 for ; Thu, 17 Oct 2024 19:05:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191937; cv=none; b=Wtszdgq5iDoMKAyn5TG4XP5pDBI9wLed9HMZgE0PO3C4q5cNrXN1u84lEu34HeMCCkO6Xbe10o9YHIdB5FqUUjP4wGRlpJxZdVLLdgOC4XoJCk+qCj6l/oMHQuCwFon63TjD2oKUToiBky+62uA+VLAJPyHey8gneUwzwotSPNk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191937; c=relaxed/simple; bh=LPQgH21PHrorEsvCIIslxzmkF3elxkJPy0vXVGAdqGU=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Z1pSeCCE0gX4B6p3kmsyh5hVP3+F+vc1HUvPT+FAUhSBkNjlmrGb0e4gEEiqjHGW2kE4pZ3Ce4VN8CdxmXgYw6XMt2LHrxdc6/7fpP7QfYtY8eH/PTLA/eC4m4amijVkmsYb6/+a7tWEthTuSc+588OMsB7GyFufMxmEcpvCiKY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MPJS+FQI; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="MPJS+FQI" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D1290C4CEC3; Thu, 17 Oct 2024 19:05:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729191936; bh=LPQgH21PHrorEsvCIIslxzmkF3elxkJPy0vXVGAdqGU=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=MPJS+FQIZ3x8vYHsyUcK9JgrS+fqMpARAacUlg4+VPj3oBxTYKz3lnTRR9JF6cT1y KXB90V4UWbbFTQy39kxT9TjstCvwHB8dhJLWDJRw3jWBv+2zbJi/HoDbmGc2aGfFyj oP8f+/VWLinOZOkCnfoQJouF3MuB8gERjls6cnittWKOWbh9Y4HHsniQDUmr4aZHfU uFQDxIYWk8VXz9wK1dD1YgLqv6NAIw1fnUL9FFNiJEj4N4Ll2EqpSTChVKjuvowcmv tuezy/tgLtEot03B+bbBBOp7vviOdvvdhYx5C0hJke7FcSAng+Hw3Tj+VF90i6fs8I E3bwWmMtjCubA== Date: Thu, 17 Oct 2024 12:05:36 -0700 Subject: [PATCH 10/34] xfs: export the geometry of realtime groups to userspace From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919071839.3453179.12760026512763026930.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Create an ioctl so that the kernel can report the status of realtime groups to userspace. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_fs.h | 16 ++++++++++++++++ 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 | 35 +++++++++++++++++++++++++++++++++++ 6 files changed, 99 insertions(+) diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index 5c224d03270ce9..4c0682173d6144 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -971,6 +971,21 @@ struct xfs_getparents_by_handle { struct xfs_getparents gph_request; }; +/* + * 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_reserved[27]; /* o: zero */ +}; +#define XFS_RTGROUP_GEOM_SICK_SUPER (1U << 0) /* superblock */ +#define XFS_RTGROUP_GEOM_SICK_BITMAP (1U << 1) /* rtbitmap */ +#define XFS_RTGROUP_GEOM_SICK_SUMMARY (1U << 2) /* rtsummary */ + /* * ioctl commands that are used by Linux filesystems */ @@ -1009,6 +1024,7 @@ struct xfs_getparents_by_handle { #define XFS_IOC_GETPARENTS _IOWR('X', 62, struct xfs_getparents) #define XFS_IOC_GETPARENTS_BY_HANDLE _IOWR('X', 63, struct xfs_getparents_by_handle) #define XFS_IOC_SCRUBV_METADATA _IOWR('X', 64, struct xfs_scrub_vec_head) +#define XFS_IOC_RTGROUP_GEOMETRY _IOWR('X', 65, struct xfs_rtgroup_geometry) /* * ioctl commands that replace IRIX syssgi()'s diff --git a/fs/xfs/libxfs/xfs_health.h b/fs/xfs/libxfs/xfs_health.h index 3d93b57cf57143..d34986ac18c3fa 100644 --- a/fs/xfs/libxfs/xfs_health.h +++ b/fs/xfs/libxfs/xfs_health.h @@ -278,6 +278,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 790a0b8c137fc8..624d8b25eba0ec 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.c +++ b/fs/xfs/libxfs/xfs_rtgroup.c @@ -214,6 +214,20 @@ xfs_rtgroup_trans_join( } } +/* 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_rgno(rtg); + rgeo->rg_length = rtg->rtg_extents * rtg_mount(rtg)->m_sb.sb_rextsize; + xfs_rtgroup_geom_health(rtg, rgeo); + return 0; +} + #ifdef CONFIG_PROVE_LOCKING static struct lock_class_key xfs_rtginode_lock_class; diff --git a/fs/xfs/libxfs/xfs_rtgroup.h b/fs/xfs/libxfs/xfs_rtgroup.h index fba62b26912a89..026f34f984b32f 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.h +++ b/fs/xfs/libxfs/xfs_rtgroup.h @@ -234,6 +234,9 @@ void xfs_rtgroup_unlock(struct xfs_rtgroup *rtg, unsigned int rtglock_flags); void xfs_rtgroup_trans_join(struct xfs_trans *tp, struct xfs_rtgroup *rtg, unsigned int rtglock_flags); +int xfs_rtgroup_get_geometry(struct xfs_rtgroup *rtg, + struct xfs_rtgroup_geometry *rgeo); + int xfs_rtginode_mkdir_parent(struct xfs_mount *mp); int xfs_rtginode_load_parent(struct xfs_trans *tp); @@ -277,6 +280,7 @@ static inline int xfs_initialize_rtgroups(struct xfs_mount *mp, # define xfs_rtgroup_trans_join(tp, rtg, gf) ((void)0) # define xfs_update_rtsb(bp, sb_bp) ((void)0) # define xfs_log_rtsb(tp, sb_bp) (NULL) +# 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 9d8ee01cd163ef..c7c2e656199862 100644 --- a/fs/xfs/xfs_health.c +++ b/fs/xfs/xfs_health.c @@ -443,6 +443,34 @@ xfs_ag_geom_health( } } +static const struct ioctl_sick_map rtgroup_map[] = { + { XFS_SICK_RG_SUPER, XFS_RTGROUP_GEOM_SICK_SUPER }, + { XFS_SICK_RG_BITMAP, XFS_RTGROUP_GEOM_SICK_BITMAP }, + { XFS_SICK_RG_SUMMARY, XFS_RTGROUP_GEOM_SICK_SUMMARY }, +}; + +/* 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_group_measure_sickness(rtg_group(rtg), &sick, &checked); + for_each_sick_map(rtgroup_map, 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 4d5df6593af5fd..30420b09115e00 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -40,6 +40,7 @@ #include "xfs_file.h" #include "xfs_exchrange.h" #include "xfs_handle.h" +#include "xfs_rtgroup.h" #include #include @@ -403,6 +404,38 @@ 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) + return -EINVAL; + if (memchr_inv(&rgeo.rg_reserved, 0, sizeof(rgeo.rg_reserved))) + return -EINVAL; + if (!xfs_has_rtgroups(mp)) + 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. */ @@ -1225,6 +1258,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 Thu Oct 17 19:05:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840715 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 E537B219CA6 for ; Thu, 17 Oct 2024 19:05:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191948; cv=none; b=r8+rdGdZ+tZkadSdzRSmHpRNVYMEqpYOiWQ3dbwXi7OTJrVTbawt7K+YLQ93Xv548FZQP/0++hROA/YaAwhrbGn2kk+fkWjseUYRQm42yN/MKUiEEG9cERoQ1N0LWB+OmGpa49ME1OXYDCCwcUlO6/yQrdY8vqoQ0sgPtatY6EQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191948; c=relaxed/simple; bh=veTTCUYBKo7jq1CcLimn3qO0UjOeP5Ic9q6wheARyws=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=J3xusRrLiz4EdeanlO/JTL6FiDH8YHZgRKCwQP4LE/wnYLr4jRmayZ+JvU171ZAhWp5eTBLmSE/+kFc3j1I5kLvEQplpJIMFXT6S9Oxrc9Pbk5oDWDThyOqFkLY2Eyw21zkmfgIlVLWYjAB6ImjXH15kcRWLRS9v2sJ84DGL+rU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LeWHSvXn; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="LeWHSvXn" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6F424C4CEC3; Thu, 17 Oct 2024 19:05:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729191947; bh=veTTCUYBKo7jq1CcLimn3qO0UjOeP5Ic9q6wheARyws=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=LeWHSvXn6veGT7FH8lHKZE1VgxGVXOURrqF+12a6diXPY9L1R5VzYk/ZLPA6Wv8mY ZiovgO7Q+OEJOGDNKWtGGScOVjQJbwWiHMN3tfNj2sMY3xuLkqipGaBI5Jeu83zzrA zKuMuWZsNvg8+pJHUe0AlJrlNSeBaX8U9ym95TSDM1i6BAquk31IO5DlgIqY7OcvSN VIeH/rNJNIpryl8LxQLNN5CYzFZvHLsTOZ7it+bxgGmtd33m3EnMv8ySjULCLVma9+ BMd0RYTr7i84WiYLZDFFl1ptJCkv0LM58WxH/UvFw5FY88y1rIr1UBWUlAtqHhEOzu zTM2JqWm4qO9g== Date: Thu, 17 Oct 2024 12:05:47 -0700 Subject: [PATCH 11/34] xfs: add block headers to realtime bitmap and summary blocks From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919071856.3453179.15686688404316046753.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Upgrade rtbitmap and rtsummary blocks to have self describing metadata like most every other thing in XFS. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_format.h | 18 +++++ fs/xfs/libxfs/xfs_ondisk.h | 1 fs/xfs/libxfs/xfs_rtbitmap.c | 146 +++++++++++++++++++++++++++++++++++---- fs/xfs/libxfs/xfs_rtbitmap.h | 50 +++++++++++++ fs/xfs/libxfs/xfs_sb.c | 21 +++++- fs/xfs/libxfs/xfs_shared.h | 2 + fs/xfs/scrub/rtsummary_repair.c | 15 +++- fs/xfs/xfs_buf_item_recover.c | 25 ++++++- fs/xfs/xfs_discard.c | 2 - fs/xfs/xfs_mount.h | 3 + fs/xfs/xfs_rtalloc.c | 2 - 11 files changed, 257 insertions(+), 28 deletions(-) diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index 3cf044a2d5f2a9..016ee4ff537440 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -1278,6 +1278,24 @@ static inline bool xfs_dinode_is_metadir(const struct xfs_dinode *dip) #define XFS_DFL_RTEXTSIZE (64 * 1024) /* 64kB */ #define XFS_MIN_RTEXTSIZE (4 * 1024) /* 4kB */ +/* + * 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 */ + __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) + /* * Dquot and dquot block format definitions */ diff --git a/fs/xfs/libxfs/xfs_ondisk.h b/fs/xfs/libxfs/xfs_ondisk.h index 38b314113d8f24..6a2bcbc392842c 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 e201064764d489..cae0b22397d007 100644 --- a/fs/xfs/libxfs/xfs_rtbitmap.c +++ b/fs/xfs/libxfs/xfs_rtbitmap.c @@ -21,28 +21,84 @@ #include "xfs_rtbitmap.h" #include "xfs_health.h" #include "xfs_sb.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)) + 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)) + 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 = { @@ -51,6 +107,22 @@ 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, +}; + +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( @@ -130,12 +202,24 @@ 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, type)); if (xfs_metadata_is_sick(error)) xfs_rtginode_mark_sick(args->rtg, type); if (error) return error; + if (xfs_has_rtgroups(mp)) { + 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_rtginode_mark_sick(args->rtg, type); + return -EFSCORRUPTED; + } + } + xfs_trans_buf_set_type(args->tp, bp, buf_type); *cbpp = bp; *coffp = block; @@ -1146,6 +1230,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. @@ -1155,7 +1252,7 @@ xfs_rtbitmap_blockcount_len( 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)); } /* How many rt extents does each rtbitmap file track? */ @@ -1192,11 +1289,12 @@ xfs_rtsummary_blockcount( struct xfs_mount *mp, unsigned int *rsumlevels) { + xfs_rtbxlen_t rextents = xfs_rtbitmap_bitcount(mp); unsigned long long rsumwords; - *rsumlevels = xfs_compute_rextslog(xfs_rtbitmap_bitcount(mp)) + 1; - rsumwords = xfs_rtbitmap_blockcount(mp) * (*rsumlevels); - return XFS_B_TO_FSB(mp, rsumwords << XFS_WORDLOG); + *rsumlevels = xfs_compute_rextslog(rextents) + 1; + rsumwords = xfs_rtbitmap_blockcount_len(mp, rextents) * (*rsumlevels); + return howmany_64(rsumwords, mp->m_blockwsize); } static int @@ -1248,6 +1346,7 @@ xfs_rtfile_initialize_block( struct xfs_inode *ip = rtg->rtg_inodes[type]; struct xfs_trans *tp; struct xfs_buf *bp; + void *bufdata; const size_t copylen = mp->m_blockwsize << XFS_WORDLOG; enum xfs_blft buf_type; int error; @@ -1271,13 +1370,30 @@ xfs_rtfile_initialize_block( xfs_trans_cancel(tp); return error; } + bufdata = bp->b_addr; xfs_trans_buf_set_type(tp, bp, buf_type); - bp->b_ops = &xfs_rtbuf_ops; + bp->b_ops = xfs_rtblock_ops(mp, type); + + if (xfs_has_rtgroups(mp)) { + struct xfs_rtbuf_blkinfo *hdr = bp->b_addr; + + if (type == XFS_RTGI_BITMAP) + 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(XFS_FSB_TO_DADDR(mp, fsbno)); + hdr->rt_lsn = 0; + uuid_copy(&hdr->rt_uuid, &mp->m_sb.sb_meta_uuid); + + bufdata += sizeof(*hdr); + } + if (data) - memcpy(bp->b_addr, data, copylen); + memcpy(bufdata, data, copylen); else - memset(bp->b_addr, 0, copylen); + memset(bufdata, 0, copylen); xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1); return xfs_trans_commit(tp); } diff --git a/fs/xfs/libxfs/xfs_rtbitmap.h b/fs/xfs/libxfs/xfs_rtbitmap.h index b2b9e59a87a278..2286a98ecb32bb 100644 --- a/fs/xfs/libxfs/xfs_rtbitmap.h +++ b/fs/xfs/libxfs/xfs_rtbitmap.h @@ -150,6 +150,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; } @@ -159,6 +162,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); } @@ -168,6 +178,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; } @@ -177,7 +190,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; } @@ -227,6 +247,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)); } @@ -241,6 +264,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; } @@ -250,7 +276,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; } @@ -279,6 +311,19 @@ xfs_suminfo_add( return info->old; } +static inline const struct xfs_buf_ops * +xfs_rtblock_ops( + struct xfs_mount *mp, + enum xfs_rtg_inodes type) +{ + if (xfs_has_rtgroups(mp)) { + if (type == XFS_RTGI_SUMMARY) + return &xfs_rtsummary_buf_ops; + return &xfs_rtbitmap_buf_ops; + } + return &xfs_rtbuf_ops; +} + /* * Functions for walking free space rtextents in the realtime bitmap. */ @@ -324,6 +369,7 @@ int xfs_rtfree_extent(struct xfs_trans *tp, struct xfs_rtgroup *rtg, int xfs_rtfree_blocks(struct xfs_trans *tp, struct xfs_rtgroup *rtg, xfs_fsblock_t rtbno, xfs_filblks_t rtlen); +xfs_rtxnum_t xfs_rtbitmap_rtx_per_rbmblock(struct xfs_mount *mp); xfs_filblks_t xfs_rtbitmap_blockcount(struct xfs_mount *mp); xfs_filblks_t xfs_rtbitmap_blockcount_len(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 d5bf886e18ab9e..c55ccecaccbda4 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -246,11 +246,26 @@ xfs_extents_per_rbm( return sbp->sb_rextents; } +/* + * Return the payload size of a single rt bitmap block (without the metadata + * header if any). + */ +static inline unsigned int +xfs_rtbmblock_size( + struct xfs_sb *sbp) +{ + if (xfs_sb_is_v5(sbp) && + (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR)) + return sbp->sb_blocksize - sizeof(struct xfs_rtbuf_blkinfo); + return sbp->sb_blocksize; +} + static uint64_t xfs_expected_rbmblocks( struct xfs_sb *sbp) { - return howmany_64(xfs_extents_per_rbm(sbp), NBBY * sbp->sb_blocksize); + return howmany_64(xfs_extents_per_rbm(sbp), + NBBY * xfs_rtbmblock_size(sbp)); } /* Validate the realtime geometry */ @@ -1098,8 +1113,8 @@ 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; + mp->m_blockwsize = xfs_rtbmblock_size(sbp) >> XFS_WORDLOG; + mp->m_rtx_per_rbmblock = mp->m_blockwsize << XFS_NBWORDLOG; ags->blocks = mp->m_sb.sb_agblocks; ags->blklog = mp->m_sb.sb_agblklog; diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h index 552365d212ea26..9363f918675ac0 100644 --- a/fs/xfs/libxfs/xfs_shared.h +++ b/fs/xfs/libxfs/xfs_shared.h @@ -38,6 +38,8 @@ 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_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 1688380988007f..8198ea84ad70e5 100644 --- a/fs/xfs/scrub/rtsummary_repair.c +++ b/fs/xfs/scrub/rtsummary_repair.c @@ -83,12 +83,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 feb3db2e891614..3d0c6402cb3634 100644 --- a/fs/xfs/xfs_buf_item_recover.c +++ b/fs/xfs/xfs_buf_item_recover.c @@ -26,6 +26,7 @@ #include "xfs_ag.h" #include "xfs_sb.h" #include "xfs_rtgroup.h" +#include "xfs_rtbitmap.h" /* * This is the number of entries in the l_buf_cancel_table used during @@ -394,9 +395,18 @@ 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, XFS_RTGI_BITMAP); + break; case XFS_BLFT_RTSUMMARY_BUF: - /* no magic numbers for verification of RT buffers */ - bp->b_ops = &xfs_rtbuf_ops; + if (xfs_has_rtgroups(mp) && magic32 != XFS_RTSUMMARY_MAGIC) { + warnmsg = "Bad rtsummary magic!"; + break; + } + bp->b_ops = xfs_rtblock_ops(mp, XFS_RTGI_SUMMARY); break; #endif /* CONFIG_XFS_RT */ default: @@ -815,11 +825,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 || + 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; + + 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_discard.c b/fs/xfs/xfs_discard.c index 42b8b5e0e931b7..e71bd64685f900 100644 --- a/fs/xfs/xfs_discard.c +++ b/fs/xfs/xfs_discard.c @@ -572,7 +572,7 @@ xfs_trim_rtextents( * trims the extents returned. */ do { - tr.stop_rtx = low + (mp->m_sb.sb_blocksize * NBBY); + tr.stop_rtx = low + xfs_rtbitmap_rtx_per_rbmblock(mp); xfs_rtgroup_lock(rtg, XFS_RTGLOCK_BITMAP_SHARED); error = xfs_rtalloc_query_range(rtg, tp, low, high, xfs_trim_gather_rtextent, &tr); diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 06d67089b91f33..e0902c08510d80 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -150,7 +150,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 27186fcfdcde73..38062c10293d6b 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -776,7 +776,7 @@ xfs_growfs_rt_nrblocks( struct xfs_mount *mp = rtg_mount(rtg); xfs_rfsblock_t step; - step = (bmbno + 1) * NBBY * mp->m_sb.sb_blocksize * rextsize; + step = (bmbno + 1) * mp->m_rtx_per_rbmblock * rextsize; if (xfs_has_rtgroups(mp)) { xfs_rfsblock_t rgblocks = mp->m_sb.sb_rgextents * rextsize; From patchwork Thu Oct 17 19:05:57 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840716 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 304CB21D2DB for ; Thu, 17 Oct 2024 19:05:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191958; cv=none; b=lQ5q+9tilWYGk6TVtKC0jlduK44W52C+aW+QI4/ekNQTi5SxhRrGFMs9ml4m9oIDMsvOSEjfbhp7Kfa/8Qiv0YdSJ8aXbpknIEOkS/zwBpSo7oBeiTC8huiqJI/0tDnwJfuLvTVUqHFEbq3KYyPikvH2/HOxnLa05F3zTOOZdPo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191958; c=relaxed/simple; bh=1KcQYzdVtkJ9svKDfS2aqKgKHzDiW6R2lCj79SY1ZVE=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=MSxd8Fo3CMogMEpi+cTFgKlcEvwMDoCUBfYe3j+jtuDyNRWHDMVbUG2Ev7CvINFVfHQwIAuNY82Y+i+zSZMDtZKvAki0mIz/AmKOWmdsoNQEMoOS2qBoY7coUAuzUk5bcstYtXrWXfE+Ji2Ish0zTjuyelStDlta1Y8ZPfVh9Jw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KK2xiLcX; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="KK2xiLcX" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0EFEEC4CEC3; Thu, 17 Oct 2024 19:05:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729191958; bh=1KcQYzdVtkJ9svKDfS2aqKgKHzDiW6R2lCj79SY1ZVE=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=KK2xiLcXAqonEAX8t58KpBiT+LMlo1tGTOg2cGNB3yGdEZwiFzD+axrBlyKkhxiNQ w87xARxx+6ia1WgG8V7fhGHtRR4I1UHjNnfKPcDTbStESIBkWXt5ACSkcoJ7dgjrii jIRlxRDR0YgGw++0YM0LYHxbI/28cRF6qWrmi+JcrDGGowfFQaR5bYsN8xCghrPV8r 7r1HSTe81FRIj2nTfeZOQWa57uzVXyMPkr2Z0g7A5imYL8icQeg8QefC6uErk7cQ2j eCJWC3GA+3l+K67ebHRbuaxjvv+iNkNHMLD1z6nNODfh+MYCmsypIsCRuVcHzhScMH NL0f3WhlZhyoQ== Date: Thu, 17 Oct 2024 12:05:57 -0700 Subject: [PATCH 12/34] xfs: encode the rtbitmap in big endian format From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919071875.3453179.13224711857139394467.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong 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. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- 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 016ee4ff537440..cd9457ed5873fe 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -709,10 +709,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 be32 ondisk. */ union xfs_rtword_raw { __u32 old; + __be32 rtg; }; /* diff --git a/fs/xfs/libxfs/xfs_rtbitmap.h b/fs/xfs/libxfs/xfs_rtbitmap.h index 2286a98ecb32bb..f9c0d241590104 100644 --- a/fs/xfs/libxfs/xfs_rtbitmap.h +++ b/fs/xfs/libxfs/xfs_rtbitmap.h @@ -210,6 +210,8 @@ xfs_rtbitmap_getword( { union xfs_rtword_raw *word = xfs_rbmblock_wordptr(args, index); + if (xfs_has_rtgroups(args->mp)) + return be32_to_cpu(word->rtg); return word->old; } @@ -222,7 +224,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_be32(value); + else + word->old = value; } /* From patchwork Thu Oct 17 19:06:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840717 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 C54121E0DC3 for ; Thu, 17 Oct 2024 19:06:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191968; cv=none; b=oHHus5JR/a8gxSyugX79FZVAlsScXXmz31q+ucatD0JDHjx9HW2ovSxPq3eGpSk3lsuCd97QGkCSdK8v5sn3zLNXgiqzrkV0sQH/A9EJHBEcXEX9AITK/oYLa+nuIXq25q/mHmIRtlU1jMv3oIJYni7gRKUtPE9awoLEExJl8pA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191968; c=relaxed/simple; bh=SxuTi0hY62G2t5zB85jSOqku0p2WQ9wrHbGwCLzRVAg=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=fHY/2EL7RarJfCYCOm9C0P80WXvqDr9aY+HSPT1syC9Lt1AWW1S8vq0Uw8LjJN+tkg4EwbDTIbcCCdBBDvX2IA15qyss0uQ2UdmXlOQ/pzgfYYm8A6ew/Lx18Fjts4sssf2OGnYHUf5Lwn2K0ZRPf0ENIIkhI9XlGGx2YhxzdOY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Vq+DLZEb; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Vq+DLZEb" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A9136C4CEC3; Thu, 17 Oct 2024 19:06:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729191968; bh=SxuTi0hY62G2t5zB85jSOqku0p2WQ9wrHbGwCLzRVAg=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=Vq+DLZEbJvsrY1rjgtCmBqb3O5ONG2L0vJD+FJoknWeHQujKUvmUzuW1onMgaSaw6 XwLKd2UYC2btRXmTAePHdWVYiOlNshn2I41B0gixAJX2ehBwayVQ0dDHAJIq87hf4W RHapHBCiDNzqBThmLI+/fNb9au/OQau49xmPg9RDdZH8+U3qzA1uQnbZw8PPPOZEQp lVOc580bTwQBp5pGQQufTmictC2RhUcqIzkmowqhI6B+fz7jzRkD6HAiYNrll5KGlu X/5iCQFWos2A88nWMWaXT8waEKwogUvQ6nDfYyMMunAM1nu668wOMbjQqWEHP3hVEa dc6H3Do+XIWig== Date: Thu, 17 Oct 2024 12:06:08 -0700 Subject: [PATCH 13/34] xfs: encode the rtsummary in big endian format From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919071892.3453179.14627804052679866991.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong 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 Reviewed-by: Christoph Hellwig --- 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 cd9457ed5873fe..f56ff9f43c218f 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -719,10 +719,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 f9c0d241590104..7be76490a31879 100644 --- a/fs/xfs/libxfs/xfs_rtbitmap.h +++ b/fs/xfs/libxfs/xfs_rtbitmap.h @@ -300,6 +300,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; } @@ -312,6 +314,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 8f3f69b26cad04..49fc6250bafcaa 100644 --- a/fs/xfs/scrub/rtsummary.c +++ b/fs/xfs/scrub/rtsummary.c @@ -151,6 +151,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 Thu Oct 17 19:06:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840718 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 B9EB021C16D for ; Thu, 17 Oct 2024 19:06:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191979; cv=none; b=PAFTbIhPFKbIs66r5rnFN6xSYt3tJAPezgyKSapKyCCj93kwd3+udB3Ave2fTufW0aHeZm0nRZKx42tyTCTvoXm7HGC43FaxHq/qsqKngTCxvLk3aEtaCQsWhcjYODVy3ZSluwRHalCHehYI+VGywjqUuQYMZH0vg5rDzYYa49o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191979; c=relaxed/simple; bh=mbiy4mb6EAE03uCtTGtiCzrs6iCg0k3fMwNK1cArCTI=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=t7FgQbNu6A7A9HvWDFoceQTZ21/Tb8bHWtol0uMTGJ42C1vXqEpvQek7NOIyumeCiIPJJxCN81saZpbk+SqESP6xYwIrpERdBCVNb7FoSqlUFovxSjb89JyNQPItrvgzt71TjZ7UGXFEW2Vdk+IRvgeGhcPeqHzfveIIRttjes4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mfu6onll; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="mfu6onll" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3CAFDC4CEC3; Thu, 17 Oct 2024 19:06:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729191979; bh=mbiy4mb6EAE03uCtTGtiCzrs6iCg0k3fMwNK1cArCTI=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=mfu6onll8MxnP31jjGb9vqB/8s+qoz9d5fPtrrVVCiDHudzNEyI3Z0cOf5Y1V8mCj kTq/U+CCMqqaNff0Mm5A5MVttNa3MICPN+8dm4uhwzhb/ORDQzuo9ULgab6/mKUEV7 xJqbcvFlKhykTdLVIRJhCygYjiL4MyM2YU28rwyNukc4MwXfdwAMJNSDnH5thTrVoH WAeLLTP0/OhdpCrx9hyLj/5P+sHzkcJ3eNJcGSrtCLAmx+347HrYYrML/WpEwntA4U Pt2wR0aFSh5XyHZxoJKIPMPjsV10NyXC2IfclD6b6LDPEX9dW35KB/VylyMH8Q58z2 XltysxZaPAXqQ== Date: Thu, 17 Oct 2024 12:06:18 -0700 Subject: [PATCH 14/34] xfs: grow the realtime section when realtime groups are enabled From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919071909.3453179.2960703072292128771.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Enable growing the rt section when realtime groups are enabled. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_shared.h | 1 fs/xfs/xfs_rtalloc.c | 270 ++++++++++++++++++++++++++++++++++++++------ fs/xfs/xfs_trans.c | 9 + fs/xfs/xfs_trans.h | 1 4 files changed, 244 insertions(+), 37 deletions(-) diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h index 9363f918675ac0..e7efdb9ceaf382 100644 --- a/fs/xfs/libxfs/xfs_shared.h +++ b/fs/xfs/libxfs/xfs_shared.h @@ -160,6 +160,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 38062c10293d6b..2093cab0cf8cb5 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -766,6 +766,31 @@ xfs_growfs_rt_alloc_fake_mount( return nmp; } +/* Free all the new space and return the number of extents actually freed. */ +static int +xfs_growfs_rt_free_new( + struct xfs_rtgroup *rtg, + struct xfs_rtalloc_args *nargs, + xfs_rtbxlen_t *freed_rtx) +{ + struct xfs_mount *mp = rtg_mount(rtg); + xfs_rgnumber_t rgno = rtg_rgno(rtg); + xfs_rtxnum_t start_rtx = 0, end_rtx; + + if (rgno < mp->m_sb.sb_rgcount) + start_rtx = xfs_rtgroup_extents(mp, rgno); + end_rtx = xfs_rtgroup_extents(nargs->mp, rgno); + + /* + * Compute the first new extent that we want to free, being careful to + * skip past a realtime superblock at the start of the realtime volume. + */ + if (xfs_has_rtsb(nargs->mp) && rgno == 0 && start_rtx == 0) + start_rtx++; + *freed_rtx = end_rtx - start_rtx; + return xfs_rtfree_range(nargs, start_rtx, *freed_rtx); +} + static xfs_rfsblock_t xfs_growfs_rt_nrblocks( struct xfs_rtgroup *rtg, @@ -786,6 +811,43 @@ xfs_growfs_rt_nrblocks( return min(nrblocks, step); } +/* + * If the post-grow filesystem will have an rtsb; we're initializing the first + * rtgroup; and the filesystem didn't have a realtime section, write the rtsb + * now, and attach the rtsb buffer to the real mount. + */ +static int +xfs_growfs_rt_init_rtsb( + const struct xfs_rtalloc_args *nargs, + const struct xfs_rtgroup *rtg, + const struct xfs_rtalloc_args *args) +{ + struct xfs_mount *mp = args->mp; + struct xfs_buf *rtsb_bp; + int error; + + if (!xfs_has_rtsb(nargs->mp)) + return 0; + if (rtg_rgno(rtg) > 0) + return 0; + if (mp->m_sb.sb_rblocks) + return 0; + + 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_update_rtsb(rtsb_bp, mp->m_sb_bp); + mp->m_rtsb_bp = rtsb_bp; + error = xfs_bwrite(rtsb_bp); + xfs_buf_unlock(rtsb_bp); + return error; +} + static int xfs_growfs_rt_bmblock( struct xfs_rtgroup *rtg, @@ -808,7 +870,8 @@ xfs_growfs_rt_bmblock( int error; /* - * Calculate new sb and mount fields for this round. + * Calculate new sb and mount fields for this round. Also ensure the + * rtg_extents value is uptodate as the rtbitmap code relies on it. */ nmp = nargs.mp = xfs_growfs_rt_alloc_fake_mount(mp, xfs_growfs_rt_nrblocks(rtg, nrblocks, rextsize, bmbno), @@ -861,6 +924,10 @@ xfs_growfs_rt_bmblock( goto out_cancel; } + error = xfs_growfs_rt_init_rtsb(&nargs, rtg, &args); + if (error) + goto out_cancel; + /* * Update superblock fields. */ @@ -879,12 +946,14 @@ xfs_growfs_rt_bmblock( if (nmp->m_sb.sb_rextslog != mp->m_sb.sb_rextslog) xfs_trans_mod_sb(args.tp, XFS_TRANS_SB_REXTSLOG, nmp->m_sb.sb_rextslog - mp->m_sb.sb_rextslog); + if (nmp->m_sb.sb_rgcount != mp->m_sb.sb_rgcount) + xfs_trans_mod_sb(args.tp, XFS_TRANS_SB_RGCOUNT, + nmp->m_sb.sb_rgcount - mp->m_sb.sb_rgcount); /* * Free the new extent. */ - freed_rtx = nmp->m_sb.sb_rextents - mp->m_sb.sb_rextents; - error = xfs_rtfree_range(&nargs, mp->m_sb.sb_rextents, freed_rtx); + error = xfs_growfs_rt_free_new(rtg, &nargs, &freed_rtx); xfs_rtbuf_cache_relse(&nargs); if (error) goto out_cancel; @@ -925,6 +994,15 @@ xfs_growfs_rt_bmblock( return error; } +static xfs_rtxnum_t +xfs_last_rtgroup_extents( + struct xfs_mount *mp) +{ + return mp->m_sb.sb_rextents - + ((xfs_rtxnum_t)(mp->m_sb.sb_rgcount - 1) * + mp->m_sb.sb_rgextents); +} + /* * Calculate the last rbmblock currently used. * @@ -935,11 +1013,20 @@ xfs_last_rt_bmblock( struct xfs_rtgroup *rtg) { struct xfs_mount *mp = rtg_mount(rtg); - xfs_fileoff_t bmbno = mp->m_sb.sb_rbmblocks; + xfs_rgnumber_t rgno = rtg_rgno(rtg); + xfs_fileoff_t bmbno = 0; + + ASSERT(!mp->m_sb.sb_rgcount || rgno >= mp->m_sb.sb_rgcount - 1); + + if (mp->m_sb.sb_rgcount && rgno == mp->m_sb.sb_rgcount - 1) { + xfs_rtxnum_t nrext = xfs_last_rtgroup_extents(mp); + + /* Also fill up the previous block if not entirely full. */ + bmbno = xfs_rtbitmap_blockcount_len(mp, nrext); + if (xfs_rtx_to_rbmword(mp, nrext) != 0) + bmbno--; + } - /* Skip the current block if it is exactly full. */ - if (xfs_rtx_to_rbmword(mp, mp->m_sb.sb_rextents) != 0) - bmbno--; return bmbno; } @@ -956,38 +1043,56 @@ xfs_growfs_rt_alloc_blocks( struct xfs_mount *mp = rtg_mount(rtg); struct xfs_inode *rbmip = rtg->rtg_inodes[XFS_RTGI_BITMAP]; struct xfs_inode *rsumip = rtg->rtg_inodes[XFS_RTGI_SUMMARY]; - xfs_extlen_t orbmblocks; - xfs_extlen_t orsumblocks; - xfs_extlen_t nrsumblocks; + xfs_extlen_t orbmblocks = 0; + xfs_extlen_t orsumblocks = 0; struct xfs_mount *nmp; - int error; - - /* - * Get the old block counts for bitmap and summary inodes. - * These can't change since other growfs callers are locked out. - */ - orbmblocks = XFS_B_TO_FSB(mp, rbmip->i_disk_size); - orsumblocks = XFS_B_TO_FSB(mp, rsumip->i_disk_size); + int error = 0; nmp = xfs_growfs_rt_alloc_fake_mount(mp, nrblocks, rextsize); if (!nmp) return -ENOMEM; - *nrbmblocks = nmp->m_sb.sb_rbmblocks; - nrsumblocks = nmp->m_rsumblocks; - kfree(nmp); + + if (xfs_has_rtgroups(mp)) { + /* + * For file systems with the rtgroups feature, the RT bitmap and + * summary are always fully allocated, which means that we never + * need to grow the existing files. + * + * But we have to be careful to only fill the bitmap until the + * end of the actually used range. + */ + if (rtg_rgno(rtg) == nmp->m_sb.sb_rgcount - 1) + *nrbmblocks = xfs_rtbitmap_blockcount_len(nmp, + xfs_last_rtgroup_extents(nmp)); + + if (mp->m_sb.sb_rgcount && + rtg_rgno(rtg) == mp->m_sb.sb_rgcount - 1) + goto out_free; + } else { + /* + * Get the old block counts for bitmap and summary inodes. + * These can't change since other growfs callers are locked out. + */ + orbmblocks = XFS_B_TO_FSB(mp, rbmip->i_disk_size); + orsumblocks = XFS_B_TO_FSB(mp, rsumip->i_disk_size); + } error = xfs_rtfile_initialize_blocks(rtg, XFS_RTGI_BITMAP, orbmblocks, - *nrbmblocks, NULL); + nmp->m_sb.sb_rbmblocks, NULL); if (error) - return error; - return xfs_rtfile_initialize_blocks(rtg, XFS_RTGI_SUMMARY, orsumblocks, - nrsumblocks, NULL); + goto out_free; + error = xfs_rtfile_initialize_blocks(rtg, XFS_RTGI_SUMMARY, orsumblocks, + nmp->m_rsumblocks, NULL); +out_free: + kfree(nmp); + return error; } static int xfs_growfs_rtg( struct xfs_mount *mp, + xfs_rgnumber_t rgno, xfs_rfsblock_t nrblocks, xfs_agblock_t rextsize) { @@ -998,7 +1103,7 @@ xfs_growfs_rtg( unsigned int i; int error; - rtg = xfs_rtgroup_grab(mp, 0); + rtg = xfs_rtgroup_grab(mp, rgno); if (!rtg) return -EINVAL; @@ -1069,14 +1174,67 @@ xfs_growfs_check_rtgeom( return error; } +/* + * Compute the new number of rt groups and ensure that /rtgroups exists. + * + * Changing the rtgroup size is not allowed (even if the rt volume hasn't yet + * been initialized) because the userspace ABI doesn't support it. + */ +static int +xfs_growfs_rt_prep_groups( + struct xfs_mount *mp, + xfs_rfsblock_t rblocks, + xfs_extlen_t rextsize, + xfs_rgnumber_t *new_rgcount) +{ + int error; + + *new_rgcount = howmany_64(rblocks, mp->m_sb.sb_rgextents * rextsize); + if (*new_rgcount > XFS_MAX_RGNUMBER) + return -EINVAL; + + /* Make sure the /rtgroups dir has been created */ + if (!mp->m_rtdirip) { + struct xfs_trans *tp; + + error = xfs_trans_alloc_empty(mp, &tp); + if (error) + return error; + error = xfs_rtginode_load_parent(tp); + xfs_trans_cancel(tp); + + if (error == -ENOENT) + error = xfs_rtginode_mkdir_parent(mp); + if (error) + return error; + } + + return 0; +} + +static bool +xfs_grow_last_rtg( + struct xfs_mount *mp) +{ + if (!xfs_has_rtgroups(mp)) + return true; + if (mp->m_sb.sb_rgcount == 0) + return false; + return xfs_rtgroup_extents(mp, mp->m_sb.sb_rgcount - 1) <= + mp->m_sb.sb_rgextents; +} + /* * Grow the realtime area of the filesystem. */ int xfs_growfs_rt( - xfs_mount_t *mp, /* mount point for filesystem */ - xfs_growfs_rt_t *in) /* growfs rt input struct */ + struct xfs_mount *mp, + struct xfs_growfs_rt *in) { + xfs_rgnumber_t old_rgcount = mp->m_sb.sb_rgcount; + xfs_rgnumber_t new_rgcount = 1; + xfs_rgnumber_t rgno; struct xfs_buf *bp; xfs_agblock_t old_rextsize = mp->m_sb.sb_rextsize; int error; @@ -1134,19 +1292,57 @@ xfs_growfs_rt( if (error) goto out_unlock; - error = xfs_growfs_rtg(mp, in->newblocks, in->extsize); - if (error) - goto out_unlock; + if (xfs_has_rtgroups(mp)) { + error = xfs_growfs_rt_prep_groups(mp, in->newblocks, + in->extsize, &new_rgcount); + if (error) + goto out_unlock; + } - if (old_rextsize != in->extsize) { + if (xfs_grow_last_rtg(mp)) { + error = xfs_growfs_rtg(mp, old_rgcount - 1, in->newblocks, + in->extsize); + if (error) + goto out_unlock; + } + + for (rgno = old_rgcount; rgno < new_rgcount; rgno++) { + xfs_rtbxlen_t rextents = div_u64(in->newblocks, in->extsize); + + error = xfs_rtgroup_alloc(mp, rgno, new_rgcount, rextents); + if (error) + goto out_unlock; + + error = xfs_growfs_rtg(mp, rgno, in->newblocks, in->extsize); + if (error) { + struct xfs_rtgroup *rtg; + + rtg = xfs_rtgroup_grab(mp, rgno); + if (!WARN_ON_ONCE(!rtg)) { + xfs_rtunmount_rtg(rtg); + xfs_rtgroup_rele(rtg); + xfs_rtgroup_free(mp, rgno); + } + break; + } + } + + if (!error && old_rextsize != in->extsize) error = xfs_growfs_rt_fixup_extsize(mp); - if (error) - goto out_unlock; + + /* + * Update secondary superblocks now the physical grow has completed. + * + * Also do this in case of an error as we might have already + * successfully updated one or more RTGs and incremented sb_rgcount. + */ + if (!xfs_is_shutdown(mp)) { + int error2 = xfs_update_secondary_sbs(mp); + + if (!error) + error = error2; } - /* Update secondary superblocks now the physical grow has completed */ - error = xfs_update_secondary_sbs(mp); - out_unlock: mutex_unlock(&mp->m_growlock); return error; diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 01b5f5b32af467..a29a181e684041 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -460,6 +460,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,10 @@ xfs_trans_apply_sb_deltas( sbp->sb_rextslog += tp->t_rextslog_delta; whole = 1; } + if (tp->t_rgcount_delta) { + be32_add_cpu(&sbp->sb_rgcount, tp->t_rgcount_delta); + whole = 1; + } xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF); if (whole) @@ -674,6 +682,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 f97e5c416efad1..71c2e82e4dadff 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -148,6 +148,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 Thu Oct 17 19:06:29 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840719 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 4ED501E0DC3 for ; Thu, 17 Oct 2024 19:06:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191990; cv=none; b=DE40Sz4QgyfW/EFRLzPfP5VPZu6GksxUQ9WFzDIjBXVyMofuYJqS39idR6KAtpoz4DPcG84nD7+kHfaZ2QyyTQINESbGzEQxwGrSOJcxF0WHhIeSUQSxGFsle59ZC+vzMAA8FDjHSxNs/1Uap3bw1kexoS1gqf/x5WMyYCT6lSc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729191990; c=relaxed/simple; bh=c+kU3CVMVG3jIUJjoCBehADbA6q2Kkqx6yUQjbhKDQg=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=XjLKEpQRygtG44rzMvogXxX/YRfuMekxWU4TyiXXmsPkCq7yDiPrQ6kXXcdmLc8Fr3Vj/ZWy3P2ic20r5HVsQeGwzTFikXTWIvVUWVWJTu5gjggLLF2Cn3t9V56r4eHpu1zRuD7hSLFk3WgNHDNJ0HALQyLfA9W2yKYke741L0M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=U30k1Gw9; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="U30k1Gw9" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D0C2AC4CEC3; Thu, 17 Oct 2024 19:06:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729191989; bh=c+kU3CVMVG3jIUJjoCBehADbA6q2Kkqx6yUQjbhKDQg=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=U30k1Gw9XFi+HYPp8Gmtm5ypjZMlRUQ1ztk+mevP5ReBqaKbTp9+wAASi0JZHXWEr 2Mc9p4L1KrKYqQk95QWCaktTaDRTe1DjHW77p/jQ4EagCutNMij65n1Q1UMWJiYy1j CjyE+yi2/mrVMrmJTFQX6fpSUdKQNXYXkaKE0llS7AwRgxJt3Pud8eTFtVir7Ede+L q5FS65q7PJbEM2fxb6bX6llk7Uy9UN+y1WOaTlg9OyKJx7T5ULv7Vj9fVH5x6Z9YFz 0qXKKjM+lcoZ+H/0gh/oQypSrZSw1REe53vT028L69A7gmc/EauwZOpzsvMbTGd9gH s9wOa1/Z9owew== Date: Thu, 17 Oct 2024 12:06:29 -0700 Subject: [PATCH 15/34] xfs: store rtgroup information with a bmap intent From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919071927.3453179.12281599307760720574.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Make 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. Technically speaking we need it even for !rtgroups filesystems to prevent the (dummy) rtgroup 0 from going away, even though this will never happen. As a bonus, we can rework the xfs_bmap_deferred_class tracepoint to use the xfs_group object to figure out the type and group number, widen the group block number field to fit 64-bit quantities, and get rid of the now redundant opdev and rtblock fields. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/xfs_bmap_item.c | 25 ++++++++----------------- fs/xfs/xfs_trace.h | 41 ++++++++++++++++++++++------------------- 2 files changed, 30 insertions(+), 36 deletions(-) diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c index 37dab184c2dfc2..3d52e9d7ad571a 100644 --- a/fs/xfs/xfs_bmap_item.c +++ b/fs/xfs/xfs_bmap_item.c @@ -318,14 +318,16 @@ xfs_bmap_update_create_done( return &budp->bud_item; } -/* Take a passive ref to the AG containing the space we're mapping. */ +/* Take a passive ref to the group containing the space we're mapping. */ static inline void xfs_bmap_update_get_group( struct xfs_mount *mp, struct xfs_bmap_intent *bi) { + enum xfs_group_type type = XG_TYPE_AG; + if (xfs_ifork_is_realtime(bi->bi_owner, bi->bi_whichfork)) - return; + type = XG_TYPE_RTG; /* * Bump the intent count on behalf of the deferred rmap and refcount @@ -335,7 +337,7 @@ xfs_bmap_update_get_group( * remains nonzero across the transaction roll. */ bi->bi_group = xfs_group_intent_get(mp, bi->bi_bmap.br_startblock, - XG_TYPE_AG); + type); } /* Add this deferred BUI to the transaction. */ @@ -344,8 +346,6 @@ xfs_bmap_defer_add( struct xfs_trans *tp, struct xfs_bmap_intent *bi) { - trace_xfs_bmap_defer(bi); - xfs_bmap_update_get_group(tp->t_mountp, bi); /* @@ -358,20 +358,11 @@ xfs_bmap_defer_add( */ if (bi->bi_type == XFS_BMAP_MAP) bi->bi_owner->i_delayed_blks += bi->bi_bmap.br_blockcount; + + trace_xfs_bmap_defer(bi); xfs_defer_add(tp, &bi->bi_list, &xfs_bmap_update_defer_type); } -/* Release a passive AG ref after finishing mapping work. */ -static inline void -xfs_bmap_update_put_group( - struct xfs_bmap_intent *bi) -{ - if (xfs_ifork_is_realtime(bi->bi_owner, bi->bi_whichfork)) - return; - - xfs_group_intent_put(bi->bi_group); -} - /* Cancel a deferred bmap update. */ STATIC void xfs_bmap_update_cancel_item( @@ -382,7 +373,7 @@ xfs_bmap_update_cancel_item( if (bi->bi_type == XFS_BMAP_MAP) bi->bi_owner->i_delayed_blks -= bi->bi_bmap.br_blockcount; - xfs_bmap_update_put_group(bi); + xfs_group_intent_put(bi->bi_group); kmem_cache_free(xfs_bmap_intent_cache, bi); } diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 33b1dda6e7cefd..419a92665f7764 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -3086,11 +3086,10 @@ DECLARE_EVENT_CLASS(xfs_bmap_deferred_class, TP_ARGS(bi), TP_STRUCT__entry( __field(dev_t, dev) - __field(dev_t, opdev) + __field(enum xfs_group_type, type) __field(xfs_agnumber_t, agno) __field(xfs_ino_t, ino) - __field(xfs_agblock_t, agbno) - __field(xfs_fsblock_t, rtbno) + __field(unsigned long long, gbno) __field(int, whichfork) __field(xfs_fileoff_t, l_loff) __field(xfs_filblks_t, l_len) @@ -3099,20 +3098,25 @@ DECLARE_EVENT_CLASS(xfs_bmap_deferred_class, ), TP_fast_assign( struct xfs_inode *ip = bi->bi_owner; + struct xfs_mount *mp = ip->i_mount; - __entry->dev = ip->i_mount->m_super->s_dev; - if (xfs_ifork_is_realtime(ip, bi->bi_whichfork)) { - __entry->agno = 0; - __entry->agbno = 0; - __entry->rtbno = bi->bi_bmap.br_startblock; - __entry->opdev = ip->i_mount->m_rtdev_targp->bt_dev; + __entry->dev = mp->m_super->s_dev; + __entry->type = bi->bi_group->xg_type; + __entry->agno = bi->bi_group->xg_gno; + if (bi->bi_group->xg_type == XG_TYPE_RTG && + !xfs_has_rtgroups(mp)) { + /* + * Legacy rt filesystems do not have allocation groups + * ondisk. We emulate this incore with one gigantic + * rtgroup whose size can exceed a 32-bit block number. + * For this tracepoint, we report group 0 and a 64-bit + * group block number. + */ + __entry->gbno = bi->bi_bmap.br_startblock; } else { - __entry->agno = XFS_FSB_TO_AGNO(ip->i_mount, - bi->bi_bmap.br_startblock); - __entry->agbno = XFS_FSB_TO_AGBNO(ip->i_mount, - bi->bi_bmap.br_startblock); - __entry->rtbno = 0; - __entry->opdev = __entry->dev; + __entry->gbno = xfs_fsb_to_gbno(mp, + bi->bi_bmap.br_startblock, + bi->bi_group->xg_type); } __entry->ino = ip->i_ino; __entry->whichfork = bi->bi_whichfork; @@ -3121,14 +3125,13 @@ DECLARE_EVENT_CLASS(xfs_bmap_deferred_class, __entry->l_state = bi->bi_bmap.br_state; __entry->op = bi->bi_type; ), - TP_printk("dev %d:%d op %s opdev %d:%d ino 0x%llx agno 0x%x agbno 0x%x rtbno 0x%llx %s fileoff 0x%llx fsbcount 0x%llx state %d", + TP_printk("dev %d:%d op %s ino 0x%llx %sno 0x%x gbno 0x%llx %s fileoff 0x%llx fsbcount 0x%llx state %d", MAJOR(__entry->dev), MINOR(__entry->dev), __print_symbolic(__entry->op, XFS_BMAP_INTENT_STRINGS), - MAJOR(__entry->opdev), MINOR(__entry->opdev), __entry->ino, + __print_symbolic(__entry->type, XG_TYPE_STRINGS), __entry->agno, - __entry->agbno, - __entry->rtbno, + __entry->gbno, __print_symbolic(__entry->whichfork, XFS_WHICHFORK_STRINGS), __entry->l_loff, __entry->l_len, From patchwork Thu Oct 17 19:06:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840720 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 9792C1E0DC3 for ; Thu, 17 Oct 2024 19:06:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192000; cv=none; b=oePNKXFWbMBd9sBt4YFBER8sGEV7PhYKjRTauy9nOIYFX+w6gPvM/ybXgqia+Yn7zUUDY8vgHd+iUKMdoTwrNF+M5c7wzLz3JelJjr/5ebVWwFlq9/Bfd8K8h0UlBQMW74WnIMKH7Ag5Sc5sIOijyqWLaSWZ1039c5qCD4EnKNM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192000; c=relaxed/simple; bh=oOiTGul6Y6dOHkU4GThTSMMYzYDjg7eqnFtTJkIedxw=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=YgI2g74KRxj6qovbUXvhHN8VO2UsR0APA4NCkkFDfGlkpRJzYR+nNz1C1k2u4Al1t9TL1OC2WsHB1gXLp55ZHNPiZruOVXfsGVutpsfgoeWp6ab1dJOte4tYACmACt/H5t1OYOLQrJ+LucfMOzGaLsoqN9DdNkwARDQrj4JYYuQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=huQ3OMY8; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="huQ3OMY8" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 709C5C4CEC3; Thu, 17 Oct 2024 19:06:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729192000; bh=oOiTGul6Y6dOHkU4GThTSMMYzYDjg7eqnFtTJkIedxw=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=huQ3OMY8ssfmIZtKzgq4PVWcyKOUZWMcmzyX71kupb7ptyv62hoiJWvawppVn3tz0 W62RjXSmL7nXQRpZSTHw15zCXZg2ZoFlIDOejDTjWs76Q58Rse9keiyyKnBleTnkLY P7svpAXnH8YEsAPkEfSeDZ3W3Eknf9fHTukp9fM2k0ga2gTc1aBZyKSmek7yztRKw0 sChMfcHnYPzSOlUi8Yoj+inDIUwK4nHVdTj9Co/swDLdM2XvW4INGsDFo8Ob4pbVbg gDgJ225TryiJp5ZZUQxbn5uxNWSmqmJCPQyKRfk9MyJao5wdoNPTd5ZjRU56rPasTm Q4aluWSUPp/xQ== Date: Thu, 17 Oct 2024 12:06:40 -0700 Subject: [PATCH 16/34] xfs: force swapext to a realtime file to use the file content exchange ioctl From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919071944.3453179.16121771276824167770.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong xfs_swap_extent_rmap does not use log items to track the overall progress of an attempt to swap the extent mappings between two files. If the system crashes in the middle of swapping a partially written realtime extent, the mapping will be left in an inconsistent state wherein a file can point to multiple extents on the rt volume. The new file range exchange functionality handles this correctly, so all callers must upgrade to that. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/xfs_bmap_util.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 9d654664a00dbd..aa745cc5922246 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -1528,6 +1528,18 @@ xfs_swap_extents( goto out_unlock; } + /* + * The rmapbt implementation is unable to resume a swapext operation + * after a crash if the allocation unit size is larger than a block. + * This (deprecated) interface will not be upgraded to handle this + * situation. Defragmentation must be performed with the commit range + * ioctl. + */ + if (XFS_IS_REALTIME_INODE(ip) && xfs_has_rtgroups(ip->i_mount)) { + error = -EOPNOTSUPP; + goto out_unlock; + } + error = xfs_qm_dqattach(ip); if (error) goto out_unlock; From patchwork Thu Oct 17 19:06:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840721 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 6454A1E0DC3 for ; Thu, 17 Oct 2024 19:06:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192011; cv=none; b=DAO7zvv5qmOUo+rCJNaCBq6ZuYIPzIVld3m3GC1JIVmgyfQRyqg+y8erC9PaYevR+M80dfLL9QhRXKboE9N2rqcGWM5oIeY8vxVcjaESuHdiSXp84/xz7h+FNeONd1OZztsXqPXxggt281AeqfHu6/rKlu5u9LZ5JXlAMSV/330= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192011; c=relaxed/simple; bh=g4Am4Qczj3lY0eVCbz1fuoOKTEnHvgvOy2J3ISJm7i4=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=INQUxVL+DTTtSKKHbpUDvpMQD1ej4PaSbzcl2BnXdiutEP0PFUgMqCHwkzs6MlYnhssk/hnahEh1khwMTdpB3PAD56cjyl6X3e4My8WDbCaA9PIBCrZzlYyWFnYH3anH2cp49VsbTAJP7/52npSvcePJwo6N13K7b5IvsW3eUhk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ExwMB7wP; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ExwMB7wP" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 06D39C4CEC3; Thu, 17 Oct 2024 19:06:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729192011; bh=g4Am4Qczj3lY0eVCbz1fuoOKTEnHvgvOy2J3ISJm7i4=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=ExwMB7wPH3GupBPacqoeuGJFHLlxBCB6+KmE0q1eSEgIvUWivAZ2sINoz+thgzYYV IBg1ypMQtTqlxLGA9CzLz/zGn1cBQIgWn26dI16t7UW7/Xx56He9Ustv3DPzzYapkH y8jYXJWXekXhgJ8Mey3R07PXdPeVX/sSz3vOP5uyBsM1wfQzVALrgOecQ4fmdILRC+ 6v+WcaZePCDvbsggY1V9itcRW19/RBY5HLJA1ttRqTcRpxzTI7lhOJmF+m5/G4h0OZ gXm3iu0922hugrDed2OtuUchWlU9MwNSvG/06ZMOK67P8Dx7fpfKQh0wPlH1L4vq+c z8EYrUvb3ouww== Date: Thu, 17 Oct 2024 12:06:50 -0700 Subject: [PATCH 17/34] xfs: support logging EFIs for realtime extents From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919071961.3453179.10676166441666901949.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Teach the EFI mechanism how to free realtime extents. We're going to need this to enforce proper ordering of operations when we enable realtime rmap. Declare a new log intent item type (XFS_LI_EFI_RT) and a separate defer ops for rt extents. This keeps the ondisk artifacts and processing code completely separate between the rt and non-rt cases. Hopefully this will make it easier to debug filesystem problems. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_alloc.c | 15 ++ fs/xfs/libxfs/xfs_alloc.h | 12 ++ fs/xfs/libxfs/xfs_defer.c | 6 + fs/xfs/libxfs/xfs_defer.h | 1 fs/xfs/libxfs/xfs_log_format.h | 6 + fs/xfs/libxfs/xfs_log_recover.h | 2 fs/xfs/xfs_extfree_item.c | 270 +++++++++++++++++++++++++++++++++++---- fs/xfs/xfs_log_recover.c | 2 fs/xfs/xfs_trace.h | 11 +- 9 files changed, 286 insertions(+), 39 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 67892665a20452..efe8d37d2919f8 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -2648,8 +2648,17 @@ xfs_defer_extent_free( ASSERT(!isnullstartblock(bno)); ASSERT(!(free_flags & ~XFS_FREE_EXTENT_ALL_FLAGS)); - if (XFS_IS_CORRUPT(mp, !xfs_verify_fsbext(mp, bno, len))) - return -EFSCORRUPTED; + if (free_flags & XFS_FREE_EXTENT_REALTIME) { + if (type != XFS_AG_RESV_NONE) { + ASSERT(type == XFS_AG_RESV_NONE); + return -EFSCORRUPTED; + } + if (XFS_IS_CORRUPT(mp, !xfs_verify_rtbext(mp, bno, len))) + return -EFSCORRUPTED; + } else { + if (XFS_IS_CORRUPT(mp, !xfs_verify_fsbext(mp, bno, len))) + return -EFSCORRUPTED; + } xefi = kmem_cache_zalloc(xfs_extfree_item_cache, GFP_KERNEL | __GFP_NOFAIL); @@ -2658,6 +2667,8 @@ xfs_defer_extent_free( xefi->xefi_agresv = type; if (free_flags & XFS_FREE_EXTENT_SKIP_DISCARD) xefi->xefi_flags |= XFS_EFI_SKIP_DISCARD; + if (free_flags & XFS_FREE_EXTENT_REALTIME) + xefi->xefi_flags |= XFS_EFI_REALTIME; if (oinfo) { ASSERT(oinfo->oi_offset == 0); diff --git a/fs/xfs/libxfs/xfs_alloc.h b/fs/xfs/libxfs/xfs_alloc.h index efbde04fbbb15f..50ef79a1ed41a1 100644 --- a/fs/xfs/libxfs/xfs_alloc.h +++ b/fs/xfs/libxfs/xfs_alloc.h @@ -237,7 +237,11 @@ int xfs_free_extent_later(struct xfs_trans *tp, xfs_fsblock_t bno, /* Don't issue a discard for the blocks freed. */ #define XFS_FREE_EXTENT_SKIP_DISCARD (1U << 0) -#define XFS_FREE_EXTENT_ALL_FLAGS (XFS_FREE_EXTENT_SKIP_DISCARD) +/* Free blocks on the realtime device. */ +#define XFS_FREE_EXTENT_REALTIME (1U << 1) + +#define XFS_FREE_EXTENT_ALL_FLAGS (XFS_FREE_EXTENT_SKIP_DISCARD | \ + XFS_FREE_EXTENT_REALTIME) /* * List of extents to be free "later". @@ -257,6 +261,12 @@ struct xfs_extent_free_item { #define XFS_EFI_ATTR_FORK (1U << 1) /* freeing attr fork block */ #define XFS_EFI_BMBT_BLOCK (1U << 2) /* freeing bmap btree block */ #define XFS_EFI_CANCELLED (1U << 3) /* dont actually free the space */ +#define XFS_EFI_REALTIME (1U << 4) /* freeing realtime extent */ + +static inline bool xfs_efi_is_realtime(const struct xfs_extent_free_item *xefi) +{ + return xefi->xefi_flags & XFS_EFI_REALTIME; +} struct xfs_alloc_autoreap { struct xfs_defer_pending *dfp; diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index 2cd212ad2c1d98..5b377cbbb1f7e0 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -846,6 +846,12 @@ xfs_defer_add( ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); + if (!ops->finish_item) { + ASSERT(ops->finish_item != NULL); + xfs_force_shutdown(tp->t_mountp, SHUTDOWN_CORRUPT_INCORE); + return NULL; + } + dfp = xfs_defer_find_last(tp, ops); if (!dfp || !xfs_defer_can_append(dfp, ops)) dfp = xfs_defer_alloc(&tp->t_dfops, ops); diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index 8b338031e487c4..ec51b8465e61cb 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -71,6 +71,7 @@ extern const struct xfs_defer_op_type xfs_refcount_update_defer_type; extern const struct xfs_defer_op_type xfs_rmap_update_defer_type; extern const struct xfs_defer_op_type xfs_extent_free_defer_type; extern const struct xfs_defer_op_type xfs_agfl_free_defer_type; +extern const struct xfs_defer_op_type xfs_rtextent_free_defer_type; extern const struct xfs_defer_op_type xfs_attr_defer_type; extern const struct xfs_defer_op_type xfs_exchmaps_defer_type; diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h index ace7384a275bfb..15dec19b6c32ad 100644 --- a/fs/xfs/libxfs/xfs_log_format.h +++ b/fs/xfs/libxfs/xfs_log_format.h @@ -248,6 +248,8 @@ typedef struct xfs_trans_header { #define XFS_LI_ATTRD 0x1247 /* attr set/remove done */ #define XFS_LI_XMI 0x1248 /* mapping exchange intent */ #define XFS_LI_XMD 0x1249 /* mapping exchange done */ +#define XFS_LI_EFI_RT 0x124a /* realtime extent free intent */ +#define XFS_LI_EFD_RT 0x124b /* realtime extent free done */ #define XFS_LI_TYPE_DESC \ { XFS_LI_EFI, "XFS_LI_EFI" }, \ @@ -267,7 +269,9 @@ typedef struct xfs_trans_header { { XFS_LI_ATTRI, "XFS_LI_ATTRI" }, \ { XFS_LI_ATTRD, "XFS_LI_ATTRD" }, \ { XFS_LI_XMI, "XFS_LI_XMI" }, \ - { XFS_LI_XMD, "XFS_LI_XMD" } + { XFS_LI_XMD, "XFS_LI_XMD" }, \ + { XFS_LI_EFI_RT, "XFS_LI_EFI_RT" }, \ + { XFS_LI_EFD_RT, "XFS_LI_EFD_RT" } /* * Inode Log Item Format definitions. diff --git a/fs/xfs/libxfs/xfs_log_recover.h b/fs/xfs/libxfs/xfs_log_recover.h index 521d327e4c89ed..5397a8ff004df8 100644 --- a/fs/xfs/libxfs/xfs_log_recover.h +++ b/fs/xfs/libxfs/xfs_log_recover.h @@ -77,6 +77,8 @@ extern const struct xlog_recover_item_ops xlog_attri_item_ops; extern const struct xlog_recover_item_ops xlog_attrd_item_ops; extern const struct xlog_recover_item_ops xlog_xmi_item_ops; extern const struct xlog_recover_item_ops xlog_xmd_item_ops; +extern const struct xlog_recover_item_ops xlog_rtefi_item_ops; +extern const struct xlog_recover_item_ops xlog_rtefd_item_ops; /* * Macros, structures, prototypes for internal log manager use. diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c index e469510986e8d0..a25c713ff888c7 100644 --- a/fs/xfs/xfs_extfree_item.c +++ b/fs/xfs/xfs_extfree_item.c @@ -25,6 +25,10 @@ #include "xfs_error.h" #include "xfs_log_priv.h" #include "xfs_log_recover.h" +#include "xfs_rtalloc.h" +#include "xfs_inode.h" +#include "xfs_rtbitmap.h" +#include "xfs_rtgroup.h" struct kmem_cache *xfs_efi_cache; struct kmem_cache *xfs_efd_cache; @@ -95,16 +99,15 @@ xfs_efi_item_format( ASSERT(atomic_read(&efip->efi_next_extent) == efip->efi_format.efi_nextents); + ASSERT(lip->li_type == XFS_LI_EFI || lip->li_type == XFS_LI_EFI_RT); - efip->efi_format.efi_type = XFS_LI_EFI; + efip->efi_format.efi_type = lip->li_type; efip->efi_format.efi_size = 1; - xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_EFI_FORMAT, - &efip->efi_format, + xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_EFI_FORMAT, &efip->efi_format, xfs_efi_log_format_sizeof(efip->efi_format.efi_nextents)); } - /* * The unpin operation is the last place an EFI is manipulated in the log. It is * either inserted in the AIL or aborted in the event of a log I/O error. In @@ -140,12 +143,14 @@ xfs_efi_item_release( STATIC struct xfs_efi_log_item * xfs_efi_init( struct xfs_mount *mp, + unsigned short item_type, uint nextents) - { struct xfs_efi_log_item *efip; + ASSERT(item_type == XFS_LI_EFI || item_type == XFS_LI_EFI_RT); ASSERT(nextents > 0); + if (nextents > XFS_EFI_MAX_FAST_EXTENTS) { efip = kzalloc(xfs_efi_log_item_sizeof(nextents), GFP_KERNEL | __GFP_NOFAIL); @@ -154,7 +159,7 @@ xfs_efi_init( GFP_KERNEL | __GFP_NOFAIL); } - xfs_log_item_init(mp, &efip->efi_item, XFS_LI_EFI, &xfs_efi_item_ops); + xfs_log_item_init(mp, &efip->efi_item, item_type, &xfs_efi_item_ops); efip->efi_format.efi_nextents = nextents; efip->efi_format.efi_id = (uintptr_t)(void *)efip; atomic_set(&efip->efi_next_extent, 0); @@ -264,12 +269,12 @@ xfs_efd_item_format( struct xfs_log_iovec *vecp = NULL; ASSERT(efdp->efd_next_extent == efdp->efd_format.efd_nextents); + ASSERT(lip->li_type == XFS_LI_EFD || lip->li_type == XFS_LI_EFD_RT); - efdp->efd_format.efd_type = XFS_LI_EFD; + efdp->efd_format.efd_type = lip->li_type; efdp->efd_format.efd_size = 1; - xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_EFD_FORMAT, - &efdp->efd_format, + xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_EFD_FORMAT, &efdp->efd_format, xfs_efd_log_format_sizeof(efdp->efd_format.efd_nextents)); } @@ -308,6 +313,14 @@ static inline struct xfs_extent_free_item *xefi_entry(const struct list_head *e) return list_entry(e, struct xfs_extent_free_item, xefi_list); } +static inline bool +xfs_efi_item_isrt(const struct xfs_log_item *lip) +{ + ASSERT(lip->li_type == XFS_LI_EFI || lip->li_type == XFS_LI_EFI_RT); + + return lip->li_type == XFS_LI_EFI_RT; +} + /* * Fill the EFD with all extents from the EFI when we need to roll the * transaction and continue with a new EFI. @@ -388,18 +401,20 @@ xfs_extent_free_log_item( } static struct xfs_log_item * -xfs_extent_free_create_intent( +__xfs_extent_free_create_intent( struct xfs_trans *tp, struct list_head *items, unsigned int count, - bool sort) + bool sort, + unsigned short item_type) { struct xfs_mount *mp = tp->t_mountp; - struct xfs_efi_log_item *efip = xfs_efi_init(mp, count); + struct xfs_efi_log_item *efip; struct xfs_extent_free_item *xefi; ASSERT(count > 0); + efip = xfs_efi_init(mp, item_type, count); if (sort) list_sort(mp, items, xfs_extent_free_diff_items); list_for_each_entry(xefi, items, xefi_list) @@ -407,6 +422,23 @@ xfs_extent_free_create_intent( return &efip->efi_item; } +static struct xfs_log_item * +xfs_extent_free_create_intent( + struct xfs_trans *tp, + struct list_head *items, + unsigned int count, + bool sort) +{ + return __xfs_extent_free_create_intent(tp, items, count, sort, + XFS_LI_EFI); +} + +static inline unsigned short +xfs_efd_type_from_efi(const struct xfs_efi_log_item *efip) +{ + return xfs_efi_item_isrt(&efip->efi_item) ? XFS_LI_EFD_RT : XFS_LI_EFD; +} + /* Get an EFD so we can process all the free extents. */ static struct xfs_log_item * xfs_extent_free_create_done( @@ -427,8 +459,8 @@ xfs_extent_free_create_done( GFP_KERNEL | __GFP_NOFAIL); } - xfs_log_item_init(tp->t_mountp, &efdp->efd_item, XFS_LI_EFD, - &xfs_efd_item_ops); + xfs_log_item_init(tp->t_mountp, &efdp->efd_item, + xfs_efd_type_from_efi(efip), &xfs_efd_item_ops); efdp->efd_efip = efip; efdp->efd_format.efd_nextents = count; efdp->efd_format.efd_efi_id = efip->efi_format.efi_id; @@ -436,6 +468,17 @@ xfs_extent_free_create_done( return &efdp->efd_item; } +static inline const struct xfs_defer_op_type * +xefi_ops( + struct xfs_extent_free_item *xefi) +{ + if (xfs_efi_is_realtime(xefi)) + return &xfs_rtextent_free_defer_type; + if (xefi->xefi_agresv == XFS_AG_RESV_AGFL) + return &xfs_agfl_free_defer_type; + return &xfs_extent_free_defer_type; +} + /* Add this deferred EFI to the transaction. */ void xfs_extent_free_defer_add( @@ -445,16 +488,11 @@ xfs_extent_free_defer_add( { struct xfs_mount *mp = tp->t_mountp; - trace_xfs_extent_free_defer(mp, xefi); - xefi->xefi_group = xfs_group_intent_get(mp, xefi->xefi_startblock, - XG_TYPE_AG); - if (xefi->xefi_agresv == XFS_AG_RESV_AGFL) - *dfpp = xfs_defer_add(tp, &xefi->xefi_list, - &xfs_agfl_free_defer_type); - else - *dfpp = xfs_defer_add(tp, &xefi->xefi_list, - &xfs_extent_free_defer_type); + xfs_efi_is_realtime(xefi) ? XG_TYPE_RTG : XG_TYPE_AG); + + trace_xfs_extent_free_defer(mp, xefi); + *dfpp = xfs_defer_add(tp, &xefi->xefi_list, xefi_ops(xefi)); } /* Cancel a free extent. */ @@ -560,8 +598,12 @@ xfs_agfl_free_finish_item( static inline bool xfs_efi_validate_ext( struct xfs_mount *mp, + bool isrt, struct xfs_extent *extp) { + if (isrt) + return xfs_verify_rtbext(mp, extp->ext_start, extp->ext_len); + return xfs_verify_fsbext(mp, extp->ext_start, extp->ext_len); } @@ -569,6 +611,7 @@ static inline void xfs_efi_recover_work( struct xfs_mount *mp, struct xfs_defer_pending *dfp, + bool isrt, struct xfs_extent *extp) { struct xfs_extent_free_item *xefi; @@ -580,7 +623,9 @@ xfs_efi_recover_work( xefi->xefi_agresv = XFS_AG_RESV_NONE; xefi->xefi_owner = XFS_RMAP_OWN_UNKNOWN; xefi->xefi_group = xfs_group_intent_get(mp, extp->ext_start, - XG_TYPE_AG); + isrt ? XG_TYPE_RTG : XG_TYPE_AG); + if (isrt) + xefi->xefi_flags |= XFS_EFI_REALTIME; xfs_defer_add_item(dfp, &xefi->xefi_list); } @@ -601,14 +646,15 @@ xfs_extent_free_recover_work( struct xfs_trans *tp; int i; int error = 0; + bool isrt = xfs_efi_item_isrt(lip); /* - * First check the validity of the extents described by the - * EFI. If any are bad, then assume that all are bad and - * just toss the EFI. + * First check the validity of the extents described by the EFI. If + * any are bad, then assume that all are bad and just toss the EFI. + * Mixing RT and non-RT extents in the same EFI item is not allowed. */ for (i = 0; i < efip->efi_format.efi_nextents; i++) { - if (!xfs_efi_validate_ext(mp, + if (!xfs_efi_validate_ext(mp, isrt, &efip->efi_format.efi_extents[i])) { XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, &efip->efi_format, @@ -616,7 +662,8 @@ xfs_extent_free_recover_work( return -EFSCORRUPTED; } - xfs_efi_recover_work(mp, dfp, &efip->efi_format.efi_extents[i]); + xfs_efi_recover_work(mp, dfp, isrt, + &efip->efi_format.efi_extents[i]); } resv = xlog_recover_resv(&M_RES(mp)->tr_itruncate); @@ -654,10 +701,12 @@ xfs_extent_free_relog_intent( count = EFI_ITEM(intent)->efi_format.efi_nextents; extp = EFI_ITEM(intent)->efi_format.efi_extents; + ASSERT(intent->li_type == XFS_LI_EFI || intent->li_type == XFS_LI_EFI_RT); + efdp->efd_next_extent = count; memcpy(efdp->efd_format.efd_extents, extp, count * sizeof(*extp)); - efip = xfs_efi_init(tp->t_mountp, count); + efip = xfs_efi_init(tp->t_mountp, intent->li_type, count); memcpy(efip->efi_format.efi_extents, extp, count * sizeof(*extp)); atomic_set(&efip->efi_next_extent, count); @@ -689,6 +738,72 @@ const struct xfs_defer_op_type xfs_agfl_free_defer_type = { .relog_intent = xfs_extent_free_relog_intent, }; +#ifdef CONFIG_XFS_RT +/* Create a realtime extent freeing */ +static struct xfs_log_item * +xfs_rtextent_free_create_intent( + struct xfs_trans *tp, + struct list_head *items, + unsigned int count, + bool sort) +{ + return __xfs_extent_free_create_intent(tp, items, count, sort, + XFS_LI_EFI_RT); +} + +/* Process a free realtime extent. */ +STATIC int +xfs_rtextent_free_finish_item( + struct xfs_trans *tp, + struct xfs_log_item *done, + struct list_head *item, + struct xfs_btree_cur **state) +{ + struct xfs_mount *mp = tp->t_mountp; + struct xfs_extent_free_item *xefi = xefi_entry(item); + struct xfs_efd_log_item *efdp = EFD_ITEM(done); + struct xfs_rtgroup **rtgp = (struct xfs_rtgroup **)state; + int error = 0; + + trace_xfs_extent_free_deferred(mp, xefi); + + if (!(xefi->xefi_flags & XFS_EFI_CANCELLED)) { + if (*rtgp != to_rtg(xefi->xefi_group)) { + *rtgp = to_rtg(xefi->xefi_group); + xfs_rtgroup_lock(*rtgp, XFS_RTGLOCK_BITMAP); + xfs_rtgroup_trans_join(tp, *rtgp, + XFS_RTGLOCK_BITMAP); + } + error = xfs_rtfree_blocks(tp, *rtgp, + xefi->xefi_startblock, xefi->xefi_blockcount); + } + if (error == -EAGAIN) { + xfs_efd_from_efi(efdp); + return error; + } + + xfs_efd_add_extent(efdp, xefi); + xfs_extent_free_cancel_item(item); + return error; +} + +const struct xfs_defer_op_type xfs_rtextent_free_defer_type = { + .name = "rtextent_free", + .max_items = XFS_EFI_MAX_FAST_EXTENTS, + .create_intent = xfs_rtextent_free_create_intent, + .abort_intent = xfs_extent_free_abort_intent, + .create_done = xfs_extent_free_create_done, + .finish_item = xfs_rtextent_free_finish_item, + .cancel_item = xfs_extent_free_cancel_item, + .recover_work = xfs_extent_free_recover_work, + .relog_intent = xfs_extent_free_relog_intent, +}; +#else +const struct xfs_defer_op_type xfs_rtextent_free_defer_type = { + .name = "rtextent_free", +}; +#endif /* CONFIG_XFS_RT */ + STATIC bool xfs_efi_item_match( struct xfs_log_item *lip, @@ -733,7 +848,7 @@ xlog_recover_efi_commit_pass2( return -EFSCORRUPTED; } - efip = xfs_efi_init(mp, efi_formatp->efi_nextents); + efip = xfs_efi_init(mp, ITEM_TYPE(item), efi_formatp->efi_nextents); error = xfs_efi_copy_format(&item->ri_buf[0], &efip->efi_format); if (error) { xfs_efi_item_free(efip); @@ -751,6 +866,58 @@ const struct xlog_recover_item_ops xlog_efi_item_ops = { .commit_pass2 = xlog_recover_efi_commit_pass2, }; +#ifdef CONFIG_XFS_RT +STATIC int +xlog_recover_rtefi_commit_pass2( + struct xlog *log, + struct list_head *buffer_list, + struct xlog_recover_item *item, + xfs_lsn_t lsn) +{ + struct xfs_mount *mp = log->l_mp; + struct xfs_efi_log_item *efip; + struct xfs_efi_log_format *efi_formatp; + int error; + + efi_formatp = item->ri_buf[0].i_addr; + + if (item->ri_buf[0].i_len < xfs_efi_log_format_sizeof(0)) { + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, + item->ri_buf[0].i_addr, item->ri_buf[0].i_len); + return -EFSCORRUPTED; + } + + efip = xfs_efi_init(mp, ITEM_TYPE(item), efi_formatp->efi_nextents); + error = xfs_efi_copy_format(&item->ri_buf[0], &efip->efi_format); + if (error) { + xfs_efi_item_free(efip); + return error; + } + atomic_set(&efip->efi_next_extent, efi_formatp->efi_nextents); + + xlog_recover_intent_item(log, &efip->efi_item, lsn, + &xfs_rtextent_free_defer_type); + return 0; +} +#else +STATIC int +xlog_recover_rtefi_commit_pass2( + struct xlog *log, + struct list_head *buffer_list, + struct xlog_recover_item *item, + xfs_lsn_t lsn) +{ + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, log->l_mp, + item->ri_buf[0].i_addr, item->ri_buf[0].i_len); + return -EFSCORRUPTED; +} +#endif + +const struct xlog_recover_item_ops xlog_rtefi_item_ops = { + .item_type = XFS_LI_EFI_RT, + .commit_pass2 = xlog_recover_rtefi_commit_pass2, +}; + /* * This routine is called when an EFD format structure is found in a committed * transaction in the log. Its purpose is to cancel the corresponding EFI if it @@ -793,3 +960,44 @@ const struct xlog_recover_item_ops xlog_efd_item_ops = { .item_type = XFS_LI_EFD, .commit_pass2 = xlog_recover_efd_commit_pass2, }; + +#ifdef CONFIG_XFS_RT +STATIC int +xlog_recover_rtefd_commit_pass2( + struct xlog *log, + struct list_head *buffer_list, + struct xlog_recover_item *item, + xfs_lsn_t lsn) +{ + struct xfs_efd_log_format *efd_formatp; + int buflen = item->ri_buf[0].i_len; + + efd_formatp = item->ri_buf[0].i_addr; + + if (buflen < sizeof(struct xfs_efd_log_format)) { + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, log->l_mp, + efd_formatp, buflen); + return -EFSCORRUPTED; + } + + if (item->ri_buf[0].i_len != xfs_efd_log_format32_sizeof( + efd_formatp->efd_nextents) && + item->ri_buf[0].i_len != xfs_efd_log_format64_sizeof( + efd_formatp->efd_nextents)) { + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, log->l_mp, + efd_formatp, buflen); + return -EFSCORRUPTED; + } + + xlog_recover_release_intent(log, XFS_LI_EFI_RT, + efd_formatp->efd_efi_id); + return 0; +} +#else +# define xlog_recover_rtefd_commit_pass2 xlog_recover_rtefi_commit_pass2 +#endif + +const struct xlog_recover_item_ops xlog_rtefd_item_ops = { + .item_type = XFS_LI_EFD_RT, + .commit_pass2 = xlog_recover_rtefd_commit_pass2, +}; diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 55e412a821483e..0af3d477197b24 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -1818,6 +1818,8 @@ static const struct xlog_recover_item_ops *xlog_recover_item_ops[] = { &xlog_attrd_item_ops, &xlog_xmi_item_ops, &xlog_xmd_item_ops, + &xlog_rtefi_item_ops, + &xlog_rtefd_item_ops, }; static const struct xlog_recover_item_ops * diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 419a92665f7764..e3218c0f6ac564 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -2766,6 +2766,7 @@ DECLARE_EVENT_CLASS(xfs_free_extent_deferred_class, TP_ARGS(mp, free), TP_STRUCT__entry( __field(dev_t, dev) + __field(enum xfs_group_type, type) __field(xfs_agnumber_t, agno) __field(xfs_agblock_t, agbno) __field(xfs_extlen_t, len) @@ -2773,13 +2774,16 @@ DECLARE_EVENT_CLASS(xfs_free_extent_deferred_class, ), TP_fast_assign( __entry->dev = mp->m_super->s_dev; - __entry->agno = XFS_FSB_TO_AGNO(mp, free->xefi_startblock); - __entry->agbno = XFS_FSB_TO_AGBNO(mp, free->xefi_startblock); + __entry->type = free->xefi_group->xg_type; + __entry->agno = free->xefi_group->xg_gno; + __entry->agbno = xfs_fsb_to_gbno(mp, free->xefi_startblock, + free->xefi_group->xg_type); __entry->len = free->xefi_blockcount; __entry->flags = free->xefi_flags; ), - TP_printk("dev %d:%d agno 0x%x agbno 0x%x fsbcount 0x%x flags 0x%x", + TP_printk("dev %d:%d %sno 0x%x gbno 0x%x fsbcount 0x%x flags 0x%x", MAJOR(__entry->dev), MINOR(__entry->dev), + __print_symbolic(__entry->type, XG_TYPE_STRINGS), __entry->agno, __entry->agbno, __entry->len, @@ -2789,7 +2793,6 @@ DECLARE_EVENT_CLASS(xfs_free_extent_deferred_class, DEFINE_EVENT(xfs_free_extent_deferred_class, name, \ TP_PROTO(struct xfs_mount *mp, struct xfs_extent_free_item *free), \ TP_ARGS(mp, free)) -DEFINE_FREE_EXTENT_DEFERRED_EVENT(xfs_agfl_free_defer); DEFINE_FREE_EXTENT_DEFERRED_EVENT(xfs_agfl_free_deferred); DEFINE_FREE_EXTENT_DEFERRED_EVENT(xfs_extent_free_defer); DEFINE_FREE_EXTENT_DEFERRED_EVENT(xfs_extent_free_deferred); From patchwork Thu Oct 17 19:07:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840722 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 BE4491E0DC3 for ; Thu, 17 Oct 2024 19:07:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192021; cv=none; b=RR866af4bbHOk+1uqr7nVTeTi6EeRpe6AbBkAdvoHXAjXe6ESW1qHKGpVp0g8YP+SPulIHTY9FwS2VGH0ZOhS/3eLzebvkAdnTS1WyODfPlJ5MKJuD0AdqPGZvdMgc2NwLyE0u4CJxVAEWJ/Bm9LGpOXEs2A2XFdLD72kA+TWqI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192021; c=relaxed/simple; bh=UamPD1cBLp3qwNsRbPtR7FoXqQ2uWOt20uFGHhaRtR4=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Q/ODuKk71m/476OkO+i4vZhwmxbS9lWFt9BBReQZd4Nkmvz7blW3MRHxc3uMpfE0WO2nZGTK7uLgDEwi7q3C0ABRVA7OSXFQ9nqTYt6Toww6cuTN2ETpfLm/TMpen3jIL/iaP5SdBVHqiAaSyP5b+Q5Qai94MBd9p3g77cX2Eio= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UuHD5DD1; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="UuHD5DD1" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9C883C4CEC3; Thu, 17 Oct 2024 19:07:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729192021; bh=UamPD1cBLp3qwNsRbPtR7FoXqQ2uWOt20uFGHhaRtR4=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=UuHD5DD1Ekj98iS3pTJGBiYDKBRkwzijfHErxBw50SEGVh33kAn5VXOpabWhJXTaQ YeWWq+7NngQHfxvJE6RyNdZFU9IjdpsxcLktnOZfxmLpf8vzbNirANPeAMQMFXUTpd YcsFE8nNJLn1ccp4lBcM82BtkZqcDCUPEsJs1dAYT3r6nbWofRjRGV1a5CXpgy0/vi ZMA7XuFuzqlHElfhpKoIYp/2ptVLCaVbgDapLF1Opgs00rJe/YDcFcEDKdqtYlR+ep sTsi5fLLS63QQ4pMTXViJqw+HL2AM658CdtBYodfGPirIEFFVSY+EQ6jGO3cJZTJsP jZwKGIjRX/k/w== Date: Thu, 17 Oct 2024 12:07:01 -0700 Subject: [PATCH 18/34] xfs: support error injection when freeing rt extents From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919071979.3453179.9098747688844513291.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong A handful of fstests expect to be able to test what happens when extent free intents fail to actually free the extent. Now that we're supporting EFIs for realtime extents, add to xfs_rtfree_extent the same injection point that exists in the regular extent freeing code. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_rtbitmap.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/xfs/libxfs/xfs_rtbitmap.c b/fs/xfs/libxfs/xfs_rtbitmap.c index cae0b22397d007..c73826aa4425af 100644 --- a/fs/xfs/libxfs/xfs_rtbitmap.c +++ b/fs/xfs/libxfs/xfs_rtbitmap.c @@ -21,6 +21,7 @@ #include "xfs_rtbitmap.h" #include "xfs_health.h" #include "xfs_sb.h" +#include "xfs_errortag.h" #include "xfs_log.h" #include "xfs_buf_item.h" @@ -1065,6 +1066,9 @@ xfs_rtfree_extent( ASSERT(rbmip->i_itemp != NULL); xfs_assert_ilocked(rbmip, XFS_ILOCK_EXCL); + if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_FREE_EXTENT)) + return -EIO; + error = xfs_rtcheck_alloc_range(&args, start, len); if (error) return error; From patchwork Thu Oct 17 19:07:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840723 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 533E81E0DC3 for ; Thu, 17 Oct 2024 19:07:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192032; cv=none; b=ZD2JyTp/sGBKvSSwih6J5PLweDwiULliFgTm42Z+pudZ4V5WKo9Mcl+x9gIFsVHizI2elO6u8bcci/3usP8z5km0tTmDqCHH2NPl7tvehSz3X+fDsuA0XnFKmbmnZHTZax4QgTY+gkBCrvPUz0XM3sIUb/3iA50huAAsKgiqbuE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192032; c=relaxed/simple; bh=ugdZLp8NfxKQy/0klcxbfwdvj+NjGEDvTOY+1bc34iM=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=spC+yG7ddROFG6NvFy1xynNqOmj65ZxTvgCMMrSvgiY6snnjKwhW8uNgpdR3CDYrPduLu+8AGix66UPT/ndpzvDL9qJ1bN3RPCyHt7fGERBJid14RPa15RPmDDSCbIjOMFVwF63KVMIPqGjKKHwMbAdg3rn6mCaGPtZNHjpCxKI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=dgsAGRWa; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="dgsAGRWa" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2E07FC4CEC3; Thu, 17 Oct 2024 19:07:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729192032; bh=ugdZLp8NfxKQy/0klcxbfwdvj+NjGEDvTOY+1bc34iM=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=dgsAGRWaMtCRkMQg/LVEYIPuyC1K8468CpRMPe8B28JrOHdQhaz9eWfQk7va4mpr3 59jnccG/tK9SweJS8cNfs2UPdL40yGjhhU+eyw5JZAGCxl9epDz8tUC6b/km34vhSN Ia1FMrgAulIv1bay5c1eE12XBscVhAcSYAvq6PV/5vEyXr3zgfkQbQsur+qjPaUwYh N1q+3aPNdtTGrO+T5NF1tA8glTff3e22aq+sPMOngSjbWXUTNcFGRQ3DKtRkMytYqs AKk4djlotauPh9KaZRoCdS7qO99AeBPqBCZaRI5AjWnrwSUcd7Vn+mjnqKrxY7h0jk DdCrsqx8HqBxg== Date: Thu, 17 Oct 2024 12:07:11 -0700 Subject: [PATCH 19/34] xfs: use realtime EFI to free extents when rtgroups are enabled From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919071996.3453179.4291910414964467609.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong When rmap is enabled, XFS expects a certain order of operations, which is: 1) remove the file mapping, 2) remove the reverse mapping, and then 3) free the blocks. When reflink is enabled, XFS replaces (3) with a deferred refcount decrement operation that can schedule freeing the blocks if that was the last refcount. For realtime files, xfs_bmap_del_extent_real tries to do 1 and 3 in the same transaction, which will break both rmap and reflink unless we switch it to use realtime EFIs. Both rmap and reflink depend on the rtgroups feature, so let's turn on EFIs for all rtgroups filesystems. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_bmap.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 482b4c0cd6b193..b15a43c18b0a57 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -5383,9 +5383,11 @@ xfs_bmap_del_extent_real( * If we need to, add to list of extents to delete. */ if (!(bflags & XFS_BMAPI_REMAP)) { + bool isrt = xfs_ifork_is_realtime(ip, whichfork); + if (xfs_is_reflink_inode(ip) && whichfork == XFS_DATA_FORK) { xfs_refcount_decrease_extent(tp, del); - } else if (xfs_ifork_is_realtime(ip, whichfork)) { + } else if (isrt && !xfs_has_rtgroups(mp)) { error = xfs_bmap_free_rtblocks(tp, del); } else { unsigned int efi_flags = 0; @@ -5394,6 +5396,19 @@ xfs_bmap_del_extent_real( del->br_state == XFS_EXT_UNWRITTEN) efi_flags |= XFS_FREE_EXTENT_SKIP_DISCARD; + /* + * Historically, we did not use EFIs to free realtime + * extents. However, when reverse mapping is enabled, + * we must maintain the same order of operations as the + * data device, which is: Remove the file mapping, + * remove the reverse mapping, and then free the + * blocks. Reflink for realtime volumes requires the + * same sort of ordering. Both features rely on + * rtgroups, so let's gate rt EFI usage on rtgroups. + */ + if (isrt) + efi_flags |= XFS_FREE_EXTENT_REALTIME; + error = xfs_free_extent_later(tp, del->br_startblock, del->br_blockcount, NULL, XFS_AG_RESV_NONE, efi_flags); From patchwork Thu Oct 17 19:07:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840724 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 DDADA1E0DC3 for ; Thu, 17 Oct 2024 19:07:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192042; cv=none; b=D4CC9ZZJo2hH0h1PvOkj1f55ktXss2mqSZW3X1z2dBOCaylfKpHjx5ak7dcN0Xh5Vzr+kRVUMkYwi2DtZvGCneUnOAk4FqPl3aTh/6ITXBBgyIAaTLieWjN/gciD3DSvRLnAW//GYUd/G377znoNaozf+U3evV7WZVe8XDKyGLM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192042; c=relaxed/simple; bh=s0uVKmkK5i0apJDWcFNlK01rnDOr92qJw2XELO42MlU=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=lzEwUEulQmbYrPjR7R/dwMoRBO0Y17bv1t6UDOMA4o34qV3BOjOY9kt6H7KPfh63mpbqpLfNBYJJ0B8P1dglToY5Zu/AjUSRcF8nq5gQSe0bCNhqoPsTBTo2509AYzLk5BHmyNrDfWMWG9s8Gr1YVEhk32IGFqGF7x4fxZ4HFj4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=OAb8kqXw; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="OAb8kqXw" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BBFE5C4CECD; Thu, 17 Oct 2024 19:07:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729192042; bh=s0uVKmkK5i0apJDWcFNlK01rnDOr92qJw2XELO42MlU=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=OAb8kqXwGOh9FqrbN40uuqYVuAT68LkfWQhlivPosGOjteWkSR6PXbWcb0wgRs1bI uzf/tO5T3FvhkRVl3iX42KW2r86LsfZYj2IuZDzCgf5HUxmZFwVeQhAdG2VrI6cc4o PCM5eQVCW9rTowH+72OtglXaSqgxmxdJEJQz4oJZbQ31+IAgNNagUm/e9m9G0Zy0s2 CNyN+Q5KA88NleHorsCR7rr/rnz0j+NGA+3xDPtrAq51V8nSLcc5YyuMA+VvXTyVwJ ijvlm/mP13y2K65qYtmbnkum0IPT2nEfoubrCVb3LiBfajF6vOzvnX+9OdmAXZBMwX MhKLgiCEJmmng== Date: Thu, 17 Oct 2024 12:07:22 -0700 Subject: [PATCH 20/34] xfs: don't merge ioends across RTGs From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919072014.3453179.3130117313373851670.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Unlike AGs, RTGs don't always have metadata in their first blocks, and thus we don't get automatic protection from merging I/O completions across RTG boundaries. Add code to set the IOMAP_F_BOUNDARY flag for ioends that start at the first block of a RTG so that they never get merged into the previous ioend. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_rtgroup.h | 9 +++++++++ fs/xfs/xfs_iomap.c | 13 ++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/fs/xfs/libxfs/xfs_rtgroup.h b/fs/xfs/libxfs/xfs_rtgroup.h index 026f34f984b32f..2ddfac9a0182f9 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.h +++ b/fs/xfs/libxfs/xfs_rtgroup.h @@ -188,6 +188,15 @@ xfs_rtb_to_rgbno( return __xfs_rtb_to_rgbno(mp, rtbno); } +/* Is rtbno the start of a RT group? */ +static inline bool +xfs_rtbno_is_group_start( + struct xfs_mount *mp, + xfs_rtblock_t rtbno) +{ + return (rtbno & mp->m_rgblkmask) == 0; +} + static inline xfs_daddr_t xfs_rtb_to_daddr( struct xfs_mount *mp, diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index c636481d651e07..fc952fe6269385 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -24,6 +24,7 @@ #include "xfs_iomap.h" #include "xfs_trace.h" #include "xfs_quota.h" +#include "xfs_rtgroup.h" #include "xfs_dquot_item.h" #include "xfs_dquot.h" #include "xfs_reflink.h" @@ -115,7 +116,9 @@ xfs_bmbt_to_iomap( iomap->addr = IOMAP_NULL_ADDR; iomap->type = IOMAP_DELALLOC; } else { - iomap->addr = BBTOB(xfs_fsb_to_db(ip, imap->br_startblock)); + xfs_daddr_t daddr = xfs_fsb_to_db(ip, imap->br_startblock); + + iomap->addr = BBTOB(daddr); if (mapping_flags & IOMAP_DAX) iomap->addr += target->bt_dax_part_off; @@ -124,6 +127,14 @@ xfs_bmbt_to_iomap( else iomap->type = IOMAP_MAPPED; + /* + * Mark iomaps starting at the first sector of a RTG as merge + * boundary so that each I/O completions is contained to a + * single RTG. + */ + if (XFS_IS_REALTIME_INODE(ip) && xfs_has_rtgroups(mp) && + xfs_rtbno_is_group_start(mp, imap->br_startblock)) + iomap->flags |= IOMAP_F_BOUNDARY; } iomap->offset = XFS_FSB_TO_B(mp, imap->br_startoff); iomap->length = XFS_FSB_TO_B(mp, imap->br_blockcount); From patchwork Thu Oct 17 19:07:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840727 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 8B7B91E0DC3 for ; Thu, 17 Oct 2024 19:07:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192053; cv=none; b=jpzfwbrEYyyRENww9zSN5w//6qjGHiBnvRoqBUVp6PBtGipJ90aaMuV81StpO8q0MaMbZK9Q2/CZRmtO0SwBAEouNapZ5DKFQHAqXqdvzPu1qeQ5oCwd9cLIPloo3kZ9omfpR/HOiH+uDu2JXLNniz5hi+15H68XQmesrq8eUvs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192053; c=relaxed/simple; bh=4lBlSROxpvhWZqUFwI3UnrMcnQojrzXw39dWA5Co4Xs=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=E8lOfRNZ9ZG7CEaobWWCIMYa7qAfOvG6J57rJZXJY4GN9VanjMcl478E016ekFxigyPiWMisFpeJNDzhVhyV10GsQORSWxEV5tJ76wnzBNT37PUcfzjVjvBB2bojSGiwSnqmkJ5cRHrQTRd5iqiyF7fFq4xmo9hcI8CaHPQeCn0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=kK4n45Pj; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="kK4n45Pj" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5D322C4CEC3; Thu, 17 Oct 2024 19:07:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729192053; bh=4lBlSROxpvhWZqUFwI3UnrMcnQojrzXw39dWA5Co4Xs=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=kK4n45PjXJhTE7a2pHgmxgY7rSszdDNBwTXguXINc5qXMWRwu0oDGeQb8A7qyr32o qYT6HPcUN4q1CO3oM+452DKYuEXpErJw/Rs9PyhRhlc6W0LC0LU1ewCB9v3S+N/Ytq T/pPjUD6oKy1znu5X3mpDsJWliM4l2ToRTtaBFQS/BiLPpFUKg7jydPgRBpEsLnNBI wbDEfZW5ycaP4XYPvoamRPiN5U4ZY0hMaSR/mwJQsCKS/Lx0LsQUz3d9AWHAouW1nr ldAgukQ7znKt+NkDuD/6jMLb2N1BF4Y76x/qpSb2oA9e8/42QxaRetM1SnknhJeB+/ Y4wMvVYxqAAdQ== Date: Thu, 17 Oct 2024 12:07:32 -0700 Subject: [PATCH 21/34] xfs: make the RT allocator rtgroup aware From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919072031.3453179.1456466386189498423.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Christoph Hellwig Make the allocator rtgroup aware by either picking a specific group if there is a hint, or loop over all groups otherwise. A simple rotor is provided to pick the placement for initial allocations. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_bmap.c | 13 +++++- fs/xfs/libxfs/xfs_rtbitmap.c | 6 ++- fs/xfs/xfs_mount.h | 1 fs/xfs/xfs_rtalloc.c | 98 ++++++++++++++++++++++++++++++++++++++---- 4 files changed, 105 insertions(+), 13 deletions(-) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index b15a43c18b0a57..3498d7b4fbc54e 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -3151,8 +3151,17 @@ xfs_bmap_adjacent_valid( struct xfs_mount *mp = ap->ip->i_mount; if (XFS_IS_REALTIME_INODE(ap->ip) && - (ap->datatype & XFS_ALLOC_USERDATA)) - return x < mp->m_sb.sb_rblocks; + (ap->datatype & XFS_ALLOC_USERDATA)) { + if (x >= mp->m_sb.sb_rblocks) + return false; + if (!xfs_has_rtgroups(mp)) + return true; + + return xfs_rtb_to_rgno(mp, x) == xfs_rtb_to_rgno(mp, y) && + xfs_rtb_to_rgno(mp, x) < mp->m_sb.sb_rgcount && + xfs_rtb_to_rtx(mp, x) < mp->m_sb.sb_rgextents; + + } return XFS_FSB_TO_AGNO(mp, x) == XFS_FSB_TO_AGNO(mp, y) && XFS_FSB_TO_AGNO(mp, x) < mp->m_sb.sb_agcount && diff --git a/fs/xfs/libxfs/xfs_rtbitmap.c b/fs/xfs/libxfs/xfs_rtbitmap.c index c73826aa4425af..5abfd84852ce3b 100644 --- a/fs/xfs/libxfs/xfs_rtbitmap.c +++ b/fs/xfs/libxfs/xfs_rtbitmap.c @@ -1084,11 +1084,13 @@ xfs_rtfree_extent( * Mark more blocks free in the superblock. */ xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len); + /* * If we've now freed all the blocks, reset the file sequence - * number to 0. + * number to 0 for pre-RTG file systems. */ - if (tp->t_frextents_delta + mp->m_sb.sb_frextents == + if (!xfs_has_rtgroups(mp) && + tp->t_frextents_delta + mp->m_sb.sb_frextents == mp->m_sb.sb_rextents) { if (!(rbmip->i_diflags & XFS_DIFLAG_NEWRTBM)) rbmip->i_diflags |= XFS_DIFLAG_NEWRTBM; diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index e0902c08510d80..7b6902c21d50c9 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -255,6 +255,7 @@ typedef struct xfs_mount { #endif xfs_agnumber_t m_agfrotor; /* last ag where space found */ atomic_t m_agirotor; /* last ag dir inode alloced */ + atomic_t m_rtgrotor; /* last rtgroup rtpicked */ /* Memory shrinker to throttle and reprioritize inodegc */ struct shrinker *m_inodegc_shrinker; diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 2093cab0cf8cb5..783674fd42ead1 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -1660,8 +1660,9 @@ xfs_rtalloc_align_minmax( } static int -xfs_rtallocate( +xfs_rtallocate_rtg( struct xfs_trans *tp, + xfs_rgnumber_t rgno, xfs_rtblock_t bno_hint, xfs_rtxlen_t minlen, xfs_rtxlen_t maxlen, @@ -1681,16 +1682,33 @@ xfs_rtallocate( xfs_rtxlen_t len = 0; int error = 0; - args.rtg = xfs_rtgroup_grab(args.mp, 0); + args.rtg = xfs_rtgroup_grab(args.mp, rgno); if (!args.rtg) return -ENOSPC; /* - * Lock out modifications to both the RT bitmap and summary inodes. + * We need to lock out modifications to both the RT bitmap and summary + * inodes for finding free space in xfs_rtallocate_extent_{near,size} + * and join the bitmap and summary inodes for the actual allocation + * down in xfs_rtallocate_range. + * + * For RTG-enabled file system we don't want to join the inodes to the + * transaction until we are committed to allocate to allocate from this + * RTG so that only one inode of each type is locked at a time. + * + * But for pre-RTG file systems we need to already to join the bitmap + * inode to the transaction for xfs_rtpick_extent, which bumps the + * sequence number in it, so we'll have to join the inode to the + * transaction early here. + * + * This is all a bit messy, but at least the mess is contained in + * this function. */ if (!*rtlocked) { xfs_rtgroup_lock(args.rtg, XFS_RTGLOCK_BITMAP); - xfs_rtgroup_trans_join(tp, args.rtg, XFS_RTGLOCK_BITMAP); + if (!xfs_has_rtgroups(args.mp)) + xfs_rtgroup_trans_join(tp, args.rtg, + XFS_RTGLOCK_BITMAP); *rtlocked = true; } @@ -1700,7 +1718,7 @@ xfs_rtallocate( */ if (bno_hint) start = xfs_rtb_to_rtx(args.mp, bno_hint); - else if (initial_user_data) + else if (!xfs_has_rtgroups(args.mp) && initial_user_data) start = xfs_rtpick_extent(args.rtg, tp, maxlen); if (start) { @@ -1721,8 +1739,16 @@ xfs_rtallocate( prod, &rtx); } - if (error) + if (error) { + if (xfs_has_rtgroups(args.mp)) { + xfs_rtgroup_unlock(args.rtg, XFS_RTGLOCK_BITMAP); + *rtlocked = false; + } goto out_release; + } + + if (xfs_has_rtgroups(args.mp)) + xfs_rtgroup_trans_join(tp, args.rtg, XFS_RTGLOCK_BITMAP); error = xfs_rtallocate_range(&args, rtx, len); if (error) @@ -1740,6 +1766,53 @@ xfs_rtallocate( return error; } +static int +xfs_rtallocate_rtgs( + struct xfs_trans *tp, + xfs_fsblock_t bno_hint, + xfs_rtxlen_t minlen, + xfs_rtxlen_t maxlen, + xfs_rtxlen_t prod, + bool wasdel, + bool initial_user_data, + xfs_rtblock_t *bno, + xfs_extlen_t *blen) +{ + struct xfs_mount *mp = tp->t_mountp; + xfs_rgnumber_t start_rgno, rgno; + int error; + + /* + * For now this just blindly iterates over the RTGs for an initial + * allocation. We could try to keep an in-memory rtg_longest member + * to avoid the locking when just looking for big enough free space, + * but for now this keeps things simple. + */ + if (bno_hint != NULLFSBLOCK) + start_rgno = xfs_rtb_to_rgno(mp, bno_hint); + else + start_rgno = (atomic_inc_return(&mp->m_rtgrotor) - 1) % + mp->m_sb.sb_rgcount; + + rgno = start_rgno; + do { + bool rtlocked = false; + + error = xfs_rtallocate_rtg(tp, rgno, bno_hint, minlen, maxlen, + prod, wasdel, initial_user_data, &rtlocked, + bno, blen); + if (error != -ENOSPC) + return error; + ASSERT(!rtlocked); + + if (++rgno == mp->m_sb.sb_rgcount) + rgno = 0; + bno_hint = NULLFSBLOCK; + } while (rgno != start_rgno); + + return -ENOSPC; +} + static int xfs_rtallocate_align( struct xfs_bmalloca *ap, @@ -1834,9 +1907,16 @@ xfs_bmap_rtalloc( if (xfs_bmap_adjacent(ap)) bno_hint = ap->blkno; - error = xfs_rtallocate(ap->tp, bno_hint, raminlen, ralen, prod, - ap->wasdel, initial_user_data, &rtlocked, - &ap->blkno, &ap->length); + if (xfs_has_rtgroups(ap->ip->i_mount)) { + error = xfs_rtallocate_rtgs(ap->tp, bno_hint, raminlen, ralen, + prod, ap->wasdel, initial_user_data, + &ap->blkno, &ap->length); + } else { + error = xfs_rtallocate_rtg(ap->tp, 0, bno_hint, raminlen, ralen, + prod, ap->wasdel, initial_user_data, + &rtlocked, &ap->blkno, &ap->length); + } + if (error == -ENOSPC) { if (!noalign) { /* From patchwork Thu Oct 17 19:07:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840728 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 2B54C1E0DC3 for ; Thu, 17 Oct 2024 19:07:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192064; cv=none; b=dpq3rGCq3Lwbw/H1H18pGxeIo641DjH7ESIXYlKxP5upEvil1uP/ltDGyOy7wQ7uuY/CIRUcHKMEUFdWlee4uye+iU0pfMMBZ4c34chtjJxEWy3H7Dzoo8LalX8eA9X2G+G0UVofP4WB1PxxcB8iTvr4I61rlw87ardaKNpLziU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192064; c=relaxed/simple; bh=sBGTL4capdNvkgP0r6UhUrGeeT4atfbQYmpU6MoLZnI=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Uz+lD53nTG/twPc5wgTZih4FuNkbhnnARegKzPTRq/dYqPtVP10am5SD1DwmvdVIpdHG5VvudyDSJutyP71xUzgbBvIqMo0fGVVmmwYSAEnAQRm6YSFIfy8b2UL0oqGBVMFtfP6c9ct1RQifLDurNi1nq6QvO0I8QOi24NnfPNQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=nWH/1CX+; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="nWH/1CX+" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0884AC4CECE; Thu, 17 Oct 2024 19:07:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729192064; bh=sBGTL4capdNvkgP0r6UhUrGeeT4atfbQYmpU6MoLZnI=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=nWH/1CX+qqlUQd3jZnY3bSbJKxwezXhj8KqdcVBFrYT4WebrQDEYXXP6BWK6adaqL 82jXLDtFYFULK0HeErUoRO7XeUPW1iU3Ct3Uaoyqkkw70Lub57zflW7Bun9Z0M9ZF3 FQqM/9NLgbCE6MCcxw1AZsLRcVlcw+UKK2SyjPxFSk/8QkPh43yaQzVcCsc2j9y6ae GYAfq5uhiB5mOJU/D2aSTWeyOzzsOTQb0xiWjAoPwew/kST8Cwq1dxvScbTj+WGAGg JYU3YlkUIB/1PS3xyNthZCIRuvxhXyu5vVYXpRnlyBAlaKPC3eSA+DJgTH4Z43wJ6J lZPTGfM7Etvyw== Date: Thu, 17 Oct 2024 12:07:43 -0700 Subject: [PATCH 22/34] xfs: don't coalesce file mappings that cross rtgroup boundaries in scrub From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919072048.3453179.5756327403798892475.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong The bmbt scrubber will combine file mappings if they are mergeable to reduce the number of cross-referencing checks. However, we shouldn't combine mappings that cross rt group boundaries because that will cause verifiers to trip incorrectly. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/scrub/bmap.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c index 008630b2b75263..7e00312225ed10 100644 --- a/fs/xfs/scrub/bmap.c +++ b/fs/xfs/scrub/bmap.c @@ -834,9 +834,12 @@ xchk_bmap_iext_mapping( /* Are these two mappings contiguous with each other? */ static inline bool xchk_are_bmaps_contiguous( + const struct xchk_bmap_info *info, const struct xfs_bmbt_irec *b1, const struct xfs_bmbt_irec *b2) { + struct xfs_mount *mp = info->sc->mp; + /* Don't try to combine unallocated mappings. */ if (!xfs_bmap_is_real_extent(b1)) return false; @@ -850,6 +853,17 @@ xchk_are_bmaps_contiguous( return false; if (b1->br_state != b2->br_state) return false; + + /* + * Don't combine bmaps that would cross rtgroup boundaries. This is a + * valid state, but if combined they will fail rtb extent checks. + */ + if (info->is_rt && xfs_has_rtgroups(mp)) { + if (xfs_rtb_to_rgno(mp, b1->br_startblock) != + xfs_rtb_to_rgno(mp, b2->br_startblock)) + return false; + } + return true; } @@ -887,7 +901,7 @@ xchk_bmap_iext_iter( * that we just read, if possible. */ while (xfs_iext_peek_next_extent(ifp, &info->icur, &got)) { - if (!xchk_are_bmaps_contiguous(irec, &got)) + if (!xchk_are_bmaps_contiguous(info, irec, &got)) break; if (!xchk_bmap_iext_mapping(info, &got)) { From patchwork Thu Oct 17 19:07:54 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840729 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 05FE821C18B for ; Thu, 17 Oct 2024 19:07:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192075; cv=none; b=LRo+EwUARPel2YI++0LVvlfkLgbPMSkp1vyIM4wI/3dCSeP3Zm1AlzIfDLObX5BTD6sYyF6zlmshYEsjGvhqcBe2f1SrEIbWyMgzcMWRWWB2rs3CI05bjObLbyZkpTfDKUXT7FXnDK9PclYHirieFAEucQSMQ3KDPgdoWqe1I6Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192075; c=relaxed/simple; bh=yWfZe4oKt1HGq+bvLaXOUpai4lQaiXcpliMjvIYqM8U=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=WjhBR7qNPyHGruGJ+G1WEHpriAuuiyVPPcEDX/rQkS0oGB0R+z+ouJ6sUEvEYemtWMS8VD69KDpazv/18Uz7zFw8k4BHvgKaCwQWvxBHk9/ASaVkTAR+p9yFahGjC0f29ZsHu7VDLFi6KMI3ty/WIjuuL6hj2YN/yuVZJ307zOo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=caEw0YAx; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="caEw0YAx" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 95754C4CEC3; Thu, 17 Oct 2024 19:07:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729192074; bh=yWfZe4oKt1HGq+bvLaXOUpai4lQaiXcpliMjvIYqM8U=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=caEw0YAx83BMY3HtrAFjqCLAKa9l+NZLLOi78u5kE0m43jJPRCoMoOzH2shpxcr1h vm2ZqA7kprySU7NL0nEcKj89F+8CaLEZS4lrp/zJ4n3WmZGJRVorE6hHcQGo9m7BHe lzk8GekGacLKZ9IdEVd2pK31EnTgHGGruWnsXcDm3T7/pdIxEuzUwTSBc8xrAaLm3D BP2V5f/l0La2pg24ms76cSOWzOTo6DBRKAHeur5AUOS4ThnLYfXmKZnagaRzIFpUO7 8GGYstY/7t/VU5cx8VgjOJ4ETqFas4iu4IzpvputXhUs4cDPQFvmycJNhgZ5TSDLXs PNT3ziVS1x5Pg== Date: Thu, 17 Oct 2024 12:07:54 -0700 Subject: [PATCH 23/34] xfs: scrub the realtime group superblock From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919072065.3453179.10909050321123561066.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Enable scrubbing of realtime group superblocks. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/Makefile | 1 + fs/xfs/libxfs/xfs_fs.h | 3 +- fs/xfs/scrub/common.h | 2 + fs/xfs/scrub/health.c | 1 + fs/xfs/scrub/rgsuper.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/scrub/scrub.c | 7 +++++ fs/xfs/scrub/scrub.h | 2 + fs/xfs/scrub/stats.c | 1 + fs/xfs/scrub/trace.h | 4 ++- 9 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 fs/xfs/scrub/rgsuper.c diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 6814debac29929..ed9b0dabc1f11d 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -191,6 +191,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 4c0682173d6144..50de6ad88dbe45 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_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.h b/fs/xfs/scrub/common.h index 672ed48d4a9fc3..9ff3cafd867962 100644 --- a/fs/xfs/scrub/common.h +++ b/fs/xfs/scrub/common.h @@ -79,9 +79,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 # 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); diff --git a/fs/xfs/scrub/health.c b/fs/xfs/scrub/health.c index 7547fb5bcd7272..ce86bdad37fa42 100644 --- a/fs/xfs/scrub/health.c +++ b/fs/xfs/scrub/health.c @@ -111,6 +111,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_RG_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 00000000000000..00dfe043dfea7f --- /dev/null +++ b/fs/xfs/scrub/rgsuper.c @@ -0,0 +1,68 @@ +// 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) +{ + if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) + return; + + xchk_xref_is_used_rt_space(sc, xfs_rgbno_to_rtb(sc->sr.rtg, 0), 1); +} + +int +xchk_rgsuperblock( + struct xfs_scrub *sc) +{ + xfs_rgnumber_t rgno = sc->sm->sm_agno; + int error; + + /* + * Only rtgroup 0 has a superblock. We may someday want to use higher + * rgno for other functions, similar to what we do with the primary + * super scrub function. + */ + if (rgno != 0) + return -ENOENT; + + /* + * 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_existing(sc, rgno, &sc->sr); + if (!xchk_xref_process_error(sc, 0, 0, &error)) + return error; + + xchk_rtgroup_lock(&sc->sr, XFS_RTGLOCK_BITMAP_SHARED); + + /* + * Since we already validated the rt superblock at mount time, we don't + * need to check its contents again. All we need is to cross-reference. + */ + xchk_rgsuperblock_xref(sc); + return 0; +} diff --git a/fs/xfs/scrub/scrub.c b/fs/xfs/scrub/scrub.c index 8cd7e36c09990e..ceb22c722d8f52 100644 --- a/fs/xfs/scrub/scrub.c +++ b/fs/xfs/scrub/scrub.c @@ -451,6 +451,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_rtsb, + .repair = xrep_notsupported, + }, }; static int diff --git a/fs/xfs/scrub/scrub.h b/fs/xfs/scrub/scrub.h index f73c6d0d90a11a..a7fda3e2b01377 100644 --- a/fs/xfs/scrub/scrub.h +++ b/fs/xfs/scrub/scrub.h @@ -273,9 +273,11 @@ 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 # 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); diff --git a/fs/xfs/scrub/stats.c b/fs/xfs/scrub/stats.c index edcd02dc2e62c0..a476c7b2ab7597 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 b6c8d0944fa453..9b38f5ad1eaf07 100644 --- a/fs/xfs/scrub/trace.h +++ b/fs/xfs/scrub/trace.h @@ -71,6 +71,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" }, \ @@ -103,7 +104,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 Thu Oct 17 19:08:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840730 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 B45F021BB06 for ; Thu, 17 Oct 2024 19:08:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192085; cv=none; b=qndf54lktjXoKYxojf7jRBzA1CGVCUXJqrp4xzugCnj47U0mrbgD4DKeE44InwUfNPQcbcU51SLSgC5PTAllxllwe1N6/m0+GXefya8T9M7rk8j65pHHm0t7AdB4tvaJGyRu+7NcuEqf8zACxF+axTK7X+v9z5P+IZLhJlw2Cm0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192085; c=relaxed/simple; bh=lRfe52tyMyBnmokqal2CmqJt6IEB3cyIqrb5SMrW8CU=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=QLXZxJYfzHZJoBhQm23tOnCP9QzY4OddjyBE10zZ6tX1Fza8oDpg+zjimqD/X0eCVmB78KPwDX66vdjQDEub0UdfYuynusFR/OvtICBOlqWqlcSxoFq5tm0YbRwmJdWaMwrlzOiTlcVy6LhU9Ntot6BFdMVg4DRdMwUqCV+McVA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=lJQjLDrJ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="lJQjLDrJ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 298D8C4CEC3; Thu, 17 Oct 2024 19:08:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729192085; bh=lRfe52tyMyBnmokqal2CmqJt6IEB3cyIqrb5SMrW8CU=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=lJQjLDrJISHVqIU9CO4PeBU2R0pjIy88lEblHYvb4pj552YqiXfEO+fXEpczh1Nkb zC3x/1kViK9HNG8ePIkSJEcgo0TDGYMC9QwgORFDLHxwe1H6Iv5YPGuHbz4G8aLvbs mDNyTMV1dDAICze3uEj+W08+by1ygsLQWc6gz0S4ddYxQ6fxxEZ1/i2ldImBRWzckV rAZj9CYmMaMGYihzI6TUfIKmeGW+xXqoFD1oHPdLhMfIaki8Hhh0MzQdxbhcNBktyr uaoBF9V1QLwL1hX6jpQ4UE3RVrVpHLoarpHEFfaJT9vCfJkif/hMgKyjXKDoUAXQzX GdMkE8alKKgEw== Date: Thu, 17 Oct 2024 12:08:04 -0700 Subject: [PATCH 24/34] xfs: repair realtime group superblock From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919072083.3453179.10995550419166957274.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Repair the realtime superblock if it has become out of date with the primary superblock. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/scrub/repair.h | 3 +++ fs/xfs/scrub/rgsuper.c | 16 ++++++++++++++++ fs/xfs/scrub/scrub.c | 2 +- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/fs/xfs/scrub/repair.h b/fs/xfs/scrub/repair.h index 4052185743910d..b649da1a93eb8c 100644 --- a/fs/xfs/scrub/repair.h +++ b/fs/xfs/scrub/repair.h @@ -146,9 +146,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 @@ -253,6 +255,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.c b/fs/xfs/scrub/rgsuper.c index 00dfe043dfea7f..463b3573bb761b 100644 --- a/fs/xfs/scrub/rgsuper.c +++ b/fs/xfs/scrub/rgsuper.c @@ -10,8 +10,12 @@ #include "xfs_trans_resv.h" #include "xfs_mount.h" #include "xfs_rtgroup.h" +#include "xfs_log_format.h" +#include "xfs_trans.h" +#include "xfs_sb.h" #include "scrub/scrub.h" #include "scrub/common.h" +#include "scrub/repair.h" /* Set us up with a transaction and an empty context. */ int @@ -66,3 +70,15 @@ xchk_rgsuperblock( xchk_rgsuperblock_xref(sc); return 0; } + +#ifdef CONFIG_XFS_ONLINE_REPAIR +int +xrep_rgsuperblock( + struct xfs_scrub *sc) +{ + ASSERT(rtg_rgno(sc->sr.rtg) == 0); + + xfs_log_sb(sc->tp); + return 0; +} +#endif /* CONFIG_XFS_ONLINE_REPAIR */ diff --git a/fs/xfs/scrub/scrub.c b/fs/xfs/scrub/scrub.c index ceb22c722d8f52..950f5a58dcd967 100644 --- a/fs/xfs/scrub/scrub.c +++ b/fs/xfs/scrub/scrub.c @@ -456,7 +456,7 @@ static const struct xchk_meta_ops meta_scrub_ops[] = { .setup = xchk_setup_rgsuperblock, .scrub = xchk_rgsuperblock, .has = xfs_has_rtsb, - .repair = xrep_notsupported, + .repair = xrep_rgsuperblock, }, }; From patchwork Thu Oct 17 19:08:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840731 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 E01B51E0DC3 for ; Thu, 17 Oct 2024 19:08:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192096; cv=none; b=r2zdijWJnYWu6P6AkSzT/bnLGKC0+JUqf7GDBXSpKFe4IGyKWQflV5aVQYlMCFSF7HiI4UyJjOx8vNbGQ2dOI30DOXv5oMHaVVyv17CqSDq0X4lQF58N8M8bl4fz+JxqaHFxT364nztvBrKSNuZJVFjWYgn/RqcOJEysRMGXx1Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192096; c=relaxed/simple; bh=DCclybK8wzM0Nc0Qu6mAf43naRWPiYtjjY5Gi+T5GUs=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=JQTeYth0v98bg7viobC9stbKzJtGCtRzHJQqC4QP/vwxh5NdElZ0wYPtH92ca3OPrEIGkMJZ7TSRODiz7v8s+I+uUQxOwb1VrA9lYpJvjDwLmiTqBia3Y+9YEP5Wo7nmKu9G09EAN/m9UI4Nhvl1freNIlyTNqrnBX8byp2+usM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=S5loYs3x; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="S5loYs3x" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BFE79C4CEC3; Thu, 17 Oct 2024 19:08:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729192095; bh=DCclybK8wzM0Nc0Qu6mAf43naRWPiYtjjY5Gi+T5GUs=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=S5loYs3xQJ86D+1o5Xmat+/AoobBuZ74EzOiG0DbKjsc0bayaw1MUMdatFbF84cIW rFHQbHwJbot67rQ2oSAAWhzRoPJhA6JWqkKgd4Ho4BB6yGyh2VUt5UQ5iyFRHlNiMb N6ZdqDFPdZ6Tg1OX0ahgDactYysDWvxsaVpaVeawHcogY/L3BDHrAauY4u4wWRjyBK o6UyQTORZ4viAb/X8Bb4Uw4ffee3cPzTaaxjhpwI7pvNQAYqUIiOILjApWROOvKRR9 iAWEVzf/KIw98wbYji4D5KTvHggACYoxGfNNsexZkSXZ1RKWpeV6M/7+LD5NZTdJg4 hzK6Iuu7MemoA== Date: Thu, 17 Oct 2024 12:08:15 -0700 Subject: [PATCH 25/34] xfs: scrub metadir paths for rtgroup metadata From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919072100.3453179.3999964281736504018.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Add the code we need to scan the metadata directory paths of rt group metadata files. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_fs.h | 5 ++- fs/xfs/scrub/metapath.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index 50de6ad88dbe45..96f7d3c95fb4bc 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -822,9 +822,12 @@ struct xfs_scrub_vec_head { * path checking. */ #define XFS_SCRUB_METAPATH_PROBE (0) /* do we have a metapath scrubber? */ +#define XFS_SCRUB_METAPATH_RTDIR (1) /* rtrgroups metadir */ +#define XFS_SCRUB_METAPATH_RTBITMAP (2) /* per-rtg bitmap */ +#define XFS_SCRUB_METAPATH_RTSUMMARY (3) /* per-rtg summary */ /* Number of metapath sm_ino values */ -#define XFS_SCRUB_METAPATH_NR (1) +#define XFS_SCRUB_METAPATH_NR (4) /* * ioctl limits diff --git a/fs/xfs/scrub/metapath.c b/fs/xfs/scrub/metapath.c index edc1a395c4015a..b8e427fd7fa73e 100644 --- a/fs/xfs/scrub/metapath.c +++ b/fs/xfs/scrub/metapath.c @@ -20,6 +20,7 @@ #include "xfs_bmap_btree.h" #include "xfs_trans_space.h" #include "xfs_attr.h" +#include "xfs_rtgroup.h" #include "scrub/scrub.h" #include "scrub/common.h" #include "scrub/trace.h" @@ -79,6 +80,91 @@ xchk_metapath_cleanup( kfree(mpath->path); } +/* Set up a metadir path scan. @path must be dynamically allocated. */ +static inline int +xchk_setup_metapath_scan( + struct xfs_scrub *sc, + struct xfs_inode *dp, + const char *path, + struct xfs_inode *ip) +{ + struct xchk_metapath *mpath; + int error; + + if (!path) + return -ENOMEM; + + error = xchk_install_live_inode(sc, ip); + if (error) { + kfree(path); + return error; + } + + mpath = kzalloc(sizeof(struct xchk_metapath), XCHK_GFP_FLAGS); + if (!mpath) { + kfree(path); + return -ENOMEM; + } + + mpath->sc = sc; + sc->buf = mpath; + sc->buf_cleanup = xchk_metapath_cleanup; + + mpath->dp = dp; + mpath->path = path; /* path is now owned by mpath */ + + mpath->xname.name = mpath->path; + mpath->xname.len = strlen(mpath->path); + mpath->xname.type = xfs_mode_to_ftype(VFS_I(ip)->i_mode); + + return 0; +} + +#ifdef CONFIG_XFS_RT +/* Scan the /rtgroups directory itself. */ +static int +xchk_setup_metapath_rtdir( + struct xfs_scrub *sc) +{ + if (!sc->mp->m_rtdirip) + return -ENOENT; + + return xchk_setup_metapath_scan(sc, sc->mp->m_metadirip, + kasprintf(GFP_KERNEL, "rtgroups"), sc->mp->m_rtdirip); +} + +/* Scan a rtgroup inode under the /rtgroups directory. */ +static int +xchk_setup_metapath_rtginode( + struct xfs_scrub *sc, + enum xfs_rtg_inodes type) +{ + struct xfs_rtgroup *rtg; + struct xfs_inode *ip; + int error; + + rtg = xfs_rtgroup_get(sc->mp, sc->sm->sm_agno); + if (!rtg) + return -ENOENT; + + ip = rtg->rtg_inodes[type]; + if (!ip) { + error = -ENOENT; + goto out_put_rtg; + } + + error = xchk_setup_metapath_scan(sc, sc->mp->m_rtdirip, + xfs_rtginode_path(rtg_rgno(rtg), type), ip); + +out_put_rtg: + xfs_rtgroup_put(rtg); + return error; +} +#else +# define xchk_setup_metapath_rtdir(...) (-ENOENT) +# define xchk_setup_metapath_rtginode(...) (-ENOENT) +#endif /* CONFIG_XFS_RT */ + int xchk_setup_metapath( struct xfs_scrub *sc) @@ -94,6 +180,12 @@ xchk_setup_metapath( if (sc->sm->sm_agno) return -EINVAL; return 0; + case XFS_SCRUB_METAPATH_RTDIR: + return xchk_setup_metapath_rtdir(sc); + case XFS_SCRUB_METAPATH_RTBITMAP: + return xchk_setup_metapath_rtginode(sc, XFS_RTGI_BITMAP); + case XFS_SCRUB_METAPATH_RTSUMMARY: + return xchk_setup_metapath_rtginode(sc, XFS_RTGI_SUMMARY); default: return -ENOENT; } From patchwork Thu Oct 17 19:08:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840732 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 D182621BAF3 for ; Thu, 17 Oct 2024 19:08:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192106; cv=none; b=Bc5B3/cCRogjJ307Zp7rKBZc/nCzO156bBj/rVTRtepZd8ddv6xPxptIjVZGhhN5vm6Xn6etS0iRx2Gk2DloAg2veeAnRF7Urik7M8BOmr4TTIcXDWbh7JRww2EWSuFiUlBO+F5+mc4FI1osfPWON5Ce4VOfFNdJVwKxNCXA7fs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192106; c=relaxed/simple; bh=ICwET0+B/TMK4Uuaz63TV3TNGsd0X2v+DEMH0t9wmtA=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=EnAKUIVMP6dkwLU22YrOSyip9bJXZcw3E3234/9TOD51aEfb9C3DzsC33B/WOplzbxJwwnOmw5fbpZoQdZdIsEIegCoIPr2qMwPdTUaLiLVsht8SS1EAUmbTJ/BnCPUzFnrm0wWKIjWhlPVCkY9S73HETBArwF18w8Uall4oQ4U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CnXK5jR4; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="CnXK5jR4" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 57458C4CEC3; Thu, 17 Oct 2024 19:08:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729192106; bh=ICwET0+B/TMK4Uuaz63TV3TNGsd0X2v+DEMH0t9wmtA=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=CnXK5jR4umZn5TMYA1/P/n2vg9jbZnA+PRFcggbWorqTR9Ckr45aj/Is6Pgr1/5+f bjV5GH2EWxqgDviQr7q1eF3ZP2NM6Z1U8+N8hY8bR71+AjeSPFDD+hGKum0+Hy40Gk vGc3TMoN7/0XXU3/aSymwYT4ELEccmfbh+ykc5GW7D6VY1RBEodNY4VHMVlZQTuxl2 4L6+CsjGZkFbWB7YKqKhn7lWq3Ut3SmWNr/5fbvAgS1UvM+4O8k2b96+qe2SM6YCRN Cg4ROOIUmLjEOuoMb8DszLf9dBSNFjpOnfnWgBnCInNMBTbFUkp26K0l1O8Fs5SjbL 0pBX3QgCQAYCw== Date: Thu, 17 Oct 2024 12:08:25 -0700 Subject: [PATCH 26/34] xfs: mask off the rtbitmap and summary inodes when metadir in use From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919072118.3453179.14385122365574800490.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Set the rtbitmap and summary file inumbers to NULLFSINO in the superblock and make sure they're zeroed whenever we write the superblock to disk, to mimic mkfs behavior. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_sb.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index c55ccecaccbda4..1af7029753ea15 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -655,6 +655,14 @@ xfs_validate_sb_common( void xfs_sb_quota_from_disk(struct xfs_sb *sbp) { + if (xfs_sb_is_v5(sbp) && + (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR)) { + sbp->sb_uquotino = NULLFSINO; + sbp->sb_gquotino = NULLFSINO; + sbp->sb_pquotino = NULLFSINO; + return; + } + /* * older mkfs doesn't initialize quota inodes to NULLFSINO. This * leads to in-core values having two different values for a quota @@ -783,6 +791,8 @@ __xfs_sb_from_disk( to->sb_metadirino = be64_to_cpu(from->sb_metadirino); to->sb_rgcount = be32_to_cpu(from->sb_rgcount); to->sb_rgextents = be32_to_cpu(from->sb_rgextents); + to->sb_rbmino = NULLFSINO; + to->sb_rsumino = NULLFSINO; } else { to->sb_metadirino = NULLFSINO; to->sb_rgcount = 1; @@ -805,6 +815,14 @@ xfs_sb_quota_to_disk( { uint16_t qflags = from->sb_qflags; + if (xfs_sb_is_v5(from) && + (from->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR)) { + to->sb_uquotino = cpu_to_be64(0); + to->sb_gquotino = cpu_to_be64(0); + to->sb_pquotino = cpu_to_be64(0); + return; + } + to->sb_uquotino = cpu_to_be64(from->sb_uquotino); /* @@ -940,6 +958,8 @@ xfs_sb_to_disk( to->sb_metadirino = cpu_to_be64(from->sb_metadirino); to->sb_rgcount = cpu_to_be32(from->sb_rgcount); to->sb_rgextents = cpu_to_be32(from->sb_rgextents); + to->sb_rbmino = cpu_to_be64(0); + to->sb_rsumino = cpu_to_be64(0); } } From patchwork Thu Oct 17 19:08:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840733 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 1A9631E0DC3 for ; Thu, 17 Oct 2024 19:08:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192117; cv=none; b=e8ZqsnUq6FlBid9+filr+gGpLBIQ+s4CD4mHNO4f3419/j0npV7yj2USV+YdIerZQkgo1JqZVbJDF1jN6nHenMe/qWNKWJg565Ea2yxYPAu+S20HQaxVteLWGf0H2X7/SRVk103o6BlPXZvHfOyCrv/Hc+5brxijKtae5pzDQpA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192117; c=relaxed/simple; bh=OlVhUw7txJo0pkSkxgT09n73spwlvOpZt0ap3mXOw4c=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=NYXKGQ0ONaF+cvPegStQF9PuDbCjLBHdLJcIqtlwpW6boI+QdUzTErfkfFd3d/qOJ/bsgOIBL8/Y5vf/awcYHXaDc5ruuhji3ELisp2fRb0PHvJlEpi+1VK+y2Z+1PceaNWXQGLPD89otPS6npyh2+iC6+V0d8MpEn9x8GVix+Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=lPzY3Xmv; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="lPzY3Xmv" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E8EA0C4CEC3; Thu, 17 Oct 2024 19:08:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729192117; bh=OlVhUw7txJo0pkSkxgT09n73spwlvOpZt0ap3mXOw4c=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=lPzY3XmvmOzRCbKyTbm8c9pU474odz9g6qPY0RSNs+tnCTFqxfEesSBiMetTBkP+1 fY69KbcUpbRH6l7zhM/VjKUhiVJW7JGKwD8sElR2yrabF4SoDYNfZpXTt+p4BtQMUO pYRXro1XLoMxbdk+iAiNVfK8zX8D4aGc7ii9zm3xgJxULn5xe2DtAOZfqqxy6JnPMB 66g0zITFrHZwDy05RRM9pIVAw3W6a99lG6aSFpBAQmO+kbb1kviwhRCWuwM8ZMXFEl jgx+PJK6Fuive+rzB5jPxjXL1yxbU0jEQIyGSx5WfNnMVrh9kW7mbCmroFp2mOYxe+ kKVKZqk5VZsdg== Date: Thu, 17 Oct 2024 12:08:36 -0700 Subject: [PATCH 27/34] xfs: create helpers to deal with rounding xfs_fileoff_t to rtx boundaries From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919072135.3453179.7112771506339901386.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong We're about to segment xfs_rtblock_t addresses, so we must create type-specific helpers to do rt extent rounding of file block offsets because the rtb helpers soon will not do the right thing there. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_rtbitmap.h | 17 +++++++++++++---- fs/xfs/xfs_bmap_util.c | 6 +++--- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/fs/xfs/libxfs/xfs_rtbitmap.h b/fs/xfs/libxfs/xfs_rtbitmap.h index 7be76490a31879..dc2b8beadfc331 100644 --- a/fs/xfs/libxfs/xfs_rtbitmap.h +++ b/fs/xfs/libxfs/xfs_rtbitmap.h @@ -135,13 +135,22 @@ xfs_rtb_roundup_rtx( return roundup_64(rtbno, mp->m_sb.sb_rextsize); } -/* Round this rtblock down to the nearest rt extent size. */ +/* Round this file block offset up to the nearest rt extent size. */ static inline xfs_rtblock_t -xfs_rtb_rounddown_rtx( +xfs_fileoff_roundup_rtx( struct xfs_mount *mp, - xfs_rtblock_t rtbno) + xfs_fileoff_t off) { - return rounddown_64(rtbno, mp->m_sb.sb_rextsize); + return roundup_64(off, mp->m_sb.sb_rextsize); +} + +/* Round this file block offset down to the nearest rt extent size. */ +static inline xfs_rtblock_t +xfs_fileoff_rounddown_rtx( + struct xfs_mount *mp, + xfs_fileoff_t off) +{ + return rounddown_64(off, mp->m_sb.sb_rextsize); } /* Convert an rt extent number to a file block offset in the rt bitmap file. */ diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index aa745cc5922246..dff27c69fccb6f 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -537,7 +537,7 @@ xfs_can_free_eofblocks( */ end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_ISIZE(ip)); if (xfs_inode_has_bigrtalloc(ip)) - end_fsb = xfs_rtb_roundup_rtx(mp, end_fsb); + end_fsb = xfs_fileoff_roundup_rtx(mp, end_fsb); last_fsb = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes); if (last_fsb <= end_fsb) return false; @@ -859,8 +859,8 @@ xfs_free_file_space( /* We can only free complete realtime extents. */ if (xfs_inode_has_bigrtalloc(ip)) { - startoffset_fsb = xfs_rtb_roundup_rtx(mp, startoffset_fsb); - endoffset_fsb = xfs_rtb_rounddown_rtx(mp, endoffset_fsb); + startoffset_fsb = xfs_fileoff_roundup_rtx(mp, startoffset_fsb); + endoffset_fsb = xfs_fileoff_rounddown_rtx(mp, endoffset_fsb); } /* From patchwork Thu Oct 17 19:08:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840734 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 091D921D2A3 for ; Thu, 17 Oct 2024 19:08:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192128; cv=none; b=CWz5KG4pXTtnuaJCJB0x41JYM8B9w9outHz3JTvRGSLqLQdjEGX2Sm0HT5OmtbuqMJTm/L6EPdGCviIKtf4VPn+tMONFRlZQTmxs9OPXChVJ91uQd5Vk3O4SNSh8XJP447FOvmlA4zk0Hf/78v+q56JX0GVDBQgBWHmFoloXqCk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192128; c=relaxed/simple; bh=EKQihhf7Eh6eAQJ+TjMakbfZK8gX7J/ZvmXPmhrZ7+0=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=exD2YJMWKQAlgD/z8LRAtBFMvEqHLbQVQrosl0g8QZBCvEcGxf1xXafy3O1R7tkWAxXlJR/F3iZ5qK2khnGYf3PzIgd9T2DhSXFz/EUqj27F79omxo/CywQCgaQBj8JCrjlVaE8yd+b4PNizNJYIk2xM/p8oBCHKY7+leBUYONA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=f4hMRiCO; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="f4hMRiCO" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8752EC4CEC3; Thu, 17 Oct 2024 19:08:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729192127; bh=EKQihhf7Eh6eAQJ+TjMakbfZK8gX7J/ZvmXPmhrZ7+0=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=f4hMRiCOZe+skcT/W0To7FuI18NN3vCPeCoEpNZs07BXI5jHS8OIGcq5MkjRph/ah ZDD5ZIPqdsOIlaIwHQOELaQi/Bm9LNnd+FzpZnHQG623gq+A3jazrhqtnqrNlTxHAY Y6xDyPYSoVkrx2HATZBbGGL3EOwf/Y+fGomp47yWz47Ablpwj9POnfL8un4yFHBrBn 7jCZc0j4TseBWfebOB3aaIQBULTusnNU0bs4C1iueZkaOGykpfPiOH7/w84GYAjzF0 b6TZ9MAZhJy1bHqhKeCH2BmNlPUnxCDi3DWYxn/yG75SODzNS4FWl/6fJy2Eb3Nx6E hon7Umk+vMDtw== Date: Thu, 17 Oct 2024 12:08:47 -0700 Subject: [PATCH 28/34] xfs: create helpers to deal with rounding xfs_filblks_t to rtx boundaries From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919072152.3453179.3056710287992098812.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong We're about to segment xfs_rtblock_t addresses, so we must create type-specific helpers to do rt extent rounding of file mapping block lengths because the rtb helpers soon will not do the right thing there. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_rtbitmap.c | 2 +- fs/xfs/libxfs/xfs_rtbitmap.h | 30 +++++++++++++++++++++--------- fs/xfs/xfs_exchrange.c | 2 +- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/fs/xfs/libxfs/xfs_rtbitmap.c b/fs/xfs/libxfs/xfs_rtbitmap.c index 5abfd84852ce3b..30220bf8c3f430 100644 --- a/fs/xfs/libxfs/xfs_rtbitmap.c +++ b/fs/xfs/libxfs/xfs_rtbitmap.c @@ -1123,7 +1123,7 @@ xfs_rtfree_blocks( ASSERT(rtlen <= XFS_MAX_BMBT_EXTLEN); - mod = xfs_rtb_to_rtxoff(mp, rtlen); + mod = xfs_blen_to_rtxoff(mp, rtlen); if (mod) { ASSERT(mod == 0); return -EIO; diff --git a/fs/xfs/libxfs/xfs_rtbitmap.h b/fs/xfs/libxfs/xfs_rtbitmap.h index dc2b8beadfc331..e0fb36f181cc9e 100644 --- a/fs/xfs/libxfs/xfs_rtbitmap.h +++ b/fs/xfs/libxfs/xfs_rtbitmap.h @@ -101,6 +101,27 @@ xfs_blen_to_rtbxlen( return div_u64(blen, mp->m_sb.sb_rextsize); } +/* Return the offset of a file block length within an rt extent. */ +static inline xfs_extlen_t +xfs_blen_to_rtxoff( + struct xfs_mount *mp, + xfs_filblks_t blen) +{ + if (likely(mp->m_rtxblklog >= 0)) + return blen & mp->m_rtxblkmask; + + return do_div(blen, mp->m_sb.sb_rextsize); +} + +/* Round this block count up to the nearest rt extent size. */ +static inline xfs_filblks_t +xfs_blen_roundup_rtx( + struct xfs_mount *mp, + xfs_filblks_t blen) +{ + return roundup_64(blen, mp->m_sb.sb_rextsize); +} + /* Convert an rt block number into an rt extent number. */ static inline xfs_rtxnum_t xfs_rtb_to_rtx( @@ -126,15 +147,6 @@ xfs_rtb_to_rtxoff( return do_div(rtbno, mp->m_sb.sb_rextsize); } -/* Round this rtblock up to the nearest rt extent size. */ -static inline xfs_rtblock_t -xfs_rtb_roundup_rtx( - struct xfs_mount *mp, - xfs_rtblock_t rtbno) -{ - return roundup_64(rtbno, mp->m_sb.sb_rextsize); -} - /* Round this file block offset up to the nearest rt extent size. */ static inline xfs_rtblock_t xfs_fileoff_roundup_rtx( diff --git a/fs/xfs/xfs_exchrange.c b/fs/xfs/xfs_exchrange.c index 75cb53f090d1f7..f644c4cc77fac1 100644 --- a/fs/xfs/xfs_exchrange.c +++ b/fs/xfs/xfs_exchrange.c @@ -217,7 +217,7 @@ xfs_exchrange_mappings( * length in @fxr are safe to round up. */ if (xfs_inode_has_bigrtalloc(ip2)) - req.blockcount = xfs_rtb_roundup_rtx(mp, req.blockcount); + req.blockcount = xfs_blen_roundup_rtx(mp, req.blockcount); error = xfs_exchrange_estimate(&req); if (error) From patchwork Thu Oct 17 19:08:57 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840735 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 A39D92204CB for ; Thu, 17 Oct 2024 19:08:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192138; cv=none; b=IWjAiES2KdlsAvYzlGLP3zbymyToTPBiNDlwMhQ+rEDL1hCL/QW+l/fsn2hwKWlAyqvFpF4RRpLfYw4z6xVJrVkel9xYRLLK9BptF0447Ulr2ZmYG5nDu1ltdcTUSvITWZEwQhU5yONLp3MlE4CdqpAHpOAcvHKz0rT9X/NXo5s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192138; c=relaxed/simple; bh=i44pbRq9rGUCHtcZWa18Z9F7LHAZm/koPgD9OYlyqe8=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=EHmISvLd9S+STG7fEoWUXnXh2gcag/N1hKUE2M6loJuj6hhx0qY3gr7DKnbVFWB9Vo4tkvzeFdVikpSUe8XPMF+6510Q4c+gKrouAScVsAvITPTmIZmPUvechNJBr/cTS7Ug7rvrmqDPGBOmiBRFZSAsYqL+AGZpmN65Ne6EJZ8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=X7qGC1mw; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="X7qGC1mw" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1EA7FC4AF09; Thu, 17 Oct 2024 19:08:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729192138; bh=i44pbRq9rGUCHtcZWa18Z9F7LHAZm/koPgD9OYlyqe8=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=X7qGC1mwaWphHvJnYg64qgEwvaT3iBSUP2fWDpsYl/B+TaAZRwV15rTy/RE5oDIMF fyG40oIlQ4NW3+MHrrwbA9DNZOcDb8z/GqOvLdh4AbnxBfKIXRlQyraYOqtjGYFrlP JFCVZ6F6n8NUOfB6UXfiH/UTfnE3wpJLio626WcwIBTicHvOnZ36yxBnJoSd+ulLgC otYO0pfcdMDnx0bArS+gN7ycinU2YRTHlofeMO6lT846SOLtYoKN+UcnK0x0JoSns8 Gha17jRJVSy+bAhA/ralds/jiTVJpEojxBUOiMp6tVOJy3qm5pbrr8L83+GtWYqMdX 2z/Feca1GkTyA== Date: Thu, 17 Oct 2024 12:08:57 -0700 Subject: [PATCH 29/34] xfs: make xfs_rtblock_t a segmented address like xfs_fsblock_t From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919072169.3453179.4216171622252724671.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Now that we've finished adding allocation groups to the realtime volume, let's make the file block mapping address (xfs_rtblock_t) a segmented value just like we do on the data device. This means that group number and block number conversions can be done with shifting and masking instead of integer division. While in theory we could continue caching the rgno shift value in m_rgblklog, the fact that we now always use the shift value means that we have an opportunity to increase the redundancy of the rt geometry by storing it in the ondisk superblock and adding more sb verifier code. Extend the sueprblock to store the rgblklog value. Now that we have segmented addresses, set the correct values in m_groups[XG_TYPE_RTG] so that the xfs_group helpers work correctly. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_bmap.c | 4 +- fs/xfs/libxfs/xfs_format.h | 6 ++++ fs/xfs/libxfs/xfs_ondisk.h | 2 + fs/xfs/libxfs/xfs_rtbitmap.h | 13 ++++---- fs/xfs/libxfs/xfs_rtgroup.h | 69 +++++++++++++----------------------------- fs/xfs/libxfs/xfs_sb.c | 65 +++++++++++++++++++++++++++++++++++----- fs/xfs/libxfs/xfs_sb.h | 4 ++ fs/xfs/libxfs/xfs_types.c | 7 ++-- fs/xfs/scrub/agheader.c | 11 +++++-- fs/xfs/xfs_mount.h | 4 +- fs/xfs/xfs_rtalloc.c | 4 +- fs/xfs/xfs_trans.c | 21 ++++++++++--- 12 files changed, 126 insertions(+), 84 deletions(-) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 3498d7b4fbc54e..9052839305e2ca 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -3152,10 +3152,8 @@ xfs_bmap_adjacent_valid( if (XFS_IS_REALTIME_INODE(ap->ip) && (ap->datatype & XFS_ALLOC_USERDATA)) { - if (x >= mp->m_sb.sb_rblocks) - return false; if (!xfs_has_rtgroups(mp)) - return true; + return x < mp->m_sb.sb_rblocks; return xfs_rtb_to_rgno(mp, x) == xfs_rtb_to_rgno(mp, y) && xfs_rtb_to_rgno(mp, x) < mp->m_sb.sb_rgcount && diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index f56ff9f43c218f..d6c10855ab023b 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -179,6 +179,9 @@ typedef struct xfs_sb { xfs_rgnumber_t sb_rgcount; /* number of realtime groups */ xfs_rtxlen_t sb_rgextents; /* size of a realtime group in rtx */ + uint8_t sb_rgblklog; /* rt group number shift */ + uint8_t sb_pad[7]; /* zeroes */ + /* must be padded to 64 bit alignment */ } xfs_sb_t; @@ -268,6 +271,9 @@ struct xfs_dsb { __be32 sb_rgcount; /* # of realtime groups */ __be32 sb_rgextents; /* size of rtgroup in rtx */ + __u8 sb_rgblklog; /* rt group number shift */ + __u8 sb_pad[7]; /* zeroes */ + /* * The size of this structure must be padded to 64 bit alignment. * diff --git a/fs/xfs/libxfs/xfs_ondisk.h b/fs/xfs/libxfs/xfs_ondisk.h index 6a2bcbc392842c..99eae7f67e961b 100644 --- a/fs/xfs/libxfs/xfs_ondisk.h +++ b/fs/xfs/libxfs/xfs_ondisk.h @@ -37,7 +37,7 @@ xfs_check_ondisk_structs(void) XFS_CHECK_STRUCT_SIZE(struct xfs_dinode, 176); XFS_CHECK_STRUCT_SIZE(struct xfs_disk_dquot, 104); XFS_CHECK_STRUCT_SIZE(struct xfs_dqblk, 136); - XFS_CHECK_STRUCT_SIZE(struct xfs_dsb, 280); + XFS_CHECK_STRUCT_SIZE(struct xfs_dsb, 288); XFS_CHECK_STRUCT_SIZE(struct xfs_dsymlink_hdr, 56); XFS_CHECK_STRUCT_SIZE(struct xfs_inobt_key, 4); XFS_CHECK_STRUCT_SIZE(struct xfs_inobt_rec, 16); diff --git a/fs/xfs/libxfs/xfs_rtbitmap.h b/fs/xfs/libxfs/xfs_rtbitmap.h index e0fb36f181cc9e..16563a44bd138a 100644 --- a/fs/xfs/libxfs/xfs_rtbitmap.h +++ b/fs/xfs/libxfs/xfs_rtbitmap.h @@ -26,7 +26,7 @@ xfs_rtx_to_rtb( xfs_rtxnum_t rtx) { struct xfs_mount *mp = rtg_mount(rtg); - xfs_rtblock_t start = xfs_rgno_start_rtb(mp, rtg_rgno(rtg)); + xfs_rtblock_t start = xfs_group_start_fsb(rtg_group(rtg)); if (mp->m_rtxblklog >= 0) return start + (rtx << mp->m_rtxblklog); @@ -128,11 +128,11 @@ xfs_rtb_to_rtx( struct xfs_mount *mp, xfs_rtblock_t rtbno) { - uint64_t __rgbno = __xfs_rtb_to_rgbno(mp, rtbno); - + /* open-coded 64-bit masking operation */ + rtbno &= mp->m_groups[XG_TYPE_RTG].blkmask; if (likely(mp->m_rtxblklog >= 0)) - return __rgbno >> mp->m_rtxblklog; - return div_u64(__rgbno, mp->m_sb.sb_rextsize); + return rtbno >> mp->m_rtxblklog; + return div_u64(rtbno, mp->m_sb.sb_rextsize); } /* Return the offset of an rt block number within an rt extent. */ @@ -141,9 +141,10 @@ xfs_rtb_to_rtxoff( struct xfs_mount *mp, xfs_rtblock_t rtbno) { + /* open-coded 64-bit masking operation */ + rtbno &= mp->m_groups[XG_TYPE_RTG].blkmask; if (likely(mp->m_rtxblklog >= 0)) return rtbno & mp->m_rtxblkmask; - return do_div(rtbno, mp->m_sb.sb_rextsize); } diff --git a/fs/xfs/libxfs/xfs_rtgroup.h b/fs/xfs/libxfs/xfs_rtgroup.h index 2ddfac9a0182f9..c15b232e1f8e77 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.h +++ b/fs/xfs/libxfs/xfs_rtgroup.h @@ -122,31 +122,12 @@ xfs_rtgroup_next( return xfs_rtgroup_next_range(mp, rtg, 0, mp->m_sb.sb_rgcount - 1); } -static inline xfs_rtblock_t -xfs_rgno_start_rtb( - struct xfs_mount *mp, - xfs_rgnumber_t rgno) -{ - if (mp->m_rgblklog >= 0) - return ((xfs_rtblock_t)rgno << mp->m_rgblklog); - return ((xfs_rtblock_t)rgno * mp->m_rgblocks); -} - -static inline xfs_rtblock_t -__xfs_rgbno_to_rtb( - struct xfs_mount *mp, - xfs_rgnumber_t rgno, - xfs_rgblock_t rgbno) -{ - return xfs_rgno_start_rtb(mp, rgno) + rgbno; -} - static inline xfs_rtblock_t xfs_rgbno_to_rtb( struct xfs_rtgroup *rtg, xfs_rgblock_t rgbno) { - return __xfs_rgbno_to_rtb(rtg_mount(rtg), rtg_rgno(rtg), rgbno); + return xfs_gbno_to_fsb(rtg_group(rtg), rgbno); } static inline xfs_rgnumber_t @@ -154,30 +135,7 @@ xfs_rtb_to_rgno( struct xfs_mount *mp, xfs_rtblock_t rtbno) { - if (!xfs_has_rtgroups(mp)) - return 0; - - if (mp->m_rgblklog >= 0) - return rtbno >> mp->m_rgblklog; - - return div_u64(rtbno, mp->m_rgblocks); -} - -static inline uint64_t -__xfs_rtb_to_rgbno( - struct xfs_mount *mp, - xfs_rtblock_t rtbno) -{ - uint32_t rem; - - if (!xfs_has_rtgroups(mp)) - return rtbno; - - if (mp->m_rgblklog >= 0) - return rtbno & mp->m_rgblkmask; - - div_u64_rem(rtbno, mp->m_rgblocks, &rem); - return rem; + return xfs_fsb_to_gno(mp, rtbno, XG_TYPE_RTG); } static inline xfs_rgblock_t @@ -185,7 +143,7 @@ xfs_rtb_to_rgbno( struct xfs_mount *mp, xfs_rtblock_t rtbno) { - return __xfs_rtb_to_rgbno(mp, rtbno); + return xfs_fsb_to_gbno(mp, rtbno, XG_TYPE_RTG); } /* Is rtbno the start of a RT group? */ @@ -194,7 +152,7 @@ xfs_rtbno_is_group_start( struct xfs_mount *mp, xfs_rtblock_t rtbno) { - return (rtbno & mp->m_rgblkmask) == 0; + return (rtbno & mp->m_groups[XG_TYPE_RTG].blkmask) == 0; } static inline xfs_daddr_t @@ -202,7 +160,11 @@ xfs_rtb_to_daddr( struct xfs_mount *mp, xfs_rtblock_t rtbno) { - return rtbno << mp->m_blkbb_log; + struct xfs_groups *g = &mp->m_groups[XG_TYPE_RTG]; + xfs_rgnumber_t rgno = xfs_rtb_to_rgno(mp, rtbno); + uint64_t start_bno = (xfs_rtblock_t)rgno * g->blocks; + + return XFS_FSB_TO_BB(mp, start_bno + (rtbno & g->blkmask)); } static inline xfs_rtblock_t @@ -210,7 +172,18 @@ xfs_daddr_to_rtb( struct xfs_mount *mp, xfs_daddr_t daddr) { - return daddr >> mp->m_blkbb_log; + xfs_rfsblock_t bno = XFS_BB_TO_FSBT(mp, daddr); + + if (xfs_has_rtgroups(mp)) { + struct xfs_groups *g = &mp->m_groups[XG_TYPE_RTG]; + xfs_rgnumber_t rgno; + uint32_t rgbno; + + rgno = div_u64_rem(bno, g->blocks, &rgbno); + return ((xfs_rtblock_t)rgno << g->blklog) + rgbno; + } + + return bno; } #ifdef CONFIG_XFS_RT diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index 1af7029753ea15..6a31f48a2c5424 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -368,12 +368,23 @@ xfs_validate_sb_write( return 0; } +int +xfs_compute_rgblklog( + xfs_rtxlen_t rgextents, + xfs_rgblock_t rextsize) +{ + uint64_t rgblocks = (uint64_t)rgextents * rextsize; + + return xfs_highbit64(rgblocks - 1) + 1; +} + static int xfs_validate_sb_rtgroups( struct xfs_mount *mp, struct xfs_sb *sbp) { uint64_t groups; + int rgblklog; if (sbp->sb_rextsize == 0) { xfs_warn(mp, @@ -418,6 +429,14 @@ xfs_validate_sb_rtgroups( return -EINVAL; } + rgblklog = xfs_compute_rgblklog(sbp->sb_rgextents, sbp->sb_rextsize); + if (sbp->sb_rgblklog != rgblklog) { + xfs_warn(mp, +"Realtime group log (%d) does not match expected value (%d).", + sbp->sb_rgblklog, rgblklog); + return -EINVAL; + } + return 0; } @@ -484,6 +503,12 @@ xfs_validate_sb_common( } if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR) { + if (memchr_inv(sbp->sb_pad, 0, sizeof(sbp->sb_pad))) { + xfs_warn(mp, +"Metadir superblock padding fields must be zero."); + return -EINVAL; + } + error = xfs_validate_sb_rtgroups(mp, sbp); if (error) return error; @@ -789,6 +814,8 @@ __xfs_sb_from_disk( if (to->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR) { to->sb_metadirino = be64_to_cpu(from->sb_metadirino); + to->sb_rgblklog = from->sb_rgblklog; + memcpy(to->sb_pad, from->sb_pad, sizeof(to->sb_pad)); to->sb_rgcount = be32_to_cpu(from->sb_rgcount); to->sb_rgextents = be32_to_cpu(from->sb_rgextents); to->sb_rbmino = NULLFSINO; @@ -956,6 +983,8 @@ xfs_sb_to_disk( if (from->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR) { to->sb_metadirino = cpu_to_be64(from->sb_metadirino); + to->sb_rgblklog = from->sb_rgblklog; + memset(to->sb_pad, 0, sizeof(to->sb_pad)); to->sb_rgcount = cpu_to_be32(from->sb_rgcount); to->sb_rgextents = cpu_to_be32(from->sb_rgextents); to->sb_rbmino = cpu_to_be64(0); @@ -1090,8 +1119,9 @@ const struct xfs_buf_ops xfs_sb_quiet_buf_ops = { .verify_write = xfs_sb_write_verify, }; +/* Compute cached rt geometry from the incore sb. */ void -xfs_mount_sb_set_rextsize( +xfs_sb_mount_rextsize( struct xfs_mount *mp, struct xfs_sb *sbp) { @@ -1100,13 +1130,32 @@ xfs_mount_sb_set_rextsize( mp->m_rtxblklog = log2_if_power2(sbp->sb_rextsize); mp->m_rtxblkmask = mask64_if_power2(sbp->sb_rextsize); - mp->m_rgblocks = sbp->sb_rgextents * sbp->sb_rextsize; - mp->m_rgblklog = log2_if_power2(mp->m_rgblocks); - mp->m_rgblkmask = mask64_if_power2(mp->m_rgblocks); + if (xfs_sb_is_v5(sbp) && + (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR)) { + rgs->blocks = sbp->sb_rgextents * sbp->sb_rextsize; + rgs->blklog = mp->m_sb.sb_rgblklog; + rgs->blkmask = xfs_mask32lo(mp->m_sb.sb_rgblklog); + } else { + rgs->blocks = 0; + rgs->blklog = 0; + rgs->blkmask = (uint64_t)-1; + } +} - rgs->blocks = 0; - rgs->blklog = 0; - rgs->blkmask = (uint64_t)-1; +/* Update incore sb rt extent size, then recompute the cached rt geometry. */ +void +xfs_mount_sb_set_rextsize( + struct xfs_mount *mp, + struct xfs_sb *sbp, + xfs_agblock_t rextsize) +{ + sbp->sb_rextsize = rextsize; + if (xfs_sb_is_v5(sbp) && + (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR)) + sbp->sb_rgblklog = xfs_compute_rgblklog(sbp->sb_rgextents, + rextsize); + + xfs_sb_mount_rextsize(mp, sbp); } /* @@ -1140,7 +1189,7 @@ xfs_sb_mount_common( ags->blklog = mp->m_sb.sb_agblklog; ags->blkmask = xfs_mask32lo(mp->m_sb.sb_agblklog); - xfs_mount_sb_set_rextsize(mp, sbp); + xfs_sb_mount_rextsize(mp, sbp); mp->m_alloc_mxr[0] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, true); mp->m_alloc_mxr[1] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, false); diff --git a/fs/xfs/libxfs/xfs_sb.h b/fs/xfs/libxfs/xfs_sb.h index 999dcfccdaf960..34d0dd374e9b0b 100644 --- a/fs/xfs/libxfs/xfs_sb.h +++ b/fs/xfs/libxfs/xfs_sb.h @@ -17,8 +17,9 @@ extern void xfs_log_sb(struct xfs_trans *tp); extern int xfs_sync_sb(struct xfs_mount *mp, bool wait); extern int xfs_sync_sb_buf(struct xfs_mount *mp, bool update_rtsb); extern void xfs_sb_mount_common(struct xfs_mount *mp, struct xfs_sb *sbp); +void xfs_sb_mount_rextsize(struct xfs_mount *mp, struct xfs_sb *sbp); void xfs_mount_sb_set_rextsize(struct xfs_mount *mp, - struct xfs_sb *sbp); + struct xfs_sb *sbp, xfs_agblock_t rextsize); extern void xfs_sb_from_disk(struct xfs_sb *to, struct xfs_dsb *from); extern void xfs_sb_to_disk(struct xfs_dsb *to, struct xfs_sb *from); extern void xfs_sb_quota_from_disk(struct xfs_sb *sbp); @@ -43,5 +44,6 @@ bool xfs_validate_stripe_geometry(struct xfs_mount *mp, bool xfs_validate_rt_geometry(struct xfs_sb *sbp); uint8_t xfs_compute_rextslog(xfs_rtbxlen_t rtextents); +int xfs_compute_rgblklog(xfs_rtxlen_t rgextents, xfs_rgblock_t rextsize); #endif /* __XFS_SB_H__ */ diff --git a/fs/xfs/libxfs/xfs_types.c b/fs/xfs/libxfs/xfs_types.c index a4c30844d42be1..1faf04204c5ddc 100644 --- a/fs/xfs/libxfs/xfs_types.c +++ b/fs/xfs/libxfs/xfs_types.c @@ -146,9 +146,6 @@ xfs_verify_rtbno( struct xfs_mount *mp, xfs_rtblock_t rtbno) { - if (rtbno >= mp->m_sb.sb_rblocks) - return false; - if (xfs_has_rtgroups(mp)) { xfs_rgnumber_t rgno = xfs_rtb_to_rgno(mp, rtbno); xfs_rtxnum_t rtx = xfs_rtb_to_rtx(mp, rtbno); @@ -159,8 +156,10 @@ xfs_verify_rtbno( return false; if (xfs_has_rtsb(mp) && rgno == 0 && rtx == 0) return false; + return true; } - return true; + + return rtbno < mp->m_sb.sb_rblocks; } /* diff --git a/fs/xfs/scrub/agheader.c b/fs/xfs/scrub/agheader.c index cad997f38a424c..05f5e94b99382b 100644 --- a/fs/xfs/scrub/agheader.c +++ b/fs/xfs/scrub/agheader.c @@ -279,8 +279,15 @@ xchk_superblock( if (!!(sb->sb_features2 & cpu_to_be32(~v2_ok))) xchk_block_set_corrupt(sc, bp); - if (sb->sb_features2 != sb->sb_bad_features2) - xchk_block_set_preen(sc, bp); + if (xfs_has_metadir(mp)) { + if (sb->sb_rgblklog != mp->m_sb.sb_rgblklog) + xchk_block_set_corrupt(sc, bp); + if (memchr_inv(sb->sb_pad, 0, sizeof(sb->sb_pad))) + xchk_block_set_preen(sc, bp); + } else { + if (sb->sb_features2 != sb->sb_bad_features2) + xchk_block_set_preen(sc, bp); + } } /* Check sb_features2 flags that are set at mkfs time. */ diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 7b6902c21d50c9..ba3dc583b68687 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -147,7 +147,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 */ /* number of rt extents per rt bitmap block if rtgroups enabled */ @@ -177,14 +177,12 @@ typedef struct xfs_mount { int m_logbsize; /* size of each log buffer */ unsigned int m_rsumlevels; /* rt summary levels */ xfs_filblks_t m_rsumblocks; /* size of rt summary, FSBs */ - uint32_t m_rgblocks; /* size of rtgroup in rtblocks */ int m_fixedfsid[2]; /* unchanged for life of FS */ uint m_qflags; /* quota status flags */ uint64_t m_features; /* active filesystem features */ 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 */ diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 783674fd42ead1..db09c086ff1c01 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -745,8 +745,7 @@ xfs_growfs_rt_alloc_fake_mount( nmp = kmemdup(mp, sizeof(*mp), GFP_KERNEL); if (!nmp) return NULL; - nmp->m_sb.sb_rextsize = rextsize; - xfs_mount_sb_set_rextsize(nmp, &nmp->m_sb); + xfs_mount_sb_set_rextsize(nmp, &nmp->m_sb, rextsize); nmp->m_sb.sb_rblocks = rblocks; nmp->m_sb.sb_rextents = xfs_blen_to_rtbxlen(nmp, nmp->m_sb.sb_rblocks); nmp->m_sb.sb_rbmblocks = xfs_rtbitmap_blockcount(nmp); @@ -968,7 +967,6 @@ xfs_growfs_rt_bmblock( */ mp->m_rsumlevels = nmp->m_rsumlevels; mp->m_rsumblocks = nmp->m_rsumblocks; - xfs_mount_sb_set_rextsize(mp, &mp->m_sb); /* * Recompute the growfsrt reservation from the new rsumsize. diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index a29a181e684041..4db022c189e134 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -26,6 +26,7 @@ #include "xfs_icache.h" #include "xfs_rtbitmap.h" #include "xfs_rtgroup.h" +#include "xfs_sb.h" struct kmem_cache *xfs_trans_cache; @@ -547,6 +548,18 @@ xfs_trans_apply_sb_deltas( } if (tp->t_rextsize_delta) { be32_add_cpu(&sbp->sb_rextsize, tp->t_rextsize_delta); + + /* + * Because the ondisk sb records rtgroup size in units of rt + * extents, any time we update the rt extent size we have to + * recompute the ondisk rtgroup block log. The incore values + * will be recomputed in xfs_trans_unreserve_and_mod_sb. + */ + if (xfs_has_rtgroups(tp->t_mountp)) { + sbp->sb_rgblklog = xfs_compute_rgblklog( + be32_to_cpu(sbp->sb_rgextents), + be32_to_cpu(sbp->sb_rextsize)); + } whole = 1; } if (tp->t_rbmblocks_delta) { @@ -673,11 +686,9 @@ xfs_trans_unreserve_and_mod_sb( 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; - mp->m_sb.sb_rextsize += tp->t_rextsize_delta; - if (tp->t_rextsize_delta) { - mp->m_rtxblklog = log2_if_power2(mp->m_sb.sb_rextsize); - mp->m_rtxblkmask = mask64_if_power2(mp->m_sb.sb_rextsize); - } + if (tp->t_rextsize_delta) + xfs_mount_sb_set_rextsize(mp, &mp->m_sb, + mp->m_sb.sb_rextsize + tp->t_rextsize_delta); mp->m_sb.sb_rbmblocks += tp->t_rbmblocks_delta; mp->m_sb.sb_rblocks += tp->t_rblocks_delta; mp->m_sb.sb_rextents += tp->t_rextents_delta; From patchwork Thu Oct 17 19:09:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840736 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 DE64321BB06 for ; Thu, 17 Oct 2024 19:09:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192148; cv=none; b=l54X4eUgaandZRYi45cbWCPD+KS8Sj2hvYHTGiV9vvDApX0Bm3PWlh63SK83exxTLkvpDJljJ8T92z/ooGK9hfRwAWoxybUfXfxKfOL+ERi2dVFlrObCXXSwCIc7/U1/jbqZdF/Nuxdn6H16JA9tqr7Rg6iq4EZS/wn9GXmqhTs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192148; c=relaxed/simple; bh=d60rH7fFcqiNEhYSd45F21wjGrMUU5O7FOMl5KZu7JI=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=oxD3FpGspmjo7nqU4C6paH6GNgUb83j4LdN3pgrwl0KNiOpc05dXQSOt6cBAPpgCiOvCivOKWJS5Lu9bdnm95pl5CO3BD9GKmNVjFHNzaYY95Cv0UsOG4TurGyEQ67X0rwfv7Bxlql/GAycsp3DV7eDFb54M6eB9wnrBPQ922OQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hr2l89mo; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hr2l89mo" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B6CD7C4CEC3; Thu, 17 Oct 2024 19:09:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729192148; bh=d60rH7fFcqiNEhYSd45F21wjGrMUU5O7FOMl5KZu7JI=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=hr2l89mo6QIr+UW/T4cMJWgGW5LKrSkU67a/oAZ7KPsy69+hIAKxurvmYMH1Af2GP gsaX4FQ5T6gcNv9n5OHaF1hfHAMLqZEdokdCKAoRwk2M0NrbJSmYP0lAKqHpC3doom jl/4bHNrQ+nIB2dVNHfJ8/XVSJhvE3izL8r4Z+fWRTmfjhJW2fd7ZFsQqB0LzO1Dni yajlbYAsPg0C2LuE7bOWyb/dnP5dX23svqZj6x9CgI+iZZ9eCW2vRSM5g8o8qVwyTN GUDm7hZ9/5HR6JlXw/BcdVCOQ3fc+OIE77gVJk6fQS5HjJAiHLUkmHgG0+4BBq+EPr qIOWZbxkuflqw== Date: Thu, 17 Oct 2024 12:09:08 -0700 Subject: [PATCH 30/34] xfs: adjust min_block usage in xfs_verify_agbno From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919072188.3453179.15405009921166966765.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong There's some weird logic in xfs_verify_agbno -- min_block ought to be the first agblock number in the AG that can be used by non-static metadata. However, we initialize it to the last agblock of the static metadata, which works due to the <= check, even though this isn't technically correct. Change the check to < and set min_block to the next agblock past the static metadata. This hasn't been an issue up to now, but we're going to move these things into the generic group struct, and this will cause problems with rtgroups, where min_block can be zero for an rtgroup that doesn't have a rt superblock. Note that there's no user-visible impact with the old logic, so this isn't a bug fix. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_ag.c | 2 +- fs/xfs/libxfs/xfs_ag.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/xfs/libxfs/xfs_ag.c b/fs/xfs/libxfs/xfs_ag.c index 47e90dbb852bba..8fe96a9e047205 100644 --- a/fs/xfs/libxfs/xfs_ag.c +++ b/fs/xfs/libxfs/xfs_ag.c @@ -242,7 +242,7 @@ xfs_perag_alloc( * Pre-calculated geometry */ pag->block_count = __xfs_ag_block_count(mp, index, agcount, dblocks); - pag->min_block = XFS_AGFL_BLOCK(mp); + pag->min_block = XFS_AGFL_BLOCK(mp) + 1; __xfs_agino_range(mp, pag->block_count, &pag->agino_min, &pag->agino_max); diff --git a/fs/xfs/libxfs/xfs_ag.h b/fs/xfs/libxfs/xfs_ag.h index 7290148fa6e6aa..9c22a76d58cfc2 100644 --- a/fs/xfs/libxfs/xfs_ag.h +++ b/fs/xfs/libxfs/xfs_ag.h @@ -222,7 +222,7 @@ xfs_verify_agbno(struct xfs_perag *pag, xfs_agblock_t agbno) { if (agbno >= pag->block_count) return false; - if (agbno <= pag->min_block) + if (agbno < pag->min_block) return false; return true; } From patchwork Thu Oct 17 19:09:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840737 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 B1F8F21C17C for ; Thu, 17 Oct 2024 19:09:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192160; cv=none; b=jMbSsrqP4vAVwJbfWIu9wJvwPA46aEEE2VX/kRj5vhMYBzto5ADXjEm1haQp7tbpaOMclgdRgEncUrSEAz+te0kCm2T9EO93N4emC+a6oVrQ5kUUHNf1NL474NvzXOAA1FB/9yohou02BygnDmxZx6sl9FwkV/qPTVAc/FtZRBg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192160; c=relaxed/simple; bh=gkfLEDcsMLznxQHBfP+gSm65EHYTQKGT982+hNWASGQ=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=YrJAuq8Kj5js5Xc1X8ATNiSIa5B+9KQ0ByMoTg7E7RR5ZteTPcN/8AbPpfoGTlo06PvKEFgfTUfsIiP9nJPHaX56MkAYraBXt/Ly+QJQD7OIgWCSlJd9qC65Zpj/sXMvNQRQ6fiKxLLYdq6fswSJiS4pLKujaFLgRhs7XHknRvo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=sav2Mc8E; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="sav2Mc8E" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 51516C4CEC3; Thu, 17 Oct 2024 19:09:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729192159; bh=gkfLEDcsMLznxQHBfP+gSm65EHYTQKGT982+hNWASGQ=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=sav2Mc8EXccTd4CjB9woZ29D3kvDq3htvWeuYsLVCKXTEv3ALBR96mRMpzfNOQa3w 583aBURQ6cMujX7whCzaymPKhp/Hr680+lDUjYRyO3cL72+w9n3w34XIlvwKlvx7Hb Z0nlIiflt3nZKBNsw7gT4pXZpiXjj1OzYuGFumN9xW7YsQgmm0/LHQEl/7eB+XeJ3h hgtJbLougKs7WvWQuTlks6n0UwgkyDxOU07fRxH9Oi1F5/z6LldSAqQOPzqP3+/r/i LHjMLsEgD+cfVTO9iJ0RFQLb9PVYybJ6PYe6n0lP+yV1M2qUQ1Yb34hWFN06YQ8B96 BXh6MPsC4tgQQ== Date: Thu, 17 Oct 2024 12:09:18 -0700 Subject: [PATCH 31/34] xfs: move the min and max group block numbers to xfs_group From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919072205.3453179.8570166922721978112.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Move the min and max agblock numbers to the generic xfs_group structure so that we can start building validators for extents within an rtgroup. While we're at it, use check_add_overflow for the extent length computation because that has much better overflow checking. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_ag.c | 22 ++++++++++++---------- fs/xfs/libxfs/xfs_ag.h | 16 ++-------------- fs/xfs/libxfs/xfs_group.h | 33 +++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_ialloc_btree.c | 2 +- fs/xfs/libxfs/xfs_rtgroup.c | 31 ++++++++++++++++++++++++++++++- fs/xfs/libxfs/xfs_rtgroup.h | 3 +++ fs/xfs/scrub/agheader.c | 4 ++-- fs/xfs/scrub/agheader_repair.c | 4 ++-- fs/xfs/scrub/repair.c | 6 +++--- fs/xfs/xfs_discard.c | 4 ++-- fs/xfs/xfs_rtalloc.c | 8 ++++---- 11 files changed, 94 insertions(+), 39 deletions(-) diff --git a/fs/xfs/libxfs/xfs_ag.c b/fs/xfs/libxfs/xfs_ag.c index 8fe96a9e047205..b59cb461e096ea 100644 --- a/fs/xfs/libxfs/xfs_ag.c +++ b/fs/xfs/libxfs/xfs_ag.c @@ -205,9 +205,10 @@ xfs_update_last_ag_size( if (!pag) return -EFSCORRUPTED; - pag->block_count = __xfs_ag_block_count(mp, prev_agcount - 1, - mp->m_sb.sb_agcount, mp->m_sb.sb_dblocks); - __xfs_agino_range(mp, pag->block_count, &pag->agino_min, + pag_group(pag)->xg_block_count = __xfs_ag_block_count(mp, + prev_agcount - 1, mp->m_sb.sb_agcount, + mp->m_sb.sb_dblocks); + __xfs_agino_range(mp, pag_group(pag)->xg_block_count, &pag->agino_min, &pag->agino_max); xfs_perag_rele(pag); return 0; @@ -241,9 +242,10 @@ xfs_perag_alloc( /* * Pre-calculated geometry */ - pag->block_count = __xfs_ag_block_count(mp, index, agcount, dblocks); - pag->min_block = XFS_AGFL_BLOCK(mp) + 1; - __xfs_agino_range(mp, pag->block_count, &pag->agino_min, + pag_group(pag)->xg_block_count = __xfs_ag_block_count(mp, index, agcount, + dblocks); + pag_group(pag)->xg_min_gbno = XFS_AGFL_BLOCK(mp) + 1; + __xfs_agino_range(mp, pag_group(pag)->xg_block_count, &pag->agino_min, &pag->agino_max); error = xfs_group_insert(mp, pag_group(pag), index, XG_TYPE_AG); @@ -852,8 +854,8 @@ xfs_ag_shrink_space( } /* Update perag geometry */ - pag->block_count -= delta; - __xfs_agino_range(mp, pag->block_count, &pag->agino_min, + pag_group(pag)->xg_block_count -= delta; + __xfs_agino_range(mp, pag_group(pag)->xg_block_count, &pag->agino_min, &pag->agino_max); xfs_ialloc_log_agi(*tpp, agibp, XFS_AGI_LENGTH); @@ -924,8 +926,8 @@ xfs_ag_extend_space( return error; /* Update perag geometry */ - pag->block_count = be32_to_cpu(agf->agf_length); - __xfs_agino_range(mp, pag->block_count, &pag->agino_min, + pag_group(pag)->xg_block_count = be32_to_cpu(agf->agf_length); + __xfs_agino_range(mp, pag_group(pag)->xg_block_count, &pag->agino_min, &pag->agino_max); return 0; } diff --git a/fs/xfs/libxfs/xfs_ag.h b/fs/xfs/libxfs/xfs_ag.h index 9c22a76d58cfc2..1f24cfa2732172 100644 --- a/fs/xfs/libxfs/xfs_ag.h +++ b/fs/xfs/libxfs/xfs_ag.h @@ -61,8 +61,6 @@ struct xfs_perag { struct xfs_ag_resv pag_rmapbt_resv; /* Precalculated geometry info */ - xfs_agblock_t block_count; - xfs_agblock_t min_block; xfs_agino_t agino_min; xfs_agino_t agino_max; @@ -220,11 +218,7 @@ void xfs_agino_range(struct xfs_mount *mp, xfs_agnumber_t agno, static inline bool xfs_verify_agbno(struct xfs_perag *pag, xfs_agblock_t agbno) { - if (agbno >= pag->block_count) - return false; - if (agbno < pag->min_block) - return false; - return true; + return xfs_verify_gbno(pag_group(pag), agbno); } static inline bool @@ -233,13 +227,7 @@ xfs_verify_agbext( xfs_agblock_t agbno, xfs_agblock_t len) { - if (agbno + len <= agbno) - return false; - - if (!xfs_verify_agbno(pag, agbno)) - return false; - - return xfs_verify_agbno(pag, agbno + len - 1); + return xfs_verify_gbext(pag_group(pag), agbno, len); } /* diff --git a/fs/xfs/libxfs/xfs_group.h b/fs/xfs/libxfs/xfs_group.h index 5b7362277c3f7a..242b05627c7a6e 100644 --- a/fs/xfs/libxfs/xfs_group.h +++ b/fs/xfs/libxfs/xfs_group.h @@ -12,6 +12,10 @@ struct xfs_group { atomic_t xg_ref; /* passive reference count */ atomic_t xg_active_ref; /* active reference count */ + /* Precalculated geometry info */ + uint32_t xg_block_count; /* max usable gbno */ + uint32_t xg_min_gbno; /* min usable gbno */ + #ifdef __KERNEL__ /* -- kernel only structures below this line -- */ @@ -128,4 +132,33 @@ xfs_fsb_to_gbno( return fsbno & mp->m_groups[type].blkmask; } +static inline bool +xfs_verify_gbno( + struct xfs_group *xg, + uint32_t gbno) +{ + if (gbno >= xg->xg_block_count) + return false; + if (gbno < xg->xg_min_gbno) + return false; + return true; +} + +static inline bool +xfs_verify_gbext( + struct xfs_group *xg, + uint32_t gbno, + uint32_t glen) +{ + uint32_t end; + + if (!xfs_verify_gbno(xg, gbno)) + return false; + if (glen == 0 || check_add_overflow(gbno, glen - 1, &end)) + return false; + if (!xfs_verify_gbno(xg, end)) + return false; + return true; +} + #endif /* __LIBXFS_GROUP_H */ diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c index 4c28deb3e9881d..9b34896dd1a32f 100644 --- a/fs/xfs/libxfs/xfs_ialloc_btree.c +++ b/fs/xfs/libxfs/xfs_ialloc_btree.c @@ -717,7 +717,7 @@ xfs_inobt_max_size( struct xfs_perag *pag) { struct xfs_mount *mp = pag_mount(pag); - xfs_agblock_t agblocks = pag->block_count; + xfs_agblock_t agblocks = pag_group(pag)->xg_block_count; /* Bail out if we're uninitialized, which can happen in mkfs. */ if (M_IGEO(mp)->inobt_mxr[0] == 0) diff --git a/fs/xfs/libxfs/xfs_rtgroup.c b/fs/xfs/libxfs/xfs_rtgroup.c index 624d8b25eba0ec..e74bb059f24fa1 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.c +++ b/fs/xfs/libxfs/xfs_rtgroup.c @@ -34,6 +34,32 @@ #include "xfs_metafile.h" #include "xfs_metadir.h" +/* Find the first usable fsblock in this rtgroup. */ +static inline uint32_t +xfs_rtgroup_min_block( + struct xfs_mount *mp, + xfs_rgnumber_t rgno) +{ + if (xfs_has_rtsb(mp) && rgno == 0) + return mp->m_sb.sb_rextsize; + + return 0; +} + +/* Precompute this group's geometry */ +void +xfs_rtgroup_calc_geometry( + struct xfs_mount *mp, + struct xfs_rtgroup *rtg, + xfs_rgnumber_t rgno, + xfs_rgnumber_t rgcount, + xfs_rtbxlen_t rextents) +{ + rtg->rtg_extents = __xfs_rtgroup_extents(mp, rgno, rgcount, rextents); + rtg_group(rtg)->xg_block_count = rtg->rtg_extents * mp->m_sb.sb_rextsize; + rtg_group(rtg)->xg_min_gbno = xfs_rtgroup_min_block(mp, rgno); +} + int xfs_rtgroup_alloc( struct xfs_mount *mp, @@ -48,6 +74,8 @@ xfs_rtgroup_alloc( if (!rtg) return -ENOMEM; + xfs_rtgroup_calc_geometry(mp, rtg, rgno, rgcount, rextents); + error = xfs_group_insert(mp, rtg_group(rtg), rgno, XG_TYPE_RTG); if (error) goto out_free_rtg; @@ -149,6 +177,7 @@ xfs_update_last_rtgroup_size( return -EFSCORRUPTED; rtg->rtg_extents = __xfs_rtgroup_extents(mp, prev_rgcount - 1, mp->m_sb.sb_rgcount, mp->m_sb.sb_rextents); + rtg_group(rtg)->xg_block_count = rtg->rtg_extents * mp->m_sb.sb_rextsize; xfs_rtgroup_rele(rtg); return 0; } @@ -223,7 +252,7 @@ xfs_rtgroup_get_geometry( /* Fill out form. */ memset(rgeo, 0, sizeof(*rgeo)); rgeo->rg_number = rtg_rgno(rtg); - rgeo->rg_length = rtg->rtg_extents * rtg_mount(rtg)->m_sb.sb_rextsize; + rgeo->rg_length = rtg_group(rtg)->xg_block_count; 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 c15b232e1f8e77..1e51dc62d1143e 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.h +++ b/fs/xfs/libxfs/xfs_rtgroup.h @@ -199,6 +199,9 @@ int xfs_initialize_rtgroups(struct xfs_mount *mp, xfs_rgnumber_t first_rgno, xfs_rtxnum_t __xfs_rtgroup_extents(struct xfs_mount *mp, xfs_rgnumber_t rgno, xfs_rgnumber_t rgcount, xfs_rtbxlen_t rextents); xfs_rtxnum_t xfs_rtgroup_extents(struct xfs_mount *mp, xfs_rgnumber_t rgno); +void xfs_rtgroup_calc_geometry(struct xfs_mount *mp, struct xfs_rtgroup *rtg, + xfs_rgnumber_t rgno, xfs_rgnumber_t rgcount, + xfs_rtbxlen_t rextents); int xfs_update_last_rtgroup_size(struct xfs_mount *mp, xfs_rgnumber_t prev_rgcount); diff --git a/fs/xfs/scrub/agheader.c b/fs/xfs/scrub/agheader.c index 05f5e94b99382b..d037de6dd821d2 100644 --- a/fs/xfs/scrub/agheader.c +++ b/fs/xfs/scrub/agheader.c @@ -564,7 +564,7 @@ xchk_agf( /* Check the AG length */ eoag = be32_to_cpu(agf->agf_length); - if (eoag != pag->block_count) + if (eoag != pag_group(pag)->xg_block_count) xchk_block_set_corrupt(sc, sc->sa.agf_bp); /* Check the AGF btree roots and levels */ @@ -944,7 +944,7 @@ xchk_agi( /* Check the AG length */ eoag = be32_to_cpu(agi->agi_length); - if (eoag != pag->block_count) + if (eoag != pag_group(pag)->xg_block_count) xchk_block_set_corrupt(sc, sc->sa.agi_bp); /* Check btree roots and levels */ diff --git a/fs/xfs/scrub/agheader_repair.c b/fs/xfs/scrub/agheader_repair.c index 0ea04d6e21cd83..0fad0baaba2f69 100644 --- a/fs/xfs/scrub/agheader_repair.c +++ b/fs/xfs/scrub/agheader_repair.c @@ -209,7 +209,7 @@ xrep_agf_init_header( agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC); agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION); agf->agf_seqno = cpu_to_be32(pag_agno(pag)); - agf->agf_length = cpu_to_be32(pag->block_count); + agf->agf_length = cpu_to_be32(pag_group(pag)->xg_block_count); agf->agf_flfirst = old_agf->agf_flfirst; agf->agf_fllast = old_agf->agf_fllast; agf->agf_flcount = old_agf->agf_flcount; @@ -898,7 +898,7 @@ xrep_agi_init_header( agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC); agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION); agi->agi_seqno = cpu_to_be32(pag_agno(pag)); - agi->agi_length = cpu_to_be32(pag->block_count); + agi->agi_length = cpu_to_be32(pag_group(pag)->xg_block_count); agi->agi_newino = cpu_to_be32(NULLAGINO); agi->agi_dirino = cpu_to_be32(NULLAGINO); if (xfs_has_crc(mp)) diff --git a/fs/xfs/scrub/repair.c b/fs/xfs/scrub/repair.c index 3fa009126170e6..91c8bc055a4fd7 100644 --- a/fs/xfs/scrub/repair.c +++ b/fs/xfs/scrub/repair.c @@ -306,7 +306,7 @@ xrep_calc_ag_resblks( /* Now grab the block counters from the AGF. */ error = xfs_alloc_read_agf(pag, NULL, 0, &bp); if (error) { - aglen = pag->block_count; + aglen = pag_group(pag)->xg_block_count; freelen = aglen; usedlen = aglen; } else { @@ -326,9 +326,9 @@ xrep_calc_ag_resblks( /* If the block counts are impossible, make worst-case assumptions. */ if (aglen == NULLAGBLOCK || - aglen != pag->block_count || + aglen != pag_group(pag)->xg_block_count || freelen >= aglen) { - aglen = pag->block_count; + aglen = pag_group(pag)->xg_block_count; freelen = aglen; usedlen = aglen; } diff --git a/fs/xfs/xfs_discard.c b/fs/xfs/xfs_discard.c index e71bd64685f900..a7635962448911 100644 --- a/fs/xfs/xfs_discard.c +++ b/fs/xfs/xfs_discard.c @@ -337,7 +337,7 @@ xfs_trim_perag_extents( }; int error = 0; - if (start != 0 || end != pag->block_count) + if (start != 0 || end != pag_group(pag)->xg_block_count) tcur.by_bno = true; do { @@ -403,7 +403,7 @@ xfs_trim_datadev_extents( end_agbno = xfs_daddr_to_agbno(mp, ddev_end); while ((pag = xfs_perag_next_range(mp, pag, start_agno, end_agno))) { - xfs_agblock_t agend = pag->block_count; + xfs_agblock_t agend = pag_group(pag)->xg_block_count; if (pag_agno(pag) == end_agno) agend = end_agbno; diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index db09c086ff1c01..8f56d5fbe7413a 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -878,7 +878,8 @@ xfs_growfs_rt_bmblock( if (!nmp) return -ENOMEM; - rtg->rtg_extents = xfs_rtgroup_extents(nmp, rtg_rgno(rtg)); + xfs_rtgroup_calc_geometry(nmp, rtg, rtg_rgno(rtg), + nmp->m_sb.sb_rgcount, nmp->m_sb.sb_rextents); /* * Recompute the growfsrt reservation from the new rsumsize, so that the @@ -1137,7 +1138,8 @@ xfs_growfs_rtg( /* * Reset rtg_extents to the old value if adding more blocks failed. */ - rtg->rtg_extents = xfs_rtgroup_extents(rtg_mount(rtg), rtg_rgno(rtg)); + xfs_rtgroup_calc_geometry(mp, rtg, rtg_rgno(rtg), mp->m_sb.sb_rgcount, + mp->m_sb.sb_rextents); if (old_rsum_cache) { kvfree(rtg->rtg_rsum_cache); rtg->rtg_rsum_cache = old_rsum_cache; @@ -1517,8 +1519,6 @@ xfs_rtmount_rtg( { int error, i; - rtg->rtg_extents = xfs_rtgroup_extents(mp, rtg_rgno(rtg)); - for (i = 0; i < XFS_RTGI_MAX; i++) { error = xfs_rtginode_load(rtg, i, tp); if (error) From patchwork Thu Oct 17 19:09:29 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840738 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 5ED57218D72 for ; Thu, 17 Oct 2024 19:09:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192170; cv=none; b=tBTFRYhBPEIrH6znKsOOL3nhc4EQtGUOk0GiQZBuVeIetEdc9VMf5PVHeo0THoVUcUySEgWaGFqoh33pZNYsgUxOJYs6VBP7MULh1iOJ4+K/eZJupvP73+Bqzmj63WrNTjOHYgoEh6pJ+ocF4B5lfLFf/k6ZbnxrY/HpW8m/EO4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192170; c=relaxed/simple; bh=m0BIQVyY6KNLTQM70EYzNn1kxPw3qRanF0Kfg6vPScQ=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=IhbsGfl7UaTEvIdKHWyk5TCdDxV+ebjcaDflnVJxyek/sv7XS/gt9iVccDTL13TckvF2I+FiqRCNW6amB3QiBqGgoK45AGFRD+9DCmXGiSNwEhdR2VCikQxgbZCY6M/dS/DRvdNGD0HQN4bwBkESm2gugtIzk104c08Fg6Lp3v0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=m9asmWuB; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="m9asmWuB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EC62DC4CEC3; Thu, 17 Oct 2024 19:09:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729192170; bh=m0BIQVyY6KNLTQM70EYzNn1kxPw3qRanF0Kfg6vPScQ=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=m9asmWuBL73PaqtMSpXL50R60iv9SPw5UGMontCNXZFw10aDFYSAJVbEUAceU+4SN FgW36cqU/MKJSbxcLBIua2zNMABVJDYzwKCt5QSoDPBzJTfN2U3UNhRi4gGi1NrFZG T29aFcM+UHHyOIdAwqTBZRGaAp75soEngLHslJ1EDJmXU7BVA7ojQ27cHoFSYWPJte n2rxE31w3PvJhD9KV03NwpQ45nAHVLI3ygdFlzFZXfeEeYk2HVAM3dw+KGesf1zPlx 5YkjdLPT7xBCpI11b/0ekQL+S1Zr64ResVDcVf17yN9951fXIPpGY22KAben/qGs4g Y3tTJhoOXMReQ== Date: Thu, 17 Oct 2024 12:09:29 -0700 Subject: [PATCH 32/34] xfs: port the perag discard code to handle generic groups From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919072223.3453179.8959262334258999078.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Port xfs_discard_extents and its tracepoints to handle generic groups instead of just perags. This is needed to enable busy extent tracking for rtgroups. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/xfs_discard.c | 35 ++++++++++++++++++++++++++--------- fs/xfs/xfs_trace.h | 19 +++++++++++-------- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/fs/xfs/xfs_discard.c b/fs/xfs/xfs_discard.c index a7635962448911..b7c1e09e9afefc 100644 --- a/fs/xfs/xfs_discard.c +++ b/fs/xfs/xfs_discard.c @@ -101,6 +101,24 @@ xfs_discard_endio( bio_put(bio); } +static inline struct block_device * +xfs_group_bdev( + const struct xfs_group *xg) +{ + struct xfs_mount *mp = xg->xg_mount; + + switch (xg->xg_type) { + case XG_TYPE_AG: + return mp->m_ddev_targp->bt_bdev; + case XG_TYPE_RTG: + return mp->m_rtdev_targp->bt_bdev; + default: + ASSERT(0); + break; + } + return NULL; +} + /* * Walk the discard list and issue discards on all the busy extents in the * list. We plug and chain the bios so that we only need a single completion @@ -118,12 +136,11 @@ xfs_discard_extents( blk_start_plug(&plug); list_for_each_entry(busyp, &extents->extent_list, list) { - struct xfs_perag *pag = to_perag(busyp->group); + trace_xfs_discard_extent(busyp->group, busyp->bno, + busyp->length); - trace_xfs_discard_extent(pag, busyp->bno, busyp->length); - - error = __blkdev_issue_discard(mp->m_ddev_targp->bt_bdev, - xfs_agbno_to_daddr(pag, busyp->bno), + error = __blkdev_issue_discard(xfs_group_bdev(busyp->group), + xfs_gbno_to_daddr(busyp->group, busyp->bno), XFS_FSB_TO_BB(mp, busyp->length), GFP_KERNEL, &bio); if (error && error != -EOPNOTSUPP) { @@ -241,11 +258,11 @@ xfs_trim_gather_extents( * overlapping ranges for now. */ if (fbno + flen < tcur->start) { - trace_xfs_discard_exclude(pag, fbno, flen); + trace_xfs_discard_exclude(pag_group(pag), fbno, flen); goto next_extent; } if (fbno > tcur->end) { - trace_xfs_discard_exclude(pag, fbno, flen); + trace_xfs_discard_exclude(pag_group(pag), fbno, flen); if (tcur->by_bno) { tcur->count = 0; break; @@ -263,7 +280,7 @@ xfs_trim_gather_extents( /* Too small? Give up. */ if (flen < tcur->minlen) { - trace_xfs_discard_toosmall(pag, fbno, flen); + trace_xfs_discard_toosmall(pag_group(pag), fbno, flen); if (tcur->by_bno) goto next_extent; tcur->count = 0; @@ -275,7 +292,7 @@ xfs_trim_gather_extents( * discard and try again the next time. */ if (xfs_extent_busy_search(pag_group(pag), fbno, flen)) { - trace_xfs_discard_busy(pag, fbno, flen); + trace_xfs_discard_busy(pag_group(pag), fbno, flen); goto next_extent; } diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index e3218c0f6ac564..79dc7620694f38 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -2480,23 +2480,26 @@ DEFINE_LOG_RECOVER_ICREATE_ITEM(xfs_log_recover_icreate_cancel); DEFINE_LOG_RECOVER_ICREATE_ITEM(xfs_log_recover_icreate_recover); DECLARE_EVENT_CLASS(xfs_discard_class, - TP_PROTO(const struct xfs_perag *pag, xfs_agblock_t agbno, + TP_PROTO(const struct xfs_group *xg, xfs_agblock_t agbno, xfs_extlen_t len), - TP_ARGS(pag, agbno, len), + TP_ARGS(xg, agbno, len), TP_STRUCT__entry( __field(dev_t, dev) + __field(enum xfs_group_type, type) __field(xfs_agnumber_t, agno) __field(xfs_agblock_t, agbno) __field(xfs_extlen_t, len) ), TP_fast_assign( - __entry->dev = pag_mount(pag)->m_super->s_dev; - __entry->agno = pag_agno(pag); + __entry->dev = xg->xg_mount->m_super->s_dev; + __entry->type = xg->xg_type; + __entry->agno = xg->xg_gno; __entry->agbno = agbno; __entry->len = len; ), - TP_printk("dev %d:%d agno 0x%x agbno 0x%x fsbcount 0x%x", + TP_printk("dev %d:%d %sno 0x%x gbno 0x%x fsbcount 0x%x", MAJOR(__entry->dev), MINOR(__entry->dev), + __print_symbolic(__entry->type, XG_TYPE_STRINGS), __entry->agno, __entry->agbno, __entry->len) @@ -2504,9 +2507,9 @@ DECLARE_EVENT_CLASS(xfs_discard_class, #define DEFINE_DISCARD_EVENT(name) \ DEFINE_EVENT(xfs_discard_class, name, \ - TP_PROTO(const struct xfs_perag *pag, xfs_agblock_t agbno, \ - xfs_extlen_t len), \ - TP_ARGS(pag, agbno, len)) + TP_PROTO(const struct xfs_group *xg, xfs_agblock_t agbno, \ + xfs_extlen_t len), \ + TP_ARGS(xg, agbno, len)) DEFINE_DISCARD_EVENT(xfs_discard_extent); DEFINE_DISCARD_EVENT(xfs_discard_toosmall); DEFINE_DISCARD_EVENT(xfs_discard_exclude); From patchwork Thu Oct 17 19:09:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840739 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 F297721D17D for ; Thu, 17 Oct 2024 19:09:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192181; cv=none; b=EaMJwQOlJwqfqQwoi6PbEdNqEj7Ni84VzWEMovscb/1VhREoE0qb/cBp8pujV+kUDsrO1xqc2Clckl0Q3daj2yIRcB6nS/jd0nE8SyHnO7HiEG48UMtNw7vcbUCykrb32LJaBmtiJA5tyv989uViYr4Z9oQJgw0uIrCjqcUViDU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192181; c=relaxed/simple; bh=2y3r0UR86rPVaHLqqREVkTgEYCX6UEVdG5lmXM0H1RA=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=aeD+bnjjr+03MrTOTX4YvTn5XINeh9ELXpop7QtGY4KMk5Cub66KVa9lmLLjv8A6nPsy3hYPjkepTqOhkOJDOn+RdMVC5vo2oryzUIdy9WsWFe4XGAYSizcoPdJLrwnFJRTTwu47TrGEB9RHK7ezDcH0sCGd2IItQwOg/XYyBjg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=i+NpWyYh; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="i+NpWyYh" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 86B73C4CEC3; Thu, 17 Oct 2024 19:09:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729192180; bh=2y3r0UR86rPVaHLqqREVkTgEYCX6UEVdG5lmXM0H1RA=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=i+NpWyYhMXwPLTLXGySeMvsq5ITKJVm1YwS5BaMdfQfk1HEwn+NaDXkjU1AaMvM4o HajU8b37cvkvhRQNMnWlA6HT6TP3a30QIKXj7RnRGiKx7urpeSjR9+Bf9dsGXRD5gB 2PWC2Lz5o+4NekQ4UHqnE1DZZJH7WWa2gFRnTlQQI7+3PMKzMV/CKHWfekixLh/zUj 0kDl1R0MS541C6UB5tZ15J1ZELAfXl7mRPgdN/TpeWwQQmctk7vJ4KOIxtBZgyO8Ag lrhWPYl93TAS5CNhVJsnb84xPzvi1QuzQ0v3s9j2me93h/X4ZhvJX0fvCQuyfPhTv/ LdxCphQySXYEg== Date: Thu, 17 Oct 2024 12:09:40 -0700 Subject: [PATCH 33/34] xfs: implement busy extent tracking for rtgroups From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919072241.3453179.18351491157070502171.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong For rtgroups filesystems, track newly freed (rt) space through the log until the rt EFIs have been committed to disk. This way we ensure that space cannot be reused until all traces of the old owner are gone. As a fringe benefit, we now support -o discard on the realtime device. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_rtbitmap.c | 12 ++++ fs/xfs/libxfs/xfs_rtgroup.h | 13 ++++ fs/xfs/xfs_extent_busy.c | 6 ++ fs/xfs/xfs_rtalloc.c | 127 ++++++++++++++++++++++++++++++++++++++++-- fs/xfs/xfs_trace.h | 75 +++++++++++++++++++++++++ 5 files changed, 227 insertions(+), 6 deletions(-) diff --git a/fs/xfs/libxfs/xfs_rtbitmap.c b/fs/xfs/libxfs/xfs_rtbitmap.c index 30220bf8c3f430..4ddfb7e395b38a 100644 --- a/fs/xfs/libxfs/xfs_rtbitmap.c +++ b/fs/xfs/libxfs/xfs_rtbitmap.c @@ -24,6 +24,7 @@ #include "xfs_errortag.h" #include "xfs_log.h" #include "xfs_buf_item.h" +#include "xfs_extent_busy.h" /* * Realtime allocator bitmap functions shared with userspace. @@ -1120,6 +1121,7 @@ xfs_rtfree_blocks( { struct xfs_mount *mp = tp->t_mountp; xfs_extlen_t mod; + int error; ASSERT(rtlen <= XFS_MAX_BMBT_EXTLEN); @@ -1135,8 +1137,16 @@ xfs_rtfree_blocks( return -EIO; } - return xfs_rtfree_extent(tp, rtg, xfs_rtb_to_rtx(mp, rtbno), + error = xfs_rtfree_extent(tp, rtg, xfs_rtb_to_rtx(mp, rtbno), xfs_extlen_to_rtxlen(mp, rtlen)); + if (error) + return error; + + if (xfs_has_rtgroups(mp)) + xfs_extent_busy_insert(tp, rtg_group(rtg), + xfs_rtb_to_rgbno(mp, rtbno), rtlen, 0); + + return 0; } /* Find all the free records within a given range. */ diff --git a/fs/xfs/libxfs/xfs_rtgroup.h b/fs/xfs/libxfs/xfs_rtgroup.h index 1e51dc62d1143e..7e7e491ff06fa5 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.h +++ b/fs/xfs/libxfs/xfs_rtgroup.h @@ -155,6 +155,19 @@ xfs_rtbno_is_group_start( return (rtbno & mp->m_groups[XG_TYPE_RTG].blkmask) == 0; } +/* Convert an rtgroups rt extent number into an rgbno. */ +static inline xfs_rgblock_t +xfs_rtx_to_rgbno( + struct xfs_rtgroup *rtg, + xfs_rtxnum_t rtx) +{ + struct xfs_mount *mp = rtg_mount(rtg); + + if (likely(mp->m_rtxblklog >= 0)) + return rtx << mp->m_rtxblklog; + return rtx * mp->m_sb.sb_rextsize; +} + static inline xfs_daddr_t xfs_rtb_to_daddr( struct xfs_mount *mp, diff --git a/fs/xfs/xfs_extent_busy.c b/fs/xfs/xfs_extent_busy.c index 457a27ab837599..ea43c9a6e54c12 100644 --- a/fs/xfs/xfs_extent_busy.c +++ b/fs/xfs/xfs_extent_busy.c @@ -18,6 +18,7 @@ #include "xfs_trans.h" #include "xfs_log.h" #include "xfs_ag.h" +#include "xfs_rtgroup.h" struct xfs_extent_busy_tree { spinlock_t eb_lock; @@ -665,9 +666,14 @@ xfs_extent_busy_wait_all( struct xfs_mount *mp) { struct xfs_perag *pag = NULL; + struct xfs_rtgroup *rtg = NULL; while ((pag = xfs_perag_next(mp, pag))) xfs_extent_busy_wait_group(pag_group(pag)); + + if (xfs_has_rtgroups(mp)) + while ((rtg = xfs_rtgroup_next(mp, rtg))) + xfs_extent_busy_wait_group(rtg_group(rtg)); } /* diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 8f56d5fbe7413a..8a8210d45f4f03 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -29,6 +29,7 @@ #include "xfs_metafile.h" #include "xfs_rtgroup.h" #include "xfs_error.h" +#include "xfs_trace.h" /* * Return whether there are any free extents in the size range given @@ -1657,6 +1658,114 @@ xfs_rtalloc_align_minmax( *raminlen = newminlen; } +/* Given a free extent, find any part of it that isn't busy, if possible. */ +STATIC bool +xfs_rtalloc_check_busy( + struct xfs_rtalloc_args *args, + xfs_rtxnum_t start, + xfs_rtxlen_t minlen_rtx, + xfs_rtxlen_t maxlen_rtx, + xfs_rtxlen_t len_rtx, + xfs_rtxlen_t prod, + xfs_rtxnum_t rtx, + xfs_rtxlen_t *reslen, + xfs_rtxnum_t *resrtx, + unsigned *busy_gen) +{ + struct xfs_rtgroup *rtg = args->rtg; + struct xfs_mount *mp = rtg_mount(rtg); + xfs_agblock_t rgbno = xfs_rtx_to_rgbno(rtg, rtx); + xfs_rgblock_t min_rgbno = xfs_rtx_to_rgbno(rtg, start); + xfs_extlen_t minlen = xfs_rtxlen_to_extlen(mp, minlen_rtx); + xfs_extlen_t len = xfs_rtxlen_to_extlen(mp, len_rtx); + xfs_extlen_t diff; + bool busy; + + busy = xfs_extent_busy_trim(rtg_group(rtg), minlen, + xfs_rtxlen_to_extlen(mp, maxlen_rtx), &rgbno, &len, + busy_gen); + + /* + * If we have a largish extent that happens to start before min_rgbno, + * see if we can shift it into range... + */ + if (rgbno < min_rgbno && rgbno + len > min_rgbno) { + diff = min_rgbno - rgbno; + if (len > diff) { + rgbno += diff; + len -= diff; + } + } + + if (prod > 1 && len >= minlen) { + xfs_rgblock_t aligned_rgbno = roundup(rgbno, prod); + + diff = aligned_rgbno - rgbno; + + *resrtx = xfs_rgbno_to_rtx(mp, aligned_rgbno); + *reslen = xfs_extlen_to_rtxlen(mp, + diff >= len ? 0 : len - diff); + } else { + *resrtx = xfs_rgbno_to_rtx(mp, rgbno); + *reslen = xfs_extlen_to_rtxlen(mp, len); + } + + return busy; +} + +/* + * Adjust the given free extent so that it isn't busy, or flush the log and + * wait for the space to become unbusy. Only needed for rtgroups. + */ +STATIC int +xfs_rtallocate_adjust_for_busy( + struct xfs_rtalloc_args *args, + xfs_rtxnum_t start, + xfs_rtxlen_t minlen, + xfs_rtxlen_t maxlen, + xfs_rtxlen_t *len, + xfs_rtxlen_t prod, + xfs_rtxnum_t *rtx) +{ + xfs_rtxnum_t resrtx; + xfs_rtxlen_t reslen; + unsigned busy_gen; + bool busy; + int error; + +again: + busy = xfs_rtalloc_check_busy(args, start, minlen, maxlen, *len, prod, + *rtx, &reslen, &resrtx, &busy_gen); + if (!busy) + return 0; + + if (reslen < minlen || (start != 0 && resrtx != *rtx)) { + /* + * Enough of the extent was busy that we cannot satisfy the + * allocation, or this is a near allocation and the start of + * the extent is busy. Flush the log and wait for the busy + * situation to resolve. + */ + trace_xfs_rtalloc_extent_busy(args->rtg, start, minlen, maxlen, + *len, prod, *rtx, busy_gen); + + error = xfs_extent_busy_flush(args->tp, rtg_group(args->rtg), + busy_gen, 0); + if (error) + return error; + + goto again; + } + + /* Some of the free space wasn't busy, hand that back to the caller. */ + trace_xfs_rtalloc_extent_busy_trim(args->rtg, *rtx, *len, resrtx, + reslen); + *len = reslen; + *rtx = resrtx; + + return 0; +} + static int xfs_rtallocate_rtg( struct xfs_trans *tp, @@ -1738,15 +1847,19 @@ xfs_rtallocate_rtg( } if (error) { - if (xfs_has_rtgroups(args.mp)) { - xfs_rtgroup_unlock(args.rtg, XFS_RTGLOCK_BITMAP); - *rtlocked = false; - } + if (xfs_has_rtgroups(args.mp)) + goto out_unlock; goto out_release; } - if (xfs_has_rtgroups(args.mp)) + if (xfs_has_rtgroups(args.mp)) { + error = xfs_rtallocate_adjust_for_busy(&args, start, minlen, + maxlen, &len, prod, &rtx); + if (error) + goto out_unlock; + xfs_rtgroup_trans_join(tp, args.rtg, XFS_RTGLOCK_BITMAP); + } error = xfs_rtallocate_range(&args, rtx, len); if (error) @@ -1762,6 +1875,10 @@ xfs_rtallocate_rtg( xfs_rtgroup_rele(args.rtg); xfs_rtbuf_cache_relse(&args); return error; +out_unlock: + xfs_rtgroup_unlock(args.rtg, XFS_RTGLOCK_BITMAP); + *rtlocked = false; + goto out_release; } static int diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 79dc7620694f38..a4bd9dcccdd716 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -97,6 +97,7 @@ struct xfs_extent_free_item; struct xfs_rmap_intent; struct xfs_refcount_intent; struct xfs_metadir_update; +struct xfs_rtgroup; #define XFS_ATTR_FILTER_FLAGS \ { XFS_ATTR_ROOT, "ROOT" }, \ @@ -1749,6 +1750,80 @@ TRACE_EVENT(xfs_extent_busy_trim, __entry->tlen) ); +#ifdef CONFIG_XFS_RT +TRACE_EVENT(xfs_rtalloc_extent_busy, + TP_PROTO(struct xfs_rtgroup *rtg, xfs_rtxnum_t start, + xfs_rtxlen_t minlen, xfs_rtxlen_t maxlen, + xfs_rtxlen_t len, xfs_rtxlen_t prod, xfs_rtxnum_t rtx, + unsigned busy_gen), + TP_ARGS(rtg, start, minlen, maxlen, len, prod, rtx, busy_gen), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_rgnumber_t, rgno) + __field(xfs_rtxnum_t, start) + __field(xfs_rtxlen_t, minlen) + __field(xfs_rtxlen_t, maxlen) + __field(xfs_rtxlen_t, mod) + __field(xfs_rtxlen_t, prod) + __field(xfs_rtxlen_t, len) + __field(xfs_rtxnum_t, rtx) + __field(unsigned, busy_gen) + ), + TP_fast_assign( + __entry->dev = rtg_mount(rtg)->m_super->s_dev; + __entry->rgno = rtg_rgno(rtg); + __entry->start = start; + __entry->minlen = minlen; + __entry->maxlen = maxlen; + __entry->prod = prod; + __entry->len = len; + __entry->rtx = rtx; + __entry->busy_gen = busy_gen; + ), + TP_printk("dev %d:%d rgno 0x%x startrtx 0x%llx minlen %u maxlen %u " + "prod %u len %u rtx 0%llx busy_gen 0x%x", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->rgno, + __entry->start, + __entry->minlen, + __entry->maxlen, + __entry->prod, + __entry->len, + __entry->rtx, + __entry->busy_gen) +) + +TRACE_EVENT(xfs_rtalloc_extent_busy_trim, + TP_PROTO(struct xfs_rtgroup *rtg, xfs_rtxnum_t old_rtx, + xfs_rtxlen_t old_len, xfs_rtxnum_t new_rtx, + xfs_rtxlen_t new_len), + TP_ARGS(rtg, old_rtx, old_len, new_rtx, new_len), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_rgnumber_t, rgno) + __field(xfs_rtxnum_t, old_rtx) + __field(xfs_rtxnum_t, new_rtx) + __field(xfs_rtxlen_t, old_len) + __field(xfs_rtxlen_t, new_len) + ), + TP_fast_assign( + __entry->dev = rtg_mount(rtg)->m_super->s_dev; + __entry->rgno = rtg_rgno(rtg); + __entry->old_rtx = old_rtx; + __entry->old_len = old_len; + __entry->new_rtx = new_rtx; + __entry->new_len = new_len; + ), + TP_printk("dev %d:%d rgno 0x%x rtx 0x%llx rtxcount 0x%x -> rtx 0x%llx rtxcount 0x%x", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->rgno, + __entry->old_rtx, + __entry->old_len, + __entry->new_rtx, + __entry->new_len) +); +#endif /* CONFIG_XFS_RT */ + DECLARE_EVENT_CLASS(xfs_agf_class, TP_PROTO(struct xfs_mount *mp, struct xfs_agf *agf, int flags, unsigned long caller_ip), From patchwork Thu Oct 17 19:09:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13840740 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 449F821D2B0 for ; Thu, 17 Oct 2024 19:09:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192191; cv=none; b=lPVTUI69H5IzN2xaaQQtv1/D7JL3nEs+yjYBOB9O4uiplMV65uFZI8+miIvlsa/ogAKQO0+yeQnybJASJaIhq34yklza9C+25MiFD+7YEXXGkVWtvSjYsn8lptwjzyy7u9VCid9+ugOUrmLcsxqnRTS2aQxjGEnEROK4HRwxtEE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192191; c=relaxed/simple; bh=/TB/0CEup4e9ubGJDB6lUB9lxWhT5oLKgd9+Nasje2k=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=uaowJrDf904OPkI7uzSp909qv/Oziozp5h4QYc4G0iaMOYiYBvaFcE2lBykkgnqf+sdwvw1h5KA4xdVcK0EoxFwOe1FFfzt6/Jzyy77NuDhTAr64FU/6ZNodFrQrEwmPwaiYDFtrNyawJ2fizgS6yR7+/7DKLHq/4NCqZJpkSec= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LiNqgS0z; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="LiNqgS0z" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1C16EC4CED4; Thu, 17 Oct 2024 19:09:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729192191; bh=/TB/0CEup4e9ubGJDB6lUB9lxWhT5oLKgd9+Nasje2k=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=LiNqgS0zOjkeAtsga/QXFuFNXuTSOPe5hexJv8cJo78xLccLC+brvYuwvO4Ngeib2 Nz4nxK9vMSVfjQBAVfyVoz7bOYqfoZaGPmNeefyc9Y7CoBf/gaWtqc8yhbf9FuBvyu f1ipbI37Gfc9xjnd1/lcTJDBMu3fpTsKIW6iTIOAGdVHQui7ZLXXRUro4wIH1UWin6 9YM6ZDSsEvnaRPdrf9TSWgzv5/0u0f8MOkx9iAvHGXv20A9XfAlFf0k/CB2Oc82rsa aPcoIgOR2A6zZuKGULSdtR6UyhiS+pFtFL/TgtB22j9Zs1R96FoO528CYeVjfgMJCO Ui/vLEIthi6lg== Date: Thu, 17 Oct 2024 12:09:50 -0700 Subject: [PATCH 34/34] xfs: use rtgroup busy extent list for FITRIM From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919072258.3453179.12429801014526643442.stgit@frogsfrogsfrogs> In-Reply-To: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> References: <172919071571.3453179.15753475627202483418.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong For filesystems that have rtgroups and hence use the busy extent list for freed rt space, use that busy extent list so that FITRIM can issue discard commands asynchronously without worrying about other callers accidentally allocating and using space that is being discarded. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/xfs_discard.c | 146 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 144 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_discard.c b/fs/xfs/xfs_discard.c index b7c1e09e9afefc..c4bd145f5ec1bf 100644 --- a/fs/xfs/xfs_discard.c +++ b/fs/xfs/xfs_discard.c @@ -73,6 +73,8 @@ * extent search so that it overlaps in flight discard IO. */ +#define XFS_DISCARD_MAX_EXAMINE (100) + struct workqueue_struct *xfs_discard_wq; static void @@ -185,7 +187,7 @@ xfs_trim_gather_extents( struct xfs_buf *agbp; int error; int i; - int batch = 100; + int batch = XFS_DISCARD_MAX_EXAMINE; /* * Force out the log. This means any transactions that might have freed @@ -565,6 +567,7 @@ xfs_trim_gather_rtextent( return 0; } +/* Trim extents on an !rtgroups realtime device */ static int xfs_trim_rtextents( struct xfs_rtgroup *rtg, @@ -619,6 +622,140 @@ xfs_trim_rtextents( return error; } +struct xfs_trim_rtgroup { + /* list of rtgroup extents to free */ + struct xfs_busy_extents *extents; + + /* minimum length that caller allows us to trim */ + xfs_rtblock_t minlen_fsb; + + /* restart point for the rtbitmap walk */ + xfs_rtxnum_t restart_rtx; + + /* number of extents to examine before stopping to issue discard ios */ + int batch; + + /* number of extents queued for discard */ + int queued; +}; + +static int +xfs_trim_gather_rtgroup_extent( + struct xfs_rtgroup *rtg, + struct xfs_trans *tp, + const struct xfs_rtalloc_rec *rec, + void *priv) +{ + struct xfs_trim_rtgroup *tr = priv; + xfs_rgblock_t rgbno; + xfs_extlen_t len; + + if (--tr->batch <= 0) { + /* + * If we've checked a large number of extents, update the + * cursor to point at this extent so we restart the next batch + * from this extent. + */ + tr->restart_rtx = rec->ar_startext; + return -ECANCELED; + } + + rgbno = xfs_rtx_to_rgbno(rtg, rec->ar_startext); + len = xfs_rtxlen_to_extlen(rtg_mount(rtg), rec->ar_extcount); + + /* Ignore too small. */ + if (len < tr->minlen_fsb) { + trace_xfs_discard_toosmall(rtg_group(rtg), rgbno, len); + return 0; + } + + /* + * If any blocks in the range are still busy, skip the discard and try + * again the next time. + */ + if (xfs_extent_busy_search(rtg_group(rtg), rgbno, len)) { + trace_xfs_discard_busy(rtg_group(rtg), rgbno, len); + return 0; + } + + xfs_extent_busy_insert_discard(rtg_group(rtg), rgbno, len, + &tr->extents->extent_list); + + tr->queued++; + tr->restart_rtx = rec->ar_startext + rec->ar_extcount; + return 0; +} + +/* Trim extents in this rtgroup using the busy extent machinery. */ +static int +xfs_trim_rtgroup_extents( + struct xfs_rtgroup *rtg, + xfs_rtxnum_t low, + xfs_rtxnum_t high, + xfs_daddr_t minlen) +{ + struct xfs_mount *mp = rtg_mount(rtg); + struct xfs_trim_rtgroup tr = { + .minlen_fsb = XFS_BB_TO_FSB(mp, minlen), + }; + struct xfs_trans *tp; + int error; + + error = xfs_trans_alloc_empty(mp, &tp); + if (error) + return error; + + /* + * Walk the free ranges between low and high. The query_range function + * trims the extents returned. + */ + do { + tr.extents = kzalloc(sizeof(*tr.extents), GFP_KERNEL); + if (!tr.extents) { + error = -ENOMEM; + break; + } + + tr.queued = 0; + tr.batch = XFS_DISCARD_MAX_EXAMINE; + tr.extents->owner = tr.extents; + INIT_LIST_HEAD(&tr.extents->extent_list); + + xfs_rtgroup_lock(rtg, XFS_RTGLOCK_BITMAP_SHARED); + error = xfs_rtalloc_query_range(rtg, tp, low, high, + xfs_trim_gather_rtgroup_extent, &tr); + xfs_rtgroup_unlock(rtg, XFS_RTGLOCK_BITMAP_SHARED); + if (error == -ECANCELED) + error = 0; + if (error) { + kfree(tr.extents); + break; + } + + if (!tr.queued) + break; + + /* + * We hand the extent list to the discard function here so the + * discarded extents can be removed from the busy extent list. + * This allows the discards to run asynchronously with + * gathering the next round of extents to discard. + * + * However, we must ensure that we do not reference the extent + * list after this function call, as it may have been freed by + * the time control returns to us. + */ + error = xfs_discard_extents(rtg_mount(rtg), tr.extents); + if (error) + break; + + low = tr.restart_rtx; + } while (!xfs_trim_should_stop() && low <= high); + + xfs_trans_cancel(tp); + return error; +} + static int xfs_trim_rtdev_extents( struct xfs_mount *mp, @@ -657,7 +794,12 @@ xfs_trim_rtdev_extents( if (rtg_rgno(rtg) == end_rgno) rtg_end = min(rtg_end, end_rtx); - error = xfs_trim_rtextents(rtg, start_rtx, rtg_end, minlen); + if (xfs_has_rtgroups(mp)) + error = xfs_trim_rtgroup_extents(rtg, start_rtx, + rtg_end, minlen); + else + error = xfs_trim_rtextents(rtg, start_rtx, rtg_end, + minlen); if (error) last_error = error;