From: Darrick J. Wong <djwong@xxxxxxxxxx> Create separate field_t definitions for the free inode btree because db needs to know that the interior block pointers point to finobt blocks, not inobt blocks. This is critical now because the buffer ops contain magic numbers, the ->verify_struct routines use the magics listed in the buffer ops, and the xfs_db iocursor calls the verifier functions. Without this patch, xfs_db emits bizarre output like this: # xfs_db -x /dev/sde -c 'agi 1' -c 'addr free_root' -c 'addr ptrs[1]' -c print 2>&1 | head Metadata corruption detected at 0x55dda21258b0, xfs_inobt block 0x275c20/0x1000 magic = 0x46494233 Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- db/btblock.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ db/btblock.h | 6 +++++ db/field.c | 8 +++++++ db/field.h | 4 +++ db/type.c | 6 ++--- 5 files changed, 91 insertions(+), 3 deletions(-) diff --git a/db/btblock.c b/db/btblock.c index c563fb0389a..30f7b5ef955 100644 --- a/db/btblock.c +++ b/db/btblock.c @@ -491,6 +491,76 @@ const field_t inobt_spcrc_flds[] = { { NULL } }; +/* free inode btree */ + +const field_t finobt_hfld[] = { + { "", FLDT_FINOBT, OI(0), C1, 0, TYP_NONE }, + { NULL } +}; + +const field_t finobt_crc_hfld[] = { + { "", FLDT_FINOBT_CRC, OI(0), C1, 0, TYP_NONE }, + { NULL } +}; + +const field_t finobt_spcrc_hfld[] = { + { "", FLDT_FINOBT_SPCRC, OI(0), C1, 0, TYP_NONE }, + { NULL } +}; + +const field_t finobt_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_AGBLOCK, OI(OFF(u.s.bb_leftsib)), C1, 0, TYP_INOBT }, + { "rightsib", FLDT_AGBLOCK, OI(OFF(u.s.bb_rightsib)), C1, 0, TYP_INOBT }, + { "recs", FLDT_INOBTREC, btblock_rec_offset, btblock_rec_count, + FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, + { "keys", FLDT_INOBTKEY, btblock_key_offset, btblock_key_count, + FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, + { "ptrs", FLDT_FINOBTPTR, btblock_ptr_offset, btblock_key_count, + FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_FINOBT }, + { NULL } +}; +const field_t finobt_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_AGBLOCK, OI(OFF(u.s.bb_leftsib)), C1, 0, TYP_INOBT }, + { "rightsib", FLDT_AGBLOCK, OI(OFF(u.s.bb_rightsib)), C1, 0, TYP_INOBT }, + { "bno", FLDT_DFSBNO, OI(OFF(u.s.bb_blkno)), C1, 0, TYP_INOBT }, + { "lsn", FLDT_UINT64X, OI(OFF(u.s.bb_lsn)), C1, 0, TYP_NONE }, + { "uuid", FLDT_UUID, OI(OFF(u.s.bb_uuid)), C1, 0, TYP_NONE }, + { "owner", FLDT_AGNUMBER, OI(OFF(u.s.bb_owner)), C1, 0, TYP_NONE }, + { "crc", FLDT_CRC, OI(OFF(u.s.bb_crc)), C1, 0, TYP_NONE }, + { "recs", FLDT_INOBTREC, btblock_rec_offset, btblock_rec_count, + FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, + { "keys", FLDT_INOBTKEY, btblock_key_offset, btblock_key_count, + FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, + { "ptrs", FLDT_FINOBTPTR, btblock_ptr_offset, btblock_key_count, + FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_FINOBT }, + { NULL } +}; +const field_t finobt_spcrc_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_AGBLOCK, OI(OFF(u.s.bb_leftsib)), C1, 0, TYP_INOBT }, + { "rightsib", FLDT_AGBLOCK, OI(OFF(u.s.bb_rightsib)), C1, 0, TYP_INOBT }, + { "bno", FLDT_DFSBNO, OI(OFF(u.s.bb_blkno)), C1, 0, TYP_INOBT }, + { "lsn", FLDT_UINT64X, OI(OFF(u.s.bb_lsn)), C1, 0, TYP_NONE }, + { "uuid", FLDT_UUID, OI(OFF(u.s.bb_uuid)), C1, 0, TYP_NONE }, + { "owner", FLDT_AGNUMBER, OI(OFF(u.s.bb_owner)), C1, 0, TYP_NONE }, + { "crc", FLDT_CRC, OI(OFF(u.s.bb_crc)), C1, 0, TYP_NONE }, + { "recs", FLDT_INOBTSPREC, btblock_rec_offset, btblock_rec_count, + FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, + { "keys", FLDT_INOBTKEY, btblock_key_offset, btblock_key_count, + FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, + { "ptrs", FLDT_FINOBTPTR, btblock_ptr_offset, btblock_key_count, + FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_FINOBT }, + { NULL } +}; + #undef OFF #define KOFF(f) bitize(offsetof(xfs_inobt_key_t, ir_ ## f)) diff --git a/db/btblock.h b/db/btblock.h index 465acde7b88..4168c9e2e15 100644 --- a/db/btblock.h +++ b/db/btblock.h @@ -24,6 +24,12 @@ extern const struct field inobt_crc_flds[]; extern const struct field inobt_spcrc_flds[]; extern const struct field inobt_crc_hfld[]; extern const struct field inobt_spcrc_hfld[]; +extern const struct field finobt_flds[]; +extern const struct field finobt_hfld[]; +extern const struct field finobt_crc_flds[]; +extern const struct field finobt_spcrc_flds[]; +extern const struct field finobt_crc_hfld[]; +extern const struct field finobt_spcrc_hfld[]; extern const struct field inobt_key_flds[]; extern const struct field inobt_rec_flds[]; extern const struct field inobt_sprec_flds[]; diff --git a/db/field.c b/db/field.c index 77cab902239..a3e47ee81cc 100644 --- a/db/field.c +++ b/db/field.c @@ -308,10 +308,18 @@ const ftattr_t ftattrtab[] = { FTARG_SIZE, NULL, inobt_crc_flds }, { FLDT_INOBT_SPCRC, "inobt", NULL, (char *)inobt_spcrc_flds, btblock_size, FTARG_SIZE, NULL, inobt_spcrc_flds }, + { FLDT_FINOBT, "finobt", NULL, (char *)finobt_flds, btblock_size, + FTARG_SIZE, NULL, finobt_flds }, + { FLDT_FINOBT_CRC, "finobt", NULL, (char *)finobt_crc_flds, btblock_size, + FTARG_SIZE, NULL, finobt_crc_flds }, + { FLDT_FINOBT_SPCRC, "finobt", NULL, (char *)finobt_spcrc_flds, + btblock_size, FTARG_SIZE, NULL, finobt_spcrc_flds }, { FLDT_INOBTKEY, "inobtkey", fp_sarray, (char *)inobt_key_flds, SI(bitsz(xfs_inobt_key_t)), 0, NULL, inobt_key_flds }, { FLDT_INOBTPTR, "inobtptr", fp_num, "%u", SI(bitsz(xfs_inobt_ptr_t)), 0, fa_agblock, NULL }, + { FLDT_FINOBTPTR, "finobtptr", fp_num, "%u", SI(bitsz(xfs_inobt_ptr_t)), + 0, fa_agblock, NULL }, { FLDT_INOBTREC, "inobtrec", fp_sarray, (char *)inobt_rec_flds, SI(bitsz(xfs_inobt_rec_t)), 0, NULL, inobt_rec_flds }, { FLDT_INOBTSPREC, "inobtsprec", fp_sarray, (char *) inobt_sprec_flds, diff --git a/db/field.h b/db/field.h index 614fd0ab414..634742a572c 100644 --- a/db/field.h +++ b/db/field.h @@ -147,8 +147,12 @@ typedef enum fldt { FLDT_INOBT, FLDT_INOBT_CRC, FLDT_INOBT_SPCRC, + FLDT_FINOBT, + FLDT_FINOBT_CRC, + FLDT_FINOBT_SPCRC, FLDT_INOBTKEY, FLDT_INOBTPTR, + FLDT_FINOBTPTR, FLDT_INOBTREC, FLDT_INOBTSPREC, FLDT_INODE, diff --git a/db/type.c b/db/type.c index f8d8b5551d3..efe7044569d 100644 --- a/db/type.c +++ b/db/type.c @@ -63,7 +63,7 @@ static const typ_t __typtab[] = { { TYP_SB, "sb", handle_struct, sb_hfld, NULL, TYP_F_NO_CRC_OFF }, { TYP_SYMLINK, "symlink", handle_string, NULL, NULL, TYP_F_NO_CRC_OFF }, { TYP_TEXT, "text", handle_text, NULL, NULL, TYP_F_NO_CRC_OFF }, - { TYP_FINOBT, "finobt", handle_struct, inobt_hfld, NULL, + { TYP_FINOBT, "finobt", handle_struct, finobt_hfld, NULL, TYP_F_NO_CRC_OFF }, { TYP_NONE, NULL } }; @@ -107,7 +107,7 @@ static const typ_t __typtab_crc[] = { { TYP_SYMLINK, "symlink", handle_struct, symlink_crc_hfld, &xfs_symlink_buf_ops, XFS_SYMLINK_CRC_OFF }, { TYP_TEXT, "text", handle_text, NULL, NULL, TYP_F_NO_CRC_OFF }, - { TYP_FINOBT, "finobt", handle_struct, inobt_crc_hfld, + { TYP_FINOBT, "finobt", handle_struct, finobt_crc_hfld, &xfs_finobt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF }, { TYP_NONE, NULL } }; @@ -151,7 +151,7 @@ static const typ_t __typtab_spcrc[] = { { TYP_SYMLINK, "symlink", handle_struct, symlink_crc_hfld, &xfs_symlink_buf_ops, XFS_SYMLINK_CRC_OFF }, { TYP_TEXT, "text", handle_text, NULL, NULL, TYP_F_NO_CRC_OFF }, - { TYP_FINOBT, "finobt", handle_struct, inobt_spcrc_hfld, + { TYP_FINOBT, "finobt", handle_struct, finobt_spcrc_hfld, &xfs_finobt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF }, { TYP_NONE, NULL } };