From: Darrick J. Wong Date: Fri, 9 Aug 2024 12:34:30 +0000 (+0200) Subject: mkfs: create the realtime rmap inode X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=refs%2Fheads%2Fxfs-realtime-rmap-rebase;p=users%2Fhch%2Fxfsprogs.git mkfs: create the realtime rmap inode Create a realtime rmapbt inode if we format the fs with realtime and rmap. Signed-off-by: Darrick J. Wong --- diff --git a/libxfs/init.c b/libxfs/init.c index 61b9e2463..3e2a74ee7 100644 --- a/libxfs/init.c +++ b/libxfs/init.c @@ -307,13 +307,6 @@ rtmount_init( return -1; } - if (xfs_has_rmapbt(mp)) { - fprintf(stderr, - _("%s: Reverse mapping btree not compatible with realtime device. Please try a newer xfsprogs.\n"), - progname); - return -1; - } - if (mp->m_rtdev_targp->bt_bdev == 0 && !xfs_is_debugger(mp)) { fprintf(stderr, _("%s: filesystem has a realtime subvolume\n"), progname); diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index 5aae3b84a..a945aeebd 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -2560,12 +2560,18 @@ _("reflink not supported with realtime devices\n")); } cli->sb_feat.reflink = false; - if (cli->sb_feat.rmapbt && cli_opt_set(&mopts, M_RMAPBT)) { - fprintf(stderr, -_("rmapbt not supported with realtime devices\n")); - usage(); + if (!cli->sb_feat.rtgroups && cli->sb_feat.rmapbt) { + if (cli_opt_set(&mopts, M_RMAPBT) && + cli_opt_set(&ropts, R_RTGROUPS)) { + fprintf(stderr, +_("rmapbt not supported on realtime devices without rtgroups feature\n")); + usage(); + } else if (cli_opt_set(&mopts, M_RMAPBT)) { + cli->sb_feat.rtgroups = true; + } else { + cli->sb_feat.rmapbt = false; + } } - cli->sb_feat.rmapbt = false; } if ((cli->fsx.fsx_xflags & FS_XFLAG_COWEXTSIZE) && @@ -4803,6 +4809,78 @@ write_rtsb( libxfs_buf_relse(sb_bp); } +static inline void +prealloc_fail( + struct xfs_mount *mp, + int error, + xfs_filblks_t ask, + const char *tag) +{ + if (error == ENOSPC) + fprintf(stderr, + _("%s: cannot handle expansion of %s; need %llu free blocks, have %llu\n"), + progname, tag, (unsigned long long)ask, + (unsigned long long)mp->m_sb.sb_fdblocks); + else + fprintf(stderr, + _("%s: error %d while checking free space for %s\n"), + progname, error, tag); + exit(1); +} + +/* + * Make sure there's enough space on the data device to handle realtime + * metadata btree expansions. + */ +static void +check_rt_meta_prealloc( + struct xfs_mount *mp) +{ + struct xfs_perag *pag; + struct xfs_rtgroup *rtg; + xfs_agnumber_t agno; + xfs_rgnumber_t rgno; + xfs_filblks_t ask; + int error; + + /* + * First create all the per-AG reservations, since they take from the + * free block count. Each AG should start with enough free space for + * the per-AG reservation. + */ + mp->m_finobt_nores = false; + + for_each_perag(mp, agno, pag) { + error = -libxfs_ag_resv_init(pag, NULL); + if (error && error != ENOSPC) { + fprintf(stderr, + _("%s: error %d while checking AG free space for realtime metadata\n"), + progname, error); + exit(1); + } + } + + /* Realtime metadata btree inode */ + for_each_rtgroup(mp, rgno, rtg) { + ask = libxfs_rtrmapbt_calc_reserves(mp); + error = -libxfs_metafile_resv_init( + rtg->rtg_inodes[XFS_RTG_RMAP], ask); + if (error) + prealloc_fail(mp, error, ask, _("realtime rmap btree")); + } + + /* Unreserve the realtime metadata reservations. */ + for_each_rtgroup(mp, rgno, rtg) { + libxfs_metafile_resv_free(rtg->rtg_inodes[XFS_RTG_RMAP]); + } + + /* Unreserve the per-AG reservations. */ + for_each_perag(mp, agno, pag) + libxfs_ag_resv_free(pag); + + mp->m_finobt_nores = false; +} + int main( int argc, @@ -5139,6 +5217,9 @@ main( */ check_root_ino(mp); + /* Make sure we can handle space preallocations of rt metadata btrees */ + check_rt_meta_prealloc(mp); + /* * Re-write multiple secondary superblocks with rootinode field set */