@@ -3376,30 +3376,28 @@ created_before(libzfs_handle_t *hdl, avl_tree_t *avl,
3376
3376
*/
3377
3377
static int
3378
3378
recv_fix_encryption_hierarchy (libzfs_handle_t * hdl , const char * top_zfs ,
3379
- nvlist_t * stream_nv )
3379
+ nvlist_t * stream_nv , avl_tree_t * stream_avl )
3380
3380
{
3381
3381
int err ;
3382
- nvpair_t * fselem = NULL ;
3383
- nvlist_t * stream_fss ;
3382
+ nvpair_t * fselem = NULL , * nextfselem ;
3383
+ nvlist_t * local_nv , * stream_fss ;
3384
+ avl_tree_t * local_avl ;
3385
+ boolean_t recursive ;
3386
+ char fsname [ZFS_MAX_DATASET_NAME_LEN ], * cp ;
3384
3387
3385
- stream_fss = fnvlist_lookup_nvlist (stream_nv , "fss" );
3388
+ recursive = (nvlist_lookup_boolean (stream_nv , "not_recursive" ) ==
3389
+ ENOENT );
3386
3390
3391
+ /*
3392
+ * Go through the send stream and find a snapshot that exists
3393
+ * locally.
3394
+ */
3395
+ stream_fss = fnvlist_lookup_nvlist (stream_nv , "fss" );
3387
3396
while ((fselem = nvlist_next_nvpair (stream_fss , fselem )) != NULL ) {
3388
- zfs_handle_t * zhp = NULL ;
3389
- uint64_t crypt ;
3390
- nvlist_t * snaps , * props , * stream_nvfs = NULL ;
3397
+ nvlist_t * snaps , * stream_nvfs ;
3391
3398
nvpair_t * snapel = NULL ;
3392
- boolean_t is_encroot , is_clone , stream_encroot ;
3393
- char * cp ;
3394
- const char * stream_keylocation = NULL ;
3395
- char keylocation [MAXNAMELEN ];
3396
- char fsname [ZFS_MAX_DATASET_NAME_LEN ];
3397
-
3398
- keylocation [0 ] = '\0' ;
3399
3399
stream_nvfs = fnvpair_value_nvlist (fselem );
3400
3400
snaps = fnvlist_lookup_nvlist (stream_nvfs , "snaps" );
3401
- props = fnvlist_lookup_nvlist (stream_nvfs , "props" );
3402
- stream_encroot = nvlist_exists (stream_nvfs , "is_encroot" );
3403
3401
3404
3402
/* find a snapshot from the stream that exists locally */
3405
3403
err = ENOENT ;
@@ -3413,45 +3411,99 @@ recv_fix_encryption_hierarchy(libzfs_handle_t *hdl, const char *top_zfs,
3413
3411
break ;
3414
3412
}
3415
3413
3416
- if (err != 0 )
3417
- continue ;
3414
+ if (err == 0 )
3415
+ break ;
3416
+ }
3418
3417
3419
- cp = strchr ( fsname , '@' );
3420
- if (cp != NULL )
3421
- * cp = '\0' ;
3418
+ /* If we failed to find a snapshot that exists locally return. */
3419
+ if (err != 0 )
3420
+ return ( 0 ) ;
3422
3421
3423
- zhp = zfs_open (hdl , fsname , ZFS_TYPE_DATASET );
3422
+ /* Convert the snapshot to fs name */
3423
+ cp = strchr (fsname , '@' );
3424
+ if (cp != NULL )
3425
+ * cp = '\0' ;
3426
+
3427
+ /* Using the fs name, gather the nvlists for all local filesystems. */
3428
+ if ((err = gather_nvlist (hdl , fsname , NULL , NULL ,
3429
+ recursive , B_TRUE , B_FALSE , recursive , B_FALSE , B_FALSE , B_FALSE ,
3430
+ B_FALSE , B_TRUE , & local_nv , & local_avl )) != 0 )
3431
+ return (err );
3432
+
3433
+ /*
3434
+ * Go through the nvlists of the local filesystems and check for
3435
+ * encryption roots.
3436
+ */
3437
+ for (fselem = nvlist_next_nvpair (local_nv , NULL ); fselem ;
3438
+ fselem = nextfselem ) {
3439
+ zfs_handle_t * zhp = NULL ;
3440
+ uint64_t crypt ;
3441
+ nvlist_t * stream_props , * snaps , * stream_nvfs = NULL ,
3442
+ * nvfs = NULL ;
3443
+ boolean_t is_encroot , is_clone , stream_encroot ;
3444
+ const char * stream_keylocation = NULL , * fs ;
3445
+ char keylocation [MAXNAMELEN ];
3446
+ nvpair_t * snapelem ;
3447
+
3448
+ nextfselem = nvlist_next_nvpair (local_nv , fselem );
3449
+
3450
+ nvfs = fnvpair_value_nvlist (fselem );
3451
+ snaps = fnvlist_lookup_nvlist (nvfs , "snaps" );
3452
+ fs = fnvlist_lookup_string (nvfs , "name" );
3453
+ zhp = zfs_open (hdl , fs , ZFS_TYPE_DATASET );
3424
3454
if (zhp == NULL ) {
3425
3455
err = ENOENT ;
3426
3456
goto error ;
3427
3457
}
3428
3458
3429
- crypt = zfs_prop_get_int (zhp , ZFS_PROP_ENCRYPTION );
3430
- is_clone = zhp -> zfs_dmustats .dds_origin [0 ] != '\0' ;
3431
- (void ) zfs_crypto_get_encryption_root (zhp , & is_encroot , NULL );
3432
-
3433
3459
/* we don't need to do anything for unencrypted datasets */
3460
+ crypt = zfs_prop_get_int (zhp , ZFS_PROP_ENCRYPTION );
3434
3461
if (crypt == ZIO_CRYPT_OFF ) {
3435
3462
zfs_close (zhp );
3436
3463
continue ;
3437
3464
}
3438
3465
3466
+ is_clone = zhp -> zfs_dmustats .dds_origin [0 ] != '\0' ;
3467
+ (void ) zfs_crypto_get_encryption_root (zhp , & is_encroot , NULL );
3468
+ keylocation [0 ] = '\0' ;
3469
+
3470
+ /*
3471
+ * Go through the snapshots of the local filesystem and find
3472
+ * the stream's filesystem.
3473
+ */
3474
+ for (snapelem = nvlist_next_nvpair (snaps , NULL );
3475
+ snapelem ; snapelem = nvlist_next_nvpair (snaps , snapelem )) {
3476
+ uint64_t thisguid ;
3477
+
3478
+ thisguid = fnvpair_value_uint64 (snapelem );
3479
+ stream_nvfs = fsavl_find (stream_avl , thisguid , NULL );
3480
+
3481
+ if (stream_nvfs != NULL )
3482
+ break ;
3483
+ }
3484
+
3485
+ if (stream_nvfs == NULL )
3486
+ continue ;
3487
+
3488
+ stream_props = fnvlist_lookup_nvlist (stream_nvfs , "props" );
3489
+ stream_encroot = nvlist_exists (stream_nvfs , "is_encroot" );
3490
+
3439
3491
/*
3440
3492
* If the dataset is flagged as an encryption root, was not
3441
3493
* received as a clone and is not currently an encryption root,
3442
3494
* force it to become one. Fixup the keylocation if necessary.
3443
3495
*/
3444
3496
if (stream_encroot ) {
3445
3497
if (!is_clone && !is_encroot ) {
3446
- err = lzc_change_key (fsname ,
3498
+ err = lzc_change_key (fs ,
3447
3499
DCP_CMD_FORCE_NEW_KEY , NULL , NULL , 0 );
3448
3500
if (err != 0 ) {
3449
3501
zfs_close (zhp );
3450
3502
goto error ;
3451
3503
}
3452
3504
}
3453
3505
3454
- stream_keylocation = fnvlist_lookup_string (props ,
3506
+ stream_keylocation = fnvlist_lookup_string (stream_props ,
3455
3507
zfs_prop_to_name (ZFS_PROP_KEYLOCATION ));
3456
3508
3457
3509
/*
@@ -3485,8 +3537,8 @@ recv_fix_encryption_hierarchy(libzfs_handle_t *hdl, const char *top_zfs,
3485
3537
* force-inherited.
3486
3538
*/
3487
3539
if (!stream_encroot && is_encroot &&
3488
- strcmp (top_zfs , fsname ) != 0 ) {
3489
- err = lzc_change_key (fsname , DCP_CMD_FORCE_INHERIT ,
3540
+ strcmp (top_zfs , fs ) != 0 ) {
3541
+ err = lzc_change_key (fs , DCP_CMD_FORCE_INHERIT ,
3490
3542
NULL , NULL , 0 );
3491
3543
if (err != 0 ) {
3492
3544
zfs_close (zhp );
@@ -3518,14 +3570,14 @@ recv_incremental_replication(libzfs_handle_t *hdl, const char *tofs,
3518
3570
boolean_t needagain , progress , recursive ;
3519
3571
const char * s1 , * s2 ;
3520
3572
3573
+ if (flags -> dryrun )
3574
+ return (0 );
3575
+
3521
3576
fromsnap = fnvlist_lookup_string (stream_nv , "fromsnap" );
3522
3577
3523
3578
recursive = (nvlist_lookup_boolean (stream_nv , "not_recursive" ) ==
3524
3579
ENOENT );
3525
3580
3526
- if (flags -> dryrun )
3527
- return (0 );
3528
-
3529
3581
again :
3530
3582
needagain = progress = B_FALSE ;
3531
3583
@@ -3999,9 +4051,9 @@ zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
3999
4051
stream_nv , stream_avl , NULL );
4000
4052
}
4001
4053
4002
- if (raw && softerr == 0 && * top_zfs != NULL ) {
4054
+ if (raw && softerr == 0 && * top_zfs != NULL && ! flags -> dryrun ) {
4003
4055
softerr = recv_fix_encryption_hierarchy (hdl , * top_zfs ,
4004
- stream_nv );
4056
+ stream_nv , stream_avl );
4005
4057
}
4006
4058
4007
4059
out :
0 commit comments