static int rtrmaproot_ptr_count(void *obj, int startoff);
static int rtrmaproot_ptr_offset(void *obj, int startoff, int idx);
+static int rtrefcroot_rec_count(void *obj, int startoff);
+static int rtrefcroot_rec_offset(void *obj, int startoff, int idx);
+static int rtrefcroot_key_count(void *obj, int startoff);
+static int rtrefcroot_key_offset(void *obj, int startoff, int idx);
+static int rtrefcroot_ptr_count(void *obj, int startoff);
+static int rtrefcroot_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 },
FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_RTRMAPBT },
{ NULL }
};
+
+/* realtime refcount btree root */
+const field_t rtrefcroot_flds[] = {
+ { "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE },
+ { "numrecs", FLDT_UINT16D, OI(OFF(numrecs)), C1, 0, TYP_NONE },
+ { "recs", FLDT_RTREFCBTREC, rtrefcroot_rec_offset, rtrefcroot_rec_count,
+ FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE },
+ { "keys", FLDT_RTREFCBTKEY, rtrefcroot_key_offset, rtrefcroot_key_count,
+ FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE },
+ { "ptrs", FLDT_RTREFCBTPTR, rtrefcroot_ptr_offset, rtrefcroot_ptr_count,
+ FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_RTREFCBT },
+ { NULL }
+};
#undef OFF
static int
dip = obj;
return bitize((int)XFS_DFORK_DSIZE(dip, mp));
}
+
+/* realtime refcount root */
+static int
+rtrefcroot_rec_count(
+ void *obj,
+ int startoff)
+{
+ struct xfs_dinode *dip = obj;
+ struct xfs_rtrefcount_root *block = XFS_DFORK_DPTR(dip);
+
+ ASSERT(block == obj + byteize(startoff));
+
+ if (be16_to_cpu(block->bb_level) > 0)
+ return 0;
+ return be16_to_cpu(block->bb_numrecs);
+}
+
+static int
+rtrefcroot_rec_offset(
+ void *obj,
+ int startoff,
+ int idx)
+{
+ struct xfs_dinode *dip = obj;
+ struct xfs_rtrefcount_root *block = XFS_DFORK_DPTR(dip);
+ struct xfs_refcount_rec *kp;
+
+ ASSERT(block == obj + byteize(startoff));
+ ASSERT(be16_to_cpu(block->bb_level) == 0);
+
+ kp = xfs_rtrefcount_droot_rec_addr(block, idx);
+ return bitize((int)((char *)kp - (char *)block));
+}
+
+static int
+rtrefcroot_key_count(
+ void *obj,
+ int startoff)
+{
+ struct xfs_dinode *dip = obj;
+ struct xfs_rtrefcount_root *block = XFS_DFORK_DPTR(dip);
+
+ ASSERT(block == obj + byteize(startoff));
+
+ if (be16_to_cpu(block->bb_level) == 0)
+ return 0;
+ return be16_to_cpu(block->bb_numrecs);
+}
+
+static int
+rtrefcroot_key_offset(
+ void *obj,
+ int startoff,
+ int idx)
+{
+ struct xfs_dinode *dip = obj;
+ struct xfs_rtrefcount_root *block = XFS_DFORK_DPTR(dip);
+ struct xfs_refcount_key *kp;
+
+ ASSERT(block == obj + byteize(startoff));
+ ASSERT(be16_to_cpu(block->bb_level) > 0);
+
+ kp = xfs_rtrefcount_droot_key_addr(block, idx);
+ return bitize((int)((char *)kp - (char *)block));
+}
+
+static int
+rtrefcroot_ptr_count(
+ void *obj,
+ int startoff)
+{
+ struct xfs_dinode *dip = obj;
+ struct xfs_rtrefcount_root *block = XFS_DFORK_DPTR(dip);
+
+ ASSERT(block == obj + byteize(startoff));
+
+ if (be16_to_cpu(block->bb_level) == 0)
+ return 0;
+ return be16_to_cpu(block->bb_numrecs);
+}
+
+static int
+rtrefcroot_ptr_offset(
+ void *obj,
+ int startoff,
+ int idx)
+{
+ struct xfs_dinode *dip = obj;
+ struct xfs_rtrefcount_root *block = XFS_DFORK_DPTR(dip);
+ xfs_rtrefcount_ptr_t *pp;
+ int dmxr;
+
+ ASSERT(block == obj + byteize(startoff));
+ ASSERT(be16_to_cpu(block->bb_level) > 0);
+
+ dmxr = libxfs_rtrefcountbt_droot_maxrecs(XFS_DFORK_DSIZE(dip, mp),
+ false);
+ pp = xfs_rtrefcount_droot_ptr_addr(block, idx, dmxr);
+ return bitize((int)((char *)pp - (char *)block));
+}
+
+int
+rtrefcroot_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));
+}
extern const struct field bmrootd_flds[];
extern const struct field bmrootd_key_flds[];
extern const struct field rtrmaproot_flds[];
+extern const struct field rtrefcroot_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);
+extern int rtrefcroot_size(void *obj, int startoff, int idx);
sizeof(struct xfs_refcount_rec),
sizeof(__be32),
},
+ { XFS_RTREFC_CRC_MAGIC,
+ XFS_BTREE_LBLOCK_CRC_LEN,
+ sizeof(struct xfs_refcount_key),
+ sizeof(struct xfs_refcount_rec),
+ sizeof(__be64),
+ },
{ 0,
},
};
{ NULL }
};
#undef ROFF
+
+/* realtime refcount btree blocks */
+const field_t rtrefcbt_crc_hfld[] = {
+ { "", FLDT_RTREFCBT_CRC, OI(0), C1, 0, TYP_NONE },
+ { NULL }
+};
+
+#define OFF(f) bitize(offsetof(struct xfs_btree_block, bb_ ## f))
+const field_t rtrefcbt_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_RTREFCBT },
+ { "rightsib", FLDT_DFSBNO, OI(OFF(u.l.bb_rightsib)), C1, 0, TYP_RTREFCBT },
+ { "bno", FLDT_DFSBNO, OI(OFF(u.l.bb_blkno)), C1, 0, TYP_REFCBT },
+ { "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_RTREFCBTREC, btblock_rec_offset, btblock_rec_count,
+ FLD_ARRAY | FLD_ABASE1 | FLD_COUNT | FLD_OFFSET, TYP_NONE },
+ { "keys", FLDT_RTREFCBTKEY, btblock_key_offset, btblock_key_count,
+ FLD_ARRAY | FLD_ABASE1 | FLD_COUNT | FLD_OFFSET, TYP_NONE },
+ { "ptrs", FLDT_RTREFCBTPTR, btblock_ptr_offset, btblock_key_count,
+ FLD_ARRAY | FLD_ABASE1 | FLD_COUNT | FLD_OFFSET, TYP_RTREFCBT },
+ { NULL }
+};
+#undef OFF
+
+const field_t rtrefcbt_key_flds[] = {
+ { "startblock", FLDT_CRGBLOCK, OI(REFCNTBT_STARTBLOCK_BITOFF), C1, 0, TYP_DATA },
+ { "cowflag", FLDT_CCOWFLG, OI(REFCNTBT_COWFLAG_BITOFF), C1, 0, TYP_DATA },
+ { NULL }
+};
+
+#define ROFF(f) bitize(offsetof(struct xfs_refcount_rec, rc_ ## f))
+const field_t rtrefcbt_rec_flds[] = {
+ { "startblock", FLDT_CRGBLOCK, OI(REFCNTBT_STARTBLOCK_BITOFF), C1, 0, TYP_DATA },
+ { "blockcount", FLDT_EXTLEN, OI(ROFF(blockcount)), C1, 0, TYP_NONE },
+ { "refcount", FLDT_UINT32D, OI(ROFF(refcount)), C1, 0, TYP_DATA },
+ { "cowflag", FLDT_CCOWFLG, OI(REFCNTBT_COWFLAG_BITOFF), C1, 0, TYP_DATA },
+ { NULL }
+};
+#undef ROFF
extern const struct field refcbt_key_flds[];
extern const struct field refcbt_rec_flds[];
+extern const struct field rtrefcbt_crc_flds[];
+extern const struct field rtrefcbt_crc_hfld[];
+extern const struct field rtrefcbt_key_flds[];
+extern const struct field rtrefcbt_rec_flds[];
+
extern int btblock_size(void *obj, int startoff, int idx);
{ FLDT_REFCBTREC, "refcntbtrec", fp_sarray, (char *)refcbt_rec_flds,
SI(bitsz(struct xfs_refcount_rec)), 0, NULL, refcbt_rec_flds },
+ { FLDT_CRGBLOCK, "crgblock", fp_num, "%u", SI(REFCNTBT_AGBLOCK_BITLEN),
+ FTARG_DONULL, NULL, NULL },
+ { FLDT_RTREFCBT_CRC, "rtrefcntbt", NULL, (char *)rtrefcbt_crc_flds,
+ btblock_size, FTARG_SIZE, NULL, rtrefcbt_crc_flds },
+ { FLDT_RTREFCBTKEY, "rtrefcntbtkey", fp_sarray,
+ (char *)rtrefcbt_key_flds, SI(bitsz(struct xfs_refcount_key)), 0,
+ NULL, rtrefcbt_key_flds },
+ { FLDT_RTREFCBTPTR, "rtrefcntbtptr", fp_num, "%u",
+ SI(bitsz(xfs_rtrefcount_ptr_t)), 0, fa_dfsbno, NULL },
+ { FLDT_RTREFCBTREC, "rtrefcntbtrec", fp_sarray,
+ (char *)rtrefcbt_rec_flds, SI(bitsz(struct xfs_refcount_rec)), 0,
+ NULL, rtrefcbt_rec_flds },
+ { FLDT_RTREFCROOT, "rtrefcroot", NULL, (char *)rtrefcroot_flds,
+ rtrefcroot_size, FTARG_SIZE, NULL, rtrefcroot_flds },
+
/* CRC field */
{ FLDT_CRC, "crc", fp_crc, "%#x (%s)", SI(bitsz(uint32_t)),
0, NULL, NULL },
FLDT_REFCBTKEY,
FLDT_REFCBTPTR,
FLDT_REFCBTREC,
+ FLDT_CRGBLOCK,
+ FLDT_RTREFCBT_CRC,
+ FLDT_RTREFCBTKEY,
+ FLDT_RTREFCBTPTR,
+ FLDT_RTREFCBTREC,
+ FLDT_RTREFCROOT,
/* CRC field type */
FLDT_CRC,
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 int inode_u_rtrefcbt_count(void *obj, int startoff);
static const cmdinfo_t inode_cmd =
{ "inode", NULL, inode_f, 0, 1, 1, "[inode#]",
TYP_NONE },
{ "rtrmapbt", FLDT_RTRMAPROOT, NULL, inode_u_rtrmapbt_count, FLD_COUNT,
TYP_NONE },
+ { "rtrefcbt", FLDT_RTREFCROOT, NULL, inode_u_rtrefcbt_count, FLD_COUNT,
+ TYP_NONE },
{ NULL }
};
static const char *metatype_name[] =
{ "unknown", "dir", "usrquota", "grpquota", "prjquota", "rtbitmap",
- "rtsummary", "rtrmap"
+ "rtsummary", "rtrmap", "rtrefcount"
};
static const int metatype_name_size = ARRAY_SIZE(metatype_name);
return TYP_RGSUMMARY;
case XFS_METAFILE_RTRMAP:
return TYP_RTRMAPBT;
+ case XFS_METAFILE_RTREFCOUNT:
+ return TYP_RTREFCBT;
default:
return TYP_DATA;
}
dip->di_metatype == cpu_to_be16(XFS_METAFILE_RTRMAP);
}
+static int
+inode_u_rtrefcbt_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_META_BTREE &&
+ dip->di_metatype == cpu_to_be16(XFS_METAFILE_RTREFCOUNT);
+}
+
int
inode_u_size(
void *obj,
{ TYP_RMAPBT, NULL },
{ TYP_RTRMAPBT, NULL },
{ TYP_REFCBT, NULL },
+ { TYP_RTREFCBT, 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 },
{ TYP_DQBLK, "dqblk", handle_struct, dqblk_hfld, NULL, TYP_F_NO_CRC_OFF },
&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_RTREFCBT, "rtrefcntbt", handle_struct, rtrefcbt_crc_hfld,
+ &xfs_rtrefcountbt_buf_ops, XFS_BTREE_LBLOCK_CRC_OFF },
{ TYP_DATA, "data", handle_block, NULL, NULL, TYP_F_NO_CRC_OFF },
{ TYP_DIR2, "dir3", handle_struct, dir3_hfld,
&xfs_dir3_db_buf_ops, TYP_F_CRC_FUNC, xfs_dir3_set_crc },
&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_RTREFCBT, "rtrefcntbt", handle_struct, rtrefcbt_crc_hfld,
+ &xfs_rtrefcountbt_buf_ops, XFS_BTREE_LBLOCK_CRC_OFF },
{ TYP_DATA, "data", handle_block, NULL, NULL, TYP_F_NO_CRC_OFF },
{ TYP_DIR2, "dir3", handle_struct, dir3_hfld,
&xfs_dir3_db_buf_ops, TYP_F_CRC_FUNC, xfs_dir3_set_crc },
TYP_RMAPBT,
TYP_RTRMAPBT,
TYP_REFCBT,
+ TYP_RTREFCBT,
TYP_DATA,
TYP_DIR2,
TYP_DQBLK,
#define xfs_update_rtsb libxfs_update_rtsb
#define xfs_rtgroup_get libxfs_rtgroup_get
#define xfs_rtgroup_put libxfs_rtgroup_put
+
+#define xfs_rtrefcountbt_droot_maxrecs libxfs_rtrefcountbt_droot_maxrecs
+#define xfs_rtrefcountbt_maxrecs libxfs_rtrefcountbt_maxrecs
+
#define xfs_rtrmapbt_calc_reserves libxfs_rtrmapbt_calc_reserves
#define xfs_rtrmapbt_calc_size libxfs_rtrmapbt_calc_size
#define xfs_rtrmapbt_commit_staged_btree libxfs_rtrmapbt_commit_staged_btree
.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 ", " rtrmapbt ", and " text .
+.BR rtsummary ", " sb ", " symlink ", " rtrmapbt ", " rtrefcbt ", and " text .
See the TYPES section below for more information on these data types.
.TP
.BI "timelimit [" OPTIONS ]
.PD
.RE
.TP
+.B rtrefcbt
+There is one reference count Btree for the entire realtime device. The
+.BR startblock " and "
+.B blockcount
+fields are 32 bits wide and record block counts within a realtime group.
+The root of this Btree is the realtime refcount 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
+RTREFC block magic number, 0x52434e54 ('RCNT').
+.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 ,
+and
+.BR refcount .
+.TP
+.B keys
+[non-leaf blocks only] array of key records. These are the first value
+of each block in the level below this one. Each record contains
+.BR startblock .
+.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 rmapbt
There is one set of filesystem blocks forming the reverse mapping Btree for
each allocation group. The root block of this Btree is designated by the