From patchwork Fri Aug 23 00:21: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: 13774441 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 DBBCF1C694 for ; Fri, 23 Aug 2024 00:21: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=1724372486; cv=none; b=SVpyg2IBDO9aHMr3G+jv+4/PIjuoEcb0wOZvADWNslo5c2fFmv3RKR1GXG2yO0hQzvDXCZfum434tl6V1dG7M0rLwDPePb0fBzTqd6chGjt89Z9f6I1GyR6CvusAZLx/r0vXxc2albjpnqjFdLwGi55ZD/MHIB4eXnblYEJOrJ0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372486; c=relaxed/simple; bh=VH+NKFncDChJOGqH4sqEI//9xIMnxzt3zD7oWGJ4hrU=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=cgOmPz5flWzo/3U4HYPMbbegf853prqwNmJqr2cXZKISTpz36gpf7zaD8vswEnjkongOQIG3y+JFf/N2uiorIlCLu3cZIKLPzRHzUDlcpKTUghMhnN21q7Zteg1lWk27CT48vh2Ng0F4JTC2AH7HH7IacFlBYU3X8tOIIkxLzeA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KMepG4nv; 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="KMepG4nv" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5F859C4AF09; Fri, 23 Aug 2024 00:21:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724372486; bh=VH+NKFncDChJOGqH4sqEI//9xIMnxzt3zD7oWGJ4hrU=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=KMepG4nvycpyrsvL+5OOZPvm5+cHBqjAvw7xTU8A6AMRY41+z0W25pwKI21NsmBBc hdzCY28909X5i/dEynFkuGuDqiVUj9DJgg2eUumRqBYmBjLsE6hXlmPo16evRV/scL l+ne9mImnvdV4FV/z4cIx9Mmr3FPevQPHUpF2Iqut6HaBwz42H7n7Y3lx5cNZwUda2 +G5tNt4upeU/NAxLi84fKmD9TELX6m0BYcVl+TmXWpRUahLgYCgcoEvfqburgQ3zFO AxQIBUbuCLFfaOtjJErTds3ji860xxeU6I4Ku7EN4gjwhxDQS6XXcHar5T4ml62gXs lqV2/1ZTf1MTA== Date: Thu, 22 Aug 2024 17:21:25 -0700 Subject: [PATCH 01/26] xfs: define the format of rt groups From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <172437088534.60592.14072619855969226822.stgit@frogsfrogsfrogs> In-Reply-To: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> References: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Define the ondisk format of realtime group metadata, and a superblock for realtime volumes. rt supers are protected by a separate rocompat bit so that we can leave them off if the rt device is zoned. Add a xfs_sb_version_hasrtgroups so that xfs_repair knows how to zero the tail of superblocks. 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 | 50 +++++++++++++++++++-- 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 | 102 +++++++++++++++++++++++++++++++++++++----- fs/xfs/libxfs/xfs_shared.h | 1 fs/xfs/xfs_mount.h | 6 ++ fs/xfs/xfs_rtalloc.c | 30 +++++++++++- 8 files changed, 268 insertions(+), 26 deletions(-) diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index fa5cfc8265d92..9e351b19bd86e 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) @@ -355,10 +362,10 @@ xfs_sb_has_compat_feature( return (sbp->sb_features_compat & feature) != 0; } -#define XFS_SB_FEAT_RO_COMPAT_FINOBT (1 << 0) /* free inode btree */ -#define XFS_SB_FEAT_RO_COMPAT_RMAPBT (1 << 1) /* reverse map btree */ -#define XFS_SB_FEAT_RO_COMPAT_REFLINK (1 << 2) /* reflinked files */ -#define XFS_SB_FEAT_RO_COMPAT_INOBTCNT (1 << 3) /* inobt block counts */ +#define XFS_SB_FEAT_RO_COMPAT_FINOBT (1 << 0) /* free inode btree */ +#define XFS_SB_FEAT_RO_COMPAT_RMAPBT (1 << 1) /* reverse map btree */ +#define XFS_SB_FEAT_RO_COMPAT_REFLINK (1 << 2) /* reflinked files */ +#define XFS_SB_FEAT_RO_COMPAT_INOBTCNT (1 << 3) /* inobt block counts */ #define XFS_SB_FEAT_RO_COMPAT_ALL \ (XFS_SB_FEAT_RO_COMPAT_FINOBT | \ XFS_SB_FEAT_RO_COMPAT_RMAPBT | \ @@ -722,6 +729,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 8bca86e350fdc..38b314113d8f2 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 7a848cacd561d..330acf1ab39f8 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 4618caf344efd..2a8d5561da9d0 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" @@ -527,3 +528,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 f1cdffb2f3392..e33afd8f3e256 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -234,11 +234,21 @@ 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_version_hasmetadir(sbp)) + 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 +270,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 +351,62 @@ 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_rextents) + return 0; + + 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 +418,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 +468,12 @@ xfs_validate_sb_common( return -EINVAL; } } + + if (xfs_sb_version_hasmetadir(sbp)) { + 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 +765,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 +922,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); + } } /* @@ -986,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 = 0; + 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); } /* diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h index 2f7413afbf46c..0343926d2a6b4 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 137fb5f88307b..6d49893fc91c7 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -355,12 +355,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 308049f2fb79d..b2c0c3fe64a11 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->rtg_mount; + 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->rtg_rgno; + } + + 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 Fri Aug 23 00:21:41 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: 13774442 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 4E1F71CD00 for ; Fri, 23 Aug 2024 00:21:42 +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=1724372502; cv=none; b=Gyu+d9GCBTJJdB3Mp+/pRfx5tjA/6YuunDLEVRYdUG6dWRMni80viH9ZnM4gpHSdOv8SzTDy+Fc3NFOV+rAtptQfWbjH96HN7PfwU5j79zE0B2rE3TGPuBFKn+yh3GjxwxeH5/1o/BmNP/csBETSdLyvk02LFyymctDectei8Zk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372502; c=relaxed/simple; bh=Q0h1mJRli+a7MUefz5V1Ws6B4imJWGnvamuhwUp7a9M=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=QXsqYJyG1xKnOOs68DJoywxVeYy4J8wEtnzEuFuL9EBxRlE2oMfJ7TF7BARvBIniy0ymN/EySnpNE4DuhCpZ9QzUDuvwasG/N7gpdQL/W/00Jm2vBlOHGFJyVepRklX65gCqGDWeSH+O8ihj5y3I7duVnb+puDXe3YUyrHBZg3A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MGY3rb4U; 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="MGY3rb4U" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2823DC32782; Fri, 23 Aug 2024 00:21:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724372502; bh=Q0h1mJRli+a7MUefz5V1Ws6B4imJWGnvamuhwUp7a9M=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=MGY3rb4UjYSMxTBfTodp0Hv8IkoBd2bpYgifVuNR/slHMAzW39UlMQ0D2nNTI+hSY Tx00XXpE+WVGMlbw+m7dw24Vz4xQXN/lI62vWxdCmxTTI87zt7GjSjjEW1uyZUPAqM w2WxuFEJ3nhawDNg0I78I8G0doflQkrm9qIatz5itd7RJYugZBdGOj8w5mYG3YcRqV D+CBC/zcRfziy1+VfUk8zMnO7scqCgYSLSJekDyCxUtsS8aeRpJ9umfHZar5/21/3j Ml/quO/LLne+v8JUUUGOvD5/1JuoHSsCQqpqyHXZHlYzKPbD9hHCoUnZDfP4RMh0y3 qqhbPW7VKXMOQ== Date: Thu, 22 Aug 2024 17:21:41 -0700 Subject: [PATCH 02/26] xfs: check the realtime superblock at mount time From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <172437088552.60592.7439081149023620735.stgit@frogsfrogsfrogs> In-Reply-To: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> References: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Check the realtime superblock at mount time, to ensure that the label 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 6d49893fc91c7..1da20fafcf978 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -85,6 +85,7 @@ typedef struct xfs_mount { struct super_block *m_super; struct xfs_ail *m_ail; /* fs active log item list */ struct xfs_buf *m_sb_bp; /* buffer for superblock */ + struct xfs_buf *m_rtsb_bp; /* realtime superblock */ char *m_rtname; /* realtime device name */ char *m_logname; /* external log device name */ struct xfs_da_geometry *m_dir_geo; /* directory block geometry */ diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index b2c0c3fe64a11..d8aa354b3bf14 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 a6836da9bebef..8e2a07b8174b7 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 2767083612bf6..835886c322a83 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); @@ -1680,9 +1682,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 @@ -1774,6 +1780,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: @@ -1793,7 +1801,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 Fri Aug 23 00:21: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: 13774444 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 541431CD00 for ; Fri, 23 Aug 2024 00:21:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372518; cv=none; b=icvfQbYzz4rjhpxmaHylpHYG6l0jK95N8qeZgDQ4q2W2u5PG+WNn4QVPRPBC/Eu7W9HWHie39sV6WO6NUdisWk6GBNR75JrunmJGmFTuJG+lfbhTIrUH840Iu3uxuQQZ/2MKGGlNisdW3laYikN7RTTZb+/ItqeyU9CZWx5pnOg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372518; c=relaxed/simple; bh=Tt6OTSVQs1jocken5z6N4HajYe+AA4ZyCY0xHKUDDao=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=kSh5wGlCqJkCWiENFSr/yBfB3VmI3GiS+JloyxFH8TgSRGadSIjtf4L+as8SVith/9qko1EGCvrbjEmnr/CEpy2B9caT8iHkHOgFyKOiHPHnMmrJpi+PFlfeMopAFd5KruB6tt0YIxsiZ5S2NBt5+ajFuoEVJKCyiaUUMTH2HqU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=XTFtYeEn; 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="XTFtYeEn" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C6296C32782; Fri, 23 Aug 2024 00:21:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724372517; bh=Tt6OTSVQs1jocken5z6N4HajYe+AA4ZyCY0xHKUDDao=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=XTFtYeEnJ/Fm0yv5+yenj7kQmRbLcz1B9RUNbarkhxCzUYapR6/EgkZNCqhkNQvXV r3/BMZ/icYGoQZJxxV5/kK0vVRQaEZfP6dHjVnyx+hf+UbLfQxlDyFSMeacSUVc7My W9jZ5n1G2p3RyWoVM9lpxQlG8/+VFg4Zonna+3cwnf9IKVq2lUPTLtsAT9vpxY6qNS LFVhGFEd5DDm1k7UZkhwCDq5wF3ynb2lNQULnzZpocDYY+D1axy6rVoadxJI36nXwu 2hzUESX4scXrr45DHvGjRV6IYzcS5+Nal8DbASHenA1X2XeWSMD0SG1dDKviIqViT1 yIlj/ilIfHDsg== Date: Thu, 22 Aug 2024 17:21:57 -0700 Subject: [PATCH 03/26] xfs: update realtime super every time we update the primary fs super From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <172437088569.60592.5726593744140992214.stgit@frogsfrogsfrogs> In-Reply-To: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> References: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Every time we update parts of the primary filesystem superblock that are echoed in the 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 | 18 ++++++++++++ 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, 124 insertions(+), 8 deletions(-) diff --git a/fs/xfs/libxfs/xfs_rtgroup.c b/fs/xfs/libxfs/xfs_rtgroup.c index 2a8d5561da9d0..89194a66267e2 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.c +++ b/fs/xfs/libxfs/xfs_rtgroup.c @@ -609,3 +609,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 e622b24a0d75f..a18ea0aca3db1 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.h +++ b/fs/xfs/libxfs/xfs_rtgroup.h @@ -258,11 +258,18 @@ 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 # define xfs_rtgroup_extents(mp, rgno) (0) # 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 e33afd8f3e256..29b20615d80bb 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. @@ -1270,10 +1271,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); @@ -1283,6 +1286,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) @@ -1291,7 +1299,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 885c837559914..999dcfccdaf96 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 09e893cf563cb..51cb239d7924c 100644 --- a/fs/xfs/xfs_buf_item_recover.c +++ b/fs/xfs/xfs_buf_item_recover.c @@ -22,6 +22,7 @@ #include "xfs_inode.h" #include "xfs_dir2.h" #include "xfs_quota.h" +#include "xfs_rtgroup.h" /* * This is the number of entries in the l_buf_cancel_table used during @@ -995,6 +996,23 @@ xlog_recover_buf_commit_pass2( ASSERT(bp->b_mount == mp); bp->b_flags |= _XBF_LOGRECOVERY; xfs_buf_delwri_queue(bp, buffer_list); + + /* + * Update the rt super if we just recovered the primary fs + * super. + */ + if (xfs_has_rtsb(mp) && bp->b_ops == &xfs_sb_buf_ops) { + struct xfs_buf *rtsb_bp = mp->m_rtsb_bp; + + if (rtsb_bp) { + xfs_buf_lock(rtsb_bp); + xfs_buf_hold(rtsb_bp); + xfs_update_rtsb(rtsb_bp, bp); + rtsb_bp->b_flags |= _XBF_LOGRECOVERY; + xfs_buf_delwri_queue(rtsb_bp, buffer_list); + xfs_buf_relse(rtsb_bp); + } + } } out_release: diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 461780ffb8fc0..c5526434f66fd 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 bdf3704dc3011..5fd1765b3dcd8 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 f06cc0f41665a..f97e5c416efad 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 e28ab74af4f0e..8e886ecfd69a3 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c @@ -168,12 +168,11 @@ xfs_trans_get_buf_map( /* * Get and lock the superblock buffer for the given transaction. */ -struct xfs_buf * -xfs_trans_getsb( - struct xfs_trans *tp) +static struct xfs_buf * +__xfs_trans_getsb( + struct xfs_trans *tp, + struct xfs_buf *bp) { - struct xfs_buf *bp = tp->t_mountp->m_sb_bp; - /* * Just increment the lock recursion count if the buffer is already * attached to this transaction. @@ -197,6 +196,22 @@ xfs_trans_getsb( return bp; } +struct xfs_buf * +xfs_trans_getsb( + struct xfs_trans *tp) +{ + return __xfs_trans_getsb(tp, tp->t_mountp->m_sb_bp); +} + +struct xfs_buf * +xfs_trans_getrtsb( + struct xfs_trans *tp) +{ + if (!tp->t_mountp->m_rtsb_bp) + return NULL; + return __xfs_trans_getsb(tp, tp->t_mountp->m_rtsb_bp); +} + /* * Get and lock the buffer for the caller if it is not already * locked within the given transaction. If it has not yet been From patchwork Fri Aug 23 00:22:12 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: 13774445 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 905091CD00 for ; Fri, 23 Aug 2024 00:22:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372533; cv=none; b=LYAZExcQ02fh3FrNsdNkaFlSzhGFTdLf1NtiwtM/95NCalabF5TPF3eTrjfIuduUvUBccU0k87ZI5ghAlGknExLXGXlodtRoGI6Ad4WyqiG6K1fbevTR7ZWXhiI+OYwF3FXxq+Zr4UVm7CNomyL/UWF16ISePEUwCzRzNsHSdcw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372533; c=relaxed/simple; bh=bmmnxBPL7FwPtuqRCjGCasmd1tRFvMqNDQZix2c9HqY=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=BtrsuVju2QwLsqaubeJOof8/stAQ6XFKPc7eMjwg7W9J9+aOQi4rIglOPrbxhbm7bos5xK/X2jC4hs2RZN7aq0ST8KrBOUj7Sc5W4YGh5X5G3Bn9+2QyQC2awkIAqWnhEcciKMBEDgEwj9VCmYkJHrDDXTZm3XIVOdVXKGOiKKY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=kUuip3bN; 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="kUuip3bN" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 67FD8C32782; Fri, 23 Aug 2024 00:22:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724372533; bh=bmmnxBPL7FwPtuqRCjGCasmd1tRFvMqNDQZix2c9HqY=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=kUuip3bNC2dxM8qlNT6CbyaYYQMjTIXAwAqI59gYbcQN7N5cYkqFzLKHKswF4ldwm 6XDDsozN2XjIWugGVNU9m9jXjRNZq2tyqm+5o4CWC3O+mNdrM3JM5OHOgkoKRdNWp6 qIxpACAbXdpJP4rcXPGBopGox6Ns9p9l/yKPVaWfPlTp+btLVLDNgB8wY74KQRQCog +2ifhK5ie/PE2uBkn3i7VqqUWFOfYHViy9NX6pe5T0C4qwYgx/nGRFVihsCzj3tZ8i 9Lc3OK1cErSdLLukEmyn8OkyFJk6ihOKvOtDVCsefz9VX6ea8yG2SbbCyaESWTd8CN 3Aml6lYtvJTYA== Date: Thu, 22 Aug 2024 17:22:12 -0700 Subject: [PATCH 04/26] xfs: export realtime group geometry via XFS_FSOP_GEOM From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <172437088588.60592.14229821430878166126.stgit@frogsfrogsfrogs> In-Reply-To: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> References: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Export the realtime geometry information so that userspace can query it. Signed-off-by: Darrick J. Wong 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 b441b9258128e..57819fea064e7 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -186,7 +186,9 @@ struct xfs_fsop_geom { __u32 logsunit; /* log stripe unit, bytes */ uint32_t sick; /* o: unhealthy fs & rt metadata */ uint32_t checked; /* o: checked fs & rt metadata */ - __u64 reserved[17]; /* reserved space */ + __u32 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 29b20615d80bb..2a0155d946c1e 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -1407,6 +1407,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 Fri Aug 23 00:22:28 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: 13774446 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 2B2D41CD00 for ; Fri, 23 Aug 2024 00:22:29 +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=1724372549; cv=none; b=pkUbxzlm2e0tQFFL5WzP6ehX96FVRUBK982CKfV5rs/lI0vFx0UUnW3oP2lt+M8Dok/gA+8JteRv/x6u1Wha56iPy2Al5vRlC6HJ9xVRrQ+EnqYAS3kAPvpwDQ6RtWmSN6pCJn7cLaUJEfyf8ajjtih6Rdzup3zTX+40M59yCpU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372549; c=relaxed/simple; bh=+40wS/gmtPRH+RbrGL5cm7dNkmca/kHfiySqKQ4H5EA=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=IvD7NIc9cSq0UQYesZEt94QAJvmSkpJbVO5gsFTIOZz243ZLv7wYNEkcOsQamX2xVec6LzqJi/0//H5xP77tlXejxTx+/q1fLylTo0C4pZL9tAT4sFhyoRwH6+GdCQM/wuMDC1QZaTuRP/+J6m2dYYZYZa317TbeM4IYOofjUeo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=k+rP5Dag; 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="k+rP5Dag" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 01F5FC32782; Fri, 23 Aug 2024 00:22:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724372549; bh=+40wS/gmtPRH+RbrGL5cm7dNkmca/kHfiySqKQ4H5EA=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=k+rP5DagT2sxGGsZUOKDYSC5s/PnIYckogzJeiJS7UH0cEy0AOFBX7EdcLFtp9/7o wPIWPNLt+LFpOQgc6MSZJBjK9aen0mmIAKgtCk+mbJeNs+lnjcorDTAlfteGmjFRQl r5M//kneF7pFl7WRIMTSBrzqsF/Nf3cn8FqvecHKH3Vgr7yF7o29L7J+1oaK9tEhM2 JxrzqDKjtxK6KFjk3/+GM/3Sqjo99QkjweoWRCG4TfgOYGdGcQsqdMCuKu0M0kqTFa Ie/ONg35vV2M+2LJHp9pAU9QrI6uvOsxUHPhqLxnYWd/92oa1sehwtgvYEFpY1yC5p s6ZY34CmKaaBQ== Date: Thu, 22 Aug 2024 17:22:28 -0700 Subject: [PATCH 05/26] xfs: check that rtblock extents do not break rtsupers or rtgroups From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <172437088605.60592.17624348368832345999.stgit@frogsfrogsfrogs> In-Reply-To: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> References: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Check 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 c299b16c9365f..8625cbaf530e5 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 Fri Aug 23 00:22:44 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: 13774447 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 09EC41CD00 for ; Fri, 23 Aug 2024 00:22: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=1724372565; cv=none; b=c/kB4zqSTWET59pVYR8z6ZNXXIWu6MraAhEL2XTy7NxP7OqCDLHfKnyGSWnQUDjujRfQ3Ds1RAyFPyQAFKMDIHPBiBLCA9UUBs0VCjlIJp8nAfEGsmB2m8WYqpneTPkyFWIDxutJ/O0tmXRwgHR0UFZHtTdsa8ML+7MPWQxl/uU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372565; c=relaxed/simple; bh=vVdYHEhp1+MQnI8Nn3HxO9xViZ8yiv0XGLe6p2oPTNc=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Rkcq9jXfypjlsp6ICzZZcYPmE1hkyqGMN/twOz2nIagreeXGLmNb4fR6Kppv9kfCXg4qpGGdm5fYDrJaQHLBMqcb7X2sK9kq3XqmMQYL7wR2lJCqIvmfXDM2CHw5ij5avz9tdw3ocS4hHLeaNPQgqn2WD6xvgFS/zzgJecAvAF0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gkb+v38G; 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="gkb+v38G" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8F697C4AF0B; Fri, 23 Aug 2024 00:22:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724372564; bh=vVdYHEhp1+MQnI8Nn3HxO9xViZ8yiv0XGLe6p2oPTNc=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=gkb+v38G8mGggF3DjIJzyvKBqSd0TyFbFd6SVwFzIDCArd/7sYyUkU8/Jt/NP33Cg htXnRm+8UREAh+1cQrNgwvWRJN5aQPTPXU/ib2TthDa92LIrg7RqZVdDXq+wlAB2s2 YiExPor4AL9becg62+/XSYYWkn5hl3dzZ9tAm0Q1N+ljnWTwDt30fLCniyQ9wMvYcK LBcdJU4OiRTU8GMnQz5Oa4BRD7BtbBcSnl6IvCoJjmAMxF7tZhhUDI7wdQlOFFBMvM R6HjkI2S36kEfq9+NFOt+bRCkj42W9EbKSsaPSKj4VHYAOv00wXmlwNRhnZ5hTm/HM mYuTFESALBaQQ== Date: Thu, 22 Aug 2024 17:22:44 -0700 Subject: [PATCH 06/26] xfs: add a helper to prevent bmap merges across rtgroup boundaries From: "Darrick J. Wong" To: djwong@kernel.org Cc: Christoph Hellwig , hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <172437088622.60592.12740637056884834042.stgit@frogsfrogsfrogs> In-Reply-To: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> References: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: 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 c056ca8ad6090..f1bf8635a8cf3 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; @@ -5766,6 +5793,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 */ @@ -5781,7 +5810,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; @@ -5817,7 +5847,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; @@ -5979,7 +6009,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); @@ -6115,7 +6146,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 Fri Aug 23 00:22:59 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: 13774448 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 63823195 for ; Fri, 23 Aug 2024 00:23:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372580; cv=none; b=mRUIqCNB4cvhKfNNDo9f6fYijv42WauaU0y1yvcvbG8HCfWp+arYCWGkAiQUcl2Q/NIXOwZ0yDVtadLKsrqfnobXaqwYZr3qPLnrhgzfcArMHTyEWf+QSCiR3VadCC38iiA/+p/fi0+J2TCHmxYu6qxQm505bIY/C9tWwHCKjh4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372580; c=relaxed/simple; bh=yBbPEYGqoX6v/ndyUJYZggAmV3C/0u8kYXInVej2KQI=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=vAEf4FAPI2dtHIDCjGZiHiT3pDb65mxDJTeNC5STL6ONKZdqJ1QAJU/V/ib8hwDSMnrJZuUCw/KJdp7640vOcZPdJTPPTVK2V4cgRKjWcRA5RIkyZnVnbmaCHQ1qS2Ucfk4vHsG/ExVQJGK5taPjYzQBQZ6QCeaxD7uG1RT5mFc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gbPwnssc; 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="gbPwnssc" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4261EC32782; Fri, 23 Aug 2024 00:23:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724372580; bh=yBbPEYGqoX6v/ndyUJYZggAmV3C/0u8kYXInVej2KQI=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=gbPwnsscIyammsqT59XzovYIPCgrlB6qlWgmlAgOTs/OE4J2coyR0P+XLbcA2tvzT lIbRvJSM5YqTjiJtKbbE1jnLRsKiMfbXglYqM5IVRS0+pr3zgNW1j3y3C6HG6lqMa0 uwaJ5ueGaUUKNtmS0vIpIO9IVxoZ5lUI2XSnY5GgzgL44ZxzLn3l7bl43/UaZ5Ocib SG5hIm64rTQ309ZEBjX5XZWcrAu3mZ5kogBmD8QuvQ+Ynkf50XOXbHAasqh0Qqm7S4 4AnLvY5byQUhQYYNhcTao7+y11l7D2HS3PDPxCZHpuVIGfUtzyejuWFNcTNcKTCWqF DbEMUnPczTiag== Date: Thu, 22 Aug 2024 17:22:59 -0700 Subject: [PATCH 07/26] xfs: add frextents to the lazysbcounters when rtgroups enabled From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <172437088640.60592.9292030505966688400.stgit@frogsfrogsfrogs> In-Reply-To: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> References: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Make the free rt extent count a part of the lazy sb counters when the realtime groups feature is enabled. This is possible because the patch to recompute frextents from the rtbitmap during log recovery predates the code adding rtgroup support, hence we know that the value will always be correct during runtime. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_sb.c | 8 ++++++++ fs/xfs/scrub/fscounters_repair.c | 9 +++++---- fs/xfs/xfs_trans.c | 17 ++++++++++++++--- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index 2a0155d946c1e..109be10c6e84f 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -1146,6 +1146,11 @@ xfs_log_sb( * sb counters, despite having a percpu counter. It is always kept * consistent with the ondisk rtbitmap by xfs_trans_apply_sb_deltas() * and hence we don't need have to update it here. + * + * sb_frextents was added to the lazy sb counters when the rt groups + * feature was introduced. 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_lazysbcount(mp)) { mp->m_sb.sb_icount = percpu_counter_sum_positive(&mp->m_icount); @@ -1155,6 +1160,9 @@ xfs_log_sb( mp->m_sb.sb_fdblocks = percpu_counter_sum_positive(&mp->m_fdblocks); } + 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); diff --git a/fs/xfs/scrub/fscounters_repair.c b/fs/xfs/scrub/fscounters_repair.c index 469bf645dbea5..cda13447a373e 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 5fd1765b3dcd8..552e3a149346c 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: /* @@ -510,8 +512,14 @@ xfs_trans_apply_sb_deltas( * * Don't touch m_frextents because it includes incore reservations, * and those are handled by the unreserve function. + * + * sb_frextents was added to the lazy sb counters when the rt groups + * feature was introduced. This is possible because we know that all + * kernels supporting rtgroups will also recompute frextents from the + * realtime bitmap. */ - if (tp->t_frextents_delta || tp->t_res_frextents_delta) { + if ((tp->t_frextents_delta || tp->t_res_frextents_delta) && + !xfs_has_rtgroups(tp->t_mountp)) { struct xfs_mount *mp = tp->t_mountp; int64_t rtxdelta; @@ -619,7 +627,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); } @@ -655,8 +663,11 @@ xfs_trans_unreserve_and_mod_sb( * Do not touch sb_frextents here because we are dealing with incore * reservation. sb_frextents is not part of the lazy sb counters so it * must be consistent with the ondisk rtbitmap and must never include - * incore reservations. + * incore reservations. sb_frextents was added to the lazy sb counters + * when the realtime groups feature was introduced. */ + if (xfs_has_rtgroups(mp)) + mp->m_sb.sb_frextents += rtxdelta; mp->m_sb.sb_dblocks += tp->t_dblocks_delta; mp->m_sb.sb_agcount += tp->t_agcount_delta; mp->m_sb.sb_imax_pct += tp->t_imaxpct_delta; From patchwork Fri Aug 23 00:23: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: 13774449 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 630AD33D8 for ; Fri, 23 Aug 2024 00:23:16 +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=1724372596; cv=none; b=PKp0+rVy414ggfPLq5b6x2vpOtnxiUOMafRiPXhDjTdKaZMCofouPzBp2LM5LaqKRaJDKvsy4xHooTexqPx78uiqYZoT7PVZ3h6g4bZi7iphQPHi30CtsNyh6ocOQMWnHB3RN8Mo+WRrrQ80WU7Dyk2nySvCkDQHvvh7mcRiO0Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372596; c=relaxed/simple; bh=VW2SPhg0sYzaTSIjhoxv+aT+VDQVA002e0u20lDNIsw=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Ffg4YiE2EKCP5ky5bW2P2NdHB8N4FID19eplWnApEWq9bdGiWBSrGDmxjk8LHzJyMNkvV2PW0BRlGukY9S+Vc+G5SudQGqoYqC0hZ2BiSRigT8TL4ug+Fzl2/AMiezfZDRMW8/oidCcNDgsqv3ddSC/CT9h428/61wRmnKgK7Z4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=c9Pzynby; 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="c9Pzynby" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E3CEAC32782; Fri, 23 Aug 2024 00:23:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724372595; bh=VW2SPhg0sYzaTSIjhoxv+aT+VDQVA002e0u20lDNIsw=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=c9PzynbyDi0CUiuOFyxkx1OMOnhCwi9exmH4T7V3RLCR+Eh4Zmaqw0t73fJAlXUXx OSyyii096QoMAaFmeDymNJV6im6gv8L1bKfQOyGe5ccjPj11/es3+bqZqBh6qX4qyv cWRYVI7cjtcMokTkKjthmjTQTV6q2ithV0qJAqFl8OQjKtjEhUeg6jNipHIsJBPvUi VEcg5XmjqkDQcDVbda8bjQpPsN9HpR/yZQ62RyDeomxJlyzaOtNqFQxOx3zKQHYtIW CFz5SYVZFaj+3z0/isLbtzVn6QWsEAxvdFOaNR9mLiJr28Y9UI86eyktPixsPkG0qw SM7gIN/qFQeHQ== Date: Thu, 22 Aug 2024 17:23:15 -0700 Subject: [PATCH 08/26] xfs: convert sick_map loops to use ARRAY_SIZE From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <172437088657.60592.5339918682104748305.stgit@frogsfrogsfrogs> In-Reply-To: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> References: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong 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 0bdbf6807bd29..cb43bd11dcac5 100644 --- a/fs/xfs/xfs_health.c +++ b/fs/xfs/xfs_health.c @@ -369,6 +369,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 }, @@ -378,13 +381,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 @@ -414,11 +415,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); } @@ -434,7 +435,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. */ @@ -451,7 +451,7 @@ xfs_ag_geom_health( ageo->ag_checked = 0; xfs_ag_measure_sickness(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) @@ -473,7 +473,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. */ @@ -490,7 +489,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 Fri Aug 23 00:23:31 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: 13774450 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 13B45AD49 for ; Fri, 23 Aug 2024 00:23:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372612; cv=none; b=CTIzsdChfBFzL5YzfY1jJD6KH7jvYont68lN3uhkRmYUekBBQ6CqcRhXrGtQquv1Ppnu9mQyXeKaGuMzdoRvA/MgV3D6f2Y2NosRPRZqrEo3fbDxj+Fw4Bp0ovfH7M6U4rAZvDzi9hBI6Xxqb5v2b0FNXS9Ybp1GP4QzDOEzxs8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372612; c=relaxed/simple; bh=9eW0BvXaOIhkvOUwCaANvv3gtpcstzbgT/OECVJ7/qQ=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=JJAvtylONBzLa5ddlam9C0+KHSAIgynftMUCV0wVw385tOIq4dlBNJFB8fhKmDO46w2aTE6Oj5hFoEXWXze5yM5UAEkCUZaIdpXCz31+bCZ2S+UGqdEk5D86Q0dARM/D4PbzoKcrE/dTF3JalInWHSYC7eoPFvqqKTSlyhKkKsA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=C6deJIVi; 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="C6deJIVi" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 849BDC32782; Fri, 23 Aug 2024 00:23:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724372611; bh=9eW0BvXaOIhkvOUwCaANvv3gtpcstzbgT/OECVJ7/qQ=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=C6deJIVifyJAycfNOrRC4zI3CLPC/uORaQthvUA+/TC6kyb5AG1mYUGk5MzPGYi1b 4y7ya6Tw95T/fPoFGMVR6QxaqSZNv8n0XrEs05GYe16zodziyupCu1JQJa8R/VnlMp a5dUxcqP5URsjdrCY+gwxkaVz/v/mKFlBQY1+wJV/Byt4PKVuHnunXTfKz5pyav/lb Iat0TlQBI+9Rx3IylQVkhrxfaNnTrHwRdlQVei2pwWNyWLE5vy9JWOX1JpqZ7rCZv8 s1LktdJUcxUKTab3tpxq2QmhUXvaaXCYSwOY91a7RQH8HRWw9VDQXgqm+IlD84s+po 5UvGBggWPbWaA== Date: Thu, 22 Aug 2024 17:23:31 -0700 Subject: [PATCH 09/26] xfs: record rt group metadata errors in the health system From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <172437088674.60592.9324530021081393314.stgit@frogsfrogsfrogs> In-Reply-To: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> References: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Record the state of per-rtgroup metadata sickness in the rtgroup structure for later reporting. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_health.h | 59 ++++++++------- fs/xfs/libxfs/xfs_rtbitmap.c | 37 +++++---- fs/xfs/libxfs/xfs_rtgroup.c | 38 ++++++++-- fs/xfs/libxfs/xfs_rtgroup.h | 9 ++ fs/xfs/scrub/health.c | 33 ++++++-- fs/xfs/xfs_health.c | 164 ++++++++++++++++++++++++------------------ fs/xfs/xfs_trace.h | 30 +++++++- 7 files changed, 236 insertions(+), 134 deletions(-) diff --git a/fs/xfs/libxfs/xfs_health.h b/fs/xfs/libxfs/xfs_health.h index 8abd345e23885..7e77e2df9704a 100644 --- a/fs/xfs/libxfs/xfs_health.h +++ b/fs/xfs/libxfs/xfs_health.h @@ -52,6 +52,7 @@ struct xfs_inode; struct xfs_fsop_geom; struct xfs_btree_cur; struct xfs_da_args; +struct xfs_rtgroup; /* Observable health issues for metadata spanning the entire filesystem. */ #define XFS_SICK_FS_COUNTERS (1 << 0) /* summary counters */ @@ -63,9 +64,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 */ @@ -109,8 +111,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 | \ @@ -140,26 +143,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) @@ -193,10 +196,12 @@ 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, +void xfs_rgno_mark_sick(struct xfs_mount *mp, xfs_rgnumber_t rgno, + unsigned int mask); +void xfs_rtgroup_mark_sick(struct xfs_rtgroup *rtg, unsigned int mask); +void xfs_rtgroup_mark_corrupt(struct xfs_rtgroup *rtg, unsigned int mask); +void xfs_rtgroup_mark_healthy(struct xfs_rtgroup *rtg, unsigned int mask); +void xfs_rtgroup_measure_sickness(struct xfs_rtgroup *rtg, unsigned int *sick, unsigned int *checked); void xfs_agno_mark_sick(struct xfs_mount *mp, xfs_agnumber_t agno, @@ -230,15 +235,6 @@ xfs_fs_has_sickness(struct xfs_mount *mp, unsigned int mask) return sick & mask; } -static inline bool -xfs_rt_has_sickness(struct xfs_mount *mp, unsigned int mask) -{ - unsigned int sick, checked; - - xfs_rt_measure_sickness(mp, &sick, &checked); - return sick & mask; -} - static inline bool xfs_ag_has_sickness(struct xfs_perag *pag, unsigned int mask) { @@ -248,6 +244,15 @@ xfs_ag_has_sickness(struct xfs_perag *pag, unsigned int mask) return sick & mask; } +static inline bool +xfs_rtgroup_has_sickness(struct xfs_rtgroup *rtg, unsigned int mask) +{ + unsigned int sick, checked; + + xfs_rtgroup_measure_sickness(rtg, &sick, &checked); + return sick & mask; +} + static inline bool xfs_inode_has_sickness(struct xfs_inode *ip, unsigned int mask) { @@ -264,9 +269,9 @@ xfs_fs_is_healthy(struct xfs_mount *mp) } static inline bool -xfs_rt_is_healthy(struct xfs_mount *mp) +xfs_rtgroup_is_healthy(struct xfs_rtgroup *rtg) { - return !xfs_rt_has_sickness(mp, -1U); + return !xfs_rtgroup_has_sickness(rtg, -1U); } static inline bool diff --git a/fs/xfs/libxfs/xfs_rtbitmap.c b/fs/xfs/libxfs/xfs_rtbitmap.c index 330acf1ab39f8..44e3c027c0537 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 89194a66267e2..3cb08f5cfc260 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.c +++ b/fs/xfs/libxfs/xfs_rtgroup.c @@ -316,6 +316,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); @@ -330,11 +332,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, }, }; @@ -368,6 +372,17 @@ xfs_rtginode_enabled( return ops->enabled(rtg->rtg_mount); } +/* 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_rtgroup_mark_sick(rtg, ops->sick); +} + /* Load and existing rtgroup inode into the rtgroup structure. */ int xfs_rtginode_load( @@ -403,8 +418,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->rtg_rgno, type); if (!path) @@ -414,17 +431,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->rtg_rgno)) { xfs_irele(ip); + xfs_rtginode_mark_sick(rtg, type); return -EFSCORRUPTED; } @@ -461,8 +483,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->rtg_rgno, type); if (!upd.path) @@ -509,8 +533,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); } @@ -522,8 +548,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 a18ea0aca3db1..f51f1a7592775 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.h +++ b/fs/xfs/libxfs/xfs_rtgroup.h @@ -36,6 +36,14 @@ struct xfs_rtgroup { /* Number of blocks in this group */ xfs_rtxnum_t rtg_extents; + /* + * Bitsets of per-rtgroup metadata that have been checked and/or are + * sick. Callers should hold rtg_state_lock before accessing this + * field. + */ + uint16_t rtg_checked; + uint16_t rtg_sick; + /* * Optional cache of rt summary level per bitmap block with the * invariant that rtg_rsum_cache[bbno] > the maximum i for which @@ -247,6 +255,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 e202d84ec5140..a0a721ae5763d 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,12 +163,15 @@ xchk_mark_all_healthy( struct xfs_mount *mp) { struct xfs_perag *pag; + struct xfs_rtgroup *rtg; xfs_agnumber_t agno; + xfs_rgnumber_t rgno; xfs_fs_mark_healthy(mp, XFS_SICK_FS_INDIRECT); - xfs_rt_mark_healthy(mp, XFS_SICK_RT_INDIRECT); for_each_perag(mp, agno, pag) xfs_ag_mark_healthy(pag, XFS_SICK_AG_INDIRECT); + for_each_rtgroup(mp, rgno, rtg) + xfs_rtgroup_mark_healthy(rtg, XFS_SICK_RG_INDIRECT); } /* @@ -185,6 +189,7 @@ xchk_update_health( struct xfs_scrub *sc) { struct xfs_perag *pag; + struct xfs_rtgroup *rtg; bool bad; /* @@ -237,11 +242,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_rtgroup_mark_corrupt(rtg, sc->sick_mask); else - xfs_rt_mark_healthy(sc->mp, sc->sick_mask); + xfs_rtgroup_mark_healthy(rtg, sc->sick_mask); + xfs_rtgroup_put(rtg); break; default: ASSERT(0); @@ -296,7 +303,9 @@ xchk_health_record( { struct xfs_mount *mp = sc->mp; struct xfs_perag *pag; + struct xfs_rtgroup *rtg; xfs_agnumber_t agno; + xfs_rgnumber_t rgno; unsigned int sick; unsigned int checked; @@ -305,15 +314,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); - for_each_perag(mp, agno, pag) { xfs_ag_measure_sickness(pag, &sick, &checked); if (sick & XFS_SICK_AG_PRIMARY) xchk_set_corrupt(sc); } + for_each_rtgroup(mp, rgno, rtg) { + xfs_rtgroup_measure_sickness(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 cb43bd11dcac5..e94a5ede103d4 100644 --- a/fs/xfs/xfs_health.c +++ b/fs/xfs/xfs_health.c @@ -18,6 +18,7 @@ #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_quota_defs.h" +#include "xfs_rtgroup.h" /* * Warn about metadata corruption that we detected but haven't fixed, and @@ -29,7 +30,9 @@ xfs_health_unmount( struct xfs_mount *mp) { struct xfs_perag *pag; + struct xfs_rtgroup *rtg; xfs_agnumber_t agno; + xfs_rgnumber_t rgno; unsigned int sick = 0; unsigned int checked = 0; bool warn = false; @@ -46,11 +49,13 @@ xfs_health_unmount( } } - /* 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. */ + for_each_rtgroup(mp, rgno, rtg) { + xfs_rtgroup_measure_sickness(rtg, &sick, &checked); + if (sick) { + trace_xfs_rtgroup_unfixed_corruption(rtg, sick); + warn = true; + } } /* @@ -150,65 +155,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( @@ -285,6 +231,82 @@ xfs_ag_measure_sickness( spin_unlock(&pag->pag_state_lock); } +/* Mark unhealthy per-rtgroup metadata given a raw rt group number. */ +void +xfs_rgno_mark_sick( + struct xfs_mount *mp, + xfs_rgnumber_t rgno, + unsigned int mask) +{ + struct xfs_rtgroup *rtg = xfs_rtgroup_get(mp, rgno); + + /* per-rtgroup structure not set up yet? */ + if (!rtg) + return; + + xfs_rtgroup_mark_sick(rtg, mask); + xfs_rtgroup_put(rtg); +} + +/* Mark unhealthy per-rtgroup metadata. */ +void +xfs_rtgroup_mark_sick( + struct xfs_rtgroup *rtg, + unsigned int mask) +{ + ASSERT(!(mask & ~XFS_SICK_RG_ALL)); + trace_xfs_rtgroup_mark_sick(rtg, mask); + + spin_lock(&rtg->rtg_state_lock); + rtg->rtg_sick |= mask; + spin_unlock(&rtg->rtg_state_lock); +} + +/* Mark rtgroup metadata as having been checked and found unhealthy by fsck. */ +void +xfs_rtgroup_mark_corrupt( + struct xfs_rtgroup *rtg, + unsigned int mask) +{ + ASSERT(!(mask & ~XFS_SICK_RG_ALL)); + trace_xfs_rtgroup_mark_corrupt(rtg, mask); + + spin_lock(&rtg->rtg_state_lock); + rtg->rtg_sick |= mask; + rtg->rtg_checked |= mask; + spin_unlock(&rtg->rtg_state_lock); +} + +/* Mark per-rtgroup metadata ok. */ +void +xfs_rtgroup_mark_healthy( + struct xfs_rtgroup *rtg, + unsigned int mask) +{ + ASSERT(!(mask & ~XFS_SICK_RG_ALL)); + trace_xfs_rtgroup_mark_healthy(rtg, mask); + + spin_lock(&rtg->rtg_state_lock); + rtg->rtg_sick &= ~mask; + if (!(rtg->rtg_sick & XFS_SICK_RG_PRIMARY)) + rtg->rtg_sick &= ~XFS_SICK_RG_SECONDARY; + rtg->rtg_checked |= mask; + spin_unlock(&rtg->rtg_state_lock); +} + +/* Sample which per-rtgroup metadata are unhealthy. */ +void +xfs_rtgroup_measure_sickness( + struct xfs_rtgroup *rtg, + unsigned int *sick, + unsigned int *checked) +{ + spin_lock(&rtg->rtg_state_lock); + *sick = rtg->rtg_sick; + *checked = rtg->rtg_checked; + spin_unlock(&rtg->rtg_state_lock); +} + /* Mark the unhealthy parts of an inode. */ void xfs_inode_mark_sick( @@ -384,8 +406,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 @@ -410,6 +432,8 @@ xfs_fsop_geom_health( const struct ioctl_sick_map *m; unsigned int sick; unsigned int checked; + struct xfs_rtgroup *rtg; + xfs_rgnumber_t rgno; geo->sick = 0; geo->checked = 0; @@ -418,9 +442,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); + for_each_rtgroup(mp, rgno, rtg) { + xfs_rtgroup_measure_sickness(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 4401a7c6230df..43bfa0d51c7d6 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -4224,10 +4224,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_ag_corrupt_class, TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, unsigned int flags), @@ -4256,6 +4252,32 @@ DEFINE_AG_CORRUPT_EVENT(xfs_ag_mark_corrupt); DEFINE_AG_CORRUPT_EVENT(xfs_ag_mark_healthy); DEFINE_AG_CORRUPT_EVENT(xfs_ag_unfixed_corruption); +DECLARE_EVENT_CLASS(xfs_rtgroup_corrupt_class, + TP_PROTO(struct xfs_rtgroup *rtg, unsigned int flags), + TP_ARGS(rtg, flags), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_rgnumber_t, rgno) + __field(unsigned int, flags) + ), + TP_fast_assign( + __entry->dev = rtg->rtg_mount->m_super->s_dev; + __entry->rgno = rtg->rtg_rgno; + __entry->flags = flags; + ), + TP_printk("dev %d:%d rgno 0x%x flags 0x%x", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->rgno, __entry->flags) +); +#define DEFINE_RTGROUP_CORRUPT_EVENT(name) \ +DEFINE_EVENT(xfs_rtgroup_corrupt_class, name, \ + TP_PROTO(struct xfs_rtgroup *rtg, unsigned int flags), \ + TP_ARGS(rtg, flags)) +DEFINE_RTGROUP_CORRUPT_EVENT(xfs_rtgroup_mark_sick); +DEFINE_RTGROUP_CORRUPT_EVENT(xfs_rtgroup_mark_corrupt); +DEFINE_RTGROUP_CORRUPT_EVENT(xfs_rtgroup_mark_healthy); +DEFINE_RTGROUP_CORRUPT_EVENT(xfs_rtgroup_unfixed_corruption); + DECLARE_EVENT_CLASS(xfs_inode_corrupt_class, TP_PROTO(struct xfs_inode *ip, unsigned int flags), TP_ARGS(ip, flags), From patchwork Fri Aug 23 00:23:46 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: 13774451 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 E660C33D8 for ; Fri, 23 Aug 2024 00:23: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=1724372628; cv=none; b=TwwoOLUvYeO0LLc/mBteHyk4Vd9tgHLbPTZgv7pm+GVUk3z5ejAZjUYvYXbChYteBBPChBSPgInXJfqt5fCET77HEKTvIj/36O/Fudw+Dz5IUYP3NIqd1eRWZRqcNX8uxebO4ZTpJ9oML3cBaD/AzfGZ5JjFt0fXMn6eEoe5WCU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372628; c=relaxed/simple; bh=7IZIvt7yUl2cqrSyM8S5VSpUqxbN35hg4Lgi3so2FFI=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=fPpQPBSf2NBF35lkIb4FQfRYGuWIIuDrdz/bfpzhzfmnigNePmSXXWSbNVi5ojnj5LBazAGjDL2U57C8B5bjz3z/jiVFjoxFVycrML22MD/zvRdhLvp8qmyeF6TW+NaUfRUk0VtyGTE8QHgYezH5A7PQan3QbpPknyAKtdkdK/Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=SWHhoXah; 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="SWHhoXah" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 321E2C32782; Fri, 23 Aug 2024 00:23:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724372627; bh=7IZIvt7yUl2cqrSyM8S5VSpUqxbN35hg4Lgi3so2FFI=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=SWHhoXahtFXsDbhrj3TENrptbWEPBp5b1ODiwWUGxzD15KsaVOKbRMG9FIGjOmx7A Da80WgvVx8+zYZa8VIRtHbETlXxjkrW2ISbuhHwgY3oHRjNyc2FfB8PobF8es2SYTh HAYumCSvjZDXRblnSYJ5ndzTtYTahHtXgUVLZTBX5hquJIOXdr+onCkFxap6Zx7+ee o860LUqevYuFG2aDYQCuS87ZHtbZcb7DV13Ya+sVrK0xEbNxyk59VNs2512nSmwpQQ 5klPzAU81wpQoqZ99gEwAAxH52heva1r/1Uetxy35j6vACBDnmkq7wciNW6Q4Dcqmj YUYBatwpSeB5g== Date: Thu, 22 Aug 2024 17:23:46 -0700 Subject: [PATCH 10/26] xfs: export the geometry of realtime groups to userspace From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <172437088693.60592.13218743269576141133.stgit@frogsfrogsfrogs> In-Reply-To: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> References: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Create an ioctl so that the kernel can report the status of realtime groups to userspace. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_fs.h | 17 +++++++++++++++++ fs/xfs/libxfs/xfs_health.h | 2 ++ fs/xfs/libxfs/xfs_rtgroup.c | 15 +++++++++++++++ fs/xfs/libxfs/xfs_rtgroup.h | 4 ++++ fs/xfs/xfs_health.c | 28 ++++++++++++++++++++++++++++ fs/xfs/xfs_ioctl.c | 33 +++++++++++++++++++++++++++++++++ 6 files changed, 99 insertions(+) diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index 57819fea064e7..2dacc19723c37 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -971,6 +971,22 @@ 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_capacity; /* o: usable capacity 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 */ + __u64 rg_reserved[13]; /* 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 +1025,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 7e77e2df9704a..2da64555434d5 100644 --- a/fs/xfs/libxfs/xfs_health.h +++ b/fs/xfs/libxfs/xfs_health.h @@ -288,6 +288,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 3cb08f5cfc260..df70015c68dd0 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.c +++ b/fs/xfs/libxfs/xfs_rtgroup.c @@ -259,6 +259,21 @@ 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->rtg_rgno; + rgeo->rg_length = rtg->rtg_extents * rtg->rtg_mount->m_sb.sb_rextsize; + rgeo->rg_capacity = rgeo->rg_length; + 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 f51f1a7592775..4525aaa26efc2 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.h +++ b/fs/xfs/libxfs/xfs_rtgroup.h @@ -249,6 +249,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); @@ -279,6 +282,7 @@ struct xfs_buf *xfs_log_rtsb(struct xfs_trans *tp, # 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 e94a5ede103d4..b3d288df4ca20 100644 --- a/fs/xfs/xfs_health.c +++ b/fs/xfs/xfs_health.c @@ -485,6 +485,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_rtgroup_measure_sickness(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 c5526434f66fd..6f5cd06267873 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,36 @@ xfs_ioc_ag_geometry( return 0; } +STATIC int +xfs_ioc_rtgroup_geometry( + struct xfs_mount *mp, + void __user *arg) +{ + struct xfs_rtgroup *rtg; + struct xfs_rtgroup_geometry rgeo; + int error; + + if (copy_from_user(&rgeo, arg, sizeof(rgeo))) + return -EFAULT; + if (rgeo.rg_flags) + return -EINVAL; + if (memchr_inv(&rgeo.rg_reserved, 0, sizeof(rgeo.rg_reserved))) + return -EINVAL; + + rtg = xfs_rtgroup_get(mp, rgeo.rg_number); + if (!rtg) + return -EINVAL; + + error = xfs_rtgroup_get_geometry(rtg, &rgeo); + xfs_rtgroup_put(rtg); + if (error) + return error; + + if (copy_to_user(arg, &rgeo, sizeof(rgeo))) + return -EFAULT; + return 0; +} + /* * Linux extended inode flags interface. */ @@ -1225,6 +1256,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 Fri Aug 23 00:24:02 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: 13774452 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 F28BEAD49 for ; Fri, 23 Aug 2024 00:24:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372643; cv=none; b=J63zz9cFu6fMBo0ZZHkfRvV/RmKNmCSS+DyFIZbWKwYnkBtyB1nbFX7wSwbgRDt/deonN8A8SrCnGZZz5CnwEbRkbb+hPBc+Wq1DYZ3wwKCDxxWWh1ku33GOPRO51xJwkO8D9mMBElJtSQAmdGEiKrGqimtFwOaLIYLG+NqCZRg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372643; c=relaxed/simple; bh=U+zUUPisBTBLEp+O3fy1R0lwdhMRWZ27jJaiGuCYdNI=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=aOo6FyNUMf26B/e1FOXMh+bCiBH2AoML5ZZ9tTPMJqZNhS8os1SMSWXpxZY/mGQFEGKNOLDd0Y1E/y4IaOF6Slo9AxOLE/1shUVAHUEyXPykDT2IHbEseVP+a/k8AOub15/RAmHOEdtadMC+0/bw5MxXiUA7S+JbzGx3zc56eKI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=XcJpIo4S; 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="XcJpIo4S" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C5DA2C4AF09; Fri, 23 Aug 2024 00:24:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724372642; bh=U+zUUPisBTBLEp+O3fy1R0lwdhMRWZ27jJaiGuCYdNI=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=XcJpIo4S4rDhldR4a5r+pj5iispvF/9pJkQLNPxlcvYxemgafg4wkB9r8VMtg/fzE ARsgR7qKVlp2eB/rSjAklv9VZikUVisXbw6s33EzUYFuGuweYeLlNS8bUuLw2EvwyK gQEySEik3Aw/LnRhKpv3ljym6bambPKF5OYTzIVordgElc0617FIf6Ilfg4+lI55JI yVpHzq6ZNc5r98kxk2lhMNfIzlPymf+N3VRMdunu8T7zAeWuPTQsqBkPvSnYiK5xOr T1icvOf6MtkHtLryUu/ESKMwt0qOEEG33D3H4zV27f+SGNdjbJyoiKGsKxDIlFB2pX 3a3HKRw4Lzhdw== Date: Thu, 22 Aug 2024 17:24:02 -0700 Subject: [PATCH 11/26] xfs: add block headers to realtime bitmap and summary blocks From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <172437088710.60592.14084013825936440220.stgit@frogsfrogsfrogs> In-Reply-To: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> References: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Upgrade rtbitmap 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 | 20 +++++ 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, 256 insertions(+), 28 deletions(-) diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index 9e351b19bd86e..27193a2b0ea62 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -1272,6 +1272,24 @@ static inline bool xfs_dinode_has_large_extent_counts( #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 38b314113d8f2..6a2bcbc392842 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 44e3c027c0537..dfac0e89409a9 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 cf21ae31bfaa4..13a05dce47601 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 109be10c6e84f..f94d081f7d928 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -245,11 +245,25 @@ 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_version_hasmetadir(sbp)) + 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 */ @@ -1092,8 +1106,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; xfs_mount_sb_set_rextsize(mp, sbp); mp->m_alloc_mxr[0] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 1); diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h index 0343926d2a6b4..4f5f1d3526803 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 1688380988007..8198ea84ad70e 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 51cb239d7924c..c55c911446728 100644 --- a/fs/xfs/xfs_buf_item_recover.c +++ b/fs/xfs/xfs_buf_item_recover.c @@ -23,6 +23,7 @@ #include "xfs_dir2.h" #include "xfs_quota.h" #include "xfs_rtgroup.h" +#include "xfs_rtbitmap.h" /* * This is the number of entries in the l_buf_cancel_table used during @@ -391,9 +392,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: @@ -728,11 +738,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 e1a024f68a68f..b66780cbe55bf 100644 --- a/fs/xfs/xfs_discard.c +++ b/fs/xfs/xfs_discard.c @@ -572,7 +572,7 @@ xfs_trim_rtg_extents( * 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 1da20fafcf978..c4e4f5414a299 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -116,7 +116,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 d8aa354b3bf14..6989ee1c13fa0 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->rtg_mount; 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 Fri Aug 23 00:24:17 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: 13774453 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 899B21C680 for ; Fri, 23 Aug 2024 00:24:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372658; cv=none; b=kL4iM+A6vaLHns31aYac11rv9t8x432pyct1Ghy0D3qCsJu4X5jIFME8wzt7/jNpaNgkfK6RiP+f13XO/8nP3tGfY6s06JO52F9E1g7IUA1+Q2Pgy/aqy5XvTlKVQyLFFn+MyXTPGcjJycFG2Uske+dPgTTigFe3DSf0PF6Hi/8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372658; c=relaxed/simple; bh=G0QICNynuxKbuWXKSkcNUUhJ2oi0wkUSC9bFeA38+RA=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Xmhaisj+c+LwFqilquyAokDB6Bn58Cfkui4+kDB8V0PpiCDsJ+d/PesV+pBKkP0+/GqEafKbgdUL3+KlJ0+wU3BsOKEmD7OwOk71HuAHjNzQ7gGjZ2EoqVnhrFC0CpOMroMW+JpnMyRaySVYuSsu/nJWeKemOoQDuTYuSHKhteQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WMxb8qya; 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="WMxb8qya" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6371DC32782; Fri, 23 Aug 2024 00:24:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724372658; bh=G0QICNynuxKbuWXKSkcNUUhJ2oi0wkUSC9bFeA38+RA=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=WMxb8qyaFfskdMiV0dpMCWD8/pkrA19mCPktuSe4lqJmN6KLuPlpqWeOdaoQ3fjnI Z3Fi+gmSAtGmeAWM9n+MJ00JU2iWlNqNsQOTFn6FpFl2SxenJBc1nslucSIll0e8zv hbwEb+9H4SacIuD7QbCTZ24Tyzl8oh60Qo0kAyyRJqEsmp5Vuytu9lVsAcWrEv0kyA BS1zNKedGUjx6QM7rgGtHDFcWu3y5aEbI9Nw/2R4DQlfZHNZaA/cBSe41FXiR9kpbn SQJJ2t3o5QUPbKoKF9VxGqL370AFY3ot3k3dKXsSW6W6h7m6IylT/RF417Iq9jV8cT eksGx4yricung== Date: Thu, 22 Aug 2024 17:24:17 -0700 Subject: [PATCH 12/26] xfs: encode the rtbitmap in big endian format From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <172437088729.60592.727533950842079798.stgit@frogsfrogsfrogs> In-Reply-To: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> References: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Currently, the ondisk realtime bitmap file is accessed in units of 32-bit words. There's no endian translation of the contents of this file, which means that the Bad Things Happen(tm) if you go from (say) x86 to powerpc. Since we have a new feature flag, let's take the opportunity to enforce an endianness on the file. 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 27193a2b0ea62..506f5d5ee03fe 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -715,10 +715,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 13a05dce47601..148f7631d7fc2 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 Fri Aug 23 00:24:33 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: 13774454 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 39E8C125AC for ; Fri, 23 Aug 2024 00:24:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372674; cv=none; b=Atz4jGOazFd9RhzuPy5SE4l3SQJgjwQcAhbqrd1U/4Y9RNtQXpeUEGB52KiOqtIAhtG0r7EPh3MJASlNKtIImvFQENzSa9tVv9zJ93oBYPJYb4oU19pb1i7zSZmbBQip+OH3+7QbJZb4V7LTZ5hNz3orKqAE9JFmDwOcfLnTrrY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372674; c=relaxed/simple; bh=RN0EPSVbkpCHJZzaYLOPnBuaz/fNE93GtDMByqdH2mA=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=GYkvjArH2lsGxJpXyuc+1CIvFy//x/RbbWKJuRvq7BA1M92pytaTNrDRoyahnq6i1P0cywdFFhIJVsPe135zLyAa2FF1kDki4frE86/ZF9nQr8F9KeeeNn63ocuHLT6YO/HREEHiiwnbwovPofBMieVlMz7a5U0xEE1pvzkyFbE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=iZzTb3jz; 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="iZzTb3jz" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 15231C32782; Fri, 23 Aug 2024 00:24:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724372674; bh=RN0EPSVbkpCHJZzaYLOPnBuaz/fNE93GtDMByqdH2mA=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=iZzTb3jz+FT0MT463k42iGlokpeyDYyfmrbf9Ybh2KmGrdpuneI2ePBxrIPX5odj3 U+nBgrtGEvP7qdeITOK4guZ/2++82CUAcCxUM/A97DJM9tRWWdfOBQ3g13MGknyp2j 0EUF9e6hh5rEPt+pXhxWb0jBlSjLVk1wzPnj0cDYvOnLughYGyWFb8u4lxnKvcG6Ip bv830EuxWfD375IDPsegaTOkJ56jFfhU19YsiQwxJRHD0r0eX34Dl6veEIhVet/IPZ nhAB6rWaffIgPyovytxXYNdm0glk1w+A9Ayzb+REhkef7X21g29UydwXQxk75mU2WY ItxTeddfnM+SA== Date: Thu, 22 Aug 2024 17:24:33 -0700 Subject: [PATCH 13/26] xfs: encode the rtsummary in big endian format From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <172437088747.60592.2913943044668719207.stgit@frogsfrogsfrogs> In-Reply-To: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> References: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Currently, the ondisk realtime summary file counters are accessed in units of 32-bit words. There's no endian translation of the contents of this file, which means that the Bad Things Happen(tm) if you go from (say) x86 to powerpc. Since we have a new feature flag, let's take the opportunity to enforce an endianness on the file. Encode the summary information in big endian format, like most of the rest of the filesystem. Signed-off-by: Darrick J. Wong 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 506f5d5ee03fe..cafac42cd51ad 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -725,10 +725,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 148f7631d7fc2..d36fe2efc56f0 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 1f01ed9450388..f6779af92d57b 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 Fri Aug 23 00:24:49 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: 13774455 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 3EAE418059 for ; Fri, 23 Aug 2024 00:24:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372690; cv=none; b=IwRUZHs6hw2sMecwhs8/bRlpGM8UxZ2UJWxgVRnF4hzu+u+jWa+PT9CGZDsRbTbp8ozpn2r/R2t4wBxhVpy6hgMwNyIpBjZCkboictDzNGsgJRhKNiu5B5RXKXe6Xb+xAuZJo/RAB6gqgZbZ9MJIOsIsKTYysvGai5rCSpH6WVc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372690; c=relaxed/simple; bh=wX0JNR0BlLhxvTPwgZ+Z22fcpv9zRAjs4c1L+7miUkY=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Zj3kgqvb10eiYD0osPdHv9bWpJqtNL20HTtZav3ggqWI6UZ0k4amQXVdc9gZoVWZgacHGHSLW8lZQ7Kmm2K/XgYnaUsa2ItRX/JhdPMWafzv60xBxRUntztqyh/W6SmYj5bUDqgFhmkPBu39TiUHZ4On4dgYx0IRNMOlZDr5dy0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QXk9FX+B; 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="QXk9FX+B" Received: by smtp.kernel.org (Postfix) with ESMTPSA id ADDF1C32782; Fri, 23 Aug 2024 00:24:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724372689; bh=wX0JNR0BlLhxvTPwgZ+Z22fcpv9zRAjs4c1L+7miUkY=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=QXk9FX+BqFBH98//VKJvt4y920QMnfBvquB9ZJiQWL1q7lUY5gxbX0f6qpoONB97Q xjLZb06nSQzsioZDIyrLj+8SgYEv/VcnTT1r9sd/7We7dBzfyqMgHF+E+cIJ8ndmbD NLvlQ8PNVnOA8eC60fV301aky6OGHC2QJiZJ0rLzplCwoV3369SEUbonq9Fm+EYXpq 7eNOEscNYH1nf6sdZDz2N/C63R7qbJLFPx0DJ+vAAdyAIrcMmt0XzpP5HlC9xZXvqT /qsdA33DlRreLbyzmNoE9I3BuEvEK6siMRvR3o9+j+wtNnfrv2ev5WIfsJXySrt8Dj 9Wl1XWQqWOQzw== Date: Thu, 22 Aug 2024 17:24:49 -0700 Subject: [PATCH 14/26] xfs: grow the realtime section when realtime groups are enabled From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <172437088764.60592.4708190326358663732.stgit@frogsfrogsfrogs> In-Reply-To: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> References: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Enable growing the rt section when realtime groups are enabled. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_shared.h | 1 fs/xfs/xfs_rtalloc.c | 268 ++++++++++++++++++++++++++++++++++++++------ fs/xfs/xfs_trans.c | 9 + fs/xfs/xfs_trans.h | 1 4 files changed, 242 insertions(+), 37 deletions(-) diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h index 4f5f1d3526803..b6e56daa6a147 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 6989ee1c13fa0..3fedc552b51b0 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->rtg_mount; + xfs_rgnumber_t rgno = rtg->rtg_rgno; + 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->rtg_rgno > 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->rtg_mount; - xfs_fileoff_t bmbno = mp->m_sb.sb_rbmblocks; + xfs_rgnumber_t rgno = rtg->rtg_rgno; + 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->rtg_mount; 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->rtg_rgno == nmp->m_sb.sb_rgcount - 1) + *nrbmblocks = xfs_rtbitmap_blockcount_len(nmp, + xfs_last_rtgroup_extents(nmp)); + + if (mp->m_sb.sb_rgcount && + rtg->rtg_rgno == 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,55 @@ 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++) { + error = xfs_rtgroup_alloc(mp, rgno); + 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 552e3a149346c..dc90856e1e9bb 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -458,6 +458,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; @@ -563,6 +567,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) @@ -680,6 +688,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 f97e5c416efad..71c2e82e4dadf 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 Fri Aug 23 00:25: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: 13774456 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 8274310953 for ; Fri, 23 Aug 2024 00:25: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=1724372705; cv=none; b=tTm+UdlFsk1mdhV0gzwNu80mzv89UncXeMJ7I9qObep5pUexBetiRNZ6JoP9/O/J5ZGIcYxbLRZJc9Pv2qddXQJgw3m4N+tgQw6+ARr+shDiTPpSUckvSP32h4d92Tj4zwNl3aMFK+iEVtWNaaxgriwGCl4jwWSWIsSmi5hPtEs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372705; c=relaxed/simple; bh=V3uKaL//fBP0VYGoUwnehrtSQRaL0Am54ZMnCteBqNo=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=h9B2JxggZT46QJJjfPls5mpED9e71VLcA2VkuhpgQjghh3ua33bsYR+NELr7BDI3NRUr5UQlaFK7KLHS8kt8kqITrE4L8vHKnYRIP3ts0Z+5jzaTChjT7o6zvj5h4kHt5L+QxsWmw5qUykS+zAgaY1wx5QJqOIraVDPuVyuyPzw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gslDYAxt; 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="gslDYAxt" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5BC5DC32782; Fri, 23 Aug 2024 00:25:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724372705; bh=V3uKaL//fBP0VYGoUwnehrtSQRaL0Am54ZMnCteBqNo=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=gslDYAxtKS1a8iciZfFFy/eIV/3h01Dp6Fg1ZGGSiB/TekZqs9cmbd7I5pGKSeclc YW+JcLUN2NrURqT2fr5v25CMcELLMTMbA0duBUif6kzifCRbTz7QHfKgcilHVy+cLv NBVczNEdJBWFvAqQ2gNwOpyeXB20eMInieRcOVrYmkSEIOUHHD4QP2S+065YZI2pIr nK5Ndx/3Z5BBrKDE7w2DV3tPINtYSZgGiZcAMVk0n8BrutrLHAM6ORohiBaa6Mp+L0 GCEGnHGVQw7KUjj2mE+cQPqGII/eBdn2Yo09tXsmoQZ5FDiKbB2O20Q93TmrmkHBys ZihOMeHzDrrZg== Date: Thu, 22 Aug 2024 17:25:04 -0700 Subject: [PATCH 15/26] xfs: store rtgroup information with a bmap intent From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <172437088782.60592.3733953729473737601.stgit@frogsfrogsfrogs> In-Reply-To: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> References: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Make the bmap intent items take an active reference to the rtgroup containing the space that is being mapped or unmapped. We will need this functionality once we start enabling rmap and reflink on the rt volume. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_bmap.h | 5 ++++- fs/xfs/xfs_bmap_item.c | 18 ++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h index 7592d46e97c66..eb3670ecd1373 100644 --- a/fs/xfs/libxfs/xfs_bmap.h +++ b/fs/xfs/libxfs/xfs_bmap.h @@ -248,7 +248,10 @@ struct xfs_bmap_intent { enum xfs_bmap_intent_type bi_type; int bi_whichfork; struct xfs_inode *bi_owner; - struct xfs_perag *bi_pag; + union { + struct xfs_perag *bi_pag; + struct xfs_rtgroup *bi_rtg; + }; struct xfs_bmbt_irec bi_bmap; }; diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c index e224b49b7cff6..9a7e97a922b6d 100644 --- a/fs/xfs/xfs_bmap_item.c +++ b/fs/xfs/xfs_bmap_item.c @@ -26,6 +26,7 @@ #include "xfs_log_recover.h" #include "xfs_ag.h" #include "xfs_trace.h" +#include "xfs_rtgroup.h" struct kmem_cache *xfs_bui_cache; struct kmem_cache *xfs_bud_cache; @@ -324,8 +325,18 @@ xfs_bmap_update_get_group( struct xfs_mount *mp, struct xfs_bmap_intent *bi) { - if (xfs_ifork_is_realtime(bi->bi_owner, bi->bi_whichfork)) + if (xfs_ifork_is_realtime(bi->bi_owner, bi->bi_whichfork)) { + if (xfs_has_rtgroups(mp)) { + xfs_rgnumber_t rgno; + + rgno = xfs_rtb_to_rgno(mp, bi->bi_bmap.br_startblock); + bi->bi_rtg = xfs_rtgroup_get(mp, rgno); + } else { + bi->bi_rtg = NULL; + } + return; + } /* * Bump the intent count on behalf of the deferred rmap and refcount @@ -354,8 +365,11 @@ static inline void xfs_bmap_update_put_group( struct xfs_bmap_intent *bi) { - if (xfs_ifork_is_realtime(bi->bi_owner, bi->bi_whichfork)) + if (xfs_ifork_is_realtime(bi->bi_owner, bi->bi_whichfork)) { + if (xfs_has_rtgroups(bi->bi_owner->i_mount)) + xfs_rtgroup_put(bi->bi_rtg); return; + } xfs_perag_intent_put(bi->bi_pag); } From patchwork Fri Aug 23 00:25:20 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: 13774457 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 9B61F538A for ; Fri, 23 Aug 2024 00:25:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372721; cv=none; b=gqn9++mK5lWBgmyCW0BEkaiWbrmtOVE/SQZyTogjl+mrGISP65szC8RkwE6hcKx6PLUgl9NEczvHo3iz8vJfTt10nhjPMqmuipSDFR51SFIr3+apDklIRRwtUbeo9Q6plREI54GEPS8vVQSLOCSMhEJII8KVkSWOT2Bv9kUUMSw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372721; c=relaxed/simple; bh=fglrqyw/TYGT5a2ze2sXMoGvaXxhbFaLfmNM4vVdKcQ=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=P/0U50Cj++kz0wVUu6CkJPpqcL6eVtytyFPGgLdvZ0+FxxmW6pbw05RfPlwe7cQMPUemwhxIDs5mTkEW2u5FPMS2onDF1j9ZejOgdfFV6bM3fu3tTpKGK+svt0PNBlLDzUaMI4tg2fg+lD0ylBHT5gSwApwgiCFINs17U8zb2sI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=C/MfNHZh; 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="C/MfNHZh" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 012DFC32782; Fri, 23 Aug 2024 00:25:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724372721; bh=fglrqyw/TYGT5a2ze2sXMoGvaXxhbFaLfmNM4vVdKcQ=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=C/MfNHZhHFttsKI4PcFjmkaHXNpsA0Zpf2QHBfz18AwrE+W6S4LmhYR3ZiTmrD3AN yr+muUKJz8oCTO8ED/ekYa1o3GIcuZ+T4FPlgVuzGh2GOvgNc+lTeTfhiTOGmX1NQS nNYlrHmnZ6TjHhSsTD2P05wYwtY+vc8PqLPSb72Gsku2RWsrAVpxxgwzm21XmprOiR ypzFRg22Xj8QsxQZqWvEY9X8qhjpSyJMrUbKw3uzgoAdrjKQ2hI2ZioOHY2f2CL49D /a8T7o6phTdmLeHE5yW/J8DU9wKvf5ZSJhK9GfQLDLDVGf2YcGoQYbmwm0fHChhMF5 vlwa3Q5WSBYEg== Date: Thu, 22 Aug 2024 17:25:20 -0700 Subject: [PATCH 16/26] xfs: force swapext to a realtime file to use the file content exchange ioctl From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <172437088799.60592.14096570051407234430.stgit@frogsfrogsfrogs> In-Reply-To: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> References: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong 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 fe2e2c9309755..025e58daf6f50 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -1522,6 +1522,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 Fri Aug 23 00:25: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: 13774458 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 26BF8AD4C for ; Fri, 23 Aug 2024 00:25:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372737; cv=none; b=jAHdXE7Up6F2jiuRU4y8FNkqKIhyToclzu+1Ga83qiWWHp9gh5HsmjLD6AItPKskyS77bRuGzfDOzegJvzzzNWetJkRqkYoWc52rfHyed4jc2MapSd0ENc9pmqmFU0oCd2bw4yF/3Fcpb/CcgpFx7zQcG7foyO1exhEyaZWy//w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372737; c=relaxed/simple; bh=BJJ1fk/fe+yrv7yzQeQm2Tseaf3sEKTr6y0UI/hVjy4=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=TTuneyv5iedG7IiRu6KyKY8xUy1PYLc70LEuOx8KVS/dNbmHoOyHeO0vWw9BjEbhV7xbhpKqTj72iAo7jZ79AwSSEZ5czsOraHmtJhZzmq10du69SCBW67F42GrCnKHXKziBeHjpODTBNhaAvkT8SmQ/bgJby63vbbI7gWl1Tyw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=lgFxniXN; 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="lgFxniXN" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A0AA1C32782; Fri, 23 Aug 2024 00:25:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724372736; bh=BJJ1fk/fe+yrv7yzQeQm2Tseaf3sEKTr6y0UI/hVjy4=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=lgFxniXNoQP3xjz1CBwlIQHemlbe7Xh/H2GTyt61xz60Be4pGQi7wOwyqYb5HW2Ez dqSufmg8tXkJGc0394S2pGzGyTcgud7XvkrjVYO04Ks8FCNSwP68r37GGD6TrcBK6/ cikt1870p5V7abvmqfW/f5P6ic7pCL1/6sBzfF1q1BbMVzkbl77DHuETEqsgsJrsqX 7bj0S2CimrFO2dQjw3Xqwu/8zKrBmbwHSNBh94JXAHVRbPaoyaK0es7yDi2+10HVKk /yA1oBV+ROhC+N7cC/BuR25RdER+jQdzyxEfXRFzuQa6xC1h0b+nIkCqojs4jYF0Uv VQbzhIFvS/ogg== Date: Thu, 22 Aug 2024 17:25:36 -0700 Subject: [PATCH 17/26] xfs: support logging EFIs for realtime extents From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <172437088816.60592.12361252562494894102.stgit@frogsfrogsfrogs> In-Reply-To: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> References: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong 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 | 17 ++ 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 | 281 ++++++++++++++++++++++++++++++++++++--- fs/xfs/xfs_log_recover.c | 2 8 files changed, 305 insertions(+), 25 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 59326f84f6a57..0eae7835c92a9 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -2645,8 +2645,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); @@ -2655,6 +2664,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 fae170825be06..349ffeb407690 100644 --- a/fs/xfs/libxfs/xfs_alloc.h +++ b/fs/xfs/libxfs/xfs_alloc.h @@ -240,7 +240,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". @@ -251,7 +255,10 @@ struct xfs_extent_free_item { uint64_t xefi_owner; xfs_fsblock_t xefi_startblock;/* starting fs block number */ xfs_extlen_t xefi_blockcount;/* number of blocks in extent */ - struct xfs_perag *xefi_pag; + union { + struct xfs_perag *xefi_pag; + struct xfs_rtgroup *xefi_rtg; + }; unsigned int xefi_flags; enum xfs_ag_resv_type xefi_agresv; }; @@ -260,6 +267,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 40021849b42f0..a33e22d091367 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -847,6 +847,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 8b338031e487c..ec51b8465e61c 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 ace7384a275bf..15dec19b6c32a 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 521d327e4c89e..5397a8ff004df 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 abffc74a924f7..57b46f1b8463d 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. @@ -395,11 +408,12 @@ xfs_extent_free_create_intent( bool sort) { 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, XFS_LI_EFI, count); if (sort) list_sort(mp, items, xfs_extent_free_diff_items); list_for_each_entry(xefi, items, xefi_list) @@ -407,6 +421,12 @@ xfs_extent_free_create_intent( return &efip->efi_item; } +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 +447,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; @@ -447,6 +467,17 @@ xfs_extent_free_defer_add( trace_xfs_extent_free_defer(mp, xefi); + if (xfs_efi_is_realtime(xefi)) { + xfs_rgnumber_t rgno; + + rgno = xfs_rtb_to_rgno(mp, xefi->xefi_startblock); + xefi->xefi_rtg = xfs_rtgroup_get(mp, rgno); + + *dfpp = xfs_defer_add(tp, &xefi->xefi_list, + &xfs_rtextent_free_defer_type); + return; + } + xefi->xefi_pag = xfs_perag_intent_get(mp, xefi->xefi_startblock); if (xefi->xefi_agresv == XFS_AG_RESV_AGFL) *dfpp = xfs_defer_add(tp, &xefi->xefi_list, @@ -559,8 +590,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); } @@ -568,6 +603,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; @@ -578,7 +614,15 @@ xfs_efi_recover_work( xefi->xefi_blockcount = extp->ext_len; xefi->xefi_agresv = XFS_AG_RESV_NONE; xefi->xefi_owner = XFS_RMAP_OWN_UNKNOWN; - xefi->xefi_pag = xfs_perag_intent_get(mp, extp->ext_start); + if (isrt) { + xfs_rgnumber_t rgno; + + xefi->xefi_flags |= XFS_EFI_REALTIME; + rgno = xfs_rtb_to_rgno(mp, extp->ext_start); + xefi->xefi_rtg = xfs_rtgroup_get(mp, rgno); + } else { + xefi->xefi_pag = xfs_perag_intent_get(mp, extp->ext_start); + } xfs_defer_add_item(dfp, &xefi->xefi_list); } @@ -599,14 +643,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, @@ -614,7 +659,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); @@ -652,10 +698,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); @@ -687,6 +735,106 @@ const struct xfs_defer_op_type xfs_agfl_free_defer_type = { .relog_intent = xfs_extent_free_relog_intent, }; +#ifdef CONFIG_XFS_RT +/* Sort realtime efi items by rtgroup for efficiency. */ +static int +xfs_rtextent_free_diff_items( + void *priv, + const struct list_head *a, + const struct list_head *b) +{ + struct xfs_extent_free_item *ra = xefi_entry(a); + struct xfs_extent_free_item *rb = xefi_entry(b); + + return ra->xefi_rtg->rtg_rgno - rb->xefi_rtg->rtg_rgno; +} + +/* 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) +{ + struct xfs_mount *mp = tp->t_mountp; + struct xfs_efi_log_item *efip; + struct xfs_extent_free_item *xefi; + + ASSERT(count > 0); + + efip = xfs_efi_init(mp, XFS_LI_EFI_RT, count); + if (sort) + list_sort(mp, items, xfs_rtextent_free_diff_items); + list_for_each_entry(xefi, items, xefi_list) + xfs_extent_free_log_item(tp, efip, xefi); + return &efip->efi_item; +} + +/* Cancel a realtime extent freeing. */ +STATIC void +xfs_rtextent_free_cancel_item( + struct list_head *item) +{ + struct xfs_extent_free_item *xefi = xefi_entry(item); + + xfs_rtgroup_put(xefi->xefi_rtg); + kmem_cache_free(xfs_extfree_item_cache, xefi); +} + +/* 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 != xefi->xefi_rtg) { + xfs_rtgroup_lock(xefi->xefi_rtg, XFS_RTGLOCK_BITMAP); + xfs_rtgroup_trans_join(tp, xefi->xefi_rtg, + XFS_RTGLOCK_BITMAP); + *rtgp = xefi->xefi_rtg; + } + error = xfs_rtfree_blocks(tp, xefi->xefi_rtg, + xefi->xefi_startblock, xefi->xefi_blockcount); + } + if (error == -EAGAIN) { + xfs_efd_from_efi(efdp); + return error; + } + + xfs_efd_add_extent(efdp, xefi); + xfs_rtextent_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_rtextent_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, @@ -731,7 +879,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); @@ -749,6 +897,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 @@ -791,3 +991,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 c627cde3bb1e0..07f63c300626a 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -1819,6 +1819,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 * From patchwork Fri Aug 23 00:25:51 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: 13774459 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 6AC4CBA46 for ; Fri, 23 Aug 2024 00:25:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372752; cv=none; b=ukjXQ4HXPTvRrCP3s3tHxAeVUQfk5nVPrbR9QAqT9L5M42mGA+pcqY0sQ0kuHPRZumJIzfoKI+pSYYeMoUjCWq6jpYmKdDxVCCL8OcYK8vQ/51KP69c+MjbdhR21U2COC5Ep2fzxk2dL3iziwclRtD9LSiHThNaM8aWnqxPfFiA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372752; c=relaxed/simple; bh=CUY+3KIaBmlKzZsA1R7I35JNmLTgfLY5ogGBHZFVZhc=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=lQaJvm9XC2sPNguIbmEprrR4GLasdp4yhctOl0qqOGTHpQUzG/BCO/sLoteQvYE5zN/CMJkq9hZH9DbxurZ7wQgxpyEjiLQAPVyKHxUc686N6gbLk4MX+rvazfY7s6TaFUWrRIqo6cv3nZq6nUQhLFXIxB7tER97jJeisogDljM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=inz66aPZ; 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="inz66aPZ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 47E10C32782; Fri, 23 Aug 2024 00:25:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724372752; bh=CUY+3KIaBmlKzZsA1R7I35JNmLTgfLY5ogGBHZFVZhc=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=inz66aPZD3QP/KglRvikAAhXcUxv+sMZSV6/Kt8O9/EnIIapTmwsz5ZJkqmqo+E1M 6Mj3aKJW+bJ1CW96moFgw010rmb4naQApIkfGhEjxmg8IyDSHLmXKMZQJ6Lb+QuA3F kAMysDTWvpNBQqXo0ogbPj7dP/MxPAUY4HeooUfNh/6jSt9My0Vz0M4u/0gdvDlnis vaElL22oqHRUX/6TXoo63GpGY1QYNI9pa9mGqcyfF03K2LDS8THIKqnJ5BtCty/hFl HtHxFNgh/KDmo/N6NC5V7tPWKD3o4bVHl0SnkIxzNv9fwIf2RV1jcHCsNwrUX1e5OT deVEwVtjI5gQA== Date: Thu, 22 Aug 2024 17:25:51 -0700 Subject: [PATCH 18/26] xfs: support error injection when freeing rt extents From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <172437088834.60592.5110162859616544393.stgit@frogsfrogsfrogs> In-Reply-To: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> References: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong 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 dfac0e89409a9..c8958d3e0abe0 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 Fri Aug 23 00:26:07 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: 13774460 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 140ACB653 for ; Fri, 23 Aug 2024 00:26: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=1724372768; cv=none; b=H3j+efPnZccauO/7qeYPrjkh3JEPyiZnfylz4hJIyKNPxEocwmD6evzDrtK/6BYwPlqbZmHq8/bo39LAP3NRnEGW24RyyyNrih0BOQL8ctv8OX5q4o7ncq6vQfgSLep3sfr8yVbsohImIBCloq5QNvKGYJeUmA8AsBPzTw9b2pg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372768; c=relaxed/simple; bh=DwWI+Ysm54Af+2PPpKtC9NkJyZXPnVHlza69Qm+aDWk=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=IhkQMOeDM3O7oMuFjC4vf4BgVc3WvmVQRSwgs73pSmZFSUFHm4R8jpi9eTJoU65Wau+BNpJT+Y6XBhtdViOJYaUXcLwV5wjnciQ6CxKLOp54gqKYVK/wnTnT7KWS/NPQnOLum9dbbDnQ+c18r9/1eji9IhSTclncsTJ88HXyRwg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Wewde9yh; 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="Wewde9yh" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E190AC32782; Fri, 23 Aug 2024 00:26:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724372767; bh=DwWI+Ysm54Af+2PPpKtC9NkJyZXPnVHlza69Qm+aDWk=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=Wewde9yhlFW6xzL+XBHni4XHMoeNyu3T8EegwzMBaJgH5s56SgZDsTNKZH3nHozzt kbBelykmwPSTFEp61FDz3RKXcLO9hiRSI27dJE8MtEhmLaS0oLBmRJ16DjiwtgriLh MCwkqAkWXz+tXJltS3wWIBBWEemM+ZX1BzxgDue6GbvCvQGvyYLfrP+mhPlNiyKX2V pOCSLJLrC49eky1TF7w9NnFBrVtOWWU8DOyXYyowYwq/R7q4AyfXwmiOVUodsNFyvY nXH3eqvesECA8GkpLajWBaz4MRrmKQoN6K3VxwVoEDRjGZq43jbq5wgnMARWDwkltl GdCXytnmb+4yA== Date: Thu, 22 Aug 2024 17:26:07 -0700 Subject: [PATCH 19/26] xfs: use realtime EFI to free extents when rtgroups are enabled From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <172437088851.60592.2012898665553673543.stgit@frogsfrogsfrogs> In-Reply-To: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> References: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong 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 f1bf8635a8cf3..126a0d253654a 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -5434,9 +5434,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; @@ -5445,6 +5447,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 Fri Aug 23 00:26:23 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: 13774461 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 C521CBE47 for ; Fri, 23 Aug 2024 00:26:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372783; cv=none; b=cp7m2pxTw9ZnvqYKV5u/Bo9yHZFIftO4L+pQ5HFgdy2IM2iIXhy3jEq8zBDf+qTFKo8Jz99JaH9H2MbtXveCAJwAwsEPzaM9qWyQeWFMOBzKwLHeG4EA9BH6+xjABWqjsY+Y8/0gVVQq/9DXzkGSfEsrvQxlbIa/U1VXWOxuOKo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372783; c=relaxed/simple; bh=/d1y6f4n3bdknVSJSlblm6U8yHUgQcoY4nAeTo8MENU=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=XHTfOS58ikRyxmr/pmlMr7+DkVZH0u0P8xP8xvkZAYm5PyMZAzf7jHDcTlBaj87dKP5tKPHbpp9P8awPHIC0VGkc3vAnlMJ58i3rOZfGRH/FQGl9ckeFx3WmOEEc3FS1tD4Um2GHsm2xITo0Ucl/iEVZEQEcERN0WASOM904T8M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=e3drdkas; 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="e3drdkas" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 93318C32782; Fri, 23 Aug 2024 00:26:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724372783; bh=/d1y6f4n3bdknVSJSlblm6U8yHUgQcoY4nAeTo8MENU=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=e3drdkasMxDKoxa0SbyYPKjKE4Nlyz9tFuGIsrdW2UNLnZJAQn+WI5/ayPbDFY1/3 yS+wJ+fITxvS1uePXr4nugvZRV4rBBXohon7pZOxmsTyrBKB68JiH7BFLIZ3p/TT1m jHY+S6QiE1riNJ+/oOxWdJz1TrGKFDIcWpr0NcJC4ULv59XB9eagO0uKD3P8EntRMA IrcsbPgwF+jXrms07TLgRS7D4zIWvNLn13S3B4PzP6z5ZXSWlx9fHtFd4noIVt3rrH Ap8fi2ae+NsnqBTbHt/mdsFJETcc6ODt7vQCpnAiWX6l7oy4Ty03KqEB9K65eqS3YD /uDHVYoqtEBZw== Date: Thu, 22 Aug 2024 17:26:23 -0700 Subject: [PATCH 20/26] xfs: don't merge ioends across RTGs From: "Darrick J. Wong" To: djwong@kernel.org Cc: Christoph Hellwig , hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <172437088869.60592.1406516687324740088.stgit@frogsfrogsfrogs> In-Reply-To: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> References: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Christoph Hellwig 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/xfs_iomap.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 13cabd345e227..607d360c4a911 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 bno = xfs_fsb_to_db(ip, imap->br_startblock); + + iomap->addr = BBTOB(bno); if (mapping_flags & IOMAP_DAX) iomap->addr += target->bt_dax_part_off; @@ -124,6 +127,15 @@ 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_rtb_to_rtx(mp, bno) == 0 && + xfs_rtb_to_rtxoff(mp, bno) == 0) + 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 Fri Aug 23 00:26:38 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: 13774468 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 B2803D51A for ; Fri, 23 Aug 2024 00:26:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372799; cv=none; b=aFQLBVbC2uFQjQnLuO5Q9zdrDONJYiF66i/ej4mgNCchYi58EvE9ht9AL7dJ3dV3fmGZKlVZOECLsJCAFKc0fi0UGuoacJFCnwL6UwGEujy0Tqnp4pvTfNIMXilNDUmzgAFxf7Xj4tTjzJScOJEf4M/QU0uc9EPxnjyGOIK5db8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372799; c=relaxed/simple; bh=gjDglHqQiu11rEXEtgRLRp/ZzI5VqWypRgvgtzpT+e8=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Gh0RmmNl5S/rkU5SNQry4DxHOkGnkYhJnOcU63gA2hZJaglrB0oQJiN89wNFVmcpa9BOWVlXRXJFzsBxiEIPoYCGYx1gm4oTKLfhp+AiJDrH9UYqKzxDmuhuA2UGluLKBRn0qzdYa4Ra8tAL2FEJ2lphv+wgGUAZLIfIcbijQVw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=oWWMLbZZ; 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="oWWMLbZZ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3CE9DC32782; Fri, 23 Aug 2024 00:26:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724372799; bh=gjDglHqQiu11rEXEtgRLRp/ZzI5VqWypRgvgtzpT+e8=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=oWWMLbZZ3BPXtzGAgr2qv96yXiAV1PQJIN3Y8Jcl1kFvLolxq6fr/4+Z8qgT79lRC euYzMrkL0uzVFUwY9UL4Sh5Tmh4/Ktnzv6GR+1OiSDth2D6n8xW8Jfk86gWYeygKp6 3j4UTp1LXdpKX7pAYxIX2IWGEK9IgpCdUlQRlzcFXrPy6Pa0EIzdjNotjniY9pJdYQ 7ep8n5Ui8xb5I3uDfpGQI491+ekQ5dK752do4+zgCN+PNaY8EwMQjZUm9i3yg2ORab L5qSCTSGWQCgVNaNVWUe4Y7QMln9cdzvkN/eENQJ+fZFnfBjoM7dUPnuvQkJxTderz xmvjQyKsd2mpg== Date: Thu, 22 Aug 2024 17:26:38 -0700 Subject: [PATCH 21/26] xfs: make the RT allocator rtgroup aware From: "Darrick J. Wong" To: djwong@kernel.org Cc: Christoph Hellwig , hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <172437088886.60592.11418423460788700576.stgit@frogsfrogsfrogs> In-Reply-To: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> References: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: 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 126a0d253654a..88c62e1158ac7 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 c8958d3e0abe0..ef94b67feccd7 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 c4e4f5414a299..7e68812db1be7 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -223,6 +223,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 3fedc552b51b0..2b57ff2687bf6 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -1661,8 +1661,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, @@ -1682,16 +1683,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; } @@ -1701,7 +1719,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) { @@ -1722,8 +1740,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) @@ -1741,6 +1767,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 keep 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, @@ -1835,9 +1908,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 Fri Aug 23 00:26: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: 13774469 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 F346510953 for ; Fri, 23 Aug 2024 00:26: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=1724372815; cv=none; b=bxM5SdZdWIT8rFZldsjly99tk8qY5J3wdhfjZqT/aWsGb3VUHGLy4jzDKoVS30yA4RN8YI/Rec3r84FP3H94a4zoNLmEDtwmd1564jrw4QSfT1r04+twqHU6+0yQ0rtCrAd6fqqacxcKnhMgzL8vjIPHoJbMKZWJI6OQ1LLyZgc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372815; c=relaxed/simple; bh=3AodzdkziR/nTy8DYtNJjSyJ3Q3clWq83O7HRit6Qyo=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=TXf32BHyEJIZ6RysDhuM0U5JAv1wzBz9+9W3K+b9HwvjD7WIziOeBI4WgTKoJOMS+vjTOsr6gwan5u0grAtmC5xg8mUARiGDfi7ZiQLDyNfmm1WnnHyO3iCmyeg0HKib4R0JKruoCCXc3AM6ChLelGB85w+1C4woiQ7Hmprb38A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ojO6hxO1; 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="ojO6hxO1" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CD433C32782; Fri, 23 Aug 2024 00:26:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724372814; bh=3AodzdkziR/nTy8DYtNJjSyJ3Q3clWq83O7HRit6Qyo=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=ojO6hxO17lMv3zQBqknlH1pDg7xQ+G76y2yeU8CGBHRcWb0KZ07ixP6BW724qvXed lg7/0CcTYTTirjmVbRTf/e/cuszEK/Bb3a0dsrc23Jk+a3JO7U6/8YzLf6HisF84zP KM/aLXL3n/QcAaWgEg2xGXYLz7dkbb4DYadhWZNeGCFowbsCyabkF7VsoYnTCQEVPh sy2xBbhMcvBbzJFI7ut3CQChlMr6hJuxI8SrrtKrWtjvnpLqaf0z7WkYmQbkc66XfG UOWO4uqSc2o0Jy/8fJz4vdu97eoeTStAx4aazWF6SwZwXkH7YlIpNHgB6gR6BmTQjd xBfGwJQuxPCKQ== Date: Thu, 22 Aug 2024 17:26:54 -0700 Subject: [PATCH 22/26] xfs: don't coalesce file mappings that cross rtgroup boundaries in scrub From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <172437088904.60592.6390649383741617327.stgit@frogsfrogsfrogs> In-Reply-To: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> References: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong The 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 69dac1bd6a83e..173c371e822f5 100644 --- a/fs/xfs/scrub/bmap.c +++ b/fs/xfs/scrub/bmap.c @@ -835,9 +835,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; @@ -851,6 +854,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; } @@ -888,7 +902,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 Fri Aug 23 00:27:10 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: 13774470 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 99C62125AC for ; Fri, 23 Aug 2024 00:27:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372830; cv=none; b=HJNOrkTsiFQ4pBl37YnCbz/aVCxzMJTkBoKZapIjyKVHoNG1pcpjvfUStH142MPqhwRyNB9WxVEptqCM3jft3C3zqkWIrb6CDDKUeOr0RxHtyA6De1Izp4KLbSe+VO7iPh5KIDqYkkpkSAeJ1QMf6RMKzMCX3i2U7HelvpN4ZBw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372830; c=relaxed/simple; bh=ObRyTY5WKSiQv2P+LVk2E+emcM8vnXXivHQ2V6BFgms=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=nXGplBazaVrdwl6Z1bH6y5MypIvXvQla5L3XOjH6q00gaionN0/sp5RCf+gx8eCJ4W/r8eKJF/3xMu9XoMXqbeizFwRtoVRmlXrivn9TlT4tS4TFgr9dICsnaPcSqbrrid5HbpZg50JbHfvQd/X6blXV5pXoY+cH80bJts51/0k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Z3jLeoTN; 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="Z3jLeoTN" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 71626C32782; Fri, 23 Aug 2024 00:27:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724372830; bh=ObRyTY5WKSiQv2P+LVk2E+emcM8vnXXivHQ2V6BFgms=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=Z3jLeoTNUq0PkNXZz8zP20J1MRz2DRaCyWlaPmu71pciUBrDhNZkNqR5xxfWUng7E cfoFuyrmvkcMs3v+z7jBQkdbLmgt1RSHUGDKx6tdwXEasfm33G8AvMydR1MIOz7kDl FSon1gq2Iakg/PXb8ux4iUxdlQItFDCdiwFtKfEs6EMvwx7otYy2fRY1V4geFeLPVl VvF3jeUhQv0S8T9hsIZEdTsGXnahhbIYvcyeX/+P5qJk1wIdelvPMpi5Mzik5029Qb S6TTsGNwp6YKlqoTm5WbWEyCf/OuF8EowRb0vKYCrj8GZAeYKQl8nbUckfJ8uRWbLD RBB5ds4fDvpWg== Date: Thu, 22 Aug 2024 17:27:10 -0700 Subject: [PATCH 23/26] xfs: scrub the realtime group superblock From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <172437088921.60592.15232505394298064283.stgit@frogsfrogsfrogs> In-Reply-To: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> References: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Enable scrubbing of realtime group superblocks. Signed-off-by: Darrick J. Wong 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 | 73 ++++++++++++++++++++++++++++++++++++++++++++++++ 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, 92 insertions(+), 2 deletions(-) create mode 100644 fs/xfs/scrub/rgsuper.c diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 388b5cef48ca5..56f518e5017fd 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -190,6 +190,7 @@ xfs-y += $(addprefix scrub/, \ xfs-$(CONFIG_XFS_ONLINE_SCRUB_STATS) += scrub/stats.o xfs-$(CONFIG_XFS_RT) += $(addprefix scrub/, \ + rgsuper.o \ rtbitmap.o \ rtsummary.o \ ) diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index 2dacc19723c37..07337958fc41a 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 0d531770e83b0..c8465a4eb594a 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 a0a721ae5763d..3406579db71eb 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 0000000000000..bfba31a03adbc --- /dev/null +++ b/fs/xfs/scrub/rgsuper.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022-2024 Oracle. All Rights Reserved. + * Author: Darrick J. Wong + */ +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_trans_resv.h" +#include "xfs_mount.h" +#include "xfs_rtgroup.h" +#include "scrub/scrub.h" +#include "scrub/common.h" + +/* Set us up with a transaction and an empty context. */ +int +xchk_setup_rgsuperblock( + struct xfs_scrub *sc) +{ + return xchk_trans_alloc(sc, 0); +} + +/* Cross-reference with the other rt metadata. */ +STATIC void +xchk_rgsuperblock_xref( + struct xfs_scrub *sc) +{ + struct xfs_mount *mp = sc->mp; + xfs_rgnumber_t rgno = sc->sr.rtg->rtg_rgno; + xfs_rtblock_t rtbno; + + if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) + return; + + rtbno = xfs_rgbno_to_rtb(mp, rgno, 0); + xchk_xref_is_used_rt_space(sc, rtbno, 1); +} + +int +xchk_rgsuperblock( + struct xfs_scrub *sc) +{ + 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 910825d4b61a2..fc8476c522746 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 f73c6d0d90a11..a7fda3e2b0137 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 edcd02dc2e62c..a476c7b2ab759 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 fe901b9138b4b..d4d0e8ceeeb7b 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 Fri Aug 23 00:27: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: 13774471 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 9D5BD13AF2 for ; Fri, 23 Aug 2024 00:27: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=1724372846; cv=none; b=O0k9iH5DYhRCfIAOaMXSzKiI+79qqxO5SPysfKubyGvIwEbgRyr5EHmJgknEIGQBsud9NrZFlMjY86QQMNZL4fnD64eTBPgXC6a9r6J3f+14o0wrI5qKK25hhG7llwbOuaU0Ar1DJGNOKQ+fWGwbRTOWnqdyRHokQ+0x/yymtD4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372846; c=relaxed/simple; bh=ohefvzWQKaKtRHiiUxXOfcGIGGdlwA/u+iIdzHcyyTM=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=qigGtU3aaf7sY9K4zxiY9ok9YQ8o5krHLHeo3LlSnPitIu2n8C4L/rWUO5IjKANEvoRXY3TTlmayRmvIZu8AKQYJuCHYoIC986vJq0bjaud+h7SJUtFseQC8yGGjVV1Y7+Fhke38rpyjvv++3GbXw0wT4ze1NLFWSkg5M4hg7Q8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=vBQcocti; 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="vBQcocti" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2051BC32782; Fri, 23 Aug 2024 00:27:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724372846; bh=ohefvzWQKaKtRHiiUxXOfcGIGGdlwA/u+iIdzHcyyTM=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=vBQcoctijLcvWd7ta63+9OqBPmKg0h1XHwHcA2p582D+bseemfvoYfLC5aCYuu+Vc E1rvK4JaunF/3ePHegRCFyVLg04TRocdneXmTVPgPBh2phzKy8h8RJ+Decit2nInfi +dAEce3N7G2FBT86nuUyMa8R44ZTRYcexsRlaRuwoTRVk+6GIKhB1oLG73BR7cmUMr iooJmAGZsQI8KYgk1Nnc5xJ9GJ0bl5u+iUQ9mq3QNFGqyqTp4DrrvufxMbZnov2NVv w9mqDWdOh1wZeNZtd0Vv5coxbLJVscC2T8Kk4ahaF4wrVDsihTNVao9g7+YBaRdnn2 HBF6Y+BjTtxBg== Date: Thu, 22 Aug 2024 17:27:25 -0700 Subject: [PATCH 24/26] xfs: repair realtime group superblock From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <172437088939.60592.12149395691309789384.stgit@frogsfrogsfrogs> In-Reply-To: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> References: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Repair 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 4052185743910..b649da1a93eb8 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 bfba31a03adbc..ad54a58cd9848 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 @@ -71,3 +75,15 @@ xchk_rgsuperblock( xchk_rgsuperblock_xref(sc); return 0; } + +#ifdef CONFIG_XFS_ONLINE_REPAIR +int +xrep_rgsuperblock( + struct xfs_scrub *sc) +{ + ASSERT(sc->sr.rtg->rtg_rgno == 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 fc8476c522746..c255882fc5e40 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 Fri Aug 23 00:27:41 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: 13774472 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 E99D1171A5 for ; Fri, 23 Aug 2024 00:27:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372862; cv=none; b=Tupe9pjYEhORI5gGM7Yl7yQuYT4/xtYMsQDKoho6HZ+qxyiG4E3uUAo+GYoc42AHL+7RLp+BmPdVqjTGPsbBHN4x/NogcluQ48t0A1TmC8wOINNCv8ly2qNKrFkcadr/gmnaUuTplSGXZ3nZ8ZmYshn8BFQ0yj32FLvEMbhUWDQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372862; c=relaxed/simple; bh=qFd35SAskEiLbZmUQKyZM+toOquoS0SMn2A0SlEljUw=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=gbi5cx3pMsPiyiWq4xzVEsUaaX5rsHvKKH3opzFj8N1bQxqSXA7vMQB3krtzm56ZKEYVCWXdRsAf5gOybAr3Dp7D3WECnymvRwLwmKx3UX9EvASnJc3p0fOeDkhPTNF4a95jiCem6Oi032ErFl+4VRZShb0BNsSIQS6F5nFORlI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CLit8wLd; 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="CLit8wLd" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C7BA9C32782; Fri, 23 Aug 2024 00:27:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724372861; bh=qFd35SAskEiLbZmUQKyZM+toOquoS0SMn2A0SlEljUw=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=CLit8wLd4HPVa1xENI01RqmuSMmIkKJFSL7q2w7AZeKO2VcYXLyLeJHQRssx9TSdY qSxU6D1ckWJSNOqloeB/NbN48llRoDv2YKbhTOuJ5QHsJqL3KIkmjd47o67AlFgV8J BF/ILgpV2q64eYVBBDLAGtuDm+K28ay1CPYFPJn86NKF5Dh2aG5G+vtiuKCoHzHJih Yd0+zHZ8Y6mJSFThZK8IqEnyf3XVi8UVQA5slZUVpfBb0t8viaUd69i2nZxRyf2/HX tzU1Rz9UMbml/MSSAD/tj0yOoTTaJtw9JHifZ18TDH/ZlZiDMQK+uITL3thyy1z+uB qcS4KjwZJMDfg== Date: Thu, 22 Aug 2024 17:27:41 -0700 Subject: [PATCH 25/26] xfs: scrub metadir paths for rtgroup metadata From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <172437088956.60592.4570792855287818081.stgit@frogsfrogsfrogs> In-Reply-To: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> References: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong 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 07337958fc41a..11fa3d0c38086 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 edc1a395c4015..e5714655152db 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->rtg_rgno, 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 Fri Aug 23 00:27:56 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: 13774473 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 EB86D171A5 for ; Fri, 23 Aug 2024 00:27:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372878; cv=none; b=fJiZqQ2cs+hSj621o0VarqOXGQ3QHVviwzlnTPs3HNg8/wycV4t4PotbNXSfXOTV2LR7P2r4CvpvcqPyuIHYjd0bUJrPPv7O3Q3W9NiREKiYqH6O9re9M63KLzd4OJbzj1n56vILWJYpthzkEqp5GURB5exR1yzvpk8rTJ9NbYk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724372878; c=relaxed/simple; bh=scTZDCFSswLnaqS6gV16unayvsayqsmKXyUwWuNHHaI=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=KbDCcyTI8MhiDt9neG9tE0rbNgb6N1P/MHIwmdeVWcKq3c1OL69GhRo3p3lRuw0nniOFvPJ0dEkVrK6hoq9/Q/e3oVm5J4qkrWPABgs9xUn4m9YlW4kH8QkKpD5ztWDhbU/7DE8vSrjSO43lvfuPE1gkZ8+C14hToiegxMcxp54= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=uxLyqH+K; 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="uxLyqH+K" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 797B0C32782; Fri, 23 Aug 2024 00:27:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724372877; bh=scTZDCFSswLnaqS6gV16unayvsayqsmKXyUwWuNHHaI=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=uxLyqH+KOAiUc40PZMJg88SvF4sZ5zAaI2EYt0WYqjHs6AIb/iPr+gwSZuOQSZXDB 6RuaAr9EPehRI4IeZQGHxg0uqohmHDlRNtrRB72MALMLzAo4rXAmpnfzkTFfVXTVhI hQ0VPaxMEYSaXZIV8NUT9gfsOF8WDKRcrkK9L8h1Fds1zR1JcKNYULElosjeihJ1wF TwWiJ43aRbGhS9KpVhlnu75HElKDJepd9dPRhYB8qc700GoXAXfrNhitIzVz5sI3em SozTy3Me/Xs6lYMcFA6bVtxLHv3QVaqFqwkKOKEinu/d3edATzXxEzqimWE8uycYVI sIE2mQX34KNVA== Date: Thu, 22 Aug 2024 17:27:56 -0700 Subject: [PATCH 26/26] xfs: mask off the rtbitmap and summary inodes when metadir in use From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <172437088974.60592.14197020803560709058.stgit@frogsfrogsfrogs> In-Reply-To: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> References: <172437088439.60592.14498225725916348568.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong 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 | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index f94d081f7d928..3dc6d272519ba 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -656,6 +656,13 @@ xfs_validate_sb_common( void xfs_sb_quota_from_disk(struct xfs_sb *sbp) { + if (xfs_sb_version_hasmetadir(sbp)) { + 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 @@ -784,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; @@ -806,6 +815,13 @@ xfs_sb_quota_to_disk( { uint16_t qflags = from->sb_qflags; + if (xfs_sb_version_hasmetadir(from)) { + 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); /* @@ -941,6 +957,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); } }