mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-09 06:43:09 +00:00
xfs: support caching rtgroup metadata inodes
Create the necessary per-rtgroup infrastructure that we need to load metadata inodes into memory. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
c29237a65c
commit
65b1231b8c
@ -30,6 +30,8 @@
|
||||
#include "xfs_icache.h"
|
||||
#include "xfs_rtgroup.h"
|
||||
#include "xfs_rtbitmap.h"
|
||||
#include "xfs_metafile.h"
|
||||
#include "xfs_metadir.h"
|
||||
|
||||
int
|
||||
xfs_rtgroup_alloc(
|
||||
@ -250,3 +252,124 @@ xfs_rtginode_lockdep_setup(
|
||||
#else
|
||||
#define xfs_rtginode_lockdep_setup(ip, rgno, type) do { } while (0)
|
||||
#endif /* CONFIG_PROVE_LOCKING */
|
||||
|
||||
struct xfs_rtginode_ops {
|
||||
const char *name; /* short name */
|
||||
|
||||
enum xfs_metafile_type metafile_type;
|
||||
|
||||
/* Does the fs have this feature? */
|
||||
bool (*enabled)(struct xfs_mount *mp);
|
||||
};
|
||||
|
||||
static const struct xfs_rtginode_ops xfs_rtginode_ops[XFS_RTGI_MAX] = {
|
||||
};
|
||||
|
||||
/* Return the shortname of this rtgroup inode. */
|
||||
const char *
|
||||
xfs_rtginode_name(
|
||||
enum xfs_rtg_inodes type)
|
||||
{
|
||||
return xfs_rtginode_ops[type].name;
|
||||
}
|
||||
|
||||
/* Return the metafile type of this rtgroup inode. */
|
||||
enum xfs_metafile_type
|
||||
xfs_rtginode_metafile_type(
|
||||
enum xfs_rtg_inodes type)
|
||||
{
|
||||
return xfs_rtginode_ops[type].metafile_type;
|
||||
}
|
||||
|
||||
/* Should this rtgroup inode be present? */
|
||||
bool
|
||||
xfs_rtginode_enabled(
|
||||
struct xfs_rtgroup *rtg,
|
||||
enum xfs_rtg_inodes type)
|
||||
{
|
||||
const struct xfs_rtginode_ops *ops = &xfs_rtginode_ops[type];
|
||||
|
||||
if (!ops->enabled)
|
||||
return true;
|
||||
return ops->enabled(rtg_mount(rtg));
|
||||
}
|
||||
|
||||
/* Load and existing rtgroup inode into the rtgroup structure. */
|
||||
int
|
||||
xfs_rtginode_load(
|
||||
struct xfs_rtgroup *rtg,
|
||||
enum xfs_rtg_inodes type,
|
||||
struct xfs_trans *tp)
|
||||
{
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
const char *path;
|
||||
struct xfs_inode *ip;
|
||||
const struct xfs_rtginode_ops *ops = &xfs_rtginode_ops[type];
|
||||
int error;
|
||||
|
||||
if (!xfs_rtginode_enabled(rtg, type))
|
||||
return 0;
|
||||
|
||||
if (!mp->m_rtdirip)
|
||||
return -EFSCORRUPTED;
|
||||
|
||||
path = xfs_rtginode_path(rtg_rgno(rtg), type);
|
||||
if (!path)
|
||||
return -ENOMEM;
|
||||
error = xfs_metadir_load(tp, mp->m_rtdirip, path, ops->metafile_type,
|
||||
&ip);
|
||||
kfree(path);
|
||||
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (XFS_IS_CORRUPT(mp, ip->i_df.if_format != XFS_DINODE_FMT_EXTENTS &&
|
||||
ip->i_df.if_format != XFS_DINODE_FMT_BTREE)) {
|
||||
xfs_irele(ip);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
if (XFS_IS_CORRUPT(mp, ip->i_projid != rtg_rgno(rtg))) {
|
||||
xfs_irele(ip);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
xfs_rtginode_lockdep_setup(ip, rtg_rgno(rtg), type);
|
||||
rtg->rtg_inodes[type] = ip;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Release an rtgroup metadata inode. */
|
||||
void
|
||||
xfs_rtginode_irele(
|
||||
struct xfs_inode **ipp)
|
||||
{
|
||||
if (*ipp)
|
||||
xfs_irele(*ipp);
|
||||
*ipp = NULL;
|
||||
}
|
||||
|
||||
/* Create the parent directory for all rtgroup inodes and load it. */
|
||||
int
|
||||
xfs_rtginode_mkdir_parent(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
if (!mp->m_metadirip)
|
||||
return -EFSCORRUPTED;
|
||||
|
||||
return xfs_metadir_mkdir(mp->m_metadirip, "rtgroups", &mp->m_rtdirip);
|
||||
}
|
||||
|
||||
/* Load the parent directory of all rtgroup inodes. */
|
||||
int
|
||||
xfs_rtginode_load_parent(
|
||||
struct xfs_trans *tp)
|
||||
{
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
|
||||
if (!mp->m_metadirip)
|
||||
return -EFSCORRUPTED;
|
||||
|
||||
return xfs_metadir_load(tp, mp->m_metadirip, "rtgroups",
|
||||
XFS_METAFILE_DIR, &mp->m_rtdirip);
|
||||
}
|
||||
|
@ -11,12 +11,23 @@
|
||||
struct xfs_mount;
|
||||
struct xfs_trans;
|
||||
|
||||
enum xfs_rtg_inodes {
|
||||
XFS_RTGI_MAX,
|
||||
};
|
||||
|
||||
#ifdef MAX_LOCKDEP_SUBCLASSES
|
||||
static_assert(XFS_RTGI_MAX <= MAX_LOCKDEP_SUBCLASSES);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Realtime group incore structure, similar to the per-AG structure.
|
||||
*/
|
||||
struct xfs_rtgroup {
|
||||
struct xfs_group rtg_group;
|
||||
|
||||
/* per-rtgroup metadata inodes */
|
||||
struct xfs_inode *rtg_inodes[1 /* hack */];
|
||||
|
||||
/* Number of blocks in this group */
|
||||
xfs_rtxnum_t rtg_extents;
|
||||
};
|
||||
@ -210,6 +221,22 @@ void xfs_rtgroup_lock(struct xfs_rtgroup *rtg, unsigned int rtglock_flags);
|
||||
void xfs_rtgroup_unlock(struct xfs_rtgroup *rtg, unsigned int rtglock_flags);
|
||||
void xfs_rtgroup_trans_join(struct xfs_trans *tp, struct xfs_rtgroup *rtg,
|
||||
unsigned int rtglock_flags);
|
||||
|
||||
int xfs_rtginode_mkdir_parent(struct xfs_mount *mp);
|
||||
int xfs_rtginode_load_parent(struct xfs_trans *tp);
|
||||
|
||||
const char *xfs_rtginode_name(enum xfs_rtg_inodes type);
|
||||
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);
|
||||
void xfs_rtginode_irele(struct xfs_inode **ipp);
|
||||
|
||||
static inline const char *xfs_rtginode_path(xfs_rgnumber_t rgno,
|
||||
enum xfs_rtg_inodes type)
|
||||
{
|
||||
return kasprintf(GFP_KERNEL, "%u.%s", rgno, xfs_rtginode_name(type));
|
||||
}
|
||||
#else
|
||||
static inline void xfs_free_rtgroups(struct xfs_mount *mp,
|
||||
xfs_rgnumber_t first_rgno, xfs_rgnumber_t end_rgno)
|
||||
|
@ -128,6 +128,7 @@ typedef struct xfs_mount {
|
||||
struct xfs_inode *m_rsumip; /* pointer to summary inode */
|
||||
struct xfs_inode *m_rootip; /* pointer to root directory */
|
||||
struct xfs_inode *m_metadirip; /* ptr to metadata directory */
|
||||
struct xfs_inode *m_rtdirip; /* ptr to realtime metadir */
|
||||
struct xfs_quotainfo *m_quotainfo; /* disk quota information */
|
||||
struct xfs_buftarg *m_ddev_targp; /* data device */
|
||||
struct xfs_buftarg *m_logdev_targp;/* log device */
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "xfs_da_format.h"
|
||||
#include "xfs_metafile.h"
|
||||
#include "xfs_rtgroup.h"
|
||||
#include "xfs_error.h"
|
||||
|
||||
/*
|
||||
* Return whether there are any free extents in the size range given
|
||||
@ -652,6 +653,16 @@ xfs_rtallocate_extent_size(
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
static void
|
||||
xfs_rtunmount_rtg(
|
||||
struct xfs_rtgroup *rtg)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < XFS_RTGI_MAX; i++)
|
||||
xfs_rtginode_irele(&rtg->rtg_inodes[i]);
|
||||
}
|
||||
|
||||
static int
|
||||
xfs_alloc_rsum_cache(
|
||||
struct xfs_mount *mp,
|
||||
@ -1127,6 +1138,43 @@ xfs_rtmount_iread_extents(
|
||||
return error;
|
||||
}
|
||||
|
||||
static void
|
||||
xfs_rtgroup_unmount_inodes(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
struct xfs_rtgroup *rtg = NULL;
|
||||
|
||||
while ((rtg = xfs_rtgroup_next(mp, rtg)))
|
||||
xfs_rtunmount_rtg(rtg);
|
||||
xfs_rtginode_irele(&mp->m_rtdirip);
|
||||
}
|
||||
|
||||
static int
|
||||
xfs_rtmount_rtg(
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_rtgroup *rtg)
|
||||
{
|
||||
int error, i;
|
||||
|
||||
rtg->rtg_extents = xfs_rtgroup_extents(mp, rtg_rgno(rtg));
|
||||
|
||||
for (i = 0; i < XFS_RTGI_MAX; i++) {
|
||||
error = xfs_rtginode_load(rtg, i, tp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (rtg->rtg_inodes[i]) {
|
||||
error = xfs_rtmount_iread_extents(tp,
|
||||
rtg->rtg_inodes[i], 0);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the bitmap and summary inodes and the summary cache into the mount
|
||||
* structure at mount time.
|
||||
@ -1168,15 +1216,28 @@ xfs_rtmount_inodes(
|
||||
if (error)
|
||||
goto out_rele_summary;
|
||||
|
||||
while ((rtg = xfs_rtgroup_next(mp, rtg)))
|
||||
rtg->rtg_extents = xfs_rtgroup_extents(mp, rtg_rgno(rtg));
|
||||
if (xfs_has_rtgroups(mp) && mp->m_sb.sb_rgcount > 0) {
|
||||
error = xfs_rtginode_load_parent(tp);
|
||||
if (error)
|
||||
goto out_rele_summary;
|
||||
}
|
||||
|
||||
while ((rtg = xfs_rtgroup_next(mp, rtg))) {
|
||||
error = xfs_rtmount_rtg(mp, tp, rtg);
|
||||
if (error) {
|
||||
xfs_rtgroup_rele(rtg);
|
||||
goto out_rele_inodes;
|
||||
}
|
||||
}
|
||||
|
||||
error = xfs_alloc_rsum_cache(mp, sbp->sb_rbmblocks);
|
||||
if (error)
|
||||
goto out_rele_summary;
|
||||
goto out_rele_inodes;
|
||||
xfs_trans_cancel(tp);
|
||||
return 0;
|
||||
|
||||
out_rele_inodes:
|
||||
xfs_rtgroup_unmount_inodes(mp);
|
||||
out_rele_summary:
|
||||
xfs_irele(mp->m_rsumip);
|
||||
out_rele_bitmap:
|
||||
@ -1191,6 +1252,8 @@ xfs_rtunmount_inodes(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
kvfree(mp->m_rsum_cache);
|
||||
|
||||
xfs_rtgroup_unmount_inodes(mp);
|
||||
if (mp->m_rbmip)
|
||||
xfs_irele(mp->m_rbmip);
|
||||
if (mp->m_rsumip)
|
||||
|
Loading…
Reference in New Issue
Block a user