summaryrefslogtreecommitdiffstats
path: root/module/zfs/arc.c
diff options
context:
space:
mode:
Diffstat (limited to 'module/zfs/arc.c')
-rw-r--r--module/zfs/arc.c117
1 files changed, 45 insertions, 72 deletions
diff --git a/module/zfs/arc.c b/module/zfs/arc.c
index fa7f62d99..6662e0fae 100644
--- a/module/zfs/arc.c
+++ b/module/zfs/arc.c
@@ -1922,10 +1922,9 @@ error:
* also decompress the data.
*/
static int
-arc_hdr_decrypt(arc_buf_hdr_t *hdr, spa_t *spa, uint64_t dsobj)
+arc_hdr_decrypt(arc_buf_hdr_t *hdr, spa_t *spa, const zbookmark_phys_t *zb)
{
int ret;
- dsl_crypto_key_t *dck = NULL;
abd_t *cabd = NULL;
void *tmp = NULL;
boolean_t no_crypt = B_FALSE;
@@ -1936,25 +1935,9 @@ arc_hdr_decrypt(arc_buf_hdr_t *hdr, spa_t *spa, uint64_t dsobj)
arc_hdr_alloc_abd(hdr, B_FALSE);
- /*
- * We must be careful to use the passed-in dsobj value here and
- * not the value in b_dsobj. b_dsobj is meant to be a best guess for
- * the L2ARC, which has the luxury of being able to fail without real
- * consequences (the data simply won't make it to the L2ARC). In
- * reality, the dsobj stored in the header may belong to a dataset
- * that has been unmounted or otherwise disowned, meaning the key
- * won't be accessible via that dsobj anymore.
- */
- ret = spa_keystore_lookup_key(spa, dsobj, FTAG, &dck);
- if (ret != 0) {
- ret = SET_ERROR(EACCES);
- goto error;
- }
-
- ret = zio_do_crypt_abd(B_FALSE, &dck->dck_key,
- hdr->b_crypt_hdr.b_salt, hdr->b_crypt_hdr.b_ot,
- hdr->b_crypt_hdr.b_iv, hdr->b_crypt_hdr.b_mac,
- HDR_GET_PSIZE(hdr), bswap, hdr->b_l1hdr.b_pabd,
+ ret = spa_do_crypt_abd(B_FALSE, spa, zb, hdr->b_crypt_hdr.b_ot,
+ B_FALSE, bswap, hdr->b_crypt_hdr.b_salt, hdr->b_crypt_hdr.b_iv,
+ hdr->b_crypt_hdr.b_mac, HDR_GET_PSIZE(hdr), hdr->b_l1hdr.b_pabd,
hdr->b_crypt_hdr.b_rabd, &no_crypt);
if (ret != 0)
goto error;
@@ -1994,14 +1977,10 @@ arc_hdr_decrypt(arc_buf_hdr_t *hdr, spa_t *spa, uint64_t dsobj)
hdr->b_l1hdr.b_pabd = cabd;
}
- spa_keystore_dsl_key_rele(spa, dck, FTAG);
-
return (0);
error:
arc_hdr_free_abd(hdr, B_FALSE);
- if (dck != NULL)
- spa_keystore_dsl_key_rele(spa, dck, FTAG);
if (cabd != NULL)
arc_free_data_buf(hdr, cabd, arc_hdr_size(hdr), hdr);
@@ -2015,7 +1994,7 @@ error:
*/
static int
arc_fill_hdr_crypt(arc_buf_hdr_t *hdr, kmutex_t *hash_lock, spa_t *spa,
- uint64_t dsobj, boolean_t noauth)
+ const zbookmark_phys_t *zb, boolean_t noauth)
{
int ret;
@@ -2029,7 +2008,7 @@ arc_fill_hdr_crypt(arc_buf_hdr_t *hdr, kmutex_t *hash_lock, spa_t *spa,
* The caller requested authenticated data but our data has
* not been authenticated yet. Verify the MAC now if we can.
*/
- ret = arc_hdr_authenticate(hdr, spa, dsobj);
+ ret = arc_hdr_authenticate(hdr, spa, zb->zb_objset);
if (ret != 0)
goto error;
} else if (HDR_HAS_RABD(hdr) && hdr->b_l1hdr.b_pabd == NULL) {
@@ -2038,7 +2017,7 @@ arc_fill_hdr_crypt(arc_buf_hdr_t *hdr, kmutex_t *hash_lock, spa_t *spa,
* unencrypted version was requested we take this opportunity
* to store the decrypted version in the header for future use.
*/
- ret = arc_hdr_decrypt(hdr, spa, dsobj);
+ ret = arc_hdr_decrypt(hdr, spa, zb);
if (ret != 0)
goto error;
}
@@ -2094,7 +2073,8 @@ arc_buf_untransform_in_place(arc_buf_t *buf, kmutex_t *hash_lock)
* the correct-sized data buffer.
*/
static int
-arc_buf_fill(arc_buf_t *buf, spa_t *spa, uint64_t dsobj, arc_fill_flags_t flags)
+arc_buf_fill(arc_buf_t *buf, spa_t *spa, const zbookmark_phys_t *zb,
+ arc_fill_flags_t flags)
{
int error = 0;
arc_buf_hdr_t *hdr = buf->b_hdr;
@@ -2131,7 +2111,7 @@ arc_buf_fill(arc_buf_t *buf, spa_t *spa, uint64_t dsobj, arc_fill_flags_t flags)
*/
if (HDR_PROTECTED(hdr)) {
error = arc_fill_hdr_crypt(hdr, hash_lock, spa,
- dsobj, !!(flags & ARC_FILL_NOAUTH));
+ zb, !!(flags & ARC_FILL_NOAUTH));
if (error != 0) {
arc_hdr_set_flags(hdr, ARC_FLAG_IO_ERROR);
return (error);
@@ -2272,13 +2252,14 @@ arc_untransform(arc_buf_t *buf, spa_t *spa, const zbookmark_phys_t *zb,
if (in_place)
flags |= ARC_FILL_IN_PLACE;
- ret = arc_buf_fill(buf, spa, zb->zb_objset, flags);
+ ret = arc_buf_fill(buf, spa, zb, flags);
if (ret == ECKSUM) {
/*
* Convert authentication and decryption errors to EIO
* (and generate an ereport) before leaving the ARC.
*/
ret = SET_ERROR(EIO);
+ spa_log_error(spa, zb);
zfs_ereport_post(FM_EREPORT_ZFS_AUTHENTICATION,
spa, NULL, zb, NULL, 0, 0);
}
@@ -2813,8 +2794,8 @@ arc_can_share(arc_buf_hdr_t *hdr, arc_buf_t *buf)
* copy was made successfully, or an error code otherwise.
*/
static int
-arc_buf_alloc_impl(arc_buf_hdr_t *hdr, spa_t *spa, uint64_t dsobj, void *tag,
- boolean_t encrypted, boolean_t compressed, boolean_t noauth,
+arc_buf_alloc_impl(arc_buf_hdr_t *hdr, spa_t *spa, const zbookmark_phys_t *zb,
+ void *tag, boolean_t encrypted, boolean_t compressed, boolean_t noauth,
boolean_t fill, arc_buf_t **ret)
{
arc_buf_t *buf;
@@ -2906,7 +2887,8 @@ arc_buf_alloc_impl(arc_buf_hdr_t *hdr, spa_t *spa, uint64_t dsobj, void *tag,
* decompress the data.
*/
if (fill) {
- return (arc_buf_fill(buf, spa, dsobj, flags));
+ ASSERT3P(zb, !=, NULL);
+ return (arc_buf_fill(buf, spa, zb, flags));
}
return (0);
@@ -3588,7 +3570,7 @@ arc_alloc_buf(spa_t *spa, void *tag, arc_buf_contents_t type, int32_t size)
ASSERT(!MUTEX_HELD(HDR_LOCK(hdr)));
arc_buf_t *buf = NULL;
- VERIFY0(arc_buf_alloc_impl(hdr, spa, 0, tag, B_FALSE, B_FALSE,
+ VERIFY0(arc_buf_alloc_impl(hdr, spa, NULL, tag, B_FALSE, B_FALSE,
B_FALSE, B_FALSE, &buf));
arc_buf_thaw(buf);
@@ -3613,7 +3595,7 @@ arc_alloc_compressed_buf(spa_t *spa, void *tag, uint64_t psize, uint64_t lsize,
ASSERT(!MUTEX_HELD(HDR_LOCK(hdr)));
arc_buf_t *buf = NULL;
- VERIFY0(arc_buf_alloc_impl(hdr, spa, 0, tag, B_FALSE,
+ VERIFY0(arc_buf_alloc_impl(hdr, spa, NULL, tag, B_FALSE,
B_TRUE, B_FALSE, B_FALSE, &buf));
arc_buf_thaw(buf);
ASSERT3P(hdr->b_l1hdr.b_freeze_cksum, ==, NULL);
@@ -3667,7 +3649,7 @@ arc_alloc_raw_buf(spa_t *spa, void *tag, uint64_t dsobj, boolean_t byteorder,
* arc_write_ready().
*/
buf = NULL;
- VERIFY0(arc_buf_alloc_impl(hdr, spa, dsobj, tag, B_TRUE, B_TRUE,
+ VERIFY0(arc_buf_alloc_impl(hdr, spa, NULL, tag, B_TRUE, B_TRUE,
B_FALSE, B_FALSE, &buf));
arc_buf_thaw(buf);
ASSERT3P(hdr->b_l1hdr.b_freeze_cksum, ==, NULL);
@@ -5814,7 +5796,7 @@ arc_read_done(zio_t *zio)
continue;
int error = arc_buf_alloc_impl(hdr, zio->io_spa,
- acb->acb_dsobj, acb->acb_private, acb->acb_encrypted,
+ &acb->acb_zb, acb->acb_private, acb->acb_encrypted,
acb->acb_compressed, acb->acb_noauth, B_TRUE,
&acb->acb_buf);
if (error != 0) {
@@ -5829,7 +5811,7 @@ arc_read_done(zio_t *zio)
* encryption key wasn't loaded
*/
ASSERT((zio->io_flags & ZIO_FLAG_SPECULATIVE) ||
- error != ENOENT);
+ error != EACCES);
/*
* If we failed to decrypt, report an error now (as the zio
@@ -5838,11 +5820,10 @@ arc_read_done(zio_t *zio)
if (error == ECKSUM) {
ASSERT(BP_IS_PROTECTED(bp));
error = SET_ERROR(EIO);
- spa_log_error(zio->io_spa, &zio->io_bookmark);
if ((zio->io_flags & ZIO_FLAG_SPECULATIVE) == 0) {
+ spa_log_error(zio->io_spa, &acb->acb_zb);
zfs_ereport_post(FM_EREPORT_ZFS_AUTHENTICATION,
- zio->io_spa, NULL, &zio->io_bookmark, zio,
- 0, 0);
+ zio->io_spa, NULL, &acb->acb_zb, zio, 0, 0);
}
}
@@ -6004,7 +5985,7 @@ top:
acb->acb_compressed = compressed_read;
acb->acb_encrypted = encrypted_read;
acb->acb_noauth = noauth_read;
- acb->acb_dsobj = zb->zb_objset;
+ acb->acb_zb = *zb;
if (pio != NULL)
acb->acb_zio_dummy = zio_null(pio,
spa, NULL, NULL, NULL, zio_flags);
@@ -6049,18 +6030,22 @@ top:
ASSERT(!BP_IS_EMBEDDED(bp) || !BP_IS_HOLE(bp));
/* Get a buf with the desired data in it. */
- rc = arc_buf_alloc_impl(hdr, spa, zb->zb_objset,
- private, encrypted_read, compressed_read,
- noauth_read, B_TRUE, &buf);
+ rc = arc_buf_alloc_impl(hdr, spa, zb, private,
+ encrypted_read, compressed_read, noauth_read,
+ B_TRUE, &buf);
if (rc == ECKSUM) {
/*
* Convert authentication and decryption errors
- * to EIO (and generate an ereport) before
- * leaving the ARC.
+ * to EIO (and generate an ereport if needed)
+ * before leaving the ARC.
*/
rc = SET_ERROR(EIO);
- zfs_ereport_post(FM_EREPORT_ZFS_AUTHENTICATION,
- spa, NULL, zb, NULL, 0, 0);
+ if ((zio_flags & ZIO_FLAG_SPECULATIVE) == 0) {
+ spa_log_error(spa, zb);
+ zfs_ereport_post(
+ FM_EREPORT_ZFS_AUTHENTICATION,
+ spa, NULL, zb, NULL, 0, 0);
+ }
}
if (rc != 0) {
(void) remove_reference(hdr, hash_lock,
@@ -6071,7 +6056,7 @@ top:
/* assert any errors weren't due to unloaded keys */
ASSERT((zio_flags & ZIO_FLAG_SPECULATIVE) ||
- rc != ENOENT);
+ rc != EACCES);
} else if (*arc_flags & ARC_FLAG_PREFETCH &&
refcount_count(&hdr->b_l1hdr.b_refcnt) == 0) {
arc_hdr_set_flags(hdr, ARC_FLAG_PREFETCH);
@@ -6223,7 +6208,7 @@ top:
acb->acb_compressed = compressed_read;
acb->acb_encrypted = encrypted_read;
acb->acb_noauth = noauth_read;
- acb->acb_dsobj = zb->zb_objset;
+ acb->acb_zb = *zb;
ASSERT3P(hdr->b_l1hdr.b_acb, ==, NULL);
hdr->b_l1hdr.b_acb = acb;
@@ -8078,7 +8063,6 @@ l2arc_untransform(zio_t *zio, l2arc_read_callback_t *cb)
spa_t *spa = zio->io_spa;
arc_buf_hdr_t *hdr = cb->l2rcb_hdr;
blkptr_t *bp = zio->io_bp;
- dsl_crypto_key_t *dck = NULL;
uint8_t salt[ZIO_DATA_SALT_LEN];
uint8_t iv[ZIO_DATA_IV_LEN];
uint8_t mac[ZIO_DATA_MAC_LEN];
@@ -8099,31 +8083,20 @@ l2arc_untransform(zio_t *zio, l2arc_read_callback_t *cb)
* until arc_read_done().
*/
if (BP_IS_ENCRYPTED(bp)) {
- abd_t *eabd = arc_get_data_abd(hdr,
- arc_hdr_size(hdr), hdr);
+ abd_t *eabd = arc_get_data_abd(hdr, arc_hdr_size(hdr), hdr);
zio_crypt_decode_params_bp(bp, salt, iv);
zio_crypt_decode_mac_bp(bp, mac);
- ret = spa_keystore_lookup_key(spa,
- cb->l2rcb_zb.zb_objset, FTAG, &dck);
+ ret = spa_do_crypt_abd(B_FALSE, spa, &cb->l2rcb_zb,
+ BP_GET_TYPE(bp), BP_GET_DEDUP(bp), BP_SHOULD_BYTESWAP(bp),
+ salt, iv, mac, HDR_GET_PSIZE(hdr), eabd,
+ hdr->b_l1hdr.b_pabd, &no_crypt);
if (ret != 0) {
arc_free_data_abd(hdr, eabd, arc_hdr_size(hdr), hdr);
goto error;
}
- ret = zio_do_crypt_abd(B_FALSE, &dck->dck_key,
- salt, BP_GET_TYPE(bp), iv, mac, HDR_GET_PSIZE(hdr),
- BP_SHOULD_BYTESWAP(bp), eabd, hdr->b_l1hdr.b_pabd,
- &no_crypt);
- if (ret != 0) {
- arc_free_data_abd(hdr, eabd, arc_hdr_size(hdr), hdr);
- spa_keystore_dsl_key_rele(spa, dck, FTAG);
- goto error;
- }
-
- spa_keystore_dsl_key_rele(spa, dck, FTAG);
-
/*
* If we actually performed decryption, replace b_pabd
* with the decrypted data. Otherwise we can just throw
@@ -8529,9 +8502,9 @@ l2arc_apply_transforms(spa_t *spa, arc_buf_hdr_t *hdr, uint64_t asize,
goto error;
ret = zio_do_crypt_abd(B_TRUE, &dck->dck_key,
- hdr->b_crypt_hdr.b_salt, hdr->b_crypt_hdr.b_ot,
- hdr->b_crypt_hdr.b_iv, mac, psize, bswap, to_write,
- eabd, &no_crypt);
+ hdr->b_crypt_hdr.b_ot, bswap, hdr->b_crypt_hdr.b_salt,
+ hdr->b_crypt_hdr.b_iv, mac, psize, to_write, eabd,
+ &no_crypt);
if (ret != 0)
goto error;