diff options
author | Darrick J. Wong <djwong@kernel.org> | 2021-09-01 11:16:38 -0700 |
---|---|---|
committer | Darrick J. Wong <djwong@kernel.org> | 2021-12-15 17:29:15 -0800 |
commit | b364c8d879c97345a3b00c25805ee07b19e062a7 (patch) | |
tree | 4fc83ebe536180d7f6c036d78c0db550563218d0 /fs/xfs | |
parent | c22ab7358ed955dcacd4807f56c8c7a66d90d84a (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/xfs')
-rw-r--r-- | fs/xfs/libxfs/xfs_format.h | 6 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_imeta.c | 2 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_imeta.h | 1 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_inode_buf.c | 6 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_inode_fork.c | 9 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_rtrmap_btree.c | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_inode.c | 19 | ||||
-rw-r--r-- | fs/xfs/xfs_inode_item.c | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_inode_item_recover.c | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_mount.h | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_rtalloc.c | 52 | ||||
-rw-r--r-- | fs/xfs/xfs_trace.h | 1 |
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), |