mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-27 04:32:16 +03:00
Fixes for #6639
Several issues were uncovered by running stress tests with zfs encryption and raw sends in particular. The issues and their associated fixes are as follows: * arc_read_done() has the ability to chain several requests for the same block of data via the arc_callback_t struct. In these cases, the ARC would only use the first request's dsobj from the bookmark to decrypt the data. This is problematic because the first request might be a prefetch zio which is able to handle the key not being loaded, while the second might use a different key that it is sure will work. The fix here is to pass the dsobj with each individual arc_callback_t so that each request can attempt to decrypt the data separately. * DRR_FREE and DRR_FREEOBJECT records in a send file were not having their transactions properly tagged as raw during raw sends, which caused a panic when the dbuf code attempted to decrypt these blocks. * traverse_prefetch_metadata() did not properly set ZIO_FLAG_SPECULATIVE when issuing prefetch IOs. * Added a few asserts and code cleanups to ensure these issues are more detectable in the future. Signed-off-by: Tom Caputi <tcaputi@datto.com>
This commit is contained in:
+20
-12
@@ -2592,7 +2592,11 @@ receive_freeobjects(struct receive_writer_arg *rwa,
|
||||
else if (err != 0)
|
||||
return (err);
|
||||
|
||||
err = dmu_free_long_object(rwa->os, obj);
|
||||
if (rwa->raw)
|
||||
err = dmu_free_long_object_raw(rwa->os, obj);
|
||||
else
|
||||
err = dmu_free_long_object(rwa->os, obj);
|
||||
|
||||
if (err != 0)
|
||||
return (err);
|
||||
|
||||
@@ -2608,9 +2612,9 @@ noinline static int
|
||||
receive_write(struct receive_writer_arg *rwa, struct drr_write *drrw,
|
||||
arc_buf_t *abuf)
|
||||
{
|
||||
dmu_tx_t *tx;
|
||||
dmu_buf_t *bonus;
|
||||
int err;
|
||||
dmu_tx_t *tx;
|
||||
dnode_t *dn;
|
||||
|
||||
if (drrw->drr_offset + drrw->drr_logical_size < drrw->drr_offset ||
|
||||
!DMU_OT_IS_VALID(drrw->drr_type))
|
||||
@@ -2635,7 +2639,6 @@ receive_write(struct receive_writer_arg *rwa, struct drr_write *drrw,
|
||||
return (SET_ERROR(EINVAL));
|
||||
|
||||
tx = dmu_tx_create(rwa->os);
|
||||
|
||||
dmu_tx_hold_write(tx, drrw->drr_object,
|
||||
drrw->drr_offset, drrw->drr_logical_size);
|
||||
err = dmu_tx_assign(tx, TXG_WAIT);
|
||||
@@ -2655,10 +2658,9 @@ receive_write(struct receive_writer_arg *rwa, struct drr_write *drrw,
|
||||
DRR_WRITE_PAYLOAD_SIZE(drrw));
|
||||
}
|
||||
|
||||
/* use the bonus buf to look up the dnode in dmu_assign_arcbuf */
|
||||
if (dmu_bonus_hold(rwa->os, drrw->drr_object, FTAG, &bonus) != 0)
|
||||
return (SET_ERROR(EINVAL));
|
||||
dmu_assign_arcbuf(bonus, drrw->drr_offset, abuf, tx);
|
||||
VERIFY0(dnode_hold(rwa->os, drrw->drr_object, FTAG, &dn));
|
||||
dmu_assign_arcbuf_by_dnode(dn, drrw->drr_offset, abuf, tx);
|
||||
dnode_rele(dn, FTAG);
|
||||
|
||||
/*
|
||||
* Note: If the receive fails, we want the resume stream to start
|
||||
@@ -2668,7 +2670,6 @@ receive_write(struct receive_writer_arg *rwa, struct drr_write *drrw,
|
||||
*/
|
||||
save_resume_state(rwa, drrw->drr_object, drrw->drr_offset, tx);
|
||||
dmu_tx_commit(tx);
|
||||
dmu_buf_rele(bonus, FTAG);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -2767,6 +2768,8 @@ receive_write_embedded(struct receive_writer_arg *rwa,
|
||||
return (SET_ERROR(EINVAL));
|
||||
if (drrwe->drr_compression >= ZIO_COMPRESS_FUNCTIONS)
|
||||
return (SET_ERROR(EINVAL));
|
||||
if (rwa->raw)
|
||||
return (SET_ERROR(EINVAL));
|
||||
|
||||
if (drrwe->drr_object > rwa->max_object)
|
||||
rwa->max_object = drrwe->drr_object;
|
||||
@@ -2841,7 +2844,7 @@ receive_spill(struct receive_writer_arg *rwa, struct drr_spill *drrs,
|
||||
if (db_spill->db_size < drrs->drr_length)
|
||||
VERIFY(0 == dbuf_spill_set_blksz(db_spill,
|
||||
drrs->drr_length, tx));
|
||||
dmu_assign_arcbuf_impl(db_spill, abuf, tx);
|
||||
dbuf_assign_arcbuf((dmu_buf_impl_t *)db_spill, abuf, tx);
|
||||
|
||||
dmu_buf_rele(db, FTAG);
|
||||
dmu_buf_rele(db_spill, FTAG);
|
||||
@@ -2866,8 +2869,13 @@ receive_free(struct receive_writer_arg *rwa, struct drr_free *drrf)
|
||||
if (drrf->drr_object > rwa->max_object)
|
||||
rwa->max_object = drrf->drr_object;
|
||||
|
||||
err = dmu_free_long_range(rwa->os, drrf->drr_object,
|
||||
drrf->drr_offset, drrf->drr_length);
|
||||
if (rwa->raw) {
|
||||
err = dmu_free_long_range_raw(rwa->os, drrf->drr_object,
|
||||
drrf->drr_offset, drrf->drr_length);
|
||||
} else {
|
||||
err = dmu_free_long_range(rwa->os, drrf->drr_object,
|
||||
drrf->drr_offset, drrf->drr_length);
|
||||
}
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user