From eee9362a72cfd615e40928e86d61747683dc9dc6 Mon Sep 17 00:00:00 2001 From: George Amanakis Date: Thu, 12 Jan 2023 03:00:39 +0100 Subject: [PATCH] Activate filesystem features only in syncing context When activating filesystem features after receiving a snapshot, do so only in syncing context. Reviewed-by: Ryan Moeller Reviewed-by: Richard Yao Reviewed-by: Brian Behlendorf Signed-off-by: George Amanakis Closes #14304 Closes #14252 --- module/zfs/dmu_objset.c | 7 -- module/zfs/dsl_dataset.c | 22 +++-- tests/runfiles/common.run | 1 + tests/zfs-tests/tests/Makefile.am | 1 + .../rsend/send_encrypted_incremental.ksh | 93 +++++++++++++++++++ .../rsend/send_raw_large_blocks.ksh | 2 +- 6 files changed, 109 insertions(+), 17 deletions(-) create mode 100755 tests/zfs-tests/tests/functional/rsend/send_encrypted_incremental.ksh diff --git a/module/zfs/dmu_objset.c b/module/zfs/dmu_objset.c index 5083b1763412..2f18075ae658 100644 --- a/module/zfs/dmu_objset.c +++ b/module/zfs/dmu_objset.c @@ -2408,13 +2408,6 @@ dmu_objset_id_quota_upgrade_cb(objset_t *os) dmu_objset_userobjspace_present(os)) return (SET_ERROR(ENOTSUP)); - if (dmu_objset_userobjused_enabled(os)) - dmu_objset_ds(os)->ds_feature_activation[ - SPA_FEATURE_USEROBJ_ACCOUNTING] = (void *)B_TRUE; - if (dmu_objset_projectquota_enabled(os)) - dmu_objset_ds(os)->ds_feature_activation[ - SPA_FEATURE_PROJECT_QUOTA] = (void *)B_TRUE; - err = dmu_objset_space_upgrade(os); if (err) return (err); diff --git a/module/zfs/dsl_dataset.c b/module/zfs/dsl_dataset.c index dcb9ad6cccc9..57a58f88cec5 100644 --- a/module/zfs/dsl_dataset.c +++ b/module/zfs/dsl_dataset.c @@ -1761,16 +1761,20 @@ dsl_dataset_snapshot_sync_impl(dsl_dataset_t *ds, const char *snapname, /* * We are not allowed to dirty a filesystem when done receiving - * a snapshot. In this case the flag SPA_FEATURE_LARGE_BLOCKS will - * not be set and a subsequent encrypted raw send will fail. Hence - * activate this feature if needed here. + * a snapshot. In this case some flags such as SPA_FEATURE_LARGE_BLOCKS + * will not be set and a subsequent encrypted raw send will fail. Hence + * activate this feature if needed here. This needs to happen only in + * syncing context. */ - for (spa_feature_t f = 0; f < SPA_FEATURES; f++) { - if (zfeature_active(f, ds->ds_feature_activation[f]) && - !(zfeature_active(f, ds->ds_feature[f]))) { - dsl_dataset_activate_feature(dsobj, f, - ds->ds_feature_activation[f], tx); - ds->ds_feature[f] = ds->ds_feature_activation[f]; + if (dmu_tx_is_syncing(tx)) { + for (spa_feature_t f = 0; f < SPA_FEATURES; f++) { + if (zfeature_active(f, ds->ds_feature_activation[f]) && + !(zfeature_active(f, ds->ds_feature[f]))) { + dsl_dataset_activate_feature(dsobj, f, + ds->ds_feature_activation[f], tx); + ds->ds_feature[f] = + ds->ds_feature_activation[f]; + } } } diff --git a/tests/runfiles/common.run b/tests/runfiles/common.run index 1b42786e9d58..5350746dbd02 100644 --- a/tests/runfiles/common.run +++ b/tests/runfiles/common.run @@ -842,6 +842,7 @@ tests = ['recv_dedup', 'recv_dedup_encrypted_zvol', 'rsend_001_pos', 'send-c_recv_lz4_disabled', 'send-c_mixed_compression', 'send-c_stream_size_estimate', 'send-c_embedded_blocks', 'send-c_resume', 'send-cpL_varied_recsize', 'send-c_recv_dedup', 'send-L_toggle', + 'send_encrypted_incremental.ksh', 'send_encrypted_hierarchy', 'send_encrypted_props', 'send_encrypted_truncated_files', 'send_freeobjects', 'send_realloc_files', 'send_realloc_encrypted_files', 'send_spill_block', 'send_holds', diff --git a/tests/zfs-tests/tests/Makefile.am b/tests/zfs-tests/tests/Makefile.am index 32726acebf67..33f78e590876 100644 --- a/tests/zfs-tests/tests/Makefile.am +++ b/tests/zfs-tests/tests/Makefile.am @@ -1806,6 +1806,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/rsend/send-c_zstreamdump.ksh \ functional/rsend/send-cpL_varied_recsize.ksh \ functional/rsend/send_doall.ksh \ + functional/rsend/send_encrypted_incremental.ksh \ functional/rsend/send_encrypted_files.ksh \ functional/rsend/send_encrypted_hierarchy.ksh \ functional/rsend/send_encrypted_props.ksh \ diff --git a/tests/zfs-tests/tests/functional/rsend/send_encrypted_incremental.ksh b/tests/zfs-tests/tests/functional/rsend/send_encrypted_incremental.ksh new file mode 100755 index 000000000000..491ad55db411 --- /dev/null +++ b/tests/zfs-tests/tests/functional/rsend/send_encrypted_incremental.ksh @@ -0,0 +1,93 @@ +#!/bin/ksh -p +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/rsend/rsend.kshlib + +# +# Description: +# Incrementally receiving a snapshot to an encrypted filesystem succeeds. +# +# Strategy: +# 1) Create a pool and an encrypted fs +# 2) Create some files and snapshots +# 3) Send the first snapshot to a second encrypted as well as an +# unencrypted fs. +# 4) Incrementally send the second snapshot to the unencrypted fs. +# 5) Rollback the second encrypted fs to the first snapshot. +# 6) Incrementally send the second snapshot from the unencrypted to the +# second encrypted fs. +# 7) Incrementally send the third snapshot from the first encrypted to the +# unencrypted fs. +# 8) Incrementally send the third snapshot from the unencrypted to the second +# encrypted fs. +# + +verify_runnable "both" + +log_assert "Incrementally receiving a snapshot to an encrypted filesystem succeeds" + +function cleanup +{ + destroy_pool pool_lb + log_must rm -f $TESTDIR/vdev_a +} + +log_onexit cleanup + +typeset passphrase="password" +typeset passphrase2="password2" + +typeset file="/pool_lb/encryptme/$TESTFILE0" +typeset file1="/pool_lb/encryptme/$TESTFILE1" +typeset file2="/pool_lb/encryptme/$TESTFILE2" + +# Create pool +truncate -s $MINVDEVSIZE $TESTDIR/vdev_a +log_must zpool create -f pool_lb $TESTDIR/vdev_a +log_must eval "echo $passphrase > /pool_lb/pwd" +log_must eval "echo $passphrase2 > /pool_lb/pwd2" + +log_must zfs create -o encryption=on -o keyformat=passphrase \ + -o keylocation=file:///pool_lb/pwd pool_lb/encryptme +log_must dd if=/dev/urandom of=$file bs=1024 count=1024 +log_must zfs snapshot pool_lb/encryptme@snap1 +log_must dd if=/dev/urandom of=$file1 bs=1024 count=1024 +log_must zfs snapshot pool_lb/encryptme@snap2 +log_must dd if=/dev/urandom of=$file2 bs=1024 count=1024 +log_must zfs snapshot pool_lb/encryptme@snap3 +log_must eval "zfs send -Lc pool_lb/encryptme@snap1 | zfs recv \ + -o encryption=on -o keyformat=passphrase -o keylocation=file:///pool_lb/pwd2 \ + pool_lb/encrypttwo" +log_must eval "zfs send -Lc pool_lb/encryptme@snap1 | zfs recv \ + pool_lb/unencryptme" +log_must eval "zfs send -Lc -i pool_lb/encryptme@{snap1,snap2} | zfs recv \ + pool_lb/unencryptme" +log_must zfs rollback pool_lb/encrypttwo@snap1 +log_must eval "zfs send -Lc -i pool_lb/unencryptme@{snap1,snap2} | zfs recv \ + pool_lb/encrypttwo" +log_must eval "zfs send -Lc -i pool_lb/encryptme@{snap2,snap3} | zfs recv \ + pool_lb/unencryptme" +log_must eval "zfs send -Lc -i pool_lb/unencryptme@{snap2,snap3} | zfs recv \ + -F pool_lb/encrypttwo" + +log_pass "Incrementally receiving a snapshot to an encrypted filesystem succeeds" diff --git a/tests/zfs-tests/tests/functional/rsend/send_raw_large_blocks.ksh b/tests/zfs-tests/tests/functional/rsend/send_raw_large_blocks.ksh index 39e93a7df3c2..48a76fca63e1 100755 --- a/tests/zfs-tests/tests/functional/rsend/send_raw_large_blocks.ksh +++ b/tests/zfs-tests/tests/functional/rsend/send_raw_large_blocks.ksh @@ -49,7 +49,7 @@ raw_backup=$TEST_BASE_DIR/raw_backup function cleanup { log_must rm -f $backup $raw_backup $ibackup $unc_backup - destroy_pool pool_lb/fs + destroy_pool pool_lb log_must rm -f $TESTDIR/vdev_a }