static void crypt_changed_cb(void *arg, uint64_t newval) { objset_t *os = arg; /* * Inheritance and range checking should have been done by now. */ ASSERT(newval != ZIO_CRYPT_INHERIT); os->os_crypt = zio_crypt_select(newval, ZIO_CRYPT_ON_VALUE); }
/* * dsl_crypto_key_gen - Generate dataset key * * Generate a new key for this dataset based on its encryption property type. * Store the key as a usable zcrypt_key_t in the in memory keystore and * put the wrapped version of it in the on disk keychain. * * returns 0 on success */ int dsl_crypto_key_create(dsl_dir_t *dd, dsl_dataset_phys_t *dsphys, uint64_t dsobj, dsl_crypto_ctx_t *ctx, dmu_tx_t *tx) { int error = -1; #ifdef DEBUG zcrypt_key_t *debugkey; #endif /* DEBUG */ zcrypt_key_t *wrappingkey, *dslkey; caddr_t wkeybuf = NULL; size_t wkeylen = 0; uint64_t crypt; spa_t *spa = dd->dd_pool->dp_spa; zcrypt_keystore_node_t *skn; if (ctx == NULL) { return (0); } crypt = ctx->dcc_crypt; if (crypt == ZIO_CRYPT_OFF || crypt == ZIO_CRYPT_INHERIT) { return (0); } crypt = zio_crypt_select(crypt, ZIO_CRYPT_ON_VALUE); wrappingkey = ctx->dcc_wrap_key; skn = zcrypt_keystore_insert(spa, dsobj, wrappingkey); if (skn == NULL) { error = ENOKEY; goto out; } dslkey = zcrypt_key_gen(crypt); zcrypt_key_hold(wrappingkey, FTAG); error = zcrypt_wrap_key(wrappingkey, dslkey, &wkeybuf, &wkeylen, zio_crypt_select_wrap(crypt)); if (error != 0) { zcrypt_key_free(dslkey); spa_history_log_internal(spa, "key create", tx, "failed dataset = %llu unable to wrap key", dsobj, error); goto out; } dsl_keychain_create_obj(dd, tx); dsl_keychain_set_key(dd, tx, wkeybuf, wkeylen, dsphys->ds_creation_time); zcrypt_keychain_insert(&skn->skn_keychain, dsphys->ds_creation_txg, dslkey); if (ctx->dcc_salt != 0) { objset_t *mos = dd->dd_pool->dp_meta_objset; uint64_t props_zapobj = dsl_dir_phys(dd)->dd_props_zapobj; error = zap_update(mos, props_zapobj, zfs_prop_to_name(ZFS_PROP_SALT), 8, 1, (void *)&ctx->dcc_salt, tx); } if (error == 0) spa_history_log_internal(spa, "key create", tx, "succeeded dataset = %llu", dsobj); #ifdef DEBUG ASSERT3U(zcrypt_unwrap_key(wrappingkey, crypt, wkeybuf, wkeylen, &debugkey), ==, 0); zcrypt_key_compare(dslkey, debugkey); zcrypt_key_free(debugkey); #endif /* DEBUG */ out: zcrypt_key_release(wrappingkey, FTAG); if (wkeylen > 0) { kmem_free(wkeybuf, wkeylen); } return (error); }
/* called from dsl for meta-objset */ objset_t * dmu_objset_create_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp, dmu_objset_type_t type, dsl_crypto_ctx_t *dcc, dmu_tx_t *tx) { objset_t *os; dnode_t *mdn; ASSERT(dmu_tx_is_syncing(tx)); if (ds != NULL) VERIFY(0 == dmu_objset_from_ds(ds, &os)); else VERIFY(0 == dmu_objset_open_impl(spa, NULL, bp, &os)); mdn = DMU_META_DNODE(os); dnode_allocate(mdn, DMU_OT_DNODE, 1 << DNODE_BLOCK_SHIFT, DN_MAX_INDBLKSHIFT, DMU_OT_NONE, 0, tx); /* * We don't want to have to increase the meta-dnode's nlevels * later, because then we could do it in quescing context while * we are also accessing it in open context. * * This precaution is not necessary for the MOS (ds == NULL), * because the MOS is only updated in syncing context. * This is most fortunate: the MOS is the only objset that * needs to be synced multiple times as spa_sync() iterates * to convergence, so minimizing its dn_nlevels matters. */ if (ds != NULL) { int levels = 1; /* * Determine the number of levels necessary for the meta-dnode * to contain DN_MAX_OBJECT dnodes. */ while ((uint64_t)mdn->dn_nblkptr << (mdn->dn_datablkshift + (levels - 1) * (mdn->dn_indblkshift - SPA_BLKPTRSHIFT)) < DN_MAX_OBJECT * sizeof (dnode_phys_t)) levels++; mdn->dn_next_nlevels[tx->tx_txg & TXG_MASK] = mdn->dn_nlevels = levels; } ASSERT(type != DMU_OST_NONE); ASSERT(type != DMU_OST_ANY); ASSERT(type < DMU_OST_NUMTYPES); /* * Note: although we should not be dirtying the objset outside of * sync context, the os_type is used directly from the os_phys * in dsl_scan so it may not be save to put os_type in the in-core * objset_t and set it in the phys in sync context (as with os_flags) */ dmu_objset_dirty(os); os->os_phys->os_type = type; if (dmu_objset_userused_enabled(os)) { os->os_phys->os_flags |= OBJSET_FLAG_USERACCOUNTING_COMPLETE; // FIXME - removed in newer. // os->os_flags = os->os_phys->os_flags; } if (dcc != NULL && dcc->dcc_crypt != ZIO_CRYPT_INHERIT) { os->os_crypt = zio_crypt_select(dcc->dcc_crypt, ZIO_CRYPT_ON_VALUE); } dsl_dataset_dirty(ds, tx); return (os); }