From: Darrick J. Wong Date: Fri, 4 Aug 2017 21:33:52 +0000 (-0500) Subject: xfs_db: write values into dir/attr blocks and recalculate CRCs X-Git-Tag: v4.13.0-rc1~29 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=89baf918bf6092fa91d06c9e49a766fad31089d8;p=thirdparty%2Fxfsprogs-dev.git xfs_db: write values into dir/attr blocks and recalculate CRCs Extend typ_t to (optionally) store a pointer to a function to calculate the CRC of the block, provide functions to do this for the dir3 and attr3 types, and then wire up the write command so that we can modify directory and extended attribute block fields. Signed-off-by: Darrick J. Wong Reviewed-by: Carlos Maiolino Signed-off-by: Eric Sandeen --- diff --git a/db/attr.c b/db/attr.c index 0284fd420..75fe23936 100644 --- a/db/attr.c +++ b/db/attr.c @@ -606,6 +606,38 @@ const struct field attr3_remote_crc_flds[] = { { NULL } }; +/* Set the CRC. */ +void +xfs_attr3_set_crc( + struct xfs_buf *bp) +{ + __be32 magic32; + __be16 magic16; + + magic32 = *(__be32 *)bp->b_addr; + magic16 = ((struct xfs_da_blkinfo *)bp->b_addr)->magic; + + switch (magic16) { + case cpu_to_be16(XFS_ATTR3_LEAF_MAGIC): + xfs_buf_update_cksum(bp, XFS_ATTR3_LEAF_CRC_OFF); + return; + case cpu_to_be16(XFS_DA3_NODE_MAGIC): + xfs_buf_update_cksum(bp, XFS_DA3_NODE_CRC_OFF); + return; + default: + break; + } + + switch (magic32) { + case cpu_to_be32(XFS_ATTR3_RMT_MAGIC): + xfs_buf_update_cksum(bp, XFS_ATTR3_RMT_CRC_OFF); + return; + default: + dbprintf(_("Unknown attribute buffer type!\n")); + break; + } +} + /* * Special read verifier for attribute buffers. Detect the magic number * appropriately and set the correct verifier and call it. diff --git a/db/attr.h b/db/attr.h index 565d6d8ab..ba23480cd 100644 --- a/db/attr.h +++ b/db/attr.h @@ -36,5 +36,6 @@ extern const field_t attr3_remote_crc_flds[]; extern int attr_leaf_name_size(void *obj, int startoff, int idx); extern int attr_size(void *obj, int startoff, int idx); +extern void xfs_attr3_set_crc(struct xfs_buf *bp); extern const struct xfs_buf_ops xfs_attr3_db_buf_ops; diff --git a/db/dir2.c b/db/dir2.c index 533f705f7..3e21a7b70 100644 --- a/db/dir2.c +++ b/db/dir2.c @@ -981,6 +981,43 @@ const field_t da3_node_hdr_flds[] = { { NULL } }; +/* Set the CRC. */ +void +xfs_dir3_set_crc( + struct xfs_buf *bp) +{ + __be32 magic32; + __be16 magic16; + + magic32 = *(__be32 *)bp->b_addr; + magic16 = ((struct xfs_da_blkinfo *)bp->b_addr)->magic; + + switch (magic32) { + case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC): + case cpu_to_be32(XFS_DIR3_DATA_MAGIC): + xfs_buf_update_cksum(bp, XFS_DIR3_DATA_CRC_OFF); + return; + case cpu_to_be32(XFS_DIR3_FREE_MAGIC): + xfs_buf_update_cksum(bp, XFS_DIR3_FREE_CRC_OFF); + return; + default: + break; + } + + switch (magic16) { + case cpu_to_be16(XFS_DIR3_LEAF1_MAGIC): + case cpu_to_be16(XFS_DIR3_LEAFN_MAGIC): + xfs_buf_update_cksum(bp, XFS_DIR3_LEAF_CRC_OFF); + return; + case cpu_to_be16(XFS_DA3_NODE_MAGIC): + xfs_buf_update_cksum(bp, XFS_DA3_NODE_CRC_OFF); + return; + default: + dbprintf(_("Unknown directory buffer type! %x %x\n"), magic32, magic16); + break; + } +} + /* * Special read verifier for directory buffers. Detect the magic number * appropriately and set the correct verifier and call it. diff --git a/db/dir2.h b/db/dir2.h index 0c2a62ec7..1b87cd2a3 100644 --- a/db/dir2.h +++ b/db/dir2.h @@ -60,5 +60,6 @@ static inline uint8_t *xfs_dir2_sf_inumberp(xfs_dir2_sf_entry_t *sfep) extern int dir2_data_union_size(void *obj, int startoff, int idx); extern int dir2_size(void *obj, int startoff, int idx); +extern void xfs_dir3_set_crc(struct xfs_buf *bp); extern const struct xfs_buf_ops xfs_dir3_db_buf_ops; diff --git a/db/type.c b/db/type.c index 10fa54ee9..bf31e0419 100644 --- a/db/type.c +++ b/db/type.c @@ -87,7 +87,7 @@ static const typ_t __typtab_crc[] = { { TYP_AGI, "agi", handle_struct, agi_hfld, &xfs_agi_buf_ops, XFS_AGI_CRC_OFF }, { TYP_ATTR, "attr3", handle_struct, attr3_hfld, - &xfs_attr3_db_buf_ops, TYP_F_NO_CRC_OFF }, + &xfs_attr3_db_buf_ops, TYP_F_CRC_FUNC, xfs_attr3_set_crc }, { TYP_BMAPBTA, "bmapbta", handle_struct, bmapbta_crc_hfld, &xfs_bmbt_buf_ops, XFS_BTREE_LBLOCK_CRC_OFF }, { TYP_BMAPBTD, "bmapbtd", handle_struct, bmapbtd_crc_hfld, @@ -102,7 +102,7 @@ static const typ_t __typtab_crc[] = { &xfs_refcountbt_buf_ops, XFS_BTREE_SBLOCK_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_NO_CRC_OFF }, + &xfs_dir3_db_buf_ops, TYP_F_CRC_FUNC, xfs_dir3_set_crc }, { TYP_DQBLK, "dqblk", handle_struct, dqblk_hfld, &xfs_dquot_buf_ops, TYP_F_NO_CRC_OFF }, { TYP_INOBT, "inobt", handle_struct, inobt_crc_hfld, @@ -131,7 +131,7 @@ static const typ_t __typtab_spcrc[] = { { TYP_AGI, "agi", handle_struct, agi_hfld, &xfs_agi_buf_ops , XFS_AGI_CRC_OFF }, { TYP_ATTR, "attr3", handle_struct, attr3_hfld, - &xfs_attr3_db_buf_ops, TYP_F_NO_CRC_OFF }, + &xfs_attr3_db_buf_ops, TYP_F_CRC_FUNC, xfs_attr3_set_crc }, { TYP_BMAPBTA, "bmapbta", handle_struct, bmapbta_crc_hfld, &xfs_bmbt_buf_ops, XFS_BTREE_LBLOCK_CRC_OFF }, { TYP_BMAPBTD, "bmapbtd", handle_struct, bmapbtd_crc_hfld, @@ -146,7 +146,7 @@ static const typ_t __typtab_spcrc[] = { &xfs_refcountbt_buf_ops, XFS_BTREE_SBLOCK_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_NO_CRC_OFF }, + &xfs_dir3_db_buf_ops, TYP_F_CRC_FUNC, xfs_dir3_set_crc }, { TYP_DQBLK, "dqblk", handle_struct, dqblk_hfld, &xfs_dquot_buf_ops, TYP_F_NO_CRC_OFF }, { TYP_INOBT, "inobt", handle_struct, inobt_spcrc_hfld, diff --git a/db/type.h b/db/type.h index 87ff1079e..85d89c74e 100644 --- a/db/type.h +++ b/db/type.h @@ -45,6 +45,8 @@ typedef struct typ const struct xfs_buf_ops *bops; unsigned long crc_off; #define TYP_F_NO_CRC_OFF (-1UL) +#define TYP_F_CRC_FUNC (-2UL) + void (*set_crc)(struct xfs_buf *); } typ_t; extern const typ_t *typtab, *cur_typ; diff --git a/db/write.c b/db/write.c index d24ea0594..266bde470 100644 --- a/db/write.c +++ b/db/write.c @@ -173,6 +173,9 @@ write_f( } else if (iocur_top->dquot_buf) { local_ops.verify_write = xfs_verify_recalc_dquot_crc; dbprintf(_("Allowing write of corrupted dquot with good CRC\n")); + } else if (iocur_top->typ->crc_off == TYP_F_CRC_FUNC) { + local_ops.verify_write = iocur_top->typ->set_crc; + dbprintf(_("Allowing write of corrupted data with good CRC\n")); } else { /* invalid data */ local_ops.verify_write = xfs_verify_recalc_crc; dbprintf(_("Allowing write of corrupted data with good CRC\n"));