Skip to content

Commit

Permalink
Iterate encrypted clones at zvol_create_minor
Browse files Browse the repository at this point in the history
Userland figures out which encryption-root keys are required to load,
and issues ZFS_IOC_LOAD_KEY. The tail section of spa_keystore_load_wkey()
will call zvol_create_minors() on the encryption-root object.

Any clones of the encrypted zvol will not be plumbed. This commits
adds additional logic to detect if zvol has clones, and is encrypted,
then adds these to the list of zvols to call zvol_create_minors() on.

Signed-off-by: Jorgen Lundman <[email protected]>
  • Loading branch information
lundman committed Aug 11, 2021
1 parent 6bc61d2 commit a83b5c8
Showing 1 changed file with 64 additions and 0 deletions.
64 changes: 64 additions & 0 deletions module/zfs/zvol.c
Original file line number Diff line number Diff line change
Expand Up @@ -1040,6 +1040,68 @@ zvol_create_snap_minor_cb(const char *dsname, void *arg)
return (0);
}

/*
* If spa_keystore_load_wkey() is called for an encrypted zvol,
* we need to look for any clones also using the key. This function
* is "best effort" - so we just skip over it if there are failures.
*/
static void
zvol_add_clones(const char *dsname, list_t *minors_list)
{
/* Also check if it has clones */
dsl_dir_t *dd = NULL;
dsl_pool_t *dp = NULL;

if (dsl_pool_hold(dsname, FTAG, &dp) != 0)
return;

if (!spa_feature_is_enabled(dp->dp_spa,
SPA_FEATURE_ENCRYPTION))
goto out;

if (dsl_dir_hold(dp, dsname, FTAG, &dd, NULL) != 0)
goto out;

if (dsl_dir_phys(dd)->dd_clones == 0)
goto out;

zap_cursor_t *zc = kmem_alloc(sizeof (zap_cursor_t), KM_SLEEP);
zap_attribute_t *za = kmem_alloc(sizeof (zap_attribute_t), KM_SLEEP);
objset_t *mos = dd->dd_pool->dp_meta_objset;

for (zap_cursor_init(zc, mos, dsl_dir_phys(dd)->dd_clones);
zap_cursor_retrieve(zc, za) == 0;
zap_cursor_advance(zc)) {
dsl_dataset_t *clone;
minors_job_t *job;

if (dsl_dataset_hold_obj(dd->dd_pool,
za->za_first_integer, FTAG, &clone) == 0) {

char name[ZFS_MAX_DATASET_NAME_LEN];
dsl_dataset_name(clone, name);

char *n = kmem_strdup(name);
job = kmem_alloc(sizeof (minors_job_t), KM_SLEEP);
job->name = n;
job->list = minors_list;
job->error = 0;
list_insert_tail(minors_list, job);

dsl_dataset_rele(clone, FTAG);
}
}
zap_cursor_fini(zc);
kmem_free(za, sizeof (zap_attribute_t));
kmem_free(zc, sizeof (zap_cursor_t));

out:
if (dd != NULL)
dsl_dir_rele(dd, FTAG);
if (dp != NULL)
dsl_pool_rele(dp, FTAG);
}

/*
* Mask errors to continue dmu_objset_find() traversal
*/
Expand Down Expand Up @@ -1078,6 +1140,8 @@ zvol_create_minors_cb(const char *dsname, void *arg)
taskq_dispatch(system_taskq, zvol_prefetch_minors_impl, job,
TQ_SLEEP);

zvol_add_clones(dsname, minors_list);

if (snapdev == ZFS_SNAPDEV_VISIBLE) {
/*
* traverse snapshots only, do not traverse children,
Expand Down

0 comments on commit a83b5c8

Please sign in to comment.