mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	xfs: support creating per-RTG files in growfs
To support adding new RT groups in growfs, we need to be able to create the per-RT group files. Add a new xfs_rtginode_create helper to create a given per-RTG file. Most of the code for that is shared, but the details of the actual file are abstracted out using a new create method in struct xfs_rtginode_ops. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Darrick J. Wong <djwong@kernel.org>
This commit is contained in:
		
							parent
							
								
									e3088ae2dc
								
							
						
					
					
						commit
						ae897e0bed
					
				
					 5 changed files with 137 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -1297,3 +1297,35 @@ xfs_rtfile_initialize_blocks(
 | 
			
		|||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
xfs_rtbitmap_create(
 | 
			
		||||
	struct xfs_rtgroup	*rtg,
 | 
			
		||||
	struct xfs_inode	*ip,
 | 
			
		||||
	struct xfs_trans	*tp,
 | 
			
		||||
	bool			init)
 | 
			
		||||
{
 | 
			
		||||
	struct xfs_mount	*mp = rtg_mount(rtg);
 | 
			
		||||
 | 
			
		||||
	ip->i_disk_size = mp->m_sb.sb_rbmblocks * mp->m_sb.sb_blocksize;
 | 
			
		||||
	if (init && !xfs_has_rtgroups(mp)) {
 | 
			
		||||
		ip->i_diflags |= XFS_DIFLAG_NEWRTBM;
 | 
			
		||||
		inode_set_atime(VFS_I(ip), 0, 0);
 | 
			
		||||
	}
 | 
			
		||||
	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
xfs_rtsummary_create(
 | 
			
		||||
	struct xfs_rtgroup	*rtg,
 | 
			
		||||
	struct xfs_inode	*ip,
 | 
			
		||||
	struct xfs_trans	*tp,
 | 
			
		||||
	bool			init)
 | 
			
		||||
{
 | 
			
		||||
	struct xfs_mount	*mp = rtg_mount(rtg);
 | 
			
		||||
 | 
			
		||||
	ip->i_disk_size = mp->m_rsumblocks * mp->m_sb.sb_blocksize;
 | 
			
		||||
	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -315,6 +315,10 @@ xfs_filblks_t xfs_rtsummary_blockcount(struct xfs_mount *mp,
 | 
			
		|||
int xfs_rtfile_initialize_blocks(struct xfs_rtgroup *rtg,
 | 
			
		||||
		enum xfs_rtg_inodes type, xfs_fileoff_t offset_fsb,
 | 
			
		||||
		xfs_fileoff_t end_fsb, void *data);
 | 
			
		||||
int xfs_rtbitmap_create(struct xfs_rtgroup *rtg, struct xfs_inode *ip,
 | 
			
		||||
		struct xfs_trans *tp, bool init);
 | 
			
		||||
int xfs_rtsummary_create(struct xfs_rtgroup *rtg, struct xfs_inode *ip,
 | 
			
		||||
		struct xfs_trans *tp, bool init);
 | 
			
		||||
 | 
			
		||||
#else /* CONFIG_XFS_RT */
 | 
			
		||||
# define xfs_rtfree_extent(t,b,l)			(-ENOSYS)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -272,16 +272,24 @@ struct xfs_rtginode_ops {
 | 
			
		|||
 | 
			
		||||
	/* Does the fs have this feature? */
 | 
			
		||||
	bool			(*enabled)(struct xfs_mount *mp);
 | 
			
		||||
 | 
			
		||||
	/* Create this rtgroup metadata inode and initialize it. */
 | 
			
		||||
	int			(*create)(struct xfs_rtgroup *rtg,
 | 
			
		||||
					  struct xfs_inode *ip,
 | 
			
		||||
					  struct xfs_trans *tp,
 | 
			
		||||
					  bool init);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct xfs_rtginode_ops xfs_rtginode_ops[XFS_RTGI_MAX] = {
 | 
			
		||||
	[XFS_RTGI_BITMAP] = {
 | 
			
		||||
		.name		= "bitmap",
 | 
			
		||||
		.metafile_type	= XFS_METAFILE_RTBITMAP,
 | 
			
		||||
		.create		= xfs_rtbitmap_create,
 | 
			
		||||
	},
 | 
			
		||||
	[XFS_RTGI_SUMMARY] = {
 | 
			
		||||
		.name		= "summary",
 | 
			
		||||
		.metafile_type	= XFS_METAFILE_RTSUMMARY,
 | 
			
		||||
		.create		= xfs_rtsummary_create,
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -389,6 +397,67 @@ xfs_rtginode_irele(
 | 
			
		|||
	*ipp = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Add a metadata inode for a realtime rmap btree. */
 | 
			
		||||
int
 | 
			
		||||
xfs_rtginode_create(
 | 
			
		||||
	struct xfs_rtgroup		*rtg,
 | 
			
		||||
	enum xfs_rtg_inodes		type,
 | 
			
		||||
	bool				init)
 | 
			
		||||
{
 | 
			
		||||
	const struct xfs_rtginode_ops	*ops = &xfs_rtginode_ops[type];
 | 
			
		||||
	struct xfs_mount		*mp = rtg_mount(rtg);
 | 
			
		||||
	struct xfs_metadir_update	upd = {
 | 
			
		||||
		.dp			= mp->m_rtdirip,
 | 
			
		||||
		.metafile_type		= ops->metafile_type,
 | 
			
		||||
	};
 | 
			
		||||
	int				error;
 | 
			
		||||
 | 
			
		||||
	if (!xfs_rtginode_enabled(rtg, type))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!mp->m_rtdirip)
 | 
			
		||||
		return -EFSCORRUPTED;
 | 
			
		||||
 | 
			
		||||
	upd.path = xfs_rtginode_path(rtg_rgno(rtg), type);
 | 
			
		||||
	if (!upd.path)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
 | 
			
		||||
	error = xfs_metadir_start_create(&upd);
 | 
			
		||||
	if (error)
 | 
			
		||||
		goto out_path;
 | 
			
		||||
 | 
			
		||||
	error = xfs_metadir_create(&upd, S_IFREG);
 | 
			
		||||
	if (error)
 | 
			
		||||
		return error;
 | 
			
		||||
 | 
			
		||||
	xfs_rtginode_lockdep_setup(upd.ip, rtg_rgno(rtg), type);
 | 
			
		||||
 | 
			
		||||
	upd.ip->i_projid = rtg_rgno(rtg);
 | 
			
		||||
	error = ops->create(rtg, upd.ip, upd.tp, init);
 | 
			
		||||
	if (error)
 | 
			
		||||
		goto out_cancel;
 | 
			
		||||
 | 
			
		||||
	error = xfs_metadir_commit(&upd);
 | 
			
		||||
	if (error)
 | 
			
		||||
		goto out_path;
 | 
			
		||||
 | 
			
		||||
	kfree(upd.path);
 | 
			
		||||
	xfs_finish_inode_setup(upd.ip);
 | 
			
		||||
	rtg->rtg_inodes[type] = upd.ip;
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
out_cancel:
 | 
			
		||||
	xfs_metadir_cancel(&upd, error);
 | 
			
		||||
	/* Have to finish setting up the inode to ensure it's deleted. */
 | 
			
		||||
	if (upd.ip) {
 | 
			
		||||
		xfs_finish_inode_setup(upd.ip);
 | 
			
		||||
		xfs_irele(upd.ip);
 | 
			
		||||
	}
 | 
			
		||||
out_path:
 | 
			
		||||
	kfree(upd.path);
 | 
			
		||||
	return error;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Create the parent directory for all rtgroup inodes and load it. */
 | 
			
		||||
int
 | 
			
		||||
xfs_rtginode_mkdir_parent(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -242,6 +242,8 @@ 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);
 | 
			
		||||
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,
 | 
			
		||||
		bool init);
 | 
			
		||||
void xfs_rtginode_irele(struct xfs_inode **ipp);
 | 
			
		||||
 | 
			
		||||
static inline const char *xfs_rtginode_path(xfs_rgnumber_t rgno,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -711,6 +711,29 @@ xfs_growfs_rt_fixup_extsize(
 | 
			
		|||
	return error;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Ensure that the rtgroup metadata inode is loaded, creating it if neeeded. */
 | 
			
		||||
static int
 | 
			
		||||
xfs_rtginode_ensure(
 | 
			
		||||
	struct xfs_rtgroup	*rtg,
 | 
			
		||||
	enum xfs_rtg_inodes	type)
 | 
			
		||||
{
 | 
			
		||||
	struct xfs_trans	*tp;
 | 
			
		||||
	int			error;
 | 
			
		||||
 | 
			
		||||
	if (rtg->rtg_inodes[type])
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	error = xfs_trans_alloc_empty(rtg_mount(rtg), &tp);
 | 
			
		||||
	if (error)
 | 
			
		||||
		return error;
 | 
			
		||||
	error = xfs_rtginode_load(rtg, type, tp);
 | 
			
		||||
	xfs_trans_cancel(tp);
 | 
			
		||||
 | 
			
		||||
	if (error != -ENOENT)
 | 
			
		||||
		return 0;
 | 
			
		||||
	return xfs_rtginode_create(rtg, type, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
xfs_growfs_rt_bmblock(
 | 
			
		||||
	struct xfs_rtgroup	*rtg,
 | 
			
		||||
| 
						 | 
				
			
			@ -927,12 +950,19 @@ xfs_growfs_rtg(
 | 
			
		|||
	xfs_extlen_t		bmblocks;
 | 
			
		||||
	xfs_fileoff_t		bmbno;
 | 
			
		||||
	struct xfs_rtgroup	*rtg;
 | 
			
		||||
	unsigned int		i;
 | 
			
		||||
	int			error;
 | 
			
		||||
 | 
			
		||||
	rtg = xfs_rtgroup_grab(mp, 0);
 | 
			
		||||
	if (!rtg)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < XFS_RTGI_MAX; i++) {
 | 
			
		||||
		error = xfs_rtginode_ensure(rtg, i);
 | 
			
		||||
		if (error)
 | 
			
		||||
			goto out_rele;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	error = xfs_growfs_rt_alloc_blocks(rtg, nrblocks, rextsize, &bmblocks);
 | 
			
		||||
	if (error)
 | 
			
		||||
		goto out_rele;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue