@@ -250,14 +250,15 @@ set_reflink(
exit(0);
}
- if (xfs_has_realtime(mp)) {
- printf(_("Reflink feature not supported with realtime.\n"));
+ if (xfs_has_realtime(mp) && !xfs_has_rtgroups(mp)) {
+ printf(_("Reference count btree requires realtime groups.\n"));
exit(0);
}
printf(_("Adding reflink support to filesystem.\n"));
new_sb->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_REFLINK;
new_sb->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR;
+
return true;
}
@@ -497,6 +498,38 @@ reserve_rtrmap_inode(
return -libxfs_metafile_resv_init(ip, ask);
}
+/*
+ * Reserve space to handle rt refcount btree expansion.
+ *
+ * If the refcount inode for this group already exists, we assume that we're
+ * adding some other feature. Note that we have not validated the metadata
+ * directory tree, so we must perform the lookup by hand and abort the upgrade
+ * if there are errors. If the inode does not exist, the amount of space
+ * needed to handle a new maximally sized refcount btree is added to @new_resv.
+ */
+static int
+reserve_rtrefcount_inode(
+ struct xfs_rtgroup *rtg,
+ xfs_rfsblock_t *new_resv)
+{
+ struct xfs_mount *mp = rtg_mount(rtg);
+ struct xfs_inode *ip = rtg_refcount(rtg);
+ xfs_filblks_t ask;
+
+ if (!xfs_has_rtreflink(mp))
+ return 0;
+
+ ask = libxfs_rtrefcountbt_calc_reserves(mp);
+
+ /* failed to load the rtdir inode? */
+ if (!ip) {
+ *new_resv += ask;
+ return 0;
+ }
+
+ return -libxfs_metafile_resv_init(ip, ask);
+}
+
static void
check_fs_free_space(
struct xfs_mount *mp,
@@ -594,6 +627,18 @@ _("Not enough free space would remain for rtgroup %u rmap inode.\n"),
do_error(
_("Error %d while checking rtgroup %u rmap inode space reservation.\n"),
error, rtg_rgno(rtg));
+
+ error = reserve_rtrefcount_inode(rtg, &new_resv);
+ if (error == ENOSPC) {
+ printf(
+_("Not enough free space would remain for rtgroup %u refcount inode.\n"),
+ rtg_rgno(rtg));
+ exit(0);
+ }
+ if (error)
+ do_error(
+_("Error %d while checking rtgroup %u refcount inode space reservation.\n"),
+ error, rtg_rgno(rtg));
}
/*
@@ -621,8 +666,10 @@ _("Error %d while checking rtgroup %u rmap inode space reservation.\n"),
}
/* Unreserve the realtime metadata reservations. */
- while ((rtg = xfs_rtgroup_next(mp, rtg)))
+ while ((rtg = xfs_rtgroup_next(mp, rtg))) {
libxfs_metafile_resv_free(rtg_rmap(rtg));
+ libxfs_metafile_resv_free(rtg_refcount(rtg));
+ }
/*
* Release the per-AG reservations and mark the per-AG structure as