@@ -582,6 +582,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.
@@ -34,5 +34,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;
@@ -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.
@@ -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;
@@ -156,6 +156,9 @@ fuzz_f(
} else if (iocur_top->ino_buf) {
local_ops.verify_write = xfs_verify_recalc_inode_crc;
dbprintf(_("Allowing fuzz of corrupted inode 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 fuzz of corrupted data with good CRC\n"));
} else { /* invalid data */
local_ops.verify_write = xfs_verify_recalc_crc;
dbprintf(_("Allowing fuzz of corrupted data with good CRC\n"));
@@ -88,7 +88,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,
@@ -103,7 +103,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,
@@ -132,7 +132,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,
@@ -147,7 +147,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,
@@ -46,6 +46,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;
@@ -164,6 +164,9 @@ write_f(
if (corrupt) {
local_ops.verify_write = xfs_dummy_verify;
dbprintf(_("Allowing write of corrupted data and bad 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"));