mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-25 11:47:43 +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:
@@ -2153,6 +2153,13 @@ dbuf_assign_arcbuf(dmu_buf_impl_t *db, arc_buf_t *buf, dmu_tx_t *tx)
|
||||
|
||||
if (db->db_state == DB_CACHED &&
|
||||
refcount_count(&db->db_holds) - 1 > db->db_dirtycnt) {
|
||||
/*
|
||||
* In practice, we will never have a case where we have an
|
||||
* encrypted arc buffer while additional holds exist on the
|
||||
* dbuf. We don't handle this here so we simply assert that
|
||||
* fact instead.
|
||||
*/
|
||||
ASSERT(!arc_is_encrypted(buf));
|
||||
mutex_exit(&db->db_mtx);
|
||||
(void) dbuf_dirty(db, tx);
|
||||
bcopy(buf->b_data, db->db.db_data, db->db.db_size);
|
||||
@@ -2168,6 +2175,8 @@ dbuf_assign_arcbuf(dmu_buf_impl_t *db, arc_buf_t *buf, dmu_tx_t *tx)
|
||||
ASSERT(db->db_buf != NULL);
|
||||
if (dr != NULL && dr->dr_txg == tx->tx_txg) {
|
||||
ASSERT(dr->dt.dl.dr_data == db->db_buf);
|
||||
IMPLY(arc_is_encrypted(buf), dr->dt.dl.dr_raw);
|
||||
|
||||
if (!arc_released(db->db_buf)) {
|
||||
ASSERT(dr->dt.dl.dr_override_state ==
|
||||
DR_OVERRIDDEN);
|
||||
|
||||
Reference in New Issue
Block a user