summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/lib/libzfs/common/libzfs_crypto.c42
-rw-r--r--usr/src/lib/libzfs/common/libzfs_dataset.c13
-rw-r--r--usr/src/lib/libzfs/common/libzfs_sendrecv.c74
-rw-r--r--usr/src/pkg/manifests/system-test-zfstest.mf3
-rw-r--r--usr/src/test/zfs-tests/include/blkdev.shlib449
-rw-r--r--usr/src/test/zfs-tests/include/default.cfg7
-rw-r--r--usr/src/test/zfs-tests/include/libtest.shlib14
-rw-r--r--usr/src/test/zfs-tests/runfiles/delphix.run2
-rw-r--r--usr/src/test/zfs-tests/runfiles/omnios.run2
-rw-r--r--usr/src/test/zfs-tests/runfiles/openindiana.run2
-rw-r--r--usr/src/test/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_encrypted.ksh20
-rw-r--r--usr/src/test/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_to_encrypted.ksh19
-rw-r--r--usr/src/test/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_to_encrypted.ksh14
-rwxr-xr-xusr/src/test/zfs-tests/tests/functional/rsend/send-wDR_encrypted_zvol.ksh103
-rw-r--r--usr/src/uts/common/fs/zfs/arc.c45
-rw-r--r--usr/src/uts/common/fs/zfs/dbuf.c1
-rw-r--r--usr/src/uts/common/fs/zfs/dmu.c9
-rw-r--r--usr/src/uts/common/fs/zfs/dmu_objset.c7
-rw-r--r--usr/src/uts/common/fs/zfs/dmu_recv.c32
-rw-r--r--usr/src/uts/common/fs/zfs/dsl_crypt.c44
-rw-r--r--usr/src/uts/common/fs/zfs/sys/dsl_crypt.h1
21 files changed, 682 insertions, 221 deletions
diff --git a/usr/src/lib/libzfs/common/libzfs_crypto.c b/usr/src/lib/libzfs/common/libzfs_crypto.c
index 4533ed8111..7c16207a58 100644
--- a/usr/src/lib/libzfs/common/libzfs_crypto.c
+++ b/usr/src/lib/libzfs/common/libzfs_crypto.c
@@ -787,14 +787,6 @@ zfs_crypto_create(libzfs_handle_t *hdl, char *parent_name, nvlist_t *props,
pcrypt = ZIO_CRYPT_OFF;
}
- /* Check for encryption being explicitly truned off */
- if (crypt == ZIO_CRYPT_OFF && pcrypt != ZIO_CRYPT_OFF) {
- ret = EINVAL;
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "Invalid encryption value. Dataset must be encrypted."));
- goto out;
- }
-
/* Get the inherited encryption property if we don't have it locally */
if (!local_crypt)
crypt = pcrypt;
@@ -885,10 +877,6 @@ int
zfs_crypto_clone_check(libzfs_handle_t *hdl, zfs_handle_t *origin_zhp,
char *parent_name, nvlist_t *props)
{
- int ret;
- zfs_handle_t *pzhp = NULL;
- uint64_t pcrypt, ocrypt;
-
/*
* No encryption properties should be specified. They will all be
* inherited from the origin dataset.
@@ -897,40 +885,12 @@ zfs_crypto_clone_check(libzfs_handle_t *hdl, zfs_handle_t *origin_zhp,
nvlist_exists(props, zfs_prop_to_name(ZFS_PROP_KEYLOCATION)) ||
nvlist_exists(props, zfs_prop_to_name(ZFS_PROP_ENCRYPTION)) ||
nvlist_exists(props, zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS))) {
- ret = EINVAL;
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"Encryption properties must inherit from origin dataset."));
- goto out;
- }
-
- /* get a reference to parent dataset, should never be NULL */
- pzhp = make_dataset_handle(hdl, parent_name);
- if (pzhp == NULL) {
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "Failed to lookup parent."));
- return (ENOENT);
- }
-
- /* Lookup parent's crypt */
- pcrypt = zfs_prop_get_int(pzhp, ZFS_PROP_ENCRYPTION);
- ocrypt = zfs_prop_get_int(origin_zhp, ZFS_PROP_ENCRYPTION);
-
- /* all children of encrypted parents must be encrypted */
- if (pcrypt != ZIO_CRYPT_OFF && ocrypt == ZIO_CRYPT_OFF) {
- ret = EINVAL;
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "Cannot create unencrypted clone as a child "
- "of encrypted parent."));
- goto out;
+ return (EINVAL);
}
- zfs_close(pzhp);
return (0);
-
-out:
- if (pzhp != NULL)
- zfs_close(pzhp);
- return (ret);
}
typedef struct loadkeys_cbdata {
diff --git a/usr/src/lib/libzfs/common/libzfs_dataset.c b/usr/src/lib/libzfs/common/libzfs_dataset.c
index 117e414a9a..628125e38b 100644
--- a/usr/src/lib/libzfs/common/libzfs_dataset.c
+++ b/usr/src/lib/libzfs/common/libzfs_dataset.c
@@ -4494,16 +4494,9 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive,
"with the new name"));
(void) zfs_error(hdl, EZFS_EXISTS, errbuf);
} else if (errno == EACCES) {
- if (zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION) ==
- ZIO_CRYPT_OFF) {
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "cannot rename an unencrypted dataset to "
- "be a decendent of an encrypted one"));
- } else {
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "cannot move encryption child outside of "
- "its encryption root"));
- }
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "cannot move encrypted child outside of "
+ "its encryption root"));
(void) zfs_error(hdl, EZFS_CRYPTOFAILED, errbuf);
} else {
(void) zfs_standard_error(zhp->zfs_hdl, errno, errbuf);
diff --git a/usr/src/lib/libzfs/common/libzfs_sendrecv.c b/usr/src/lib/libzfs/common/libzfs_sendrecv.c
index c933a24e89..a25574cc19 100644
--- a/usr/src/lib/libzfs/common/libzfs_sendrecv.c
+++ b/usr/src/lib/libzfs/common/libzfs_sendrecv.c
@@ -63,7 +63,7 @@ extern void zfs_setprop_error(libzfs_handle_t *, zfs_prop_t, int, char *);
static int zfs_receive_impl(libzfs_handle_t *, const char *, const char *,
recvflags_t *, int, const char *, nvlist_t *, avl_tree_t *, char **, int,
- uint64_t *, const char *);
+ uint64_t *, const char *, nvlist_t *);
static int guid_to_name(libzfs_handle_t *, const char *,
uint64_t, boolean_t, char *);
@@ -2645,7 +2645,7 @@ recv_fix_encryption_hierarchy(libzfs_handle_t *hdl, const char *destname,
is_clone = zhp->zfs_dmustats.dds_origin[0] != '\0';
(void) zfs_crypto_get_encryption_root(zhp, &is_encroot, NULL);
- /* we don't need to do anything for unencrypted filesystems */
+ /* we don't need to do anything for unencrypted datasets */
if (crypt == ZIO_CRYPT_OFF) {
zfs_close(zhp);
continue;
@@ -2997,7 +2997,8 @@ again:
static int
zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
recvflags_t *flags, dmu_replay_record_t *drr, zio_cksum_t *zc,
- char **top_zfs, int cleanup_fd, uint64_t *action_handlep)
+ char **top_zfs, int cleanup_fd, uint64_t *action_handlep,
+ nvlist_t *cmdprops)
{
nvlist_t *stream_nv = NULL;
avl_tree_t *stream_avl = NULL;
@@ -3174,7 +3175,7 @@ zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
*/
error = zfs_receive_impl(hdl, destname, NULL, flags, fd,
sendfs, stream_nv, stream_avl, top_zfs, cleanup_fd,
- action_handlep, sendsnap);
+ action_handlep, sendsnap, cmdprops);
if (error == ENODATA) {
error = 0;
break;
@@ -3350,7 +3351,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
const char *originsnap, recvflags_t *flags, dmu_replay_record_t *drr,
dmu_replay_record_t *drr_noswap, const char *sendfs, nvlist_t *stream_nv,
avl_tree_t *stream_avl, char **top_zfs, int cleanup_fd,
- uint64_t *action_handlep, const char *finalsnap)
+ uint64_t *action_handlep, const char *finalsnap, nvlist_t *cmdprops)
{
zfs_cmd_t zc = { 0 };
time_t begin_time;
@@ -3371,6 +3372,8 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
char *snapname = NULL;
nvlist_t *props = NULL;
char tmp_keylocation[MAXNAMELEN];
+ nvlist_t *rcvprops = NULL; /* props received from the send stream */
+ nvlist_t *oxprops = NULL; /* override (-o) and exclude (-x) props */
begin_time = time(NULL);
bzero(tmp_keylocation, MAXNAMELEN);
@@ -3721,8 +3724,6 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
zfs_close(zhp);
} else {
- zfs_handle_t *zhp;
-
/*
* Destination filesystem does not exist. Therefore we better
* be creating a new filesystem (either from a full backup, or
@@ -3752,39 +3753,6 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
goto out;
}
- /*
- * It is invalid to receive a properties stream that was
- * unencrypted on the send side as a child of an encrypted
- * parent. Technically there is nothing preventing this, but
- * it would mean that the encryption=off property which is
- * locally set on the send side would not be received correctly.
- * We can infer encryption=off if the stream is not raw and
- * properties were included since the send side will only ever
- * send the encryption property in a raw nvlist header.
- */
- if (!raw && props != NULL) {
- uint64_t crypt;
-
- zhp = zfs_open(hdl, zc.zc_name, ZFS_TYPE_DATASET);
- if (zhp == NULL) {
- err = zfs_error(hdl, EZFS_BADRESTORE,
- errbuf);
- goto out;
- }
-
- crypt = zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION);
- zfs_close(zhp);
-
- if (crypt != ZIO_CRYPT_OFF) {
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "parent '%s' must not be encrypted to "
- "receive unencrypted property"),
- zc.zc_name);
- err = zfs_error(hdl, EZFS_BADPROP, errbuf);
- goto out;
- }
- }
-
newfs = B_TRUE;
*cp = '/';
}
@@ -3807,6 +3775,24 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
goto out;
}
+ /*
+ * When sending with properties (zfs send -p), the encryption property
+ * is not included because it is a SETONCE property and therefore
+ * treated as read only. However, we are always able to determine its
+ * value because raw sends will include it in the DRR_BDEGIN payload
+ * and non-raw sends with properties are not allowed for encrypted
+ * datasets. Therefore, if this is a non-raw properties stream, we can
+ * infer that the value should be ZIO_CRYPT_OFF and manually add that
+ * to the received properties.
+ */
+ if (stream_wantsnewfs && !raw && rcvprops != NULL &&
+ !nvlist_exists(cmdprops, zfs_prop_to_name(ZFS_PROP_ENCRYPTION))) {
+ if (oxprops == NULL)
+ oxprops = fnvlist_alloc();
+ fnvlist_add_uint64(oxprops,
+ zfs_prop_to_name(ZFS_PROP_ENCRYPTION), ZIO_CRYPT_OFF);
+ }
+
zc.zc_nvlist_dst = (uint64_t)(uintptr_t)prop_errbuf;
zc.zc_nvlist_dst_size = sizeof (prop_errbuf);
zc.zc_cleanup_fd = cleanup_fd;
@@ -4080,7 +4066,7 @@ static int
zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap,
const char *originsnap, recvflags_t *flags, int infd, const char *sendfs,
nvlist_t *stream_nv, avl_tree_t *stream_avl, char **top_zfs, int cleanup_fd,
- uint64_t *action_handlep, const char *finalsnap)
+ uint64_t *action_handlep, const char *finalsnap, nvlist_t *cmdprops)
{
int err;
dmu_replay_record_t drr, drr_noswap;
@@ -4182,12 +4168,12 @@ zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap,
}
return (zfs_receive_one(hdl, infd, tosnap, originsnap, flags,
&drr, &drr_noswap, sendfs, stream_nv, stream_avl, top_zfs,
- cleanup_fd, action_handlep, finalsnap));
+ cleanup_fd, action_handlep, finalsnap, cmdprops));
} else {
assert(DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) ==
DMU_COMPOUNDSTREAM);
return (zfs_receive_package(hdl, infd, tosnap, flags, &drr,
- &zcksum, top_zfs, cleanup_fd, action_handlep));
+ &zcksum, top_zfs, cleanup_fd, action_handlep, cmdprops));
}
}
@@ -4217,7 +4203,7 @@ zfs_receive(libzfs_handle_t *hdl, const char *tosnap, nvlist_t *props,
VERIFY(cleanup_fd >= 0);
err = zfs_receive_impl(hdl, tosnap, originsnap, flags, infd, NULL, NULL,
- stream_avl, &top_zfs, cleanup_fd, &action_handle, NULL);
+ stream_avl, &top_zfs, cleanup_fd, &action_handle, NULL, props);
VERIFY(0 == close(cleanup_fd));
diff --git a/usr/src/pkg/manifests/system-test-zfstest.mf b/usr/src/pkg/manifests/system-test-zfstest.mf
index c0a85644aa..e2a3c9fa2f 100644
--- a/usr/src/pkg/manifests/system-test-zfstest.mf
+++ b/usr/src/pkg/manifests/system-test-zfstest.mf
@@ -196,6 +196,7 @@ file path=opt/zfs-tests/bin/rm_lnkcnt_zero_file mode=0555
file path=opt/zfs-tests/bin/zfstest mode=0555
file path=opt/zfs-tests/callbacks/zfs_dbgmsg mode=0555
file path=opt/zfs-tests/callbacks/zfs_mmp mode=0555
+file path=opt/zfs-tests/include/blkdev.shlib mode=0444
file path=opt/zfs-tests/include/commands.cfg mode=0444
file path=opt/zfs-tests/include/default.cfg mode=0444
file path=opt/zfs-tests/include/libtest.shlib mode=0444
@@ -2806,6 +2807,8 @@ file path=opt/zfs-tests/tests/functional/rsend/send-c_volume mode=0555
file path=opt/zfs-tests/tests/functional/rsend/send-c_zstreamdump mode=0555
file path=opt/zfs-tests/tests/functional/rsend/send-cpL_varied_recsize \
mode=0555
+file path=opt/zfs-tests/tests/functional/rsend/send-wDR_encrypted_zvol \
+ mode=0555
file path=opt/zfs-tests/tests/functional/rsend/send_encrypted_files mode=0555
file path=opt/zfs-tests/tests/functional/rsend/send_encrypted_hierarchy \
mode=0555
diff --git a/usr/src/test/zfs-tests/include/blkdev.shlib b/usr/src/test/zfs-tests/include/blkdev.shlib
new file mode 100644
index 0000000000..bf4bfbbd87
--- /dev/null
+++ b/usr/src/test/zfs-tests/include/blkdev.shlib
@@ -0,0 +1,449 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+# Copyright 2016 Nexenta Systems, Inc.
+# Copyright (c) 2016, 2017 by Intel Corporation. All rights reserved.
+# Copyright (c) 2017 Lawrence Livermore National Security, LLC.
+# Copyright (c) 2017 Datto Inc.
+# Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
+#
+
+#
+# Returns SCSI host number for the given disk
+#
+function get_scsi_host #disk
+{
+ typeset disk=$1
+ ls /sys/block/${disk}/device/scsi_device | cut -d : -f 1
+}
+
+#
+# Cause a scan of all scsi host adapters by default
+#
+# $1 optional host number
+#
+function scan_scsi_hosts
+{
+ typeset hostnum=${1}
+
+ if is_linux; then
+ if [[ -z $hostnum ]]; then
+ for host in /sys/class/scsi_host/host*; do
+ log_must eval "echo '- - -' > $host/scan"
+ done
+ else
+ log_must eval \
+ "echo /sys/class/scsi_host/host$hostnum/scan" \
+ > /dev/null
+ log_must eval \
+ "echo '- - -' > /sys/class/scsi_host/host$hostnum/scan"
+ fi
+ fi
+}
+
+#
+# Wait for newly created block devices to have their minors created.
+#
+function block_device_wait
+{
+ if is_linux; then
+ udevadm trigger
+ udevadm settle
+ fi
+}
+
+#
+# Check if the given device is physical device
+#
+function is_physical_device #device
+{
+ typeset device=${1#$DEV_DSKDIR}
+ device=${device#$DEV_RDSKDIR}
+
+ if is_linux; then
+ [[ -b "$DEV_DSKDIR/$device" ]] && \
+ [[ -f /sys/module/loop/parameters/max_part ]]
+ return $?
+ else
+ echo $device | egrep "^c[0-F]+([td][0-F]+)+$" > /dev/null 2>&1
+ return $?
+ fi
+}
+
+#
+# Check if the given device is a real device (ie SCSI device)
+#
+function is_real_device #disk
+{
+ typeset disk=$1
+ [[ -z $disk ]] && log_fail "No argument for disk given."
+
+ if is_linux; then
+ lsblk $DEV_RDSKDIR/$disk -o TYPE 2>/dev/null | \
+ egrep disk >/dev/null
+ return $?
+ fi
+}
+
+#
+# Check if the given device is a loop device
+#
+function is_loop_device #disk
+{
+ typeset disk=$1
+ [[ -z $disk ]] && log_fail "No argument for disk given."
+
+ if is_linux; then
+ lsblk $DEV_RDSKDIR/$disk -o TYPE 2>/dev/null | \
+ egrep loop >/dev/null
+ return $?
+ fi
+}
+
+#
+# Check if the given device is a multipath device and if there is a symbolic
+# link to a device mapper and to a disk
+# Currently no support for dm devices alone without multipath
+#
+function is_mpath_device #disk
+{
+ typeset disk=$1
+ [[ -z $disk ]] && log_fail "No argument for disk given."
+
+ if is_linux; then
+ lsblk $DEV_MPATHDIR/$disk -o TYPE 2>/dev/null | \
+ egrep mpath >/dev/null
+ if (($? == 0)); then
+ readlink $DEV_MPATHDIR/$disk > /dev/null 2>&1
+ return $?
+ else
+ return $?
+ fi
+ fi
+}
+
+# Set the slice prefix for disk partitioning depending
+# on whether the device is a real, multipath, or loop device.
+# Currently all disks have to be of the same type, so only
+# checks first disk to determine slice prefix.
+#
+function set_slice_prefix
+{
+ typeset disk
+ typeset -i i=0
+
+ if is_linux; then
+ while (( i < $DISK_ARRAY_NUM )); do
+ disk="$(echo $DISKS | nawk '{print $(i + 1)}')"
+ if ( is_mpath_device $disk ) && [[ -z $(echo $disk | awk 'substr($1,18,1)\
+ ~ /^[[:digit:]]+$/') ]] || ( is_real_device $disk ); then
+ export SLICE_PREFIX=""
+ return 0
+ elif ( is_mpath_device $disk || is_loop_device \
+ $disk ); then
+ export SLICE_PREFIX="p"
+ return 0
+ else
+ log_fail "$disk not supported for partitioning."
+ fi
+ (( i = i + 1))
+ done
+ fi
+}
+
+#
+# Set the directory path of the listed devices in $DISK_ARRAY_NUM
+# Currently all disks have to be of the same type, so only
+# checks first disk to determine device directory
+# default = /dev (linux)
+# real disk = /dev (linux)
+# multipath device = /dev/mapper (linux)
+#
+function set_device_dir
+{
+ typeset disk
+ typeset -i i=0
+
+ if is_linux; then
+ while (( i < $DISK_ARRAY_NUM )); do
+ disk="$(echo $DISKS | nawk '{print $(i + 1)}')"
+ if is_mpath_device $disk; then
+ export DEV_DSKDIR=$DEV_MPATHDIR
+ return 0
+ else
+ export DEV_DSKDIR=$DEV_RDSKDIR
+ return 0
+ fi
+ (( i = i + 1))
+ done
+ else
+ export DEV_DSKDIR=$DEV_RDSKDIR
+ fi
+}
+
+#
+# Get the directory path of given device
+#
+function get_device_dir #device
+{
+ typeset device=$1
+
+ if ! $(is_physical_device $device) ; then
+ if [[ $device != "/" ]]; then
+ device=${device%/*}
+ fi
+ if [[ -b "$DEV_DSKDIR/$device" ]]; then
+ device="$DEV_DSKDIR"
+ fi
+ echo $device
+ else
+ echo "$DEV_DSKDIR"
+ fi
+}
+
+#
+# Get persistent name for given disk
+#
+function get_persistent_disk_name #device
+{
+ typeset device=$1
+ typeset dev_id
+
+ if is_linux; then
+ if is_real_device $device; then
+ dev_id="$(udevadm info -q all -n $DEV_DSKDIR/$device \
+ | egrep disk/by-id | nawk '{print $2; exit}' \
+ | nawk -F / '{print $3}')"
+ echo $dev_id
+ elif is_mpath_device $device; then
+ dev_id="$(udevadm info -q all -n $DEV_DSKDIR/$device \
+ | egrep disk/by-id/dm-uuid \
+ | nawk '{print $2; exit}' \
+ | nawk -F / '{print $3}')"
+ echo $dev_id
+ else
+ echo $device
+ fi
+ else
+ echo $device
+ fi
+}
+
+#
+# Online or offline a disk on the system
+#
+# First checks state of disk. Test will fail if disk is not properly onlined
+# or offlined. Online is a full rescan of SCSI disks by echoing to every
+# host entry.
+#
+function on_off_disk # disk state{online,offline} host
+{
+ typeset disk=$1
+ typeset state=$2
+ typeset host=$3
+
+ [[ -z $disk ]] || [[ -z $state ]] && \
+ log_fail "Arguments invalid or missing"
+
+ if is_linux; then
+ if [[ $state == "offline" ]] && ( is_mpath_device $disk ); then
+ dm_name="$(readlink $DEV_DSKDIR/$disk \
+ | nawk -F / '{print $2}')"
+ slave="$(ls /sys/block/${dm_name}/slaves \
+ | nawk '{print $1}')"
+ while [[ -n $slave ]]; do
+ #check if disk is online
+ lsscsi | egrep $slave > /dev/null
+ if (($? == 0)); then
+ slave_dir="/sys/block/${dm_name}"
+ slave_dir+="/slaves/${slave}/device"
+ ss="${slave_dir}/state"
+ sd="${slave_dir}/delete"
+ log_must eval "echo 'offline' > ${ss}"
+ log_must eval "echo '1' > ${sd}"
+ lsscsi | egrep $slave > /dev/null
+ if (($? == 0)); then
+ log_fail "Offlining" \
+ "$disk failed"
+ fi
+ fi
+ slave="$(ls /sys/block/$dm_name/slaves \
+ 2>/dev/null | nawk '{print $1}')"
+ done
+ elif [[ $state == "offline" ]] && ( is_real_device $disk ); then
+ #check if disk is online
+ lsscsi | egrep $disk > /dev/null
+ if (($? == 0)); then
+ dev_state="/sys/block/$disk/device/state"
+ dev_delete="/sys/block/$disk/device/delete"
+ log_must eval "echo 'offline' > ${dev_state}"
+ log_must eval "echo '1' > ${dev_delete}"
+ lsscsi | egrep $disk > /dev/null
+ if (($? == 0)); then
+ log_fail "Offlining $disk" \
+ "failed"
+ fi
+ else
+ log_note "$disk is already offline"
+ fi
+ elif [[ $state == "online" ]]; then
+ #force a full rescan
+ scan_scsi_hosts $host
+ block_device_wait
+ if is_mpath_device $disk; then
+ dm_name="$(readlink $DEV_DSKDIR/$disk \
+ | nawk -F / '{print $2}')"
+ slave="$(ls /sys/block/$dm_name/slaves \
+ | nawk '{print $1}')"
+ lsscsi | egrep $slave > /dev/null
+ if (($? != 0)); then
+ log_fail "Onlining $disk failed"
+ fi
+ elif is_real_device $disk; then
+ block_device_wait
+ typeset -i retries=0
+ while ! lsscsi | egrep -q $disk; do
+ if (( $retries > 2 )); then
+ log_fail "Onlining $disk failed"
+ break
+ fi
+ (( ++retries ))
+ sleep 1
+ done
+ else
+ log_fail "$disk is not a real dev"
+ fi
+ else
+ log_fail "$disk failed to $state"
+ fi
+ fi
+}
+
+#
+# Simulate disk removal
+#
+function remove_disk #disk
+{
+ typeset disk=$1
+ on_off_disk $disk "offline"
+ block_device_wait
+}
+
+#
+# Simulate disk insertion for the given SCSI host
+#
+function insert_disk #disk scsi_host
+{
+ typeset disk=$1
+ typeset scsi_host=$2
+ on_off_disk $disk "online" $scsi_host
+ block_device_wait
+}
+
+#
+# Load scsi_debug module with specified parameters
+# $blksz can be either one of: < 512b | 512e | 4Kn >
+#
+function load_scsi_debug # dev_size_mb add_host num_tgts max_luns blksz
+{
+ typeset devsize=$1
+ typeset hosts=$2
+ typeset tgts=$3
+ typeset luns=$4
+ typeset blksz=$5
+
+ [[ -z $devsize ]] || [[ -z $hosts ]] || [[ -z $tgts ]] || \
+ [[ -z $luns ]] || [[ -z $blksz ]] && \
+ log_fail "Arguments invalid or missing"
+
+ case "$5" in
+ '512b')
+ typeset sector=512
+ typeset blkexp=0
+ ;;
+ '512e')
+ typeset sector=512
+ typeset blkexp=3
+ ;;
+ '4Kn')
+ typeset sector=4096
+ typeset blkexp=0
+ ;;
+ *) log_fail "Unsupported blksz value: $5" ;;
+ esac
+
+ if is_linux; then
+ modprobe -n scsi_debug
+ if (($? != 0)); then
+ log_unsupported "Platform does not have scsi_debug"
+ "module"
+ fi
+ lsmod | egrep scsi_debug > /dev/null
+ if (($? == 0)); then
+ log_fail "scsi_debug module already installed"
+ else
+ log_must modprobe scsi_debug dev_size_mb=$devsize \
+ add_host=$hosts num_tgts=$tgts max_luns=$luns \
+ sector_size=$sector physblk_exp=$blkexp
+ block_device_wait
+ lsscsi | egrep scsi_debug > /dev/null
+ if (($? == 1)); then
+ log_fail "scsi_debug module install failed"
+ fi
+ fi
+ fi
+}
+
+#
+# Unload scsi_debug module, if needed.
+#
+function unload_scsi_debug
+{
+ log_must_retry "in use" 5 modprobe -r scsi_debug
+}
+
+#
+# Get scsi_debug device name.
+# Returns basename of scsi_debug device (for example "sdb").
+#
+function get_debug_device
+{
+ for i in {1..10} ; do
+ val=$(lsscsi | nawk '/scsi_debug/ {print $6; exit}' | cut -d / -f3)
+
+ # lsscsi can take time to settle
+ if [ "$val" != "-" ] ; then
+ break
+ fi
+ sleep 1
+ done
+ echo "$val"
+}
+
+#
+# Get actual devices used by the pool (i.e. linux sdb1 not sdb).
+#
+function get_pool_devices #testpool #devdir
+{
+ typeset testpool=$1
+ typeset devdir=$2
+ typeset out=""
+
+ if is_linux; then
+ out=$(zpool status -P $testpool |grep ${devdir} | awk '{print $1}')
+ out=$(echo $out | sed -e "s|${devdir}/||g" | tr '\n' ' ')
+ fi
+ echo $out
+}
diff --git a/usr/src/test/zfs-tests/include/default.cfg b/usr/src/test/zfs-tests/include/default.cfg
index cf61660b76..a4e0e28bee 100644
--- a/usr/src/test/zfs-tests/include/default.cfg
+++ b/usr/src/test/zfs-tests/include/default.cfg
@@ -141,3 +141,10 @@ export ZFS_ALL_VERSIONS="1 2 3 4 5"
for i in $ZFS_ALL_VERSIONS; do
eval 'export ZFS_VERSION_$i="v${i}-fs"'
done
+
+export ZVOL_DEVDIR="/dev/zvol/dsk"
+export ZVOL_RDEVDIR="/dev/zvol/rdsk"
+export DEV_DSKDIR="/dev/dsk"
+export DEV_RDSKDIR="/dev/rdsk"
+
+export NEWFS_DEFAULT_FS="ufs"
diff --git a/usr/src/test/zfs-tests/include/libtest.shlib b/usr/src/test/zfs-tests/include/libtest.shlib
index bedd71c4b4..8bced82ee1 100644
--- a/usr/src/test/zfs-tests/include/libtest.shlib
+++ b/usr/src/test/zfs-tests/include/libtest.shlib
@@ -28,6 +28,20 @@
#
. ${STF_TOOLS}/contrib/include/logapi.shlib
+. ${STF_SUITE}/include/blkdev.shlib
+
+# Determine if this is a Linux test system
+#
+# Return 0 if platform Linux, 1 if otherwise
+
+function is_linux
+{
+ if [[ $(uname -o) == "GNU/Linux" ]]; then
+ return 0
+ else
+ return 1
+ fi
+}
# Determine whether a dataset is mounted
#
diff --git a/usr/src/test/zfs-tests/runfiles/delphix.run b/usr/src/test/zfs-tests/runfiles/delphix.run
index fb5c8e7bbe..c1563223ec 100644
--- a/usr/src/test/zfs-tests/runfiles/delphix.run
+++ b/usr/src/test/zfs-tests/runfiles/delphix.run
@@ -606,7 +606,7 @@ tests = ['rsend_001_pos', 'rsend_002_pos', 'rsend_003_pos', 'rsend_004_pos',
'send-c_recv_dedup', 'send_encrypted_files', 'send_encrypted_hierarchy',
'send_encrypted_truncated_files',
'send_realloc_encrypted_files',
- 'send_mixed_raw']
+ 'send_mixed_raw', 'send-wDR_encrypted_zvol']
[/opt/zfs-tests/tests/functional/scrub_mirror]
tests = ['scrub_mirror_001_pos', 'scrub_mirror_002_pos',
diff --git a/usr/src/test/zfs-tests/runfiles/omnios.run b/usr/src/test/zfs-tests/runfiles/omnios.run
index 5d3571307e..8c26d6dfbd 100644
--- a/usr/src/test/zfs-tests/runfiles/omnios.run
+++ b/usr/src/test/zfs-tests/runfiles/omnios.run
@@ -605,7 +605,7 @@ tests = ['rsend_001_pos', 'rsend_002_pos', 'rsend_003_pos', 'rsend_004_pos',
'send-c_recv_dedup', 'send_encrypted_files', 'send_encrypted_hierarchy',
'send_encrypted_truncated_files',
'send_realloc_encrypted_files',
- 'send_mixed_raw']
+ 'send_mixed_raw', 'send-wDR_encrypted_zvol']
[/opt/zfs-tests/tests/functional/scrub_mirror]
tests = ['scrub_mirror_001_pos', 'scrub_mirror_002_pos',
diff --git a/usr/src/test/zfs-tests/runfiles/openindiana.run b/usr/src/test/zfs-tests/runfiles/openindiana.run
index 451852e863..5ee4230f66 100644
--- a/usr/src/test/zfs-tests/runfiles/openindiana.run
+++ b/usr/src/test/zfs-tests/runfiles/openindiana.run
@@ -605,7 +605,7 @@ tests = ['rsend_001_pos', 'rsend_002_pos', 'rsend_003_pos', 'rsend_004_pos',
'send-c_recv_dedup', 'send_encrypted_files', 'send_encrypted_hierarchy',
'send_encrypted_truncated_files',
'send_realloc_encrypted_files',
- 'send_mixed_raw']
+ 'send_mixed_raw', 'send-wDR_encrypted_zvol']
[/opt/zfs-tests/tests/functional/scrub_mirror]
tests = ['scrub_mirror_001_pos', 'scrub_mirror_002_pos',
diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_encrypted.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_encrypted.ksh
index 9d5ecab0df..7e5072f0d5 100644
--- a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_encrypted.ksh
+++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_encrypted.ksh
@@ -51,10 +51,10 @@
# yes unspec 0 1 no no keyformat specified
# yes unspec 1 0 yes new encryption root, crypt inherited
# yes unspec 1 1 yes new encryption root, crypt inherited
-# yes off 0 0 no unencrypted child of encrypted parent
-# yes off 0 1 no unencrypted child of encrypted parent
-# yes off 1 0 no unencrypted child of encrypted parent
-# yes off 1 1 no unencrypted child of encrypted parent
+# yes off 0 0 yes unencrypted child of encrypted parent
+# yes off 0 1 no keylocation given, but crypt off
+# yes off 1 0 no keyformat given, but crypt off
+# yes off 1 1 no keyformat given, but crypt off
# yes on 0 0 yes inherited encryption, local crypt
# yes on 0 1 no no keyformat specified for new key
# yes on 1 0 yes new encryption root
@@ -113,7 +113,9 @@ log_must eval "echo $PASSPHRASE | zfs create -o keyformat=passphrase" \
log_must eval "echo $PASSPHRASE | zfs create -o keyformat=passphrase" \
"-o keylocation=prompt $TESTPOOL/$TESTFS2/c4"
-log_mustnot zfs create -o encryption=off $TESTPOOL/$TESTFS2/c5
+log_must zfs create -o encryption=off $TESTPOOL/$TESTFS2/c5
+log_must test "$(get_prop 'encryption' $TESTPOOL/$TESTFS2/c5)" == "off"
+
log_mustnot zfs create -o encryption=off -o keylocation=prompt \
$TESTPOOL/$TESTFS2/c5
log_mustnot zfs create -o encryption=off -o keyformat=passphrase \
@@ -122,13 +124,13 @@ log_mustnot zfs create -o encryption=off -o keyformat=passphrase \
-o keylocation=prompt $TESTPOOL/$TESTFS2/c5
log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
- "$TESTPOOL/$TESTFS2/c5"
+ "$TESTPOOL/$TESTFS2/c6"
log_mustnot zfs create -o encryption=on -o keylocation=prompt \
- $TESTPOOL/$TESTFS2/c6
+ $TESTPOOL/$TESTFS2/c7
log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
- "-o keyformat=passphrase $TESTPOOL/$TESTFS2/c6"
+ "-o keyformat=passphrase $TESTPOOL/$TESTFS2/c7"
log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
- "-o keyformat=passphrase -o keylocation=prompt $TESTPOOL/$TESTFS2/c7"
+ "-o keyformat=passphrase -o keylocation=prompt $TESTPOOL/$TESTFS2/c8"
log_pass "ZFS creates datasets only if they have a valid combination of" \
"encryption properties set."
diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_to_encrypted.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_to_encrypted.ksh
index 57896c6fd3..3ce5ddc36c 100644
--- a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_to_encrypted.ksh
+++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_to_encrypted.ksh
@@ -46,7 +46,7 @@ function cleanup
log_onexit cleanup
-log_assert "ZFS should receive to an encrypted child dataset"
+log_assert "ZFS should receive encrypted filesystems into child dataset"
typeset passphrase="password"
typeset snap="$TESTPOOL/$TESTFS@snap"
@@ -57,14 +57,21 @@ log_must zfs snapshot $snap
log_must eval "echo $passphrase | zfs create -o encryption=on" \
"-o keyformat=passphrase $TESTPOOL/$TESTFS1"
+# XXX - on illumos we're currently conflicting on mount prop
+log_must zfs set mountpoint=none $TESTPOOL/$TESTFS
+
log_note "Verifying ZFS will receive to an encrypted child"
log_must eval "zfs send $snap | zfs receive $TESTPOOL/$TESTFS1/c1"
-log_note "Verifying 'send -p' will not receive to an encrypted child"
-log_mustnot eval "zfs send -p $snap | zfs receive $TESTPOOL/$TESTFS1/c2"
+log_note "Verifying 'send -p' will receive to an encrypted child"
+log_must eval "zfs send -p $snap | zfs receive $TESTPOOL/$TESTFS1/c2"
+# XXX - on illumos, not sending encryption prop yet
+# log_must test "$(get_prop 'encryption' $TESTPOOL/$TESTFS1/c2)" == "off"
-log_note "Verifying 'send -R' will not receive to an encrypted child"
-log_mustnot eval "zfs send -R $snap | zfs receive $TESTPOOL/$TESTFS1/c3"
+log_note "Verifying 'send -R' will receive to an encrypted child"
+log_must eval "zfs send -R $snap | zfs receive $TESTPOOL/$TESTFS1/c3"
+# XXX - on illumos, not sending encryption prop yet
+# log_must test "$(get_prop 'encryption' $TESTPOOL/$TESTFS1/c3)" == "off"
log_note "Verifying ZFS will not receive to an encrypted child when the" \
"parent key is unloaded"
@@ -72,4 +79,4 @@ log_must zfs unmount $TESTPOOL/$TESTFS1
log_must zfs unload-key $TESTPOOL/$TESTFS1
log_mustnot eval "zfs send $snap | zfs receive $TESTPOOL/$TESTFS1/c4"
-log_pass "ZFS can receive to an encrypted child dataset"
+log_pass "ZFS can receive encrypted filesystems into child dataset"
diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_to_encrypted.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_to_encrypted.ksh
index 400592aaca..1b9c6e3c70 100644
--- a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_to_encrypted.ksh
+++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_to_encrypted.ksh
@@ -23,12 +23,13 @@
#
# DESCRIPTION:
-# 'zfs rename' should not rename an unencrypted dataset to a child
+# 'zfs rename' should be able to move an unencrypted dataset to a child
# of an encrypted dataset
#
# STRATEGY:
# 1. Create an encrypted dataset
-# 2. Attempt to rename the default dataset to a child of the encrypted dataset
+# 2. Rename the default dataset to a child of the encrypted dataset
+# 3. Confirm the child dataset doesn't have any encryption properties
#
verify_runnable "both"
@@ -36,16 +37,17 @@ verify_runnable "both"
function cleanup
{
datasetexists $TESTPOOL/$TESTFS2 && \
- log_must zfs destroy $TESTPOOL/$TESTFS2
+ log_must zfs destroy -r $TESTPOOL/$TESTFS2
}
log_onexit cleanup
-log_assert "'zfs rename' should not rename an unencrypted dataset to a" \
+log_assert "'zfs rename' should allow renaming an unencrypted dataset to a" \
"child of an encrypted dataset"
log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
"-o keyformat=passphrase -o keylocation=prompt $TESTPOOL/$TESTFS2"
-log_mustnot zfs rename $TESTPOOL/$TESTFS $TESTPOOL/$TESTFS2/$TESTFS
+log_must zfs rename $TESTPOOL/$TESTFS $TESTPOOL/$TESTFS2/$TESTFS
+log_must test "$(get_prop 'encryption' $TESTPOOL/$TESTFS2/$TESTFS)" == "off"
-log_pass "'zfs rename' does not rename an unencrypted dataset to a child" \
+log_pass "'zfs rename' allows renaming an unencrypted dataset to a child" \
"of an encrypted dataset"
diff --git a/usr/src/test/zfs-tests/tests/functional/rsend/send-wDR_encrypted_zvol.ksh b/usr/src/test/zfs-tests/tests/functional/rsend/send-wDR_encrypted_zvol.ksh
new file mode 100755
index 0000000000..83fe3556d4
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/rsend/send-wDR_encrypted_zvol.ksh
@@ -0,0 +1,103 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2018 by Datto Inc. All rights reserved.
+# Copyright 2019 Joyent, Inc.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# DESCRIPTION:
+# Verify that zvols with dedup=on and encryption=on can be sent and received
+# with a deduplicated raw send stream.
+#
+# STRATEGY:
+# 1. Create a zvol with dedup and encryption on and put a filesystem on it
+# 2. Copy a file into the zvol a few times and take a snapshot
+# 3. Repeat step 2 a few times to create more snapshots
+# 4. Send all snapshots in a recursive, raw, deduplicated send stream
+# 5. Mount the received zvol and verify that all of the data there is correct
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if is_linux; then
+ ismounted $recvmnt ext4 && log_must umount $recvmnt
+ ismounted $mntpnt ext4 && log_must umount $mntpnt
+ else
+ ismounted $recvmnt ufs && log_must umount $recvmnt
+ ismounted $mntpnt ufs && log_must umount $mntpnt
+ fi
+ [[ -d $recvmnt ]] && log_must rm -rf $keyfile
+ [[ -d $mntpnt ]] && log_must rm -rf $keyfile
+ destroy_dataset $TESTPOOL/recv "-r"
+ destroy_dataset $TESTPOOL/$TESTVOL "-r"
+ [[ -f $keyfile ]] && log_must rm $keyfile
+ [[ -f $sendfile ]] && log_must rm $sendfile
+}
+log_onexit cleanup
+
+log_assert "Verify zfs can receive raw, recursive, and deduplicated send streams"
+
+typeset keyfile=/$TESTPOOL/pkey
+typeset snap_count=5
+typeset zdev=$ZVOL_DEVDIR/$TESTPOOL/$TESTVOL
+typeset mntpnt=$TESTDIR/$TESTVOL
+typeset recvdev=$ZVOL_DEVDIR/$TESTPOOL/recv
+typeset recvmnt=$TESTDIR/recvmnt
+typeset sendfile=$TESTDIR/sendfile
+
+log_must eval "echo 'password' > $keyfile"
+
+log_must zfs create -o dedup=on -o encryption=on -o keyformat=passphrase \
+ -o keylocation=file://$keyfile -V 128M $TESTPOOL/$TESTVOL
+log_must block_device_wait
+
+if is_linux; then
+ log_must eval "echo 'y' | newfs -t ext4 -v $zdev"
+else
+ log_must eval "echo 'y' | newfs $zdev"
+fi
+log_must mkdir -p $mntpnt
+log_must mkdir -p $recvmnt
+log_must mount $zdev $mntpnt
+
+for ((i = 1; i <= $snap_count; i++)); do
+ log_must dd if=/dev/urandom of=$mntpnt/file bs=1M count=1
+ for ((j = 0; j < 10; j++)); do
+ log_must cp $mntpnt/file $mntpnt/file$j
+ done
+
+ log_must sync
+ log_must zfs snap $TESTPOOL/$TESTVOL@snap$i
+done
+
+log_must eval "zfs send -wDR $TESTPOOL/$TESTVOL@snap$snap_count > $sendfile"
+log_must eval "zfs recv $TESTPOOL/recv < $sendfile"
+log_must zfs load-key $TESTPOOL/recv
+log_must block_device_wait
+
+log_must mount $recvdev $recvmnt
+
+md5_1=$(cat $mntpnt/* | md5sum | awk '{print $1}')
+md5_2=$(cat $recvmnt/* | md5sum | awk '{print $1}')
+[[ "$md5_1" == "$md5_2" ]] || log_fail "md5 mismatch: $md5_1 != $md5_2"
+
+log_pass "zfs can receive raw, recursive, and deduplicated send streams"
diff --git a/usr/src/uts/common/fs/zfs/arc.c b/usr/src/uts/common/fs/zfs/arc.c
index 90f5314d81..1cdd882872 100644
--- a/usr/src/uts/common/fs/zfs/arc.c
+++ b/usr/src/uts/common/fs/zfs/arc.c
@@ -1710,6 +1710,9 @@ arc_cksum_free(arc_buf_hdr_t *hdr)
static boolean_t
arc_hdr_has_uncompressed_buf(arc_buf_hdr_t *hdr)
{
+ ASSERT(hdr->b_l1hdr.b_state == arc_anon ||
+ MUTEX_HELD(HDR_LOCK(hdr)) || HDR_EMPTY(hdr));
+
for (arc_buf_t *b = hdr->b_l1hdr.b_buf; b != NULL; b = b->b_next) {
if (!ARC_BUF_COMPRESSED(b)) {
return (B_TRUE);
@@ -1732,15 +1735,13 @@ arc_cksum_verify(arc_buf_t *buf)
if (!(zfs_flags & ZFS_DEBUG_MODIFY))
return;
- if (ARC_BUF_COMPRESSED(buf)) {
- ASSERT(hdr->b_l1hdr.b_freeze_cksum == NULL ||
- arc_hdr_has_uncompressed_buf(hdr));
+ if (ARC_BUF_COMPRESSED(buf))
return;
- }
ASSERT(HDR_HAS_L1HDR(hdr));
mutex_enter(&hdr->b_l1hdr.b_freeze_lock);
+
if (hdr->b_l1hdr.b_freeze_cksum == NULL || HDR_IO_ERROR(hdr)) {
mutex_exit(&hdr->b_l1hdr.b_freeze_lock);
return;
@@ -1844,11 +1845,7 @@ arc_cksum_compute(arc_buf_t *buf)
ASSERT(HDR_HAS_L1HDR(hdr));
mutex_enter(&buf->b_hdr->b_l1hdr.b_freeze_lock);
- if (hdr->b_l1hdr.b_freeze_cksum != NULL) {
- ASSERT(arc_hdr_has_uncompressed_buf(hdr));
- mutex_exit(&hdr->b_l1hdr.b_freeze_lock);
- return;
- } else if (ARC_BUF_COMPRESSED(buf)) {
+ if (hdr->b_l1hdr.b_freeze_cksum != NULL || ARC_BUF_COMPRESSED(buf)) {
mutex_exit(&hdr->b_l1hdr.b_freeze_lock);
return;
}
@@ -1952,14 +1949,10 @@ arc_buf_thaw(arc_buf_t *buf)
arc_cksum_verify(buf);
/*
- * Compressed buffers do not manipulate the b_freeze_cksum or
- * allocate b_thawed.
+ * Compressed buffers do not manipulate the b_freeze_cksum.
*/
- if (ARC_BUF_COMPRESSED(buf)) {
- ASSERT(hdr->b_l1hdr.b_freeze_cksum == NULL ||
- arc_hdr_has_uncompressed_buf(hdr));
+ if (ARC_BUF_COMPRESSED(buf))
return;
- }
ASSERT(HDR_HAS_L1HDR(hdr));
arc_cksum_free(hdr);
@@ -1981,26 +1974,14 @@ arc_buf_thaw(arc_buf_t *buf)
void
arc_buf_freeze(arc_buf_t *buf)
{
- arc_buf_hdr_t *hdr = buf->b_hdr;
- kmutex_t *hash_lock;
-
if (!(zfs_flags & ZFS_DEBUG_MODIFY))
return;
- if (ARC_BUF_COMPRESSED(buf)) {
- ASSERT(hdr->b_l1hdr.b_freeze_cksum == NULL ||
- arc_hdr_has_uncompressed_buf(hdr));
+ if (ARC_BUF_COMPRESSED(buf))
return;
- }
-
- hash_lock = HDR_LOCK(hdr);
- mutex_enter(hash_lock);
- ASSERT(HDR_HAS_L1HDR(hdr));
- ASSERT(hdr->b_l1hdr.b_freeze_cksum != NULL ||
- hdr->b_l1hdr.b_state == arc_anon);
+ ASSERT(HDR_HAS_L1HDR(buf->b_hdr));
arc_cksum_compute(buf);
- mutex_exit(hash_lock);
}
/*
@@ -2128,7 +2109,7 @@ arc_hdr_authenticate(arc_buf_hdr_t *hdr, spa_t *spa, uint64_t dsobj)
void *tmpbuf = NULL;
abd_t *abd = hdr->b_l1hdr.b_pabd;
- ASSERT(HDR_LOCK(hdr) == NULL || MUTEX_HELD(HDR_LOCK(hdr)));
+ ASSERT(MUTEX_HELD(HDR_LOCK(hdr)) || HDR_EMPTY(hdr));
ASSERT(HDR_AUTHENTICATED(hdr));
ASSERT3P(hdr->b_l1hdr.b_pabd, !=, NULL);
@@ -2198,7 +2179,7 @@ arc_hdr_decrypt(arc_buf_hdr_t *hdr, spa_t *spa, const zbookmark_phys_t *zb)
boolean_t no_crypt = B_FALSE;
boolean_t bswap = (hdr->b_l1hdr.b_byteswap != DMU_BSWAP_NUMFUNCS);
- ASSERT(HDR_LOCK(hdr) == NULL || MUTEX_HELD(HDR_LOCK(hdr)));
+ ASSERT(MUTEX_HELD(HDR_LOCK(hdr)) || HDR_EMPTY(hdr));
ASSERT(HDR_ENCRYPTED(hdr));
arc_hdr_alloc_pabd(hdr, B_FALSE);
@@ -2318,7 +2299,7 @@ arc_buf_untransform_in_place(arc_buf_t *buf, kmutex_t *hash_lock)
ASSERT(HDR_ENCRYPTED(hdr));
ASSERT3U(hdr->b_crypt_hdr.b_ot, ==, DMU_OT_DNODE);
- ASSERT(HDR_LOCK(hdr) == NULL || MUTEX_HELD(HDR_LOCK(hdr)));
+ ASSERT(MUTEX_HELD(HDR_LOCK(hdr)) || HDR_EMPTY(hdr));
ASSERT3P(hdr->b_l1hdr.b_pabd, !=, NULL);
zio_crypt_copy_dnode_bonus(hdr->b_l1hdr.b_pabd, buf->b_data,
diff --git a/usr/src/uts/common/fs/zfs/dbuf.c b/usr/src/uts/common/fs/zfs/dbuf.c
index 9c7205bd0d..6a60ac7fdf 100644
--- a/usr/src/uts/common/fs/zfs/dbuf.c
+++ b/usr/src/uts/common/fs/zfs/dbuf.c
@@ -1037,7 +1037,6 @@ dbuf_read_verify_dnode_crypt(dmu_buf_impl_t *db, uint32_t flags)
!DMU_OT_IS_ENCRYPTED(dn->dn_bonustype))))
err = 0;
-
DB_DNODE_EXIT(db);
return (err);
diff --git a/usr/src/uts/common/fs/zfs/dmu.c b/usr/src/uts/common/fs/zfs/dmu.c
index 02bdfdfa12..d19c801c61 100644
--- a/usr/src/uts/common/fs/zfs/dmu.c
+++ b/usr/src/uts/common/fs/zfs/dmu.c
@@ -1711,6 +1711,7 @@ dmu_copy_from_buf(objset_t *os, uint64_t object, uint64_t offset,
dmu_buf_t *dst_handle;
dmu_buf_impl_t *dstdb;
dmu_buf_impl_t *srcdb = (dmu_buf_impl_t *)handle;
+ dmu_object_type_t type;
arc_buf_t *abuf;
uint64_t datalen;
boolean_t byteorder;
@@ -1726,11 +1727,15 @@ dmu_copy_from_buf(objset_t *os, uint64_t object, uint64_t offset,
dstdb = (dmu_buf_impl_t *)dst_handle;
datalen = arc_buf_size(srcdb->db_buf);
+ DB_DNODE_ENTER(dstdb);
+ type = DB_DNODE(dstdb)->dn_type;
+ DB_DNODE_EXIT(dstdb);
+
/* allocated an arc buffer that matches the type of srcdb->db_buf */
if (arc_is_encrypted(srcdb->db_buf)) {
arc_get_raw_params(srcdb->db_buf, &byteorder, salt, iv, mac);
abuf = arc_loan_raw_buf(os->os_spa, dmu_objset_id(os),
- byteorder, salt, iv, mac, DB_DNODE(dstdb)->dn_type,
+ byteorder, salt, iv, mac, type,
datalen, arc_buf_lsize(srcdb->db_buf),
arc_get_compression(srcdb->db_buf));
} else {
@@ -1738,7 +1743,7 @@ dmu_copy_from_buf(objset_t *os, uint64_t object, uint64_t offset,
ASSERT3U(arc_get_compression(srcdb->db_buf),
==, ZIO_COMPRESS_OFF);
abuf = arc_loan_buf(os->os_spa,
- DMU_OT_IS_METADATA(DB_DNODE(dstdb)->dn_type), datalen);
+ DMU_OT_IS_METADATA(type), datalen);
}
ASSERT3U(datalen, ==, arc_buf_size(abuf));
diff --git a/usr/src/uts/common/fs/zfs/dmu_objset.c b/usr/src/uts/common/fs/zfs/dmu_objset.c
index 4d0a5d2fd5..8174222826 100644
--- a/usr/src/uts/common/fs/zfs/dmu_objset.c
+++ b/usr/src/uts/common/fs/zfs/dmu_objset.c
@@ -1259,13 +1259,6 @@ dmu_objset_clone_check(void *arg, dmu_tx_t *tx)
return (SET_ERROR(EINVAL));
}
- error = dmu_objset_clone_crypt_check(pdd, origin->ds_dir);
- if (error != 0) {
- dsl_dataset_rele(origin, FTAG);
- dsl_dir_rele(pdd, FTAG);
- return (error);
- }
-
dsl_dataset_rele(origin, FTAG);
dsl_dir_rele(pdd, FTAG);
diff --git a/usr/src/uts/common/fs/zfs/dmu_recv.c b/usr/src/uts/common/fs/zfs/dmu_recv.c
index b6f63e7e22..b72aa21922 100644
--- a/usr/src/uts/common/fs/zfs/dmu_recv.c
+++ b/usr/src/uts/common/fs/zfs/dmu_recv.c
@@ -306,7 +306,7 @@ dmu_recv_begin_check(void *arg, dmu_tx_t *tx)
/* Open the parent of tofs */
ASSERT3U(strlen(tofs), <, sizeof (buf));
(void) strlcpy(buf, tofs, strrchr(tofs, '/') - tofs + 1);
- error = dsl_dataset_hold_flags(dp, buf, dsflags, FTAG, &ds);
+ error = dsl_dataset_hold(dp, buf, FTAG, &ds);
if (error != 0)
return (error);
@@ -324,13 +324,13 @@ dmu_recv_begin_check(void *arg, dmu_tx_t *tx)
error = dmu_objset_create_crypt_check(ds->ds_dir,
drba->drba_dcp, &will_encrypt);
if (error != 0) {
- dsl_dataset_rele_flags(ds, dsflags, FTAG);
+ dsl_dataset_rele(ds, FTAG);
return (error);
}
if (will_encrypt &&
(featureflags & DMU_BACKUP_FEATURE_EMBED_DATA)) {
- dsl_dataset_rele_flags(ds, dsflags, FTAG);
+ dsl_dataset_rele(ds, FTAG);
return (SET_ERROR(EINVAL));
}
}
@@ -343,46 +343,46 @@ dmu_recv_begin_check(void *arg, dmu_tx_t *tx)
error = dsl_fs_ss_limit_check(ds->ds_dir, 1,
ZFS_PROP_FILESYSTEM_LIMIT, NULL, drba->drba_cred);
if (error != 0) {
- dsl_dataset_rele_flags(ds, dsflags, FTAG);
+ dsl_dataset_rele(ds, FTAG);
return (error);
}
error = dsl_fs_ss_limit_check(ds->ds_dir, 1,
ZFS_PROP_SNAPSHOT_LIMIT, NULL, drba->drba_cred);
if (error != 0) {
- dsl_dataset_rele_flags(ds, dsflags, FTAG);
+ dsl_dataset_rele(ds, FTAG);
return (error);
}
if (drba->drba_origin != NULL) {
dsl_dataset_t *origin;
- error = dsl_dataset_hold_flags(dp, drba->drba_origin,
- dsflags, FTAG, &origin);
+ error = dsl_dataset_hold(dp, drba->drba_origin,
+ FTAG, &origin);
if (error != 0) {
- dsl_dataset_rele_flags(ds, dsflags, FTAG);
+ dsl_dataset_rele(ds, FTAG);
return (error);
}
if (!origin->ds_is_snapshot) {
- dsl_dataset_rele_flags(origin, dsflags, FTAG);
- dsl_dataset_rele_flags(ds, dsflags, FTAG);
+ dsl_dataset_rele(origin, FTAG);
+ dsl_dataset_rele(ds, FTAG);
return (SET_ERROR(EINVAL));
}
if (dsl_dataset_phys(origin)->ds_guid != fromguid &&
fromguid != 0) {
- dsl_dataset_rele_flags(origin, dsflags, FTAG);
- dsl_dataset_rele_flags(ds, dsflags, FTAG);
+ dsl_dataset_rele(origin, FTAG);
+ dsl_dataset_rele(ds, FTAG);
return (SET_ERROR(ENODEV));
}
if (origin->ds_dir->dd_crypto_obj != 0 &&
(featureflags & DMU_BACKUP_FEATURE_EMBED_DATA)) {
- dsl_dataset_rele_flags(origin, dsflags, FTAG);
- dsl_dataset_rele_flags(ds, dsflags, FTAG);
+ dsl_dataset_rele(origin, FTAG);
+ dsl_dataset_rele(ds, FTAG);
return (SET_ERROR(EINVAL));
}
- dsl_dataset_rele_flags(origin, dsflags, FTAG);
+ dsl_dataset_rele(origin, FTAG);
}
- dsl_dataset_rele_flags(ds, dsflags, FTAG);
+ dsl_dataset_rele(ds, FTAG);
error = 0;
}
return (error);
diff --git a/usr/src/uts/common/fs/zfs/dsl_crypt.c b/usr/src/uts/common/fs/zfs/dsl_crypt.c
index 3937d3cb51..3896efbc76 100644
--- a/usr/src/uts/common/fs/zfs/dsl_crypt.c
+++ b/usr/src/uts/common/fs/zfs/dsl_crypt.c
@@ -1588,15 +1588,8 @@ dsl_dir_rename_crypt_check(dsl_dir_t *dd, dsl_dir_t *newparent)
int ret;
uint64_t curr_rddobj, parent_rddobj;
- if (dd->dd_crypto_obj == 0) {
- /* children of encrypted parents must be encrypted */
- if (newparent->dd_crypto_obj != 0) {
- ret = SET_ERROR(EACCES);
- goto error;
- }
-
+ if (dd->dd_crypto_obj == 0)
return (0);
- }
ret = dsl_dir_get_encryption_root_ddobj(dd, &curr_rddobj);
if (ret != 0)
@@ -1726,34 +1719,6 @@ dsl_dataset_promote_crypt_sync(dsl_dir_t *target, dsl_dir_t *origin,
}
int
-dmu_objset_clone_crypt_check(dsl_dir_t *parentdd, dsl_dir_t *origindd)
-{
- int ret;
- uint64_t pcrypt, crypt;
-
- /*
- * Check that we are not making an unencrypted child of an
- * encrypted parent.
- */
- ret = dsl_dir_get_crypt(parentdd, &pcrypt);
- if (ret != 0)
- return (ret);
-
- ret = dsl_dir_get_crypt(origindd, &crypt);
- if (ret != 0)
- return (ret);
-
- ASSERT3U(pcrypt, !=, ZIO_CRYPT_INHERIT);
- ASSERT3U(crypt, !=, ZIO_CRYPT_INHERIT);
-
- if (crypt == ZIO_CRYPT_OFF && pcrypt != ZIO_CRYPT_OFF)
- return (SET_ERROR(EINVAL));
-
- return (0);
-}
-
-
-int
dmu_objset_create_crypt_check(dsl_dir_t *parentdd, dsl_crypto_params_t *dcp,
boolean_t *will_encrypt)
{
@@ -1783,13 +1748,6 @@ dmu_objset_create_crypt_check(dsl_dir_t *parentdd, dsl_crypto_params_t *dcp,
ASSERT3U(pcrypt, !=, ZIO_CRYPT_INHERIT);
ASSERT3U(crypt, !=, ZIO_CRYPT_INHERIT);
- /*
- * We can't create an unencrypted child of an encrypted parent
- * under any circumstances.
- */
- if (crypt == ZIO_CRYPT_OFF && pcrypt != ZIO_CRYPT_OFF)
- return (SET_ERROR(EINVAL));
-
/* check for valid dcp with no encryption (inherited or local) */
if (crypt == ZIO_CRYPT_OFF) {
/* Must not specify encryption params */
diff --git a/usr/src/uts/common/fs/zfs/sys/dsl_crypt.h b/usr/src/uts/common/fs/zfs/sys/dsl_crypt.h
index 360a69b329..cf19665aae 100644
--- a/usr/src/uts/common/fs/zfs/sys/dsl_crypt.h
+++ b/usr/src/uts/common/fs/zfs/sys/dsl_crypt.h
@@ -209,7 +209,6 @@ void dsl_dataset_create_crypt_sync(uint64_t dsobj, dsl_dir_t *dd,
struct dsl_dataset *origin, dsl_crypto_params_t *dcp, dmu_tx_t *tx);
uint64_t dsl_crypto_key_create_sync(uint64_t crypt, dsl_wrapping_key_t *wkey,
dmu_tx_t *tx);
-int dmu_objset_clone_crypt_check(dsl_dir_t *parentdd, dsl_dir_t *origindd);
uint64_t dsl_crypto_key_clone_sync(dsl_dir_t *origindd, dmu_tx_t *tx);
void dsl_crypto_key_destroy_sync(uint64_t dckobj, dmu_tx_t *tx);