summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2020-10-25 17:16:03 -0700
committerDarrick J. Wong <darrick.wong@oracle.com>2020-10-26 18:32:30 -0700
commitbc96e0eabdb435b1b15f8f5b216db0fc1206cf06 (patch)
treef71dc93313bbd396fe185c00790392f5b07d2ad5 /fs
parent0491ae7c38cded2cda562815156fdc0826215c48 (diff)
xfs: define the on-disk format for the metadir feature
Define the on-disk layout and feature flags for the metadata inode directory feature. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/libxfs/xfs_format.h36
-rw-r--r--fs/xfs/xfs_inode.c8
-rw-r--r--fs/xfs/xfs_inode.h5
-rw-r--r--fs/xfs/xfs_super.c4
4 files changed, 51 insertions, 2 deletions
diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index c6a3e71f99eb..bf96b006bd24 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/libxfs/xfs_format.h
@@ -175,6 +175,14 @@ typedef struct xfs_sb {
xfs_lsn_t sb_lsn; /* last write sequence */
uuid_t sb_meta_uuid; /* metadata file system unique id */
+ /*
+ * Metadata Directory Inode. On disk this lives in the sb_rbmino slot,
+ * but we continue to use the in-core superblock to cache the classic
+ * inodes (rt bitmap; rt summary; user, group, and project quotas) so
+ * we cache the metadir inode value here too.
+ */
+ xfs_ino_t sb_metadirino;
+
/* must be padded to 64 bit alignment */
} xfs_sb_t;
@@ -193,7 +201,14 @@ typedef struct xfs_dsb {
uuid_t sb_uuid; /* user-visible file system unique id */
__be64 sb_logstart; /* starting block of log if internal */
__be64 sb_rootino; /* root inode number */
- __be64 sb_rbmino; /* bitmap inode for realtime extents */
+ /*
+ * bitmap inode for realtime extents.
+ *
+ * The metadata directory feature uses the sb_rbmino field to point to
+ * the root of the metadata directory tree. All other sb inode
+ * pointers are no longer used.
+ */
+ __be64 sb_rbmino;
__be64 sb_rsumino; /* summary inode for rt bitmap */
__be32 sb_rextsize; /* realtime extent size, blocks */
__be32 sb_agblocks; /* size of an allocation group */
@@ -468,6 +483,7 @@ xfs_sb_has_ro_compat_feature(
#define XFS_SB_FEAT_INCOMPAT_SPINODES (1 << 1) /* sparse inode chunks */
#define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */
#define XFS_SB_FEAT_INCOMPAT_BIGTIME (1 << 3) /* large timestamps */
+#define XFS_SB_FEAT_INCOMPAT_METADIR (1 << 4) /* metadata ino dir */
#define XFS_SB_FEAT_INCOMPAT_ALL \
(XFS_SB_FEAT_INCOMPAT_FTYPE| \
XFS_SB_FEAT_INCOMPAT_SPINODES| \
@@ -593,6 +609,12 @@ static inline bool xfs_sb_version_hasatomicswap(struct xfs_sb *sbp)
XFS_SB_FEAT_INCOMPAT_LOG_ATOMIC_SWAP);
}
+static inline bool xfs_sb_version_hasmetadir(struct xfs_sb *sbp)
+{
+ return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 &&
+ (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR);
+}
+
/*
* end of superblock version macros
*/
@@ -1174,15 +1196,25 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev)
#define XFS_DIFLAG2_REFLINK_BIT 1 /* file's blocks may be shared */
#define XFS_DIFLAG2_COWEXTSIZE_BIT 2 /* copy on write extent size hint */
#define XFS_DIFLAG2_BIGTIME_BIT 3 /* big timestamps */
+#define XFS_DIFLAG2_METADATA_BIT 4 /* filesystem metadata */
#define XFS_DIFLAG2_DAX (1 << XFS_DIFLAG2_DAX_BIT)
#define XFS_DIFLAG2_REFLINK (1 << XFS_DIFLAG2_REFLINK_BIT)
#define XFS_DIFLAG2_COWEXTSIZE (1 << XFS_DIFLAG2_COWEXTSIZE_BIT)
#define XFS_DIFLAG2_BIGTIME (1 << XFS_DIFLAG2_BIGTIME_BIT)
+/*
+ * The inode contains filesystem metadata and can be found through the metadata
+ * directory tree. The only valid modes are regular files and directories;
+ * the user, group, and project IDs must be zero; and none of the access mode
+ * bits can be set. Metadata inodes must never be resolvable through the root
+ * directory and cannot be accessed by userspace.
+ */
+#define XFS_DIFLAG2_METADATA (1 << XFS_DIFLAG2_METADATA_BIT)
+
#define XFS_DIFLAG2_ANY \
(XFS_DIFLAG2_DAX | XFS_DIFLAG2_REFLINK | XFS_DIFLAG2_COWEXTSIZE | \
- XFS_DIFLAG2_BIGTIME)
+ XFS_DIFLAG2_BIGTIME | XFS_DIFLAG2_METADATA)
static inline bool xfs_dinode_has_bigtime(const struct xfs_dinode *dip)
{
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 2fed392c158c..41bc5d947945 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1503,6 +1503,10 @@ xfs_inode_needs_inactivation(
if (mp->m_flags & XFS_MOUNT_RDONLY)
return false;
+ /* Metadata inodes require explicit resource cleanup. */
+ if (xfs_is_metadata_inode(ip))
+ return false;
+
/* Try to clean out the cow blocks if there are any. */
if (cow_ifp && cow_ifp->if_bytes > 0)
return true;
@@ -1597,6 +1601,10 @@ xfs_inactive(
if (mp->m_flags & XFS_MOUNT_RDONLY)
return;
+ /* Metadata inodes require explicit resource cleanup. */
+ if (xfs_is_metadata_inode(ip))
+ return;
+
xfs_inactive_health(ip);
/*
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index aa000a2a60fd..78311c2a74f8 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -177,6 +177,11 @@ static inline bool xfs_is_reflink_inode(struct xfs_inode *ip)
return ip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK;
}
+static inline bool xfs_is_metadata_inode(struct xfs_inode *ip)
+{
+ return ip->i_d.di_flags2 & XFS_DIFLAG2_METADATA;
+}
+
bool xfs_is_always_cow_inode(struct xfs_inode *ip);
/*
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index fbbf341bd215..19c3804aae20 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -1684,6 +1684,10 @@ xfs_fc_fill_super(
}
}
+ if (xfs_sb_version_hasmetadir(&mp->m_sb))
+ xfs_warn(mp,
+"EXPERIMENTAL metadata directory feature in use. Use at your own risk!");
+
if (xfs_sb_version_hasreflink(&mp->m_sb)) {
if (mp->m_sb.sb_rblocks) {
xfs_alert(mp,