git: ba27dd8be821 - main - zfs: merge OpenZFS master-9312e0fd1

Martin Matuska mm at FreeBSD.org
Mon Feb 22 12:02:05 UTC 2021


The branch main has been updated by mm:

URL: https://cgit.FreeBSD.org/src/commit/?id=ba27dd8be821792e15bdabfac69fd6cab0cf9dd3

commit ba27dd8be821792e15bdabfac69fd6cab0cf9dd3
Merge: c02a28754bc2 0626917d0786
Author:     Martin Matuska <mm at FreeBSD.org>
AuthorDate: 2021-02-22 11:35:56 +0000
Commit:     Martin Matuska <mm at FreeBSD.org>
CommitDate: 2021-02-22 12:01:17 +0000

    zfs: merge OpenZFS master-9312e0fd1
    
    Notable upstream changes:
      778869fa1 Fix reporting of mount progress
      e7adccf7f Disable use of hardware crypto offload drivers on FreeBSD
      03e02e5b5 Fix checksum errors not being counted on repeated repair
      64e0fe14f Restore FreeBSD resource usage accounting
      11f2e9a49 Fix panic if scrubbing after removing a slog device
    
    MFC after:      2 weeks

 cddl/lib/libzpool/Makefile                         |   1 +
 stand/libsa/zfs/zstd_shim.c                        |   5 +
 sys/contrib/openzfs/cmd/zfs/zfs_main.c             |   3 -
 sys/contrib/openzfs/cmd/ztest/ztest.c              | 113 ++++++++-
 .../openzfs/include/os/freebsd/spl/sys/uio.h       |  43 +---
 sys/contrib/openzfs/include/os/linux/spl/sys/uio.h |  22 +-
 .../include/os/linux/zfs/sys/zfs_context_os.h      |   1 -
 sys/contrib/openzfs/include/sys/Makefile.am        |   1 +
 sys/contrib/openzfs/include/sys/spa.h              |   3 +-
 sys/contrib/openzfs/include/sys/uio_impl.h         |  21 +-
 sys/contrib/openzfs/include/sys/zfs_context.h      |   3 +-
 sys/contrib/openzfs/include/sys/zfs_racct.h        |  37 +++
 sys/contrib/openzfs/lib/libzpool/Makefile.am       |   1 +
 sys/contrib/openzfs/lib/libzpool/util.c            |  74 ++++--
 .../lib/libzutil/os/linux/zutil_device_path_os.c   | 252 ++++++++++++---------
 sys/contrib/openzfs/module/Makefile.bsd            |   1 +
 .../openzfs/module/os/freebsd/spl/spl_uio.c        |   9 +-
 .../openzfs/module/os/freebsd/zfs/crypto_os.c      |  15 +-
 .../openzfs/module/os/freebsd/zfs/zfs_racct.c      |  55 +++++
 .../openzfs/module/os/linux/zfs/Makefile.in        |   1 +
 .../openzfs/module/os/linux/zfs/zfs_racct.c        |  36 +++
 sys/contrib/openzfs/module/zfs/arc.c               |   2 +
 sys/contrib/openzfs/module/zfs/dmu.c               |   5 +
 sys/contrib/openzfs/module/zfs/dsl_scan.c          |   6 +-
 sys/contrib/openzfs/module/zfs/spa_config.c        |   2 +-
 sys/contrib/openzfs/module/zfs/vdev.c              |   9 +-
 sys/contrib/openzfs/module/zfs/vdev_indirect.c     |  10 +-
 sys/contrib/openzfs/module/zfs/vdev_raidz.c        |  20 +-
 sys/contrib/openzfs/module/zfs/vdev_rebuild.c      |   3 +
 sys/contrib/openzfs/module/zfs/zfs_fm.c            |  46 +++-
 sys/contrib/openzfs/module/zfs/zfs_ioctl.c         |   2 +-
 sys/contrib/openzfs/module/zfs/zfs_vnops.c         |   2 +-
 sys/contrib/openzfs/module/zfs/zio.c               |  11 +-
 sys/contrib/openzfs/scripts/zfs.sh                 |   2 +-
 sys/contrib/openzfs/tests/runfiles/common.run      |   3 +-
 .../functional/cli_root/zpool_events/Makefile.am   |   3 +-
 .../zpool_events/zpool_events_clear_retained.ksh   | 135 +++++++++++
 .../zpool_events/zpool_events_duplicates.ksh       |  11 -
 sys/modules/zfs/Makefile                           |   1 +
 sys/modules/zfs/zfs_config.h                       |   2 +-
 40 files changed, 724 insertions(+), 248 deletions(-)

diff --cc cddl/lib/libzpool/Makefile
index d9b2e67094e3,000000000000..6893e31ff20a
mode 100644,000000..100644
--- a/cddl/lib/libzpool/Makefile
+++ b/cddl/lib/libzpool/Makefile
@@@ -1,266 -1,0 +1,267 @@@
 +# $FreeBSD$
 +
 +ZFSTOP=	${SRCTOP}/sys/contrib/openzfs
 +
 +# ZFS_COMMON_SRCS
 +.PATH: ${ZFSTOP}/module/zfs
 +.PATH: ${ZFSTOP}/module/zcommon
 +.PATH: ${ZFSTOP}/module/unicode
 +# LUA_SRCS
 +.PATH: ${ZFSTOP}/module/lua
 +# ZSTD_SRCS
 +.PATH: ${ZFSTOP}/module/zstd
 +.PATH: ${ZFSTOP}/module/zstd/lib
 +
 +.PATH: ${ZFSTOP}/module/os/linux/zfs
 +
 +.PATH: ${ZFSTOP}/lib/libzpool
 +
 +.if exists(${SRCTOP}/sys/cddl/contrib/opensolaris/common/atomic/${MACHINE_ARCH}/opensolaris_atomic.S)
 +.PATH: ${SRCTOP}/sys/cddl/contrib/opensolaris/common/atomic/${MACHINE_ARCH}
 +ATOMIC_SRCS=	opensolaris_atomic.S
 +ACFLAGS+=	-Wa,--noexecstack
 +.else
 +.PATH: ${SRCTOP}/sys/cddl/compat/opensolaris/kern
 +ATOMIC_SRCS=	opensolaris_atomic.c
 +.endif
 +
 +.if ${MACHINE_ARCH} == "powerpc" || ${MACHINE_ARCH} == "powerpcspe"
 +# Don't waste GOT entries on small data.
 +PICFLAG=	-fPIC
 +.endif
 +
 +LIB=		zpool
 +
 +USER_C = \
 +	kernel.c \
 +	taskq.c \
 +	util.c
 +
 +KERNEL_C = \
 +	zfeature_common.c \
 +	zfs_comutil.c \
 +	zfs_deleg.c \
 +	zfs_fletcher.c \
 +	zfs_fletcher_superscalar.c \
 +	zfs_fletcher_superscalar4.c \
 +	zfs_namecheck.c \
 +	zfs_prop.c \
 +	zfs_zstd.c \
 +	zpool_prop.c \
 +	zprop_common.c \
 +	abd.c \
 +	abd_os.c \
 +	aggsum.c \
 +	arc.c \
 +	arc_os.c \
 +	blkptr.c \
 +	bplist.c \
 +	bpobj.c \
 +	bptree.c \
 +	btree.c \
 +	bqueue.c \
 +	cityhash.c \
 +	dbuf.c \
 +	dbuf_stats.c \
 +	ddt.c \
 +	ddt_zap.c \
 +	dmu.c \
 +	dmu_diff.c \
 +	dmu_object.c \
 +	dmu_objset.c \
 +	dmu_recv.c \
 +	dmu_redact.c \
 +	dmu_send.c \
 +	dmu_traverse.c \
 +	dmu_tx.c \
 +	dmu_zfetch.c \
 +	dnode.c \
 +	dnode_sync.c \
 +	dsl_bookmark.c \
 +	dsl_dataset.c \
 +	dsl_deadlist.c \
 +	dsl_deleg.c \
 +	dsl_dir.c \
 +	dsl_crypt.c \
 +	dsl_pool.c \
 +	dsl_prop.c \
 +	dsl_scan.c \
 +	dsl_synctask.c \
 +	dsl_destroy.c \
 +	dsl_userhold.c \
 +	edonr_zfs.c \
 +	hkdf.c \
 +	fm.c \
 +	gzip.c \
 +	lzjb.c \
 +	lz4.c \
 +	metaslab.c \
 +	mmp.c \
 +	multilist.c \
 +	objlist.c \
 +	pathname.c \
 +	range_tree.c \
 +	refcount.c \
 +	rrwlock.c \
 +	sa.c \
 +	sha256.c \
 +	skein_zfs.c \
 +	spa.c \
 +	spa_boot.c \
 +	spa_checkpoint.c \
 +	spa_config.c \
 +	spa_errlog.c \
 +	spa_history.c \
 +	spa_log_spacemap.c \
 +	spa_misc.c \
 +	spa_stats.c \
 +	space_map.c \
 +	space_reftree.c \
 +	txg.c \
 +	trace.c \
 +	uberblock.c \
 +	unique.c \
 +	vdev.c \
 +	vdev_cache.c \
 +	vdev_draid.c \
 +	vdev_draid_rand.c \
 +	vdev_file.c \
 +	vdev_indirect_births.c \
 +	vdev_indirect.c \
 +	vdev_indirect_mapping.c \
 +	vdev_initialize.c \
 +	vdev_label.c \
 +	vdev_mirror.c \
 +	vdev_missing.c \
 +	vdev_queue.c \
 +	vdev_raidz.c \
 +	vdev_raidz_math_aarch64_neon.c \
 +	vdev_raidz_math_aarch64_neonx2.c \
 +	vdev_raidz_math_avx2.c \
 +	vdev_raidz_math_avx512bw.c \
 +	vdev_raidz_math_avx512f.c \
 +	vdev_raidz_math.c \
 +	vdev_raidz_math_scalar.c \
 +	vdev_rebuild.c \
 +	vdev_removal.c \
 +	vdev_root.c \
 +	vdev_trim.c \
 +	zap.c \
 +	zap_leaf.c \
 +	zap_micro.c \
 +	zcp.c \
 +	zcp_get.c \
 +	zcp_global.c \
 +	zcp_iter.c \
 +	zcp_set.c \
 +	zcp_synctask.c \
 +	zfeature.c \
 +	zfs_byteswap.c \
 +	zfs_debug.c \
 +	zfs_fm.c \
 +	zfs_fuid.c \
 +	zfs_sa.c \
 +	zfs_znode.c \
++	zfs_racct.c \
 +	zfs_ratelimit.c \
 +	zfs_rlock.c \
 +	zil.c \
 +	zio.c \
 +	zio_checksum.c \
 +	zio_compress.c \
 +	zio_crypt.c \
 +	zio_inject.c \
 +	zle.c \
 +	zrlock.c \
 +	zstd.c \
 +	zthr.c
 +
 +ARCH_C =
 +.if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386"
 +ARCH_C += 	vdev_raidz_math_sse2.c \
 +		vdev_raidz_math_ssse3.c \
 +		zfs_fletcher_intel.c \
 +		zfs_fletcher_sse.c 
 +CFLAGS +=  -DHAVE_SSE2 	-DHAVE_SSE3
 +.endif
 +.if ${MACHINE_ARCH} == "amd64"
 +ARCH_C +=	zfs_fletcher_avx512.c
 +CFLAGS+= -DHAVE_AVX2 -DHAVE_AVX -D__x86_64 -DHAVE_AVX512F \
 +	-DHAVE_AVX512BW
 +.endif
 +.if ${MACHINE_CPUARCH} == "aarch64"
 +ARCH_C +=	zfs_fletcher_aarch64_neon.c
 +.endif
 +
 +LUA_C = \
 +	lapi.c \
 +	lauxlib.c \
 +	lbaselib.c \
 +	lcode.c \
 +	lcompat.c \
 +	lcorolib.c \
 +	lctype.c \
 +	ldebug.c \
 +	ldo.c \
 +	lfunc.c \
 +	lgc.c \
 +	llex.c \
 +	lmem.c \
 +	lobject.c \
 +	lopcodes.c \
 +	lparser.c \
 +	lstate.c \
 +	lstring.c \
 +	lstrlib.c \
 +	ltable.c \
 +	ltablib.c \
 +	ltm.c \
 +	lvm.c \
 +	lzio.c
 +
 +UNICODE_C = u8_textprep.c uconv.c
 +
 +SRCS=		${USER_C} ${KERNEL_C} ${LUA_C} ${UNICODE_C} ${ARCH_C}
 +
 +WARNS?=		2
 +CFLAGS+= \
 +	-DIN_BASE \
 +	-I${ZFSTOP}/include \
 +	-I${ZFSTOP}/lib/libspl/include \
 +	-I${ZFSTOP}/lib/libspl/include/os/freebsd \
 +	-I${SRCTOP}/sys \
 +	-I${ZFSTOP}/include/os/freebsd/zfs \
 +	-I${SRCTOP}/cddl/compat/opensolaris/include \
 +	-I${ZFSTOP}/module/icp/include \
 +	-include ${ZFSTOP}/include/os/freebsd/spl/sys/ccompile.h \
 +	-DHAVE_ISSETUGID \
 +	-include ${SRCTOP}/sys/modules/zfs/zfs_config.h \
 +	-I${SRCTOP}/sys/modules/zfs \
 +	-I${ZFSTOP}/include/os/freebsd/zfs \
 +	-DLIB_ZPOOL_BUILD -DZFS_DEBUG \
 +
 +# XXX: pthread doesn't have mutex_owned() equivalent, so we need to look
 +#      into libthr private structures. That's sooo evil, but it's only for
 +#      ZFS debugging tools needs.
 +CFLAGS+=	-DWANTS_MUTEX_OWNED
 +CFLAGS+=	-I${SRCTOP}/lib/libpthread/thread
 +CFLAGS+=	-I${SRCTOP}/lib/libpthread/sys
 +CFLAGS+=	-I${SRCTOP}/lib/libthr/arch/${MACHINE_CPUARCH}/include
 +CFLAGS.gcc+=	-fms-extensions
 +
 +LIBADD=		md pthread z spl icp nvpair avl umem
 +
 +# atomic.S doesn't like profiling.
 +MK_PROFILE=	no
 +
 +CSTD=	c99
 +
 +# Since there are many asserts in this library, it makes no sense to compile
 +# it without debugging.
 +
 +CFLAGS+=	-g -DDEBUG=1
 +
 +CFLAGS.zfs_zstd.c=	-Wno-cast-qual -Wno-pointer-arith
 +CFLAGS.zstd.c+=	-fno-tree-vectorize
 +
 +.include <bsd.lib.mk>
diff --cc stand/libsa/zfs/zstd_shim.c
index b94df6f51913,000000000000..91f5171a72b5
mode 100644,000000..100644
--- a/stand/libsa/zfs/zstd_shim.c
+++ b/stand/libsa/zfs/zstd_shim.c
@@@ -1,40 -1,0 +1,45 @@@
 +/*-
 + * Copyright (c) 2020 M. Warner Losh <imp at FreeBSD.org>
 + *
 + * Redistribution and use in source and binary forms, with or without
 + * modification, are permitted provided that the following conditions
 + * are met:
 + * 1. Redistributions of source code must retain the above copyright
 + *    notice, this list of conditions and the following disclaimer.
 + * 2. Redistributions in binary form must reproduce the above copyright
 + *    notice, this list of conditions and the following disclaimer in the
 + *    documentation and/or other materials provided with the distribution.
 + *
 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 + * SUCH DAMAGE.
 + *
 + */
 +#include <sys/cdefs.h>
 +__FBSDID("$FreeBSD$");
 +
 +/*
 + * Small amount of shim code needed to get zfs_zstd.c to compile. These items
 + * here should all be defined in the SPL or as part of libstand somewhere, but
 + * aren't for reasons that haven't been tracked down yet. Ideally, they would
 + * all go away and we'd compile zfs_zstd.c directly. Based on an original by
 + * Matt Macey, but only the #include remains untouched from that.
 + */
 +
 +#define ZFS_MODULE_PARAM_ARGS void
 +typedef int boolean_t;	/* This one may be tough to get rid of */
 +
++/* TODO: openzfs/include/sys/uio_impl.h must not be included */
++#ifndef _SYS_UIO_IMPL_H
++#define _SYS_UIO_IMPL_H
++#endif
++
 +#include <contrib/openzfs/module/zstd/zfs_zstd.c>
diff --cc sys/contrib/openzfs/include/sys/zfs_racct.h
index 000000000000,cfcdd336ea42..cfcdd336ea42
mode 000000,100644..100644
--- a/sys/contrib/openzfs/include/sys/zfs_racct.h
+++ b/sys/contrib/openzfs/include/sys/zfs_racct.h
diff --cc sys/contrib/openzfs/module/os/freebsd/zfs/zfs_racct.c
index 000000000000,b46cc046268e..b46cc046268e
mode 000000,100644..100644
--- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_racct.c
+++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_racct.c
diff --cc sys/contrib/openzfs/module/os/linux/zfs/zfs_racct.c
index 000000000000,7897e0f9edc1..7897e0f9edc1
mode 000000,100644..100644
--- a/sys/contrib/openzfs/module/os/linux/zfs/zfs_racct.c
+++ b/sys/contrib/openzfs/module/os/linux/zfs/zfs_racct.c
diff --cc sys/contrib/openzfs/module/zfs/zfs_ioctl.c
index 0e35fd069cbb,000000000000..922253469fba
mode 100644,000000..100644
--- a/sys/contrib/openzfs/module/zfs/zfs_ioctl.c
+++ b/sys/contrib/openzfs/module/zfs/zfs_ioctl.c
@@@ -1,7688 -1,0 +1,7688 @@@
 +/*
 + * 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 http://www.opensolaris.org/os/licensing.
 + * 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
 + */
 +
 +/*
 + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
 + * Portions Copyright 2011 Martin Matuska
 + * Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved.
 + * Portions Copyright 2012 Pawel Jakub Dawidek <pawel at dawidek.net>
 + * Copyright (c) 2014, 2016 Joyent, Inc. All rights reserved.
 + * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
 + * Copyright (c) 2014, Joyent, Inc. All rights reserved.
 + * Copyright (c) 2011, 2020 by Delphix. All rights reserved.
 + * Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
 + * Copyright (c) 2013 Steven Hartland. All rights reserved.
 + * Copyright (c) 2014 Integros [integros.com]
 + * Copyright 2016 Toomas Soome <tsoome at me.com>
 + * Copyright (c) 2016 Actifio, Inc. All rights reserved.
 + * Copyright (c) 2018, loli10K <ezomori.nozomu at gmail.com>. All rights reserved.
 + * Copyright 2017 RackTop Systems.
 + * Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
 + * Copyright (c) 2019 Datto Inc.
 + * Copyright (c) 2019, 2020 by Christian Schwarz. All rights reserved.
 + * Copyright (c) 2019, Klara Inc.
 + * Copyright (c) 2019, Allan Jude
 + */
 +
 +/*
 + * ZFS ioctls.
 + *
 + * This file handles the ioctls to /dev/zfs, used for configuring ZFS storage
 + * pools and filesystems, e.g. with /sbin/zfs and /sbin/zpool.
 + *
 + * There are two ways that we handle ioctls: the legacy way where almost
 + * all of the logic is in the ioctl callback, and the new way where most
 + * of the marshalling is handled in the common entry point, zfsdev_ioctl().
 + *
 + * Non-legacy ioctls should be registered by calling
 + * zfs_ioctl_register() from zfs_ioctl_init().  The ioctl is invoked
 + * from userland by lzc_ioctl().
 + *
 + * The registration arguments are as follows:
 + *
 + * const char *name
 + *   The name of the ioctl.  This is used for history logging.  If the
 + *   ioctl returns successfully (the callback returns 0), and allow_log
 + *   is true, then a history log entry will be recorded with the input &
 + *   output nvlists.  The log entry can be printed with "zpool history -i".
 + *
 + * zfs_ioc_t ioc
 + *   The ioctl request number, which userland will pass to ioctl(2).
 + *   We want newer versions of libzfs and libzfs_core to run against
 + *   existing zfs kernel modules (i.e. a deferred reboot after an update).
 + *   Therefore the ioctl numbers cannot change from release to release.
 + *
 + * zfs_secpolicy_func_t *secpolicy
 + *   This function will be called before the zfs_ioc_func_t, to
 + *   determine if this operation is permitted.  It should return EPERM
 + *   on failure, and 0 on success.  Checks include determining if the
 + *   dataset is visible in this zone, and if the user has either all
 + *   zfs privileges in the zone (SYS_MOUNT), or has been granted permission
 + *   to do this operation on this dataset with "zfs allow".
 + *
 + * zfs_ioc_namecheck_t namecheck
 + *   This specifies what to expect in the zfs_cmd_t:zc_name -- a pool
 + *   name, a dataset name, or nothing.  If the name is not well-formed,
 + *   the ioctl will fail and the callback will not be called.
 + *   Therefore, the callback can assume that the name is well-formed
 + *   (e.g. is null-terminated, doesn't have more than one '@' character,
 + *   doesn't have invalid characters).
 + *
 + * zfs_ioc_poolcheck_t pool_check
 + *   This specifies requirements on the pool state.  If the pool does
 + *   not meet them (is suspended or is readonly), the ioctl will fail
 + *   and the callback will not be called.  If any checks are specified
 + *   (i.e. it is not POOL_CHECK_NONE), namecheck must not be NO_NAME.
 + *   Multiple checks can be or-ed together (e.g. POOL_CHECK_SUSPENDED |
 + *   POOL_CHECK_READONLY).
 + *
 + * zfs_ioc_key_t *nvl_keys
 + *  The list of expected/allowable innvl input keys. This list is used
 + *  to validate the nvlist input to the ioctl.
 + *
 + * boolean_t smush_outnvlist
 + *   If smush_outnvlist is true, then the output is presumed to be a
 + *   list of errors, and it will be "smushed" down to fit into the
 + *   caller's buffer, by removing some entries and replacing them with a
 + *   single "N_MORE_ERRORS" entry indicating how many were removed.  See
 + *   nvlist_smush() for details.  If smush_outnvlist is false, and the
 + *   outnvlist does not fit into the userland-provided buffer, then the
 + *   ioctl will fail with ENOMEM.
 + *
 + * zfs_ioc_func_t *func
 + *   The callback function that will perform the operation.
 + *
 + *   The callback should return 0 on success, or an error number on
 + *   failure.  If the function fails, the userland ioctl will return -1,
 + *   and errno will be set to the callback's return value.  The callback
 + *   will be called with the following arguments:
 + *
 + *   const char *name
 + *     The name of the pool or dataset to operate on, from
 + *     zfs_cmd_t:zc_name.  The 'namecheck' argument specifies the
 + *     expected type (pool, dataset, or none).
 + *
 + *   nvlist_t *innvl
 + *     The input nvlist, deserialized from zfs_cmd_t:zc_nvlist_src.  Or
 + *     NULL if no input nvlist was provided.  Changes to this nvlist are
 + *     ignored.  If the input nvlist could not be deserialized, the
 + *     ioctl will fail and the callback will not be called.
 + *
 + *   nvlist_t *outnvl
 + *     The output nvlist, initially empty.  The callback can fill it in,
 + *     and it will be returned to userland by serializing it into
 + *     zfs_cmd_t:zc_nvlist_dst.  If it is non-empty, and serialization
 + *     fails (e.g. because the caller didn't supply a large enough
 + *     buffer), then the overall ioctl will fail.  See the
 + *     'smush_nvlist' argument above for additional behaviors.
 + *
 + *     There are two typical uses of the output nvlist:
 + *       - To return state, e.g. property values.  In this case,
 + *         smush_outnvlist should be false.  If the buffer was not large
 + *         enough, the caller will reallocate a larger buffer and try
 + *         the ioctl again.
 + *
 + *       - To return multiple errors from an ioctl which makes on-disk
 + *         changes.  In this case, smush_outnvlist should be true.
 + *         Ioctls which make on-disk modifications should generally not
 + *         use the outnvl if they succeed, because the caller can not
 + *         distinguish between the operation failing, and
 + *         deserialization failing.
 + *
 + * IOCTL Interface Errors
 + *
 + * The following ioctl input errors can be returned:
 + *   ZFS_ERR_IOC_CMD_UNAVAIL	the ioctl number is not supported by kernel
 + *   ZFS_ERR_IOC_ARG_UNAVAIL	an input argument is not supported by kernel
 + *   ZFS_ERR_IOC_ARG_REQUIRED	a required input argument is missing
 + *   ZFS_ERR_IOC_ARG_BADTYPE	an input argument has an invalid type
 + */
 +
 +#include <sys/types.h>
 +#include <sys/param.h>
 +#include <sys/errno.h>
- #include <sys/uio.h>
++#include <sys/uio_impl.h>
 +#include <sys/file.h>
 +#include <sys/kmem.h>
 +#include <sys/cmn_err.h>
 +#include <sys/stat.h>
 +#include <sys/zfs_ioctl.h>
 +#include <sys/zfs_quota.h>
 +#include <sys/zfs_vfsops.h>
 +#include <sys/zfs_znode.h>
 +#include <sys/zap.h>
 +#include <sys/spa.h>
 +#include <sys/spa_impl.h>
 +#include <sys/vdev.h>
 +#include <sys/vdev_impl.h>
 +#include <sys/dmu.h>
 +#include <sys/dsl_dir.h>
 +#include <sys/dsl_dataset.h>
 +#include <sys/dsl_prop.h>
 +#include <sys/dsl_deleg.h>
 +#include <sys/dmu_objset.h>
 +#include <sys/dmu_impl.h>
 +#include <sys/dmu_redact.h>
 +#include <sys/dmu_tx.h>
 +#include <sys/sunddi.h>
 +#include <sys/policy.h>
 +#include <sys/zone.h>
 +#include <sys/nvpair.h>
 +#include <sys/pathname.h>
 +#include <sys/fs/zfs.h>
 +#include <sys/zfs_ctldir.h>
 +#include <sys/zfs_dir.h>
 +#include <sys/zfs_onexit.h>
 +#include <sys/zvol.h>
 +#include <sys/dsl_scan.h>
 +#include <sys/fm/util.h>
 +#include <sys/dsl_crypt.h>
 +#include <sys/rrwlock.h>
 +#include <sys/zfs_file.h>
 +
 +#include <sys/dmu_recv.h>
 +#include <sys/dmu_send.h>
 +#include <sys/dmu_recv.h>
 +#include <sys/dsl_destroy.h>
 +#include <sys/dsl_bookmark.h>
 +#include <sys/dsl_userhold.h>
 +#include <sys/zfeature.h>
 +#include <sys/zcp.h>
 +#include <sys/zio_checksum.h>
 +#include <sys/vdev_removal.h>
 +#include <sys/vdev_impl.h>
 +#include <sys/vdev_initialize.h>
 +#include <sys/vdev_trim.h>
 +
 +#include "zfs_namecheck.h"
 +#include "zfs_prop.h"
 +#include "zfs_deleg.h"
 +#include "zfs_comutil.h"
 +
 +#include <sys/lua/lua.h>
 +#include <sys/lua/lauxlib.h>
 +#include <sys/zfs_ioctl_impl.h>
 +
 +kmutex_t zfsdev_state_lock;
 +zfsdev_state_t *zfsdev_state_list;
 +
 +/*
 + * Limit maximum nvlist size.  We don't want users passing in insane values
 + * for zc->zc_nvlist_src_size, since we will need to allocate that much memory.
 + * Defaults to 0=auto which is handled by platform code.
 + */
 +unsigned long zfs_max_nvlist_src_size = 0;
 +
 +/*
 + * When logging the output nvlist of an ioctl in the on-disk history, limit
 + * the logged size to this many bytes.  This must be less then DMU_MAX_ACCESS.
 + * This applies primarily to zfs_ioc_channel_program().
 + */
 +unsigned long zfs_history_output_max = 1024 * 1024;
 +
 +uint_t zfs_fsyncer_key;
 +uint_t zfs_allow_log_key;
 +
 +/* DATA_TYPE_ANY is used when zkey_type can vary. */
 +#define	DATA_TYPE_ANY	DATA_TYPE_UNKNOWN
 +
 +typedef struct zfs_ioc_vec {
 +	zfs_ioc_legacy_func_t	*zvec_legacy_func;
 +	zfs_ioc_func_t		*zvec_func;
 +	zfs_secpolicy_func_t	*zvec_secpolicy;
 +	zfs_ioc_namecheck_t	zvec_namecheck;
 +	boolean_t		zvec_allow_log;
 +	zfs_ioc_poolcheck_t	zvec_pool_check;
 +	boolean_t		zvec_smush_outnvlist;
 +	const char		*zvec_name;
 +	const zfs_ioc_key_t	*zvec_nvl_keys;
 +	size_t			zvec_nvl_key_count;
 +} zfs_ioc_vec_t;
 +
 +/* This array is indexed by zfs_userquota_prop_t */
 +static const char *userquota_perms[] = {
 +	ZFS_DELEG_PERM_USERUSED,
 +	ZFS_DELEG_PERM_USERQUOTA,
 +	ZFS_DELEG_PERM_GROUPUSED,
 +	ZFS_DELEG_PERM_GROUPQUOTA,
 +	ZFS_DELEG_PERM_USEROBJUSED,
 +	ZFS_DELEG_PERM_USEROBJQUOTA,
 +	ZFS_DELEG_PERM_GROUPOBJUSED,
 +	ZFS_DELEG_PERM_GROUPOBJQUOTA,
 +	ZFS_DELEG_PERM_PROJECTUSED,
 +	ZFS_DELEG_PERM_PROJECTQUOTA,
 +	ZFS_DELEG_PERM_PROJECTOBJUSED,
 +	ZFS_DELEG_PERM_PROJECTOBJQUOTA,
 +};
 +
 +static int zfs_ioc_userspace_upgrade(zfs_cmd_t *zc);
 +static int zfs_ioc_id_quota_upgrade(zfs_cmd_t *zc);
 +static int zfs_check_settable(const char *name, nvpair_t *property,
 +    cred_t *cr);
 +static int zfs_check_clearable(const char *dataset, nvlist_t *props,
 +    nvlist_t **errors);
 +static int zfs_fill_zplprops_root(uint64_t, nvlist_t *, nvlist_t *,
 +    boolean_t *);
 +int zfs_set_prop_nvlist(const char *, zprop_source_t, nvlist_t *, nvlist_t *);
 +static int get_nvlist(uint64_t nvl, uint64_t size, int iflag, nvlist_t **nvp);
 +
 +static void
 +history_str_free(char *buf)
 +{
 +	kmem_free(buf, HIS_MAX_RECORD_LEN);
 +}
 +
 +static char *
 +history_str_get(zfs_cmd_t *zc)
 +{
 +	char *buf;
 +
 +	if (zc->zc_history == 0)
 +		return (NULL);
 +
 +	buf = kmem_alloc(HIS_MAX_RECORD_LEN, KM_SLEEP);
 +	if (copyinstr((void *)(uintptr_t)zc->zc_history,
 +	    buf, HIS_MAX_RECORD_LEN, NULL) != 0) {
 +		history_str_free(buf);
 +		return (NULL);
 +	}
 +
 +	buf[HIS_MAX_RECORD_LEN -1] = '\0';
 +
 +	return (buf);
 +}
 +
 +/*
 + * Return non-zero if the spa version is less than requested version.
 + */
 +static int
 +zfs_earlier_version(const char *name, int version)
 +{
 +	spa_t *spa;
 +
 +	if (spa_open(name, &spa, FTAG) == 0) {
 +		if (spa_version(spa) < version) {
 +			spa_close(spa, FTAG);
 +			return (1);
 +		}
 +		spa_close(spa, FTAG);
 +	}
 +	return (0);
 +}
 +
 +/*
 + * Return TRUE if the ZPL version is less than requested version.
 + */
 +static boolean_t
 +zpl_earlier_version(const char *name, int version)
 +{
 +	objset_t *os;
 +	boolean_t rc = B_TRUE;
 +
 +	if (dmu_objset_hold(name, FTAG, &os) == 0) {
 +		uint64_t zplversion;
 +
 +		if (dmu_objset_type(os) != DMU_OST_ZFS) {
 +			dmu_objset_rele(os, FTAG);
 +			return (B_TRUE);
 +		}
 +		/* XXX reading from non-owned objset */
 +		if (zfs_get_zplprop(os, ZFS_PROP_VERSION, &zplversion) == 0)
 +			rc = zplversion < version;
 +		dmu_objset_rele(os, FTAG);
 +	}
 +	return (rc);
 +}
 +
 +static void
 +zfs_log_history(zfs_cmd_t *zc)
 +{
 +	spa_t *spa;
 +	char *buf;
 +
 +	if ((buf = history_str_get(zc)) == NULL)
 +		return;
 +
 +	if (spa_open(zc->zc_name, &spa, FTAG) == 0) {
 +		if (spa_version(spa) >= SPA_VERSION_ZPOOL_HISTORY)
 +			(void) spa_history_log(spa, buf);
 +		spa_close(spa, FTAG);
 +	}
 +	history_str_free(buf);
 +}
 +
 +/*
 + * Policy for top-level read operations (list pools).  Requires no privileges,
 + * and can be used in the local zone, as there is no associated dataset.
 + */
 +/* ARGSUSED */
 +static int
 +zfs_secpolicy_none(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 +{
 +	return (0);
 +}
 +
 +/*
 + * Policy for dataset read operations (list children, get statistics).  Requires
 + * no privileges, but must be visible in the local zone.
 + */
 +/* ARGSUSED */
 +static int
 +zfs_secpolicy_read(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 +{
 +	if (INGLOBALZONE(curproc) ||
 +	    zone_dataset_visible(zc->zc_name, NULL))
 +		return (0);
 +
 +	return (SET_ERROR(ENOENT));
 +}
 +
 +static int
 +zfs_dozonecheck_impl(const char *dataset, uint64_t zoned, cred_t *cr)
 +{
 +	int writable = 1;
 +
 +	/*
 +	 * The dataset must be visible by this zone -- check this first
 +	 * so they don't see EPERM on something they shouldn't know about.
 +	 */
 +	if (!INGLOBALZONE(curproc) &&
 +	    !zone_dataset_visible(dataset, &writable))
 +		return (SET_ERROR(ENOENT));
 +
 +	if (INGLOBALZONE(curproc)) {
 +		/*
 +		 * If the fs is zoned, only root can access it from the
 +		 * global zone.
 +		 */
 +		if (secpolicy_zfs(cr) && zoned)
 +			return (SET_ERROR(EPERM));
 +	} else {
 +		/*
 +		 * If we are in a local zone, the 'zoned' property must be set.
 +		 */
 +		if (!zoned)
 +			return (SET_ERROR(EPERM));
 +
 +		/* must be writable by this zone */
 +		if (!writable)
 +			return (SET_ERROR(EPERM));
 +	}
 +	return (0);
 +}
 +
 +static int
 +zfs_dozonecheck(const char *dataset, cred_t *cr)
 +{
 +	uint64_t zoned;
 +
 +	if (dsl_prop_get_integer(dataset, zfs_prop_to_name(ZFS_PROP_ZONED),
 +	    &zoned, NULL))
 +		return (SET_ERROR(ENOENT));
 +
 +	return (zfs_dozonecheck_impl(dataset, zoned, cr));
 +}
 +
 +static int
 +zfs_dozonecheck_ds(const char *dataset, dsl_dataset_t *ds, cred_t *cr)
 +{
 +	uint64_t zoned;
 +
 +	if (dsl_prop_get_int_ds(ds, zfs_prop_to_name(ZFS_PROP_ZONED), &zoned))
 +		return (SET_ERROR(ENOENT));
 +
 +	return (zfs_dozonecheck_impl(dataset, zoned, cr));
 +}
 +
 +static int
 +zfs_secpolicy_write_perms_ds(const char *name, dsl_dataset_t *ds,
 +    const char *perm, cred_t *cr)
 +{
 +	int error;
 +
 +	error = zfs_dozonecheck_ds(name, ds, cr);
 +	if (error == 0) {
 +		error = secpolicy_zfs(cr);
 +		if (error != 0)
 +			error = dsl_deleg_access_impl(ds, perm, cr);
 +	}
 +	return (error);
 +}
 +
 +static int
 +zfs_secpolicy_write_perms(const char *name, const char *perm, cred_t *cr)
 +{
 +	int error;
 +	dsl_dataset_t *ds;
 +	dsl_pool_t *dp;
 +
 +	/*
 +	 * First do a quick check for root in the global zone, which
 +	 * is allowed to do all write_perms.  This ensures that zfs_ioc_*
 +	 * will get to handle nonexistent datasets.
 +	 */
 +	if (INGLOBALZONE(curproc) && secpolicy_zfs(cr) == 0)
 +		return (0);
 +
 +	error = dsl_pool_hold(name, FTAG, &dp);
 +	if (error != 0)
 +		return (error);
 +
 +	error = dsl_dataset_hold(dp, name, FTAG, &ds);
 +	if (error != 0) {
 +		dsl_pool_rele(dp, FTAG);
 +		return (error);
 +	}
 +
 +	error = zfs_secpolicy_write_perms_ds(name, ds, perm, cr);
 +
 +	dsl_dataset_rele(ds, FTAG);
 +	dsl_pool_rele(dp, FTAG);
 +	return (error);
 +}
 +
 +/*
 + * Policy for setting the security label property.
 + *
 + * Returns 0 for success, non-zero for access and other errors.
 + */
 +static int
 +zfs_set_slabel_policy(const char *name, const char *strval, cred_t *cr)
 +{
 +#ifdef HAVE_MLSLABEL
 +	char		ds_hexsl[MAXNAMELEN];
 +	bslabel_t	ds_sl, new_sl;
 +	boolean_t	new_default = FALSE;
 +	uint64_t	zoned;
 +	int		needed_priv = -1;
 +	int		error;
 +
 +	/* First get the existing dataset label. */
 +	error = dsl_prop_get(name, zfs_prop_to_name(ZFS_PROP_MLSLABEL),
 +	    1, sizeof (ds_hexsl), &ds_hexsl, NULL);
 +	if (error != 0)
 +		return (SET_ERROR(EPERM));
 +
 +	if (strcasecmp(strval, ZFS_MLSLABEL_DEFAULT) == 0)
 +		new_default = TRUE;
 +
 +	/* The label must be translatable */
 +	if (!new_default && (hexstr_to_label(strval, &new_sl) != 0))
 +		return (SET_ERROR(EINVAL));
 +
 +	/*
 +	 * In a non-global zone, disallow attempts to set a label that
 +	 * doesn't match that of the zone; otherwise no other checks
 +	 * are needed.
 +	 */
 +	if (!INGLOBALZONE(curproc)) {
 +		if (new_default || !blequal(&new_sl, CR_SL(CRED())))
 +			return (SET_ERROR(EPERM));
 +		return (0);
 +	}
 +
 +	/*
 +	 * For global-zone datasets (i.e., those whose zoned property is
 +	 * "off", verify that the specified new label is valid for the
 +	 * global zone.
 +	 */
 +	if (dsl_prop_get_integer(name,
 +	    zfs_prop_to_name(ZFS_PROP_ZONED), &zoned, NULL))
 +		return (SET_ERROR(EPERM));
 +	if (!zoned) {
 +		if (zfs_check_global_label(name, strval) != 0)
 +			return (SET_ERROR(EPERM));
 +	}
 +
 +	/*
 +	 * If the existing dataset label is nondefault, check if the
 +	 * dataset is mounted (label cannot be changed while mounted).
 +	 * Get the zfsvfs_t; if there isn't one, then the dataset isn't
 +	 * mounted (or isn't a dataset, doesn't exist, ...).
 +	 */
 +	if (strcasecmp(ds_hexsl, ZFS_MLSLABEL_DEFAULT) != 0) {
 +		objset_t *os;
 +		static const char *setsl_tag = "setsl_tag";
 +
 +		/*
 +		 * Try to own the dataset; abort if there is any error,
 +		 * (e.g., already mounted, in use, or other error).
 +		 */
 +		error = dmu_objset_own(name, DMU_OST_ZFS, B_TRUE, B_TRUE,
 +		    setsl_tag, &os);
 +		if (error != 0)
 +			return (SET_ERROR(EPERM));
 +
 +		dmu_objset_disown(os, B_TRUE, setsl_tag);
 +
 +		if (new_default) {
 +			needed_priv = PRIV_FILE_DOWNGRADE_SL;
*** 13292 LINES SKIPPED ***


More information about the dev-commits-src-all mailing list