]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs_db: display the realtime rmap btree contents
authorDarrick J. Wong <djwong@kernel.org>
Wed, 3 Jul 2024 21:22:20 +0000 (14:22 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 9 Jul 2024 22:37:19 +0000 (15:37 -0700)
Implement all the code we need to dump rtrmapbt contents, starting
from the root inode.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
12 files changed:
db/bmroot.c
db/bmroot.h
db/btblock.c
db/btblock.h
db/field.c
db/field.h
db/inode.c
db/inode.h
db/type.c
db/type.h
libxfs/libxfs_api_defs.h
man/man8/xfs_db.8

index 7ef07da181e6ff72684714954675bcf3ca47c3ae..19490bd24998c5274d2d3f0e97533b71f9992816 100644 (file)
@@ -24,6 +24,13 @@ static int   bmrootd_key_offset(void *obj, int startoff, int idx);
 static int     bmrootd_ptr_count(void *obj, int startoff);
 static int     bmrootd_ptr_offset(void *obj, int startoff, int idx);
 
+static int     rtrmaproot_rec_count(void *obj, int startoff);
+static int     rtrmaproot_rec_offset(void *obj, int startoff, int idx);
+static int     rtrmaproot_key_count(void *obj, int startoff);
+static int     rtrmaproot_key_offset(void *obj, int startoff, int idx);
+static int     rtrmaproot_ptr_count(void *obj, int startoff);
+static int     rtrmaproot_ptr_offset(void *obj, int startoff, int idx);
+
 #define        OFF(f)  bitize(offsetof(xfs_bmdr_block_t, bb_ ## f))
 const field_t  bmroota_flds[] = {
        { "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE },
@@ -54,6 +61,20 @@ const field_t        bmrootd_key_flds[] = {
        { NULL }
 };
 
+/* realtime rmap btree root */
+const field_t  rtrmaproot_flds[] = {
+       { "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE },
+       { "numrecs", FLDT_UINT16D, OI(OFF(numrecs)), C1, 0, TYP_NONE },
+       { "recs", FLDT_RTRMAPBTREC, rtrmaproot_rec_offset, rtrmaproot_rec_count,
+         FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE },
+       { "keys", FLDT_RTRMAPBTKEY, rtrmaproot_key_offset, rtrmaproot_key_count,
+         FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE },
+       { "ptrs", FLDT_RTRMAPBTPTR, rtrmaproot_ptr_offset, rtrmaproot_ptr_count,
+         FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_RTRMAPBT },
+       { NULL }
+};
+#undef OFF
+
 static int
 bmroota_key_count(
        void                    *obj,
@@ -241,3 +262,131 @@ bmrootd_size(
        dip = obj;
        return bitize((int)XFS_DFORK_DSIZE(dip, mp));
 }
+
+/* realtime rmap root */
+static int
+rtrmaproot_rec_count(
+       void                    *obj,
+       int                     startoff)
+{
+       struct xfs_rtrmap_root  *block;
+#ifdef DEBUG
+       struct xfs_dinode       *dip = obj;
+#endif
+
+       ASSERT(bitoffs(startoff) == 0);
+       ASSERT(obj == iocur_top->data);
+       block = (struct xfs_rtrmap_root *)((char *)obj + byteize(startoff));
+       ASSERT((char *)block == XFS_DFORK_DPTR(dip));
+       if (be16_to_cpu(block->bb_level) > 0)
+               return 0;
+       return be16_to_cpu(block->bb_numrecs);
+}
+
+static int
+rtrmaproot_rec_offset(
+       void                    *obj,
+       int                     startoff,
+       int                     idx)
+{
+       struct xfs_rtrmap_root  *block;
+       struct xfs_rmap_rec     *kp;
+
+       ASSERT(bitoffs(startoff) == 0);
+       ASSERT(obj == iocur_top->data);
+       block = (struct xfs_rtrmap_root *)((char *)obj + byteize(startoff));
+       ASSERT(be16_to_cpu(block->bb_level) == 0);
+       kp = xfs_rtrmap_droot_rec_addr(block, idx);
+       return bitize((int)((char *)kp - (char *)block));
+}
+
+static int
+rtrmaproot_key_count(
+       void                    *obj,
+       int                     startoff)
+{
+       struct xfs_rtrmap_root  *block;
+#ifdef DEBUG
+       struct xfs_dinode       *dip = obj;
+#endif
+
+       ASSERT(bitoffs(startoff) == 0);
+       ASSERT(obj == iocur_top->data);
+       block = (struct xfs_rtrmap_root *)((char *)obj + byteize(startoff));
+       ASSERT((char *)block == XFS_DFORK_DPTR(dip));
+       if (be16_to_cpu(block->bb_level) == 0)
+               return 0;
+       return be16_to_cpu(block->bb_numrecs);
+}
+
+static int
+rtrmaproot_key_offset(
+       void                    *obj,
+       int                     startoff,
+       int                     idx)
+{
+       struct xfs_rtrmap_root  *block;
+       struct xfs_rmap_key     *kp;
+
+       ASSERT(bitoffs(startoff) == 0);
+       ASSERT(obj == iocur_top->data);
+       block = (struct xfs_rtrmap_root *)((char *)obj + byteize(startoff));
+       ASSERT(be16_to_cpu(block->bb_level) > 0);
+       kp = xfs_rtrmap_droot_key_addr(block, idx);
+       return bitize((int)((char *)kp - (char *)block));
+}
+
+static int
+rtrmaproot_ptr_count(
+       void                    *obj,
+       int                     startoff)
+{
+       struct xfs_rtrmap_root  *block;
+#ifdef DEBUG
+       struct xfs_dinode       *dip = obj;
+#endif
+
+       ASSERT(bitoffs(startoff) == 0);
+       ASSERT(obj == iocur_top->data);
+       block = (struct xfs_rtrmap_root *)((char *)obj + byteize(startoff));
+       ASSERT((char *)block == XFS_DFORK_DPTR(dip));
+       if (be16_to_cpu(block->bb_level) == 0)
+               return 0;
+       return be16_to_cpu(block->bb_numrecs);
+}
+
+static int
+rtrmaproot_ptr_offset(
+       void                    *obj,
+       int                     startoff,
+       int                     idx)
+{
+       struct xfs_rtrmap_root  *block;
+       xfs_rtrmap_ptr_t        *pp;
+       struct xfs_dinode       *dip;
+       int                     dmxr;
+
+       ASSERT(bitoffs(startoff) == 0);
+       ASSERT(obj == iocur_top->data);
+       dip = obj;
+       block = (struct xfs_rtrmap_root *)((char *)obj + byteize(startoff));
+       ASSERT(be16_to_cpu(block->bb_level) > 0);
+       dmxr = libxfs_rtrmapbt_droot_maxrecs(XFS_DFORK_DSIZE(dip, mp), false);
+       pp = xfs_rtrmap_droot_ptr_addr(block, idx, dmxr);
+       return bitize((int)((char *)pp - (char *)block));
+}
+
+int
+rtrmaproot_size(
+       void                    *obj,
+       int                     startoff,
+       int                     idx)
+{
+       struct xfs_dinode       *dip;
+
+       ASSERT(bitoffs(startoff) == 0);
+       ASSERT(obj == iocur_top->data);
+       ASSERT(idx == 0);
+       dip = obj;
+       return bitize((int)XFS_DFORK_DSIZE(dip, mp));
+}
index a1274cf6a94bdf3484e9cb1afdb3f96f5c64df70..a2c5cfb18f0bb2ec0474f1a8317fb5036ffa2ad2 100644 (file)
@@ -8,6 +8,8 @@ extern const struct field       bmroota_flds[];
 extern const struct field      bmroota_key_flds[];
 extern const struct field      bmrootd_flds[];
 extern const struct field      bmrootd_key_flds[];
+extern const struct field      rtrmaproot_flds[];
 
 extern int     bmroota_size(void *obj, int startoff, int idx);
 extern int     bmrootd_size(void *obj, int startoff, int idx);
+extern int     rtrmaproot_size(void *obj, int startoff, int idx);
index d5be6adb734cef06f828609ecad378fa54cd4aa7..5cad166278d98b034ab2dcbe4b67f322c00cf919 100644 (file)
@@ -92,6 +92,12 @@ static struct xfs_db_btree {
                sizeof(struct xfs_rmap_rec),
                sizeof(__be32),
        },
+       {       XFS_RTRMAP_CRC_MAGIC,
+               XFS_BTREE_LBLOCK_CRC_LEN,
+               2 * sizeof(struct xfs_rmap_key),
+               sizeof(struct xfs_rmap_rec),
+               sizeof(__be64),
+       },
        {       XFS_REFC_CRC_MAGIC,
                XFS_BTREE_SBLOCK_CRC_LEN,
                sizeof(struct xfs_refcount_key),
@@ -813,6 +819,100 @@ const field_t     rmapbt_rec_flds[] = {
        { NULL }
 };
 
+/* realtime RMAP btree blocks */
+const field_t  rtrmapbt_crc_hfld[] = {
+       { "", FLDT_RTRMAPBT_CRC, OI(0), C1, 0, TYP_NONE },
+       { NULL }
+};
+
+#define        OFF(f)  bitize(offsetof(struct xfs_btree_block, bb_ ## f))
+const field_t  rtrmapbt_crc_flds[] = {
+       { "magic", FLDT_UINT32X, OI(OFF(magic)), C1, 0, TYP_NONE },
+       { "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE },
+       { "numrecs", FLDT_UINT16D, OI(OFF(numrecs)), C1, 0, TYP_NONE },
+       { "leftsib", FLDT_DFSBNO, OI(OFF(u.l.bb_leftsib)), C1, 0, TYP_RTRMAPBT },
+       { "rightsib", FLDT_DFSBNO, OI(OFF(u.l.bb_rightsib)), C1, 0, TYP_RTRMAPBT },
+       { "bno", FLDT_DFSBNO, OI(OFF(u.l.bb_blkno)), C1, 0, TYP_RTRMAPBT },
+       { "lsn", FLDT_UINT64X, OI(OFF(u.l.bb_lsn)), C1, 0, TYP_NONE },
+       { "uuid", FLDT_UUID, OI(OFF(u.l.bb_uuid)), C1, 0, TYP_NONE },
+       { "owner", FLDT_INO, OI(OFF(u.l.bb_owner)), C1, 0, TYP_NONE },
+       { "crc", FLDT_CRC, OI(OFF(u.l.bb_crc)), C1, 0, TYP_NONE },
+       { "recs", FLDT_RTRMAPBTREC, btblock_rec_offset, btblock_rec_count,
+         FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE },
+       { "keys", FLDT_RTRMAPBTKEY, btblock_key_offset, btblock_key_count,
+         FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE },
+       { "ptrs", FLDT_RTRMAPBTPTR, btblock_ptr_offset, btblock_key_count,
+         FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_RTRMAPBT },
+       { NULL }
+};
+#undef OFF
+
+#define        KOFF(f) bitize(offsetof(struct xfs_rmap_key, rm_ ## f))
+
+#define RTRMAPBK_STARTBLOCK_BITOFF     0
+#define RTRMAPBK_OWNER_BITOFF          (RTRMAPBK_STARTBLOCK_BITOFF + RMAPBT_STARTBLOCK_BITLEN)
+#define RTRMAPBK_ATTRFLAG_BITOFF       (RTRMAPBK_OWNER_BITOFF + RMAPBT_OWNER_BITLEN)
+#define RTRMAPBK_BMBTFLAG_BITOFF       (RTRMAPBK_ATTRFLAG_BITOFF + RMAPBT_ATTRFLAG_BITLEN)
+#define RTRMAPBK_EXNTFLAG_BITOFF       (RTRMAPBK_BMBTFLAG_BITOFF + RMAPBT_BMBTFLAG_BITLEN)
+#define RTRMAPBK_UNUSED_OFFSET_BITOFF  (RTRMAPBK_EXNTFLAG_BITOFF + RMAPBT_EXNTFLAG_BITLEN)
+#define RTRMAPBK_OFFSET_BITOFF         (RTRMAPBK_UNUSED_OFFSET_BITOFF + RMAPBT_UNUSED_OFFSET_BITLEN)
+
+#define HI_KOFF(f)     bitize(sizeof(struct xfs_rmap_key) + offsetof(struct xfs_rmap_key, rm_ ## f))
+
+#define RTRMAPBK_STARTBLOCKHI_BITOFF   (bitize(sizeof(struct xfs_rmap_key)))
+#define RTRMAPBK_OWNERHI_BITOFF                (RTRMAPBK_STARTBLOCKHI_BITOFF + RMAPBT_STARTBLOCK_BITLEN)
+#define RTRMAPBK_ATTRFLAGHI_BITOFF     (RTRMAPBK_OWNERHI_BITOFF + RMAPBT_OWNER_BITLEN)
+#define RTRMAPBK_BMBTFLAGHI_BITOFF     (RTRMAPBK_ATTRFLAGHI_BITOFF + RMAPBT_ATTRFLAG_BITLEN)
+#define RTRMAPBK_EXNTFLAGHI_BITOFF     (RTRMAPBK_BMBTFLAGHI_BITOFF + RMAPBT_BMBTFLAG_BITLEN)
+#define RTRMAPBK_UNUSED_OFFSETHI_BITOFF        (RTRMAPBK_EXNTFLAGHI_BITOFF + RMAPBT_EXNTFLAG_BITLEN)
+#define RTRMAPBK_OFFSETHI_BITOFF       (RTRMAPBK_UNUSED_OFFSETHI_BITOFF + RMAPBT_UNUSED_OFFSET_BITLEN)
+
+const field_t  rtrmapbt_key_flds[] = {
+       { "startblock", FLDT_RGBLOCK, OI(KOFF(startblock)), C1, 0, TYP_DATA },
+       { "owner", FLDT_INT64D, OI(KOFF(owner)), C1, 0, TYP_NONE },
+       { "offset", FLDT_RFILEOFFD, OI(RTRMAPBK_OFFSET_BITOFF), C1, 0, TYP_NONE },
+       { "attrfork", FLDT_RATTRFORKFLG, OI(RTRMAPBK_ATTRFLAG_BITOFF), C1, 0,
+         TYP_NONE },
+       { "bmbtblock", FLDT_RBMBTFLG, OI(RTRMAPBK_BMBTFLAG_BITOFF), C1, 0,
+         TYP_NONE },
+       { "startblock_hi", FLDT_RGBLOCK, OI(HI_KOFF(startblock)), C1, 0, TYP_DATA },
+       { "owner_hi", FLDT_INT64D, OI(HI_KOFF(owner)), C1, 0, TYP_NONE },
+       { "offset_hi", FLDT_RFILEOFFD, OI(RTRMAPBK_OFFSETHI_BITOFF), C1, 0, TYP_NONE },
+       { "attrfork_hi", FLDT_RATTRFORKFLG, OI(RTRMAPBK_ATTRFLAGHI_BITOFF), C1, 0,
+         TYP_NONE },
+       { "bmbtblock_hi", FLDT_RBMBTFLG, OI(RTRMAPBK_BMBTFLAGHI_BITOFF), C1, 0,
+         TYP_NONE },
+       { NULL }
+};
+#undef HI_KOFF
+#undef KOFF
+
+#define        ROFF(f) bitize(offsetof(struct xfs_rmap_rec, rm_ ## f))
+
+#define RTRMAPBT_STARTBLOCK_BITOFF     0
+#define RTRMAPBT_BLOCKCOUNT_BITOFF     (RTRMAPBT_STARTBLOCK_BITOFF + RMAPBT_STARTBLOCK_BITLEN)
+#define RTRMAPBT_OWNER_BITOFF          (RTRMAPBT_BLOCKCOUNT_BITOFF + RMAPBT_BLOCKCOUNT_BITLEN)
+#define RTRMAPBT_ATTRFLAG_BITOFF       (RTRMAPBT_OWNER_BITOFF + RMAPBT_OWNER_BITLEN)
+#define RTRMAPBT_BMBTFLAG_BITOFF       (RTRMAPBT_ATTRFLAG_BITOFF + RMAPBT_ATTRFLAG_BITLEN)
+#define RTRMAPBT_EXNTFLAG_BITOFF       (RTRMAPBT_BMBTFLAG_BITOFF + RMAPBT_BMBTFLAG_BITLEN)
+#define RTRMAPBT_UNUSED_OFFSET_BITOFF  (RTRMAPBT_EXNTFLAG_BITOFF + RMAPBT_EXNTFLAG_BITLEN)
+#define RTRMAPBT_OFFSET_BITOFF         (RTRMAPBT_UNUSED_OFFSET_BITOFF + RMAPBT_UNUSED_OFFSET_BITLEN)
+
+const field_t  rtrmapbt_rec_flds[] = {
+       { "startblock", FLDT_RGBLOCK, OI(RTRMAPBT_STARTBLOCK_BITOFF), C1, 0, TYP_DATA },
+       { "blockcount", FLDT_EXTLEN, OI(RTRMAPBT_BLOCKCOUNT_BITOFF), C1, 0, TYP_NONE },
+       { "owner", FLDT_INT64D, OI(RTRMAPBT_OWNER_BITOFF), C1, 0, TYP_NONE },
+       { "offset", FLDT_RFILEOFFD, OI(RTRMAPBT_OFFSET_BITOFF), C1, 0, TYP_NONE },
+       { "extentflag", FLDT_REXTFLG, OI(RTRMAPBT_EXNTFLAG_BITOFF), C1, 0,
+         TYP_NONE },
+       { "attrfork", FLDT_RATTRFORKFLG, OI(RTRMAPBT_ATTRFLAG_BITOFF), C1, 0,
+         TYP_NONE },
+       { "bmbtblock", FLDT_RBMBTFLG, OI(RTRMAPBT_BMBTFLAG_BITOFF), C1, 0,
+         TYP_NONE },
+       { NULL }
+};
+#undef ROFF
+
 /* refcount btree blocks */
 const field_t  refcbt_crc_hfld[] = {
        { "", FLDT_REFCBT_CRC, OI(0), C1, 0, TYP_NONE },
index 4168c9e2e15ac443c49a78e8340f7b482e34c37b..b4013ea8073ec62b7bdad927b3d059d6c94eacb2 100644 (file)
@@ -53,6 +53,11 @@ extern const struct field    rmapbt_crc_hfld[];
 extern const struct field      rmapbt_key_flds[];
 extern const struct field      rmapbt_rec_flds[];
 
+extern const struct field      rtrmapbt_crc_flds[];
+extern const struct field      rtrmapbt_crc_hfld[];
+extern const struct field      rtrmapbt_key_flds[];
+extern const struct field      rtrmapbt_rec_flds[];
+
 extern const struct field      refcbt_crc_flds[];
 extern const struct field      refcbt_crc_hfld[];
 extern const struct field      refcbt_key_flds[];
index 2adf04e0d05a7174ceac6b4ae64785361db1282b..6da6c0b589447cdef6d3f55e5175e0acd80dca39 100644 (file)
@@ -192,6 +192,17 @@ const ftattr_t     ftattrtab[] = {
        { FLDT_RMAPBTREC, "rmapbtrec", fp_sarray, (char *)rmapbt_rec_flds,
          SI(bitsz(struct xfs_rmap_rec)), 0, NULL, rmapbt_rec_flds },
 
+       { FLDT_RTRMAPBT_CRC, "rtrmapbt", NULL, (char *)rtrmapbt_crc_flds, btblock_size,
+         FTARG_SIZE, NULL, rtrmapbt_crc_flds },
+       { FLDT_RTRMAPBTKEY, "rtrmapbtkey", fp_sarray, (char *)rtrmapbt_key_flds,
+         SI(bitize(2 * sizeof(struct xfs_rmap_key))), 0, NULL, rtrmapbt_key_flds },
+       { FLDT_RTRMAPBTPTR, "rtrmapbtptr", fp_num, "%llu",
+         SI(bitsz(xfs_rtrmap_ptr_t)), 0, fa_dfsbno, NULL },
+       { FLDT_RTRMAPBTREC, "rtrmapbtrec", fp_sarray, (char *)rtrmapbt_rec_flds,
+         SI(bitsz(struct xfs_rmap_rec)), 0, NULL, rtrmapbt_rec_flds },
+       { FLDT_RTRMAPROOT, "rtrmaproot", NULL, (char *)rtrmaproot_flds, rtrmaproot_size,
+         FTARG_SIZE, NULL, rtrmaproot_flds },
+
        { FLDT_REFCBT_CRC, "refcntbt", NULL, (char *)refcbt_crc_flds, btblock_size,
          FTARG_SIZE, NULL, refcbt_crc_flds },
        { FLDT_REFCBTKEY, "refcntbtkey", fp_sarray, (char *)refcbt_key_flds,
index 8f08c890bc7fd2f199c4b622c3cad3b27ac3367c..5c8253ed41688174fedaada0d282133b60c09e9d 100644 (file)
@@ -83,6 +83,11 @@ typedef enum fldt    {
        FLDT_RMAPBTKEY,
        FLDT_RMAPBTPTR,
        FLDT_RMAPBTREC,
+       FLDT_RTRMAPBT_CRC,
+       FLDT_RTRMAPBTKEY,
+       FLDT_RTRMAPBTPTR,
+       FLDT_RTRMAPBTREC,
+       FLDT_RTRMAPROOT,
        FLDT_REFCBT_CRC,
        FLDT_REFCBTKEY,
        FLDT_REFCBTPTR,
index 1f6906653fffda22629f6b68348c16d049019419..29ce4154d5556d61a7573bec20413fbd442b64a6 100644 (file)
@@ -17,6 +17,7 @@
 #include "bit.h"
 #include "output.h"
 #include "init.h"
+#include "libfrog/bitmap.h"
 
 static int     inode_a_bmbt_count(void *obj, int startoff);
 static int     inode_a_bmx_count(void *obj, int startoff);
@@ -47,6 +48,7 @@ static int    inode_u_muuid_count(void *obj, int startoff);
 static int     inode_u_sfdir2_count(void *obj, int startoff);
 static int     inode_u_sfdir3_count(void *obj, int startoff);
 static int     inode_u_symlink_count(void *obj, int startoff);
+static int     inode_u_rtrmapbt_count(void *obj, int startoff);
 
 static const cmdinfo_t inode_cmd =
        { "inode", NULL, inode_f, 0, 1, 1, "[inode#]",
@@ -230,6 +232,8 @@ const field_t       inode_u_flds[] = {
        { "sfdir3", FLDT_DIR3SF, NULL, inode_u_sfdir3_count, FLD_COUNT, TYP_NONE },
        { "symlink", FLDT_CHARNS, NULL, inode_u_symlink_count, FLD_COUNT,
          TYP_NONE },
+       { "rtrmapbt", FLDT_RTRMAPROOT, NULL, inode_u_rtrmapbt_count, FLD_COUNT,
+         TYP_NONE },
        { NULL }
 };
 
@@ -243,7 +247,7 @@ const field_t       inode_a_flds[] = {
 };
 
 static const char      *dinode_fmt_name[] =
-       { "dev", "local", "extents", "btree", "uuid" };
+       { "dev", "local", "extents", "btree", "uuid", "rmap" };
 static const int       dinode_fmt_name_size =
        sizeof(dinode_fmt_name) / sizeof(dinode_fmt_name[0]);
 
@@ -633,9 +637,86 @@ inode_init(void)
        add_command(&inode_cmd);
 }
 
+static struct bitmap   *rmap_inodes;
+
+static inline int
+set_rtgroup_rmap_inode(
+       struct xfs_mount        *mp,
+       xfs_rgnumber_t          rgno)
+{
+       struct xfs_imeta_path   *path;
+       struct xfs_trans        *tp;
+       xfs_ino_t               rtino;
+       int                     error;
+
+       if (!xfs_has_rtrmapbt(mp))
+               return 0;
+
+       path = xfs_rtrmapbt_create_path(mp, rgno);
+       if (!path)
+               return ENOMEM;
+
+       error = -libxfs_trans_alloc_empty(mp, &tp);
+       if (error)
+               goto out_path;
+
+       error = -libxfs_imeta_lookup(tp, path, &rtino);
+       if (error)
+               goto out_trans;
+
+       if (!libxfs_verify_ino(mp, rtino)) {
+               error = EFSCORRUPTED;
+               goto out_trans;
+       }
+
+       error = bitmap_set(rmap_inodes, rtino, 1);
+
+out_trans:
+       libxfs_trans_cancel(tp);
+out_path:
+       libxfs_imeta_free_path(path);
+       return error;
+}
+
+int
+init_rtmeta_inode_bitmaps(
+       struct xfs_mount        *mp)
+{
+       xfs_rgnumber_t          rgno;
+       int                     error;
+
+       if (rmap_inodes)
+               return 0;
+
+       error = bitmap_alloc(&rmap_inodes);
+       if (error)
+               return error;
+
+       for (rgno = 0; rgno < mp->m_sb.sb_rgcount; rgno++) {
+               int err2 = set_rtgroup_rmap_inode(mp, rgno);
+               if (err2 && !error)
+                       error = err2;
+       }
+
+       return error;
+}
+
+bool is_rtrmap_inode(xfs_ino_t ino)
+{
+       return bitmap_test(rmap_inodes, ino, 1);
+}
+
 typnm_t
 inode_next_type(void)
 {
+       int             error;
+
+       error = init_rtmeta_inode_bitmaps(mp);
+       if (error) {
+               dbprintf(_("error %d setting up rt metadata inode bitmaps\n"),
+                               error);
+       }
+
        switch (iocur_top->mode & S_IFMT) {
        case S_IFDIR:
                return TYP_DIR2;
@@ -655,8 +736,9 @@ inode_next_type(void)
                         iocur_top->ino == mp->m_sb.sb_gquotino ||
                         iocur_top->ino == mp->m_sb.sb_pquotino)
                        return TYP_DQBLK;
-               else
-                       return TYP_DATA;
+               else if (is_rtrmap_inode(iocur_top->ino))
+                       return TYP_RTRMAPBT;
+               return TYP_DATA;
        default:
                return TYP_NONE;
        }
@@ -790,6 +872,20 @@ inode_u_sfdir3_count(
               xfs_has_ftype(mp);
 }
 
+static int
+inode_u_rtrmapbt_count(
+       void                    *obj,
+       int                     startoff)
+{
+       struct xfs_dinode       *dip;
+
+       ASSERT(bitoffs(startoff) == 0);
+       ASSERT(obj == iocur_top->data);
+       dip = obj;
+       ASSERT((char *)XFS_DFORK_DPTR(dip) - (char *)dip == byteize(startoff));
+       return dip->di_format == XFS_DINODE_FMT_RMAP;
+}
+
 int
 inode_u_size(
        void                    *obj,
index 31a2ebbba6a175469a18dcdfd7a0323e6908eb1b..a47b0575a153af3d271234e3b00f414dca3c084e 100644 (file)
@@ -23,3 +23,6 @@ extern int    inode_size(void *obj, int startoff, int idx);
 extern int     inode_u_size(void *obj, int startoff, int idx);
 extern void    xfs_inode_set_crc(struct xfs_buf *);
 extern void    set_cur_inode(xfs_ino_t ino);
+
+int init_rtmeta_inode_bitmaps(struct xfs_mount *mp);
+bool is_rtrmap_inode(xfs_ino_t ino);
index 2091b4ac8b139b4daa3548d161fbdf977b4da12a..1dfc33ffb44b87f975a3b6d859071c5d03cc389b 100644 (file)
--- a/db/type.c
+++ b/db/type.c
@@ -51,6 +51,7 @@ static const typ_t    __typtab[] = {
        { TYP_BNOBT, "bnobt", handle_struct, bnobt_hfld, NULL, TYP_F_NO_CRC_OFF },
        { TYP_CNTBT, "cntbt", handle_struct, cntbt_hfld, NULL, TYP_F_NO_CRC_OFF },
        { TYP_RMAPBT, NULL },
+       { TYP_RTRMAPBT, NULL },
        { TYP_REFCBT, NULL },
        { TYP_DATA, "data", handle_block, NULL, NULL, TYP_F_NO_CRC_OFF },
        { TYP_DIR2, "dir2", handle_struct, dir2_hfld, NULL, TYP_F_NO_CRC_OFF },
@@ -91,6 +92,8 @@ static const typ_t    __typtab_crc[] = {
                &xfs_cntbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF },
        { TYP_RMAPBT, "rmapbt", handle_struct, rmapbt_crc_hfld,
                &xfs_rmapbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF },
+       { TYP_RTRMAPBT, "rtrmapbt", handle_struct, rtrmapbt_crc_hfld,
+               &xfs_rtrmapbt_buf_ops, XFS_BTREE_LBLOCK_CRC_OFF },
        { TYP_REFCBT, "refcntbt", handle_struct, refcbt_crc_hfld,
                &xfs_refcountbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF },
        { TYP_DATA, "data", handle_block, NULL, NULL, TYP_F_NO_CRC_OFF },
@@ -141,6 +144,8 @@ static const typ_t  __typtab_spcrc[] = {
                &xfs_cntbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF },
        { TYP_RMAPBT, "rmapbt", handle_struct, rmapbt_crc_hfld,
                &xfs_rmapbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF },
+       { TYP_RTRMAPBT, "rtrmapbt", handle_struct, rtrmapbt_crc_hfld,
+               &xfs_rtrmapbt_buf_ops, XFS_BTREE_LBLOCK_CRC_OFF },
        { TYP_REFCBT, "refcntbt", handle_struct, refcbt_crc_hfld,
                &xfs_refcountbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF },
        { TYP_DATA, "data", handle_block, NULL, NULL, TYP_F_NO_CRC_OFF },
index e7f0ecc17680bf24d9fc1c04506063f690b6669b..c98f3640202e876ddd31b5b41c3ae0213a687964 100644 (file)
--- a/db/type.h
+++ b/db/type.h
@@ -20,6 +20,7 @@ typedef enum typnm
        TYP_BNOBT,
        TYP_CNTBT,
        TYP_RMAPBT,
+       TYP_RTRMAPBT,
        TYP_REFCBT,
        TYP_DATA,
        TYP_DIR2,
index 00b0ab3450391bef279cb2c850b10d2dfe125627..a2b0b797efcc5a4e56f771dc352e48eb164b0d2e 100644 (file)
 #define xfs_rtfree_extent              libxfs_rtfree_extent
 #define xfs_rtfree_blocks              libxfs_rtfree_blocks
 #define xfs_rtgroup_update_super       libxfs_rtgroup_update_super
+#define xfs_rtrmapbt_droot_maxrecs     libxfs_rtrmapbt_droot_maxrecs
+#define xfs_rtrmapbt_maxrecs           libxfs_rtrmapbt_maxrecs
+
 #define xfs_sb_from_disk               libxfs_sb_from_disk
 #define xfs_sb_quota_from_disk         libxfs_sb_quota_from_disk
 #define xfs_sb_read_secondary          libxfs_sb_read_secondary
index e07629a34f49d41d825d020dcc9eb09bc9870c34..93a23659904061db89a7b7bb500e1eea2e09e412 100644 (file)
@@ -1224,7 +1224,7 @@ The possible data types are:
 .BR agf ", " agfl ", " agi ", " attr ", " bmapbta ", " bmapbtd ,
 .BR bnobt ", " cntbt ", " data ", " dir ", " dir2 ", " dqblk ,
 .BR inobt ", " inode ", " log ", " refcntbt ", " rmapbt ", " rtbitmap ,
-.BR rtsummary ", " sb ", " symlink " and " text .
+.BR rtsummary ", " sb ", " symlink ", " rtrmapbt ", and " text .
 See the TYPES section below for more information on these data types.
 .TP
 .BI "timelimit [" OPTIONS ]
@@ -2372,6 +2372,64 @@ block number within the allocation group to the next level in the Btree.
 .PD
 .RE
 .TP
+.B rtrmapbt
+There is one reverse mapping Btree for each realtime group.
+The
+.BR startblock " and "
+.B blockcount
+fields are 32 bits wide and record blocks within a realtime group.
+The root of this Btree is the reverse-mapping inode, which is recorded in the
+metadata directory.
+Blocks are linked to sibling left and right blocks at each level, as well as by
+pointers from parent to child blocks.
+Each block has the following fields:
+.RS 1.4i
+.PD 0
+.TP 1.2i
+.B magic
+RTRMAP block magic number, 0x4d415052 ('MAPR').
+.TP
+.B level
+level number of this block, 0 is a leaf.
+.TP
+.B numrecs
+number of data entries in the block.
+.TP
+.B leftsib
+left (logically lower) sibling block, 0 if none.
+.TP
+.B rightsib
+right (logically higher) sibling block, 0 if none.
+.TP
+.B recs
+[leaf blocks only] array of reference count records. Each record contains
+.BR startblock ,
+.BR blockcount ,
+.BR owner ,
+.BR offset ,
+.BR attr_fork ,
+.BR bmbt_block ,
+and
+.BR unwritten .
+.TP
+.B keys
+[non-leaf blocks only] array of double-key records. The first ("low") key
+contains the first value of each block in the level below this one. The second
+("high") key contains the largest key that can be used to identify any record
+in the subtree. Each record contains
+.BR startblock ,
+.BR owner ,
+.BR offset ,
+.BR attr_fork ,
+and
+.BR bmbt_block .
+.TP
+.B ptrs
+[non-leaf blocks only] array of child block pointers. Each pointer is a
+block number within the allocation group to the next level in the Btree.
+.PD
+.RE
+.TP
 .B rtbitmap
 If the filesystem has a realtime subvolume, then the
 .B rbmino