mp->m_rsumip = rsumip;
}
+/* Create the realtime rmap btree inode. */
+static void
+rtrmapbt_create(
+ struct xfs_rtgroup *rtg)
+{
+ struct xfs_imeta_update upd;
+ struct xfs_rmap_irec rmap = {
+ .rm_startblock = 0,
+ .rm_blockcount = rtg->rtg_mount->m_sb.sb_rextsize,
+ .rm_owner = XFS_RMAP_OWN_FS,
+ .rm_offset = 0,
+ .rm_flags = 0,
+ };
+ struct xfs_mount *mp = rtg->rtg_mount;
+ struct xfs_imeta_path *path;
+ struct xfs_btree_cur *cur;
+ int error;
+
+ error = -libxfs_rtrmapbt_create_path(mp, rtg->rtg_rgno, &path);
+ if (error)
+ fail( _("rtrmap inode path creation failed"), error);
+
+ error = -libxfs_imeta_ensure_dirpath(mp, path);
+ if (error)
+ fail(_("rtgroup directory allocation failed"), error);
+
+ error = -libxfs_imeta_start_create(mp, path, &upd);
+ if (error)
+ res_failed(error);
+
+ error = -libxfs_rtrmapbt_create(&upd, &rtg->rtg_rmapip);
+ if (error)
+ fail(_("rtrmap inode creation failed"), error);
+
+ /* Adding an rmap for the rtgroup super should fit in the data fork */
+ cur = libxfs_rtrmapbt_init_cursor(mp, upd.tp, rtg, rtg->rtg_rmapip);
+ error = -libxfs_rmap_map_raw(cur, &rmap);
+ libxfs_btree_del_cursor(cur, error);
+ if (error)
+ fail(_("rtrmapbt initialization failed"), error);
+
+ error = -libxfs_imeta_commit_update(&upd);
+ if (error)
+ fail(_("rtrmapbt commit failed"), error);
+
+ libxfs_imeta_free_path(path);
+}
+
/* Initialize block headers of rt free space files. */
static int
init_rtblock_headers(
rtinit(
struct xfs_mount *mp)
{
+ struct xfs_rtgroup *rtg;
+ xfs_rgnumber_t rgno;
+
rtbitmap_create(mp);
rtsummary_create(mp);
+ for_each_rtgroup(mp, rgno, rtg) {
+ if (xfs_has_rtrmapbt(mp))
+ rtrmapbt_create(rtg);
+ }
+
rtbitmap_init(mp);
rtsummary_init(mp);
if (xfs_has_rtgroups(mp))
}
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) &&
cli->cfgfile);
}
+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_imeta_resv_init_inode(rtg->rtg_rmapip, ask);
+ if (error)
+ prealloc_fail(mp, error, ask, _("realtime rmap btree"));
+ }
+
+ /* Unreserve the realtime metadata reservations. */
+ for_each_rtgroup(mp, rgno, rtg) {
+ libxfs_imeta_resv_free_inode(rtg->rtg_rmapip);
+ }
+
+ /* 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,
*/
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
*/