Skip to content

Commit

Permalink
Fix double mutex_init bug in send code
Browse files Browse the repository at this point in the history
It was possible to cause a kernel panic in the send code by 
initializing an already-initialized mutex, if a record was created 
with type DATA, destroyed with a different type (bypassing the 
mutex_destroy call) and then re-allocated as a DATA record again.

We tweak the logic to not change the type of a record once it has 
been created, avoiding the issue.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Jorgen Lundman <lundman@lundman.net>
Signed-off-by: Paul Dagnelie <pcd@delphix.com>
Closes openzfs#10374
  • Loading branch information
pcd1193182 authored Jun 4, 2020
1 parent 52998c7 commit 99b281f
Showing 1 changed file with 12 additions and 5 deletions.
17 changes: 12 additions & 5 deletions module/zfs/dmu_send.c
Original file line number Diff line number Diff line change
Expand Up @@ -1153,23 +1153,30 @@ send_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
if (zb->zb_blkid == DMU_SPILL_BLKID)
ASSERT3U(BP_GET_TYPE(bp), ==, DMU_OT_SA);

record = range_alloc(DATA, zb->zb_object, start, (start + span < start ?
0 : start + span), B_FALSE);
enum type record_type = DATA;
if (BP_IS_HOLE(bp))
record_type = HOLE;
else if (BP_IS_REDACTED(bp))
record_type = REDACT;
else
record_type = DATA;

record = range_alloc(record_type, zb->zb_object, start,
(start + span < start ? 0 : start + span), B_FALSE);

uint64_t datablksz = (zb->zb_blkid == DMU_SPILL_BLKID ?
BP_GET_LSIZE(bp) : dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT);

if (BP_IS_HOLE(bp)) {
record->type = HOLE;
record->sru.hole.datablksz = datablksz;
} else if (BP_IS_REDACTED(bp)) {
record->type = REDACT;
record->sru.redact.datablksz = datablksz;
} else {
record->type = DATA;
record->sru.data.datablksz = datablksz;
record->sru.data.obj_type = dnp->dn_type;
record->sru.data.bp = *bp;
}

bqueue_enqueue(&sta->q, record, sizeof (*record));
return (0);
}
Expand Down

0 comments on commit 99b281f

Please sign in to comment.