summaryrefslogtreecommitdiff
path: root/fs/xfs
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2021-09-01 11:13:24 -0700
committerDarrick J. Wong <djwong@kernel.org>2021-09-17 18:55:05 -0700
commit5db1070157b675356d56968f492d3c50a1379da9 (patch)
tree15e0abf1e86c0db66b414d6217700bb5cc55a19a /fs/xfs
parentd2e8785e534714b6bc0c31fd92a60e510f09f7f4 (diff)
xfs: load metadata directory root at mount time
Load the metadata directory root inode into memory at mount time and release it at unmount time. We also make sure that the obsolete inode pointers in the superblock are not logged or read from the superblock. Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/libxfs/xfs_sb.c31
-rw-r--r--fs/xfs/libxfs/xfs_types.c2
-rw-r--r--fs/xfs/xfs_mount.c19
-rw-r--r--fs/xfs/xfs_mount.h1
4 files changed, 50 insertions, 3 deletions
diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
index 488f1dfbbe12..fb59294c3e6c 100644
--- a/fs/xfs/libxfs/xfs_sb.c
+++ b/fs/xfs/libxfs/xfs_sb.c
@@ -571,6 +571,25 @@ __xfs_sb_from_disk(
/* Convert on-disk flags to in-memory flags? */
if (convert_xquota)
xfs_sb_quota_from_disk(to);
+
+ if (to->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR) {
+ /*
+ * Set metadirino here and null out the in-core fields for
+ * the other inodes because metadir initialization will load
+ * them later.
+ */
+ to->sb_metadirino = be64_to_cpu(from->sb_rbmino);
+ to->sb_rbmino = NULLFSINO;
+ to->sb_rsumino = NULLFSINO;
+
+ /*
+ * We don't have to worry about quota inode conversion here
+ * because metadir requires a v5 filesystem.
+ */
+ to->sb_uquotino = NULLFSINO;
+ to->sb_gquotino = NULLFSINO;
+ to->sb_pquotino = NULLFSINO;
+ }
}
void
@@ -718,6 +737,18 @@ xfs_sb_to_disk(
to->sb_lsn = cpu_to_be64(from->sb_lsn);
if (from->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_META_UUID)
uuid_copy(&to->sb_meta_uuid, &from->sb_meta_uuid);
+
+ if (from->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR) {
+ /*
+ * Save metadirino here and null out the on-disk fields for
+ * the other inodes, at least until we reuse the fields.
+ */
+ to->sb_rbmino = cpu_to_be64(from->sb_metadirino);
+ to->sb_rsumino = cpu_to_be64(NULLFSINO);
+ to->sb_uquotino = cpu_to_be64(NULLFSINO);
+ to->sb_gquotino = cpu_to_be64(NULLFSINO);
+ to->sb_pquotino = cpu_to_be64(NULLFSINO);
+ }
}
/*
diff --git a/fs/xfs/libxfs/xfs_types.c b/fs/xfs/libxfs/xfs_types.c
index d12dc9a4bdb9..6099c7c3291c 100644
--- a/fs/xfs/libxfs/xfs_types.c
+++ b/fs/xfs/libxfs/xfs_types.c
@@ -201,7 +201,7 @@ xfs_verify_dir_ino(
struct xfs_mount *mp,
xfs_ino_t ino)
{
- if (xfs_internal_inum(mp, ino))
+ if (!xfs_has_metadir(mp) && xfs_internal_inum(mp, ino))
return false;
return xfs_verify_ino(mp, ino);
}
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index adaf46ba05ee..ccf833ccb50f 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -521,6 +521,16 @@ xfs_mountfs_imeta(
{
int error;
+ /* Load the metadata directory inode into memory. */
+ if (xfs_has_metadir(mp)) {
+ error = xfs_imeta_iget(mp, mp->m_sb.sb_metadirino,
+ XFS_DIR3_FT_DIR, &mp->m_metadirip);
+ if (error) {
+ xfs_warn(mp, "Failed metadir ino init: %d", error);
+ return error;
+ }
+ }
+
error = xfs_imeta_mount(mp);
if (error) {
xfs_warn(mp, "Failed to load metadata inode info, error %d",
@@ -813,7 +823,7 @@ xfs_mountfs(
/* Load the metadata directory tree. */
error = xfs_mountfs_imeta(mp);
if (error)
- goto out_log_dealloc;
+ goto out_free_metadir;
/*
* Get and sanity-check the root inode.
@@ -825,7 +835,7 @@ xfs_mountfs(
xfs_warn(mp,
"Failed to read root inode 0x%llx, error %d",
sbp->sb_rootino, -error);
- goto out_log_dealloc;
+ goto out_free_metadir;
}
ASSERT(rip != NULL);
@@ -973,6 +983,9 @@ xfs_mountfs(
xfs_irele(rip);
/* Clean out dquots that might be in memory after quotacheck. */
xfs_qm_unmount(mp);
+ out_free_metadir:
+ if (mp->m_metadirip)
+ xfs_imeta_irele(mp->m_metadirip);
/*
* Inactivate all inodes that might still be in memory after a log
@@ -1046,6 +1059,8 @@ xfs_unmountfs(
xfs_qm_unmount_quotas(mp);
xfs_rtunmount_inodes(mp);
xfs_irele(mp->m_rootip);
+ if (mp->m_metadirip)
+ xfs_imeta_irele(mp->m_metadirip);
xfs_unmount_flush_inodes(mp);
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 47ab2472f8a5..a4c149670476 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -94,6 +94,7 @@ typedef struct xfs_mount {
struct xfs_inode *m_rbmip; /* pointer to bitmap inode */
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_quotainfo *m_quotainfo; /* disk quota information */
xfs_buftarg_t *m_ddev_targp; /* saves taking the address */
xfs_buftarg_t *m_logdev_targp;/* ptr to log device */