summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2021-09-01 11:16:38 -0700
committerDarrick J. Wong <djwong@kernel.org>2021-12-15 17:29:15 -0800
commitb364c8d879c97345a3b00c25805ee07b19e062a7 (patch)
tree4fc83ebe536180d7f6c036d78c0db550563218d0 /fs
parentc22ab7358ed955dcacd4807f56c8c7a66d90d84a (diff)
xfs: add realtime reverse map inode to metadata directory
Add a metadir path to select the realtime rmap btree inode and load it at mount time. The rtrmapbt inode will have a unique extent format code, which means that we also have to update the inode validation and flush routines to look for it. Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/libxfs/xfs_format.h6
-rw-r--r--fs/xfs/libxfs/xfs_imeta.c2
-rw-r--r--fs/xfs/libxfs/xfs_imeta.h1
-rw-r--r--fs/xfs/libxfs/xfs_inode_buf.c6
-rw-r--r--fs/xfs/libxfs/xfs_inode_fork.c9
-rw-r--r--fs/xfs/libxfs/xfs_rtrmap_btree.c1
-rw-r--r--fs/xfs/xfs_inode.c19
-rw-r--r--fs/xfs/xfs_inode_item.c2
-rw-r--r--fs/xfs/xfs_inode_item_recover.c1
-rw-r--r--fs/xfs/xfs_mount.h1
-rw-r--r--fs/xfs/xfs_rtalloc.c52
-rw-r--r--fs/xfs/xfs_trace.h1
12 files changed, 90 insertions, 11 deletions
diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index 6abaca457e82..b92035f68b76 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/libxfs/xfs_format.h
@@ -862,7 +862,8 @@ enum xfs_dinode_fmt {
XFS_DINODE_FMT_LOCAL, /* bulk data */
XFS_DINODE_FMT_EXTENTS, /* struct xfs_bmbt_rec */
XFS_DINODE_FMT_BTREE, /* struct xfs_bmdr_block */
- XFS_DINODE_FMT_UUID /* added long ago, but never used */
+ XFS_DINODE_FMT_UUID, /* added long ago, but never used */
+ XFS_DINODE_FMT_RMAP, /* reverse mapping btree */
};
#define XFS_INODE_FORMAT_STR \
@@ -870,7 +871,8 @@ enum xfs_dinode_fmt {
{ XFS_DINODE_FMT_LOCAL, "local" }, \
{ XFS_DINODE_FMT_EXTENTS, "extent" }, \
{ XFS_DINODE_FMT_BTREE, "btree" }, \
- { XFS_DINODE_FMT_UUID, "uuid" }
+ { XFS_DINODE_FMT_UUID, "uuid" }, \
+ { XFS_DINODE_FMT_RMAP, "rmap" }
/*
* Inode minimum and maximum sizes.
diff --git a/fs/xfs/libxfs/xfs_imeta.c b/fs/xfs/libxfs/xfs_imeta.c
index 8c0b8cbbf96d..a91bf747d12a 100644
--- a/fs/xfs/libxfs/xfs_imeta.c
+++ b/fs/xfs/libxfs/xfs_imeta.c
@@ -63,12 +63,14 @@
/* Static metadata inode paths */
static const char *rtbitmap_path[] = {"realtime", "0.bitmap"};
static const char *rtsummary_path[] = {"realtime", "0.summary"};
+static const char *rtrmapbt_path[] = {"realtime", "0.rmap"};
static const char *usrquota_path[] = {"quota", "user"};
static const char *grpquota_path[] = {"quota", "group"};
static const char *prjquota_path[] = {"quota", "project"};
XFS_IMETA_DEFINE_PATH(XFS_IMETA_RTBITMAP, rtbitmap_path);
XFS_IMETA_DEFINE_PATH(XFS_IMETA_RTSUMMARY, rtsummary_path);
+XFS_IMETA_DEFINE_PATH(XFS_IMETA_RTRMAPBT, rtrmapbt_path);
XFS_IMETA_DEFINE_PATH(XFS_IMETA_USRQUOTA, usrquota_path);
XFS_IMETA_DEFINE_PATH(XFS_IMETA_GRPQUOTA, grpquota_path);
XFS_IMETA_DEFINE_PATH(XFS_IMETA_PRJQUOTA, prjquota_path);
diff --git a/fs/xfs/libxfs/xfs_imeta.h b/fs/xfs/libxfs/xfs_imeta.h
index 9633351b8839..3ee616678633 100644
--- a/fs/xfs/libxfs/xfs_imeta.h
+++ b/fs/xfs/libxfs/xfs_imeta.h
@@ -37,6 +37,7 @@ struct xfs_imeta_end {
/* Lookup keys for static metadata inodes. */
extern const struct xfs_imeta_path XFS_IMETA_RTBITMAP;
extern const struct xfs_imeta_path XFS_IMETA_RTSUMMARY;
+extern const struct xfs_imeta_path XFS_IMETA_RTRMAPBT;
extern const struct xfs_imeta_path XFS_IMETA_USRQUOTA;
extern const struct xfs_imeta_path XFS_IMETA_GRPQUOTA;
extern const struct xfs_imeta_path XFS_IMETA_PRJQUOTA;
diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
index 7892b1a01c3f..32a56e1a6a38 100644
--- a/fs/xfs/libxfs/xfs_inode_buf.c
+++ b/fs/xfs/libxfs/xfs_inode_buf.c
@@ -371,6 +371,12 @@ xfs_dinode_verify_fork(
return __this_address;
}
break;
+ case XFS_DINODE_FMT_RMAP:
+ if (!xfs_has_rtrmapbt(mp))
+ return __this_address;
+ if (!(dip->di_flags2 & cpu_to_be64(XFS_DIFLAG2_METADATA)))
+ return __this_address;
+ break;
default:
return __this_address;
}
diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
index 4cb6d51aa31e..660f6fda122a 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.c
+++ b/fs/xfs/libxfs/xfs_inode_fork.c
@@ -258,6 +258,11 @@ xfs_iformat_data_fork(
return xfs_iformat_extents(ip, dip, XFS_DATA_FORK);
case XFS_DINODE_FMT_BTREE:
return xfs_iformat_btree(ip, dip, XFS_DATA_FORK);
+ case XFS_DINODE_FMT_RMAP:
+ if (!xfs_has_rtrmapbt(ip->i_mount))
+ return -EFSCORRUPTED;
+ ASSERT(0); /* to be implemented later */
+ return -EFSCORRUPTED;
default:
xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__,
dip, sizeof(*dip), __this_address);
@@ -639,6 +644,10 @@ xfs_iflush_fork(
}
break;
+ case XFS_DINODE_FMT_RMAP:
+ ASSERT(0); /* to be implemented later */
+ break;
+
default:
ASSERT(0);
break;
diff --git a/fs/xfs/libxfs/xfs_rtrmap_btree.c b/fs/xfs/libxfs/xfs_rtrmap_btree.c
index 5c144a813cea..c4f95b8d98ab 100644
--- a/fs/xfs/libxfs/xfs_rtrmap_btree.c
+++ b/fs/xfs/libxfs/xfs_rtrmap_btree.c
@@ -423,6 +423,7 @@ xfs_rtrmapbt_commit_staged_btree(
int flags = XFS_ILOG_CORE | XFS_ILOG_DBROOT;
ASSERT(cur->bc_flags & XFS_BTREE_STAGING);
+ ASSERT(ifake->if_fork->if_format == XFS_DINODE_FMT_RMAP);
/*
* Free any resources hanging off the real fork, then shallow-copy the
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index a13bd83573d0..ebca74b20499 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -2516,7 +2516,15 @@ xfs_iflush(
__func__, ip->i_ino, be16_to_cpu(dip->di_magic), dip);
goto flush_out;
}
- if (S_ISREG(VFS_I(ip)->i_mode)) {
+ if (ip->i_df.if_format == XFS_DINODE_FMT_RMAP) {
+ if (!S_ISREG(VFS_I(ip)->i_mode) ||
+ !(ip->i_diflags2 & XFS_DIFLAG2_METADATA)) {
+ xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
+ "%s: Bad rt rmapbt inode %Lu, ptr "PTR_FMT,
+ __func__, ip->i_ino, ip);
+ goto flush_out;
+ }
+ } else if (S_ISREG(VFS_I(ip)->i_mode)) {
if (XFS_TEST_ERROR(
ip->i_df.if_format != XFS_DINODE_FMT_EXTENTS &&
ip->i_df.if_format != XFS_DINODE_FMT_BTREE,
@@ -2556,6 +2564,15 @@ xfs_iflush(
goto flush_out;
}
+ if (ip->i_afp) {
+ if (ip->i_afp->if_format == XFS_DINODE_FMT_RMAP) {
+ xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
+ "%s: rt rmapbt in inode %Lu attr fork, ptr "PTR_FMT,
+ __func__, ip->i_ino, ip);
+ goto flush_out;
+ }
+ }
+
/*
* Inode item log recovery for v2 inodes are dependent on the flushiter
* count for correct sequencing. We bump the flush iteration count so
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 90d8e591baf8..e7ac4adf1c55 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -61,6 +61,7 @@ xfs_inode_item_data_fork_size(
}
break;
case XFS_DINODE_FMT_BTREE:
+ case XFS_DINODE_FMT_RMAP:
if ((iip->ili_fields & XFS_ILOG_DBROOT) &&
ip->i_df.if_broot_bytes > 0) {
*nbytes += ip->i_df.if_broot_bytes;
@@ -181,6 +182,7 @@ xfs_inode_item_format_data_fork(
}
break;
case XFS_DINODE_FMT_BTREE:
+ case XFS_DINODE_FMT_RMAP:
iip->ili_fields &=
~(XFS_ILOG_DDATA | XFS_ILOG_DEXT | XFS_ILOG_DEV);
diff --git a/fs/xfs/xfs_inode_item_recover.c b/fs/xfs/xfs_inode_item_recover.c
index 239dd2e3384e..5b6ebe5fd791 100644
--- a/fs/xfs/xfs_inode_item_recover.c
+++ b/fs/xfs/xfs_inode_item_recover.c
@@ -316,6 +316,7 @@ xlog_recover_inode_commit_pass2(
if (unlikely(S_ISREG(ldip->di_mode))) {
if ((ldip->di_format != XFS_DINODE_FMT_EXTENTS) &&
+ (ldip->di_format != XFS_DINODE_FMT_RMAP) &&
(ldip->di_format != XFS_DINODE_FMT_BTREE)) {
XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(3)",
XFS_ERRLEVEL_LOW, mp, ldip,
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 16f133728f9d..934a9fb9e1f7 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -106,6 +106,7 @@ typedef struct xfs_mount {
struct xlog *m_log; /* log specific stuff */
struct xfs_inode *m_rbmip; /* pointer to bitmap inode */
struct xfs_inode *m_rsumip; /* pointer to summary inode */
+ struct xfs_inode *m_rrmapip; /* pointer to rmap 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 */
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index bb7e874240fd..67774cf86998 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -24,6 +24,7 @@
#include "xfs_da_format.h"
#include "xfs_imeta.h"
#include "xfs_quota.h"
+#include "xfs_error.h"
/*
* Read and return the summary information for a given extent size,
@@ -1316,6 +1317,7 @@ xfs_rt_resv_init(
*/
static struct lock_class_key xfs_rbmip_key;
static struct lock_class_key xfs_rsumip_key;
+static struct lock_class_key xfs_rrmapip_key;
static inline int
xfs_rt_iget(
@@ -1338,12 +1340,13 @@ xfs_rt_iget(
* Get the bitmap and summary inodes and the summary cache into the mount
* structure at mount time.
*/
-int /* error */
+int
xfs_rtmount_inodes(
- xfs_mount_t *mp) /* file system mount structure */
+ struct xfs_mount *mp)
{
- int error; /* error return value */
- xfs_sb_t *sbp;
+ struct xfs_sb *sbp;
+ xfs_ino_t ino;
+ int error;
sbp = &mp->m_sb;
error = xfs_rt_iget(mp, mp->m_sb.sb_rbmino, &xfs_rbmip_key,
@@ -1358,13 +1361,38 @@ xfs_rtmount_inodes(
&mp->m_rsumip);
if (xfs_metadata_is_sick(error))
xfs_rt_mark_sick(mp, XFS_SICK_RT_SUMMARY);
- if (error) {
- xfs_imeta_irele(mp->m_rbmip);
- return error;
- }
+ if (error)
+ goto out_rbm;
ASSERT(mp->m_rsumip != NULL);
+
+ /* If we have rmap and a realtime device, look for the rtrmapbt. */
+ if (xfs_has_rtrmapbt(mp)) {
+ error = xfs_imeta_lookup(mp, &XFS_IMETA_RTRMAPBT, &ino);
+ if (error)
+ goto out_rsum;
+
+ error = xfs_rt_iget(mp, ino, &xfs_rrmapip_key,
+ &mp->m_rrmapip);
+ if (error)
+ goto out_rsum;
+
+ if (XFS_IS_CORRUPT(mp,
+ mp->m_rrmapip->i_df.if_format !=
+ XFS_DINODE_FMT_RMAP)) {
+ error = -EFSCORRUPTED;
+ goto out_rrmap;
+ }
+ }
+
xfs_alloc_rsum_cache(mp, sbp->sb_rbmblocks);
return 0;
+out_rrmap:
+ xfs_imeta_irele(mp->m_rrmapip);
+out_rsum:
+ xfs_imeta_irele(mp->m_rsumip);
+out_rbm:
+ xfs_imeta_irele(mp->m_rbmip);
+ return error;
}
/* Attach dquots for realtime metadata files. */
@@ -1382,6 +1410,12 @@ xfs_rtmount_dqattach(
if (error)
return error;
+ if (xfs_has_rtrmapbt(mp)) {
+ error = xfs_qm_dqattach(mp->m_rrmapip);
+ if (error)
+ return error;
+ }
+
return 0;
}
@@ -1390,6 +1424,8 @@ xfs_rtunmount_inodes(
struct xfs_mount *mp)
{
kmem_free(mp->m_rsum_cache);
+ if (mp->m_rrmapip)
+ xfs_imeta_irele(mp->m_rrmapip);
if (mp->m_rbmip)
xfs_imeta_irele(mp->m_rbmip);
if (mp->m_rsumip)
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index 7da298008ea7..3988ab860564 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -2201,6 +2201,7 @@ TRACE_DEFINE_ENUM(XFS_DINODE_FMT_LOCAL);
TRACE_DEFINE_ENUM(XFS_DINODE_FMT_EXTENTS);
TRACE_DEFINE_ENUM(XFS_DINODE_FMT_BTREE);
TRACE_DEFINE_ENUM(XFS_DINODE_FMT_UUID);
+TRACE_DEFINE_ENUM(XFS_DINODE_FMT_RMAP);
DECLARE_EVENT_CLASS(xfs_swap_extent_class,
TP_PROTO(struct xfs_inode *ip, int which),