DF-3150 / fix.diff
--- a/sys/vfs/hammer/hammer_mirror.c +++ b/sys/vfs/hammer/hammer_mirror.c @@ -426,7 +426,9 @@ break; } - switch(mrec.head.type & HAMMER_MRECF_TYPE_MASK) { + /* DF-3150: include NODATA so REC_NODATA is dispatchable */ + switch(mrec.head.type & + (HAMMER_MRECF_TYPE_MASK | HAMMER_MRECF_NODATA)) { case HAMMER_MREC_TYPE_SKIP: if (mrec.head.rec_size != sizeof(mrec.skip)) error = EINVAL; @@ -579,6 +581,13 @@ } /* + * DF-3148: the wire leaf is stored verbatim in the B-Tree; its + * element type must be a record element. + */ + if (mrec->leaf.base.btype != HAMMER_BTREE_TYPE_RECORD) + return(EINVAL); + + /* * Re-localize for target. relocalization of data is handled * by hammer_create_at_cursor(). */ @@ -823,6 +832,14 @@ return(0); /* + * DF-3149: a record cannot be deleted at or before its own + * create_tid (hammer_delete_at_cursor KKASSERTs delete_tid != + * create_tid; earlier deletes produce a bogus on-disk state). + */ + if (mrec->leaf.base.delete_tid <= cursor->leaf->base.create_tid) + return(EINVAL); + + /* * Mark the record deleted on the mirror target. */ error = hammer_delete_at_cursor(cursor, HAMMER_DELETE_ADJUST, |