diff --git a/mkfs/proto.c b/mkfs/proto.c
index 65072f7b5..8a51bfb26 100644
--- a/mkfs/proto.c
+++ b/mkfs/proto.c
@@ -750,78 +750,102 @@ parse_proto(
 	parseproto(mp, NULL, fsx, pp, NULL);
 }
 
-/*
- * Allocate the realtime bitmap and summary inodes, and fill in data if any.
- */
+/* Create a sb-rooted metadata file. */
 static void
-rtinit(
-	struct xfs_mount	*mp)
+create_sb_metadata_file(
+	struct xfs_mount	*mp,
+	void			(*create)(struct xfs_inode *ip))
 {
-	struct cred		creds;
-	struct fsxattr		fsxattrs;
-	struct xfs_bmbt_irec	map[XFS_BMAP_MAX_NMAP];
-	struct xfs_inode	*rbmip;
-	struct xfs_inode	*rsumip;
+	struct xfs_icreate_args	args = {
+		.mode		= S_IFREG,
+		.flags		= XFS_ICREATE_UNLINKABLE,
+	};
 	struct xfs_trans	*tp;
-	struct xfs_bmbt_irec	*ep;
-	xfs_fileoff_t		bno;
-	xfs_extlen_t		nsumblocks;
-	uint			blocks;
-	int			i;
-	int			nmap;
+	struct xfs_inode	*ip = NULL;
+	xfs_ino_t		ino;
 	int			error;
 
-	/* Create the realtime bitmap inode. */
 	error = -libxfs_trans_alloc_rollable(mp, MKFS_BLOCKRES_INODE, &tp);
 	if (error)
 		res_failed(error);
 
-	memset(&creds, 0, sizeof(creds));
-	memset(&fsxattrs, 0, sizeof(fsxattrs));
-	error = creatproto(&tp, NULL, S_IFREG, 0, &creds, &fsxattrs, &rbmip);
-	if (error) {
-		fail(_("Realtime bitmap inode allocation failed"), error);
-	}
-	/*
-	 * Do our thing with rbmip before allocating rsumip,
-	 * because the next call to createproto may
-	 * commit the transaction in which rbmip was allocated.
-	 */
-	mp->m_sb.sb_rbmino = rbmip->i_ino;
-	rbmip->i_disk_size = mp->m_sb.sb_rbmblocks * mp->m_sb.sb_blocksize;
-	rbmip->i_diflags = XFS_DIFLAG_NEWRTBM;
-	inode_set_atime(VFS_I(rbmip), 0, 0);
-	libxfs_trans_log_inode(tp, rbmip, XFS_ILOG_CORE);
-	libxfs_log_sb(tp);
-	mp->m_rbmip = rbmip;
+	error = -libxfs_dialloc(&tp, 0, args.mode, &ino);
+	if (error)
+		goto fail;
+
+	error = -libxfs_icreate(tp, ino, &args, &ip);
+	if (error)
+		goto fail;
 
-	/* Create the realtime summary inode. */
-	error = creatproto(&tp, NULL, S_IFREG, 0, &creds, &fsxattrs, &rsumip);
-	if (error) {
-		fail(_("Realtime summary inode allocation failed"), error);
-	}
-	mp->m_sb.sb_rsumino = rsumip->i_ino;
-	rsumip->i_disk_size = mp->m_rsumsize;
-	libxfs_trans_log_inode(tp, rsumip, XFS_ILOG_CORE);
+	create(ip);
+
+	libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 	libxfs_log_sb(tp);
+
 	error = -libxfs_trans_commit(tp);
 	if (error)
-		fail(_("Completion of the realtime summary inode failed"),
-				error);
-	mp->m_rsumip = rsumip;
+		goto fail;
+
+fail:
+	if (ip)
+		libxfs_irele(ip);
+	if (error)
+		fail(_("Realtime inode allocation failed"), error);
+}
+
+static void
+rtbitmap_create(
+	struct xfs_inode	*ip)
+{
+	struct xfs_mount	*mp = ip->i_mount;
+
+	ip->i_disk_size = mp->m_sb.sb_rbmblocks * mp->m_sb.sb_blocksize;
+	ip->i_diflags |= XFS_DIFLAG_NEWRTBM;
+	inode_set_atime(VFS_I(ip), 0, 0);
+
+	mp->m_sb.sb_rbmino = ip->i_ino;
+	mp->m_rbmip = ip;
+	ihold(VFS_I(ip));
+}
+
+static void
+rtsummary_create(
+	struct xfs_inode	*ip)
+{
+	struct xfs_mount	*mp = ip->i_mount;
+
+	ip->i_disk_size = mp->m_rsumsize;
+
+	mp->m_sb.sb_rsumino = ip->i_ino;
+	mp->m_rsumip = ip;
+	ihold(VFS_I(ip));
+}
+
+/* Zero the realtime bitmap. */
+static void
+rtbitmap_init(
+	struct xfs_mount	*mp)
+{
+	struct xfs_bmbt_irec	map[XFS_BMAP_MAX_NMAP];
+	struct xfs_trans	*tp;
+	struct xfs_bmbt_irec	*ep;
+	xfs_fileoff_t		bno;
+	uint			blocks;
+	int			i;
+	int			nmap;
+	int			error;
 
-	/* Zero the realtime bitmap. */
 	blocks = mp->m_sb.sb_rbmblocks +
 			XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1;
 	error = -libxfs_trans_alloc_rollable(mp, blocks, &tp);
 	if (error)
 		res_failed(error);
 
-	libxfs_trans_ijoin(tp, rbmip, 0);
+	libxfs_trans_ijoin(tp, mp->m_rbmip, 0);
 	bno = 0;
 	while (bno < mp->m_sb.sb_rbmblocks) {
 		nmap = XFS_BMAP_MAX_NMAP;
-		error = -libxfs_bmapi_write(tp, rbmip, bno,
+		error = -libxfs_bmapi_write(tp, mp->m_rbmip, bno,
 				(xfs_extlen_t)(mp->m_sb.sb_rbmblocks - bno),
 				0, mp->m_sb.sb_rbmblocks, map, &nmap);
 		if (error)
@@ -840,19 +864,34 @@ rtinit(
 	if (error)
 		fail(_("Block allocation of the realtime bitmap inode failed"),
 				error);
+}
+
+/* Zero the realtime summary file. */
+static void
+rtsummary_init(
+	struct xfs_mount	*mp)
+{
+	struct xfs_bmbt_irec	map[XFS_BMAP_MAX_NMAP];
+	struct xfs_trans	*tp;
+	struct xfs_bmbt_irec	*ep;
+	xfs_fileoff_t		bno;
+	xfs_extlen_t		nsumblocks;
+	uint			blocks;
+	int			i;
+	int			nmap;
+	int			error;
 
-	/* Zero the summary file. */
 	nsumblocks = mp->m_rsumsize >> mp->m_sb.sb_blocklog;
 	blocks = nsumblocks + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1;
 	error = -libxfs_trans_alloc_rollable(mp, blocks, &tp);
 	if (error)
 		res_failed(error);
-	libxfs_trans_ijoin(tp, rsumip, 0);
+	libxfs_trans_ijoin(tp, mp->m_rsumip, 0);
 
 	bno = 0;
 	while (bno < nsumblocks) {
 		nmap = XFS_BMAP_MAX_NMAP;
-		error = -libxfs_bmapi_write(tp, rsumip, bno,
+		error = -libxfs_bmapi_write(tp, mp->m_rsumip, bno,
 				(xfs_extlen_t)(nsumblocks - bno),
 				0, nsumblocks, map, &nmap);
 		if (error)
@@ -870,8 +909,6 @@ rtinit(
 	if (error)
 		fail(_("Block allocation of the realtime summary inode failed"),
 				error);
-
-	rtfreesp_init(mp);
 }
 
 /*
@@ -910,6 +947,21 @@ rtfreesp_init(
 	}
 }
 
+/*
+ * Allocate the realtime bitmap and summary inodes, and fill in data if any.
+ */
+static void
+rtinit(
+	struct xfs_mount	*mp)
+{
+	create_sb_metadata_file(mp, rtbitmap_create);
+	create_sb_metadata_file(mp, rtsummary_create);
+
+	rtbitmap_init(mp);
+	rtsummary_init(mp);
+	rtfreesp_init(mp);
+}
+
 static long
 filesize(
 	int		fd)
