diff options
Diffstat (limited to 'lib/libzfs')
25 files changed, 0 insertions, 38887 deletions
diff --git a/lib/libzfs/.gitignore b/lib/libzfs/.gitignore deleted file mode 100644 index 9336a5c00b46..000000000000 --- a/lib/libzfs/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/libzfs.pc diff --git a/lib/libzfs/Makefile.am b/lib/libzfs/Makefile.am deleted file mode 100644 index 5f8963dccd1a..000000000000 --- a/lib/libzfs/Makefile.am +++ /dev/null @@ -1,78 +0,0 @@ -libzfs_la_CFLAGS = $(AM_CFLAGS) $(LIBRARY_CFLAGS) -libzfs_la_CFLAGS += $(LIBCRYPTO_CFLAGS) $(ZLIB_CFLAGS) -libzfs_la_CFLAGS += -fvisibility=hidden - -lib_LTLIBRARIES += libzfs.la -CPPCHECKTARGETS += libzfs.la - -dist_libzfs_la_SOURCES = \ - %D%/libzfs_impl.h \ - %D%/libzfs_changelist.c \ - %D%/libzfs_config.c \ - %D%/libzfs_crypto.c \ - %D%/libzfs_dataset.c \ - %D%/libzfs_diff.c \ - %D%/libzfs_import.c \ - %D%/libzfs_iter.c \ - %D%/libzfs_mount.c \ - %D%/libzfs_pool.c \ - %D%/libzfs_sendrecv.c \ - %D%/libzfs_status.c \ - %D%/libzfs_util.c - -if BUILD_FREEBSD -dist_libzfs_la_SOURCES += \ - %D%/os/freebsd/libzfs_compat.c \ - %D%/os/freebsd/libzfs_zmount.c -endif - -if BUILD_LINUX -dist_libzfs_la_SOURCES += \ - %D%/os/linux/libzfs_mount_os.c \ - %D%/os/linux/libzfs_pool_os.c \ - %D%/os/linux/libzfs_util_os.c -endif - -nodist_libzfs_la_SOURCES = \ - module/zcommon/cityhash.c \ - module/zcommon/zfeature_common.c \ - module/zcommon/zfs_comutil.c \ - module/zcommon/zfs_deleg.c \ - module/zcommon/zfs_fletcher.c \ - module/zcommon/zfs_fletcher_aarch64_neon.c \ - module/zcommon/zfs_fletcher_avx512.c \ - module/zcommon/zfs_fletcher_intel.c \ - module/zcommon/zfs_fletcher_sse.c \ - module/zcommon/zfs_fletcher_superscalar.c \ - module/zcommon/zfs_fletcher_superscalar4.c \ - module/zcommon/zfs_namecheck.c \ - module/zcommon/zfs_prop.c \ - module/zcommon/zfs_valstr.c \ - module/zcommon/zpool_prop.c \ - module/zcommon/zprop_common.c - -libzfs_la_LIBADD = \ - libshare.la \ - libzfs_core.la \ - libnvpair.la \ - libzutil.la \ - libuutil.la - -libzfs_la_LIBADD += -lrt -lm $(LIBCRYPTO_LIBS) $(ZLIB_LIBS) $(LIBFETCH_LIBS) $(LTLIBINTL) - -libzfs_la_LDFLAGS = -pthread - -if !ASAN_ENABLED -libzfs_la_LDFLAGS += -Wl,-z,defs -endif - -if BUILD_FREEBSD -libzfs_la_LIBADD += -lutil -lgeom -endif - -libzfs_la_LDFLAGS += -version-info 6:0:0 - -pkgconfig_DATA += %D%/libzfs.pc - -dist_noinst_DATA += %D%/libzfs.abi %D%/libzfs.suppr -dist_noinst_DATA += %D%/THIRDPARTYLICENSE.openssl %D%/THIRDPARTYLICENSE.openssl.descrip diff --git a/lib/libzfs/THIRDPARTYLICENSE.openssl b/lib/libzfs/THIRDPARTYLICENSE.openssl deleted file mode 100644 index 92c9e196a318..000000000000 --- a/lib/libzfs/THIRDPARTYLICENSE.openssl +++ /dev/null @@ -1,127 +0,0 @@ - - LICENSE ISSUES - ============== - - The OpenSSL toolkit stays under a dual license, i.e. both the conditions of - the OpenSSL License and the original SSLeay license apply to the toolkit. - See below for the actual license texts. Actually both licenses are BSD-style - Open Source licenses. In case of any license issues related to OpenSSL - please contact openssl-core@openssl.org. - - OpenSSL License - --------------- - -/* ==================================================================== - * Copyright (c) 1998-2008 The OpenSSL Project. All rights reserved. - * - * 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. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED 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 OpenSSL PROJECT OR - * ITS 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. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). - * - */ - - Original SSLeay License - ----------------------- - -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * 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 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the routines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ - diff --git a/lib/libzfs/THIRDPARTYLICENSE.openssl.descrip b/lib/libzfs/THIRDPARTYLICENSE.openssl.descrip deleted file mode 100644 index a9125ea21122..000000000000 --- a/lib/libzfs/THIRDPARTYLICENSE.openssl.descrip +++ /dev/null @@ -1 +0,0 @@ -PBKDF2 IMPLEMENTATION diff --git a/lib/libzfs/libzfs.abi b/lib/libzfs/libzfs.abi deleted file mode 100644 index f988d27a286a..000000000000 --- a/lib/libzfs/libzfs.abi +++ /dev/null @@ -1,10281 +0,0 @@ -<abi-corpus version='2.0' architecture='elf-amd-x86_64' soname='libzfs.so.6'> - <elf-needed> - <dependency name='libzfs_core.so.3'/> - <dependency name='libnvpair.so.3'/> - <dependency name='libunwind.so.8'/> - <dependency name='libuuid.so.1'/> - <dependency name='libblkid.so.1'/> - <dependency name='libudev.so.1'/> - <dependency name='libuutil.so.3'/> - <dependency name='libm.so.6'/> - <dependency name='libcrypto.so.3'/> - <dependency name='libz.so.1'/> - <dependency name='libc.so.6'/> - <dependency name='ld-linux-x86-64.so.2'/> - </elf-needed> - <elf-function-symbols> - <elf-symbol name='_sol_getmntent' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_add_16' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_add_16_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_add_32' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_add_32_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_add_64' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_add_64_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_add_8' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_add_8_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_add_char' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_add_char_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_add_int' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_add_int_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_add_long' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_add_long_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_add_ptr' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_add_ptr_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_add_short' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_add_short_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_and_16' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_and_16_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_and_32' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_and_32_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_and_64' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_and_64_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_and_8' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_and_8_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_and_uchar' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_and_uchar_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_and_uint' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_and_uint_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_and_ulong' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_and_ulong_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_and_ushort' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_and_ushort_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_cas_16' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_cas_32' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_cas_64' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_cas_8' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_cas_ptr' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_cas_uchar' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_cas_uint' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_cas_ulong' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_cas_ushort' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_clear_long_excl' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_dec_16' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_dec_16_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_dec_32' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_dec_32_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_dec_64' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_dec_64_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_dec_8' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_dec_8_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_dec_uchar' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_dec_uchar_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_dec_uint' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_dec_uint_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_dec_ulong' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_dec_ulong_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_dec_ushort' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_dec_ushort_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_inc_16' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_inc_16_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_inc_32' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_inc_32_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_inc_64' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_inc_64_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_inc_8' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_inc_8_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_inc_uchar' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_inc_uchar_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_inc_uint' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_inc_uint_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_inc_ulong' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_inc_ulong_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_inc_ushort' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_inc_ushort_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_or_16' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_or_16_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_or_32' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_or_32_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_or_64' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_or_64_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_or_8' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_or_8_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_or_uchar' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_or_uchar_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_or_uint' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_or_uint_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_or_ulong' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_or_ulong_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_or_ushort' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_or_ushort_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_set_long_excl' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_sub_16' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_sub_16_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_sub_32' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_sub_32_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_sub_64' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_sub_64_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_sub_8' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_sub_8_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_sub_char' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_sub_char_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_sub_int' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_sub_int_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_sub_long' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_sub_long_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_sub_ptr' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_sub_ptr_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_sub_short' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_sub_short_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_swap_16' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_swap_32' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_swap_64' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_swap_8' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_swap_ptr' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_swap_uchar' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_swap_uint' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_swap_ulong' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='atomic_swap_ushort' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='avl_add' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='avl_create' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='avl_destroy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='avl_destroy_nodes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='avl_find' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='avl_first' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='avl_insert' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='avl_insert_here' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='avl_is_empty' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='avl_last' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='avl_nearest' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='avl_numnodes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='avl_remove' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='avl_swap' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='avl_update' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='avl_update_gt' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='avl_update_lt' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='avl_walk' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='bookmark_namecheck' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='cityhash1' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='cityhash2' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='cityhash3' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='cityhash4' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='color_end' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='color_start' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='dataset_namecheck' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='dataset_nestcheck' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='efi_alloc_and_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='efi_alloc_and_read' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='efi_err_check' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='efi_free' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='efi_rescan' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='efi_use_whole_disk' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='efi_write' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='entity_namecheck' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='fletcher_2_byteswap' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='fletcher_2_incremental_byteswap' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='fletcher_2_incremental_native' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='fletcher_2_native' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='fletcher_4_byteswap' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='fletcher_4_fini' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='fletcher_4_impl_set' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='fletcher_4_incremental_byteswap' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='fletcher_4_incremental_native' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='fletcher_4_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='fletcher_4_native' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='fletcher_4_native_varsize' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='fletcher_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='format_timestamp' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='fsleep' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='get_dataset_depth' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='get_system_hostid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='get_timestamp' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='getexecname' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='getextmntent' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='getmntany' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='getprop_uint64' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='getzoneid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='is_mounted' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='is_mpath_whole_disk' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='libpc_error_description' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='libspl_assertf' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='libspl_backtrace' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='libspl_set_assert_ok' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='libzfs_add_handle' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='libzfs_envvar_is_set' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='libzfs_errno' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='libzfs_error_action' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='libzfs_error_description' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='libzfs_error_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='libzfs_fini' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='libzfs_free_str_array' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='libzfs_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='libzfs_mnttab_add' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='libzfs_mnttab_cache' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='libzfs_mnttab_find' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='libzfs_mnttab_fini' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='libzfs_mnttab_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='libzfs_mnttab_remove' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='libzfs_print_on_error' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='libzfs_run_process' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='libzfs_run_process_get_stdout' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='libzfs_run_process_get_stdout_nopath' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='list_create' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='list_destroy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='list_head' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='list_insert_after' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='list_insert_before' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='list_insert_head' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='list_insert_tail' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='list_is_empty' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='list_link_active' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='list_link_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='list_link_replace' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='list_move_tail' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='list_next' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='list_prev' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='list_remove' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='list_remove_head' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='list_remove_tail' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='list_tail' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='membar_consumer' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='membar_enter' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='membar_exit' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='membar_producer' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='membar_sync' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='mkdirp' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='mountpoint_namecheck' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='permset_namecheck' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='pool_namecheck' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='print_timestamp' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='printf_color' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='sa_commit_shares' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='sa_disable_share' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='sa_enable_share' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='sa_errorstr' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='sa_is_shared' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='sa_truncate_shares' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='sa_validate_shareopts' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='snapshot_namecheck' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='spl_pagesize' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='strlcat' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='strlcpy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='tpool_abandon' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='tpool_create' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='tpool_destroy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='tpool_dispatch' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='tpool_member' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='tpool_resume' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='tpool_suspend' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='tpool_suspended' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='tpool_wait' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='update_vdev_config_dev_strs' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='update_vdev_config_dev_sysfs_path' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='use_color' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='vdev_expand_proplist' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='vdev_name_to_prop' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='vdev_prop_align_right' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='vdev_prop_column_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='vdev_prop_default_numeric' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='vdev_prop_default_string' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='vdev_prop_get_table' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='vdev_prop_get_type' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='vdev_prop_index_to_string' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='vdev_prop_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='vdev_prop_random_value' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='vdev_prop_readonly' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='vdev_prop_string_to_index' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='vdev_prop_to_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='vdev_prop_user' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='vdev_prop_values' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zcmd_print_json' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfeature_depends_on' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfeature_is_supported' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfeature_is_valid_guid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfeature_lookup_guid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfeature_lookup_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_adjust_mount_options' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_allocatable_devs' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_append_partition' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_basename' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_bookmark_exists' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_clone' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_close' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_commit_shares' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_component_namecheck' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_create' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_create_ancestors' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_crypto_attempt_load_keys' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_crypto_clone_check' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_crypto_create' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_crypto_get_encryption_root' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_crypto_load_key' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_crypto_rewrap' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_crypto_unload_key' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_dataset_exists' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_dataset_name_hidden' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_deleg_canonicalize_perm' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_deleg_verify_nvlist' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_deleg_whokey' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_destroy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_destroy_snaps' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_destroy_snaps_nvl' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_destroy_snaps_nvl_os' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_dev_flush' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_dev_is_dm' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_dev_is_whole_disk' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_device_get_devid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_device_get_physical' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_dirnamelen' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_expand_proplist' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_foreach_mountpoint' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_get_all_props' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_get_clones_nvl' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_get_enclosure_sysfs_path' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_get_fsacl' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_get_handle' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_get_holds' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_get_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_get_pool_handle' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_get_pool_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_get_recvd_props' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_get_type' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_get_underlying_path' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_get_underlying_type' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_get_user_props' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_handle_dup' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_hold' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_hold_nvl' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_ioctl' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_is_encrypted' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_is_mounted' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_is_shared' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_isnumber' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_iter_bookmarks' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_iter_bookmarks_v2' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_iter_children' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_iter_children_v2' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_iter_dependents' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_iter_dependents_v2' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_iter_filesystems' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_iter_filesystems_v2' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_iter_mounted' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_iter_root' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_iter_snapshots' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_iter_snapshots_sorted' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_iter_snapshots_sorted_v2' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_iter_snapshots_v2' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_iter_snapspec' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_iter_snapspec_v2' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_mod_supported' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_mount' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_mount_at' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_mount_delegation_check' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_name_to_prop' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_name_valid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_nicebytes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_nicenum' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_nicenum_format' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_niceraw' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_nicestrtonum' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_nicetime' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_open' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_parent_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_parse_mount_options' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_path_to_zhandle' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_promote' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_align_right' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_column_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_default_numeric' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_default_string' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_delegatable' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_encryption_key_param' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_get' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_get_int' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_get_numeric' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_get_recvd' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_get_table' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_get_type' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_get_userquota' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_get_userquota_int' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_get_written' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_get_written_int' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_index_to_string' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_inherit' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_inheritable' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_is_string' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_random_value' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_readonly' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_set' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_set_list' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_set_list_flags' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_setonce' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_string_to_index' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_to_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_user' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_userquota' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_valid_for_type' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_valid_keylocation' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_values' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_visible' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prop_written' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_prune_proplist' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_receive' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_refresh_properties' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_release' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_rename' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_resolve_shortname' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_rollback' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_save_arguments' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_send' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_send_one' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_send_progress' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_send_resume' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_send_resume_token_to_nvlist' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_send_saved' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_set_fsacl' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_setproctitle' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_setproctitle_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_share' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_show_diffs' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_smb_acl_add' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_smb_acl_purge' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_smb_acl_remove' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_smb_acl_rename' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_snapshot' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_snapshot_nvl' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_spa_version' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_spa_version_map' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_special_devs' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_standard_error' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_strcmp_pathname' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_strip_partition' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_strip_path' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_truncate_shares' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_tunable_get' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_tunable_iter' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_tunable_lookup' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_tunable_set' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_type_to_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_unmount' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_unmountall' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_unshare' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_unshareall' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_userns' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_userspace' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_valid_proplist' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_valstr_zio_flag' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_valstr_zio_flag_bits' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_valstr_zio_flag_pairs' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_valstr_zio_priority' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_valstr_zio_stage' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_valstr_zio_stage_bits' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_valstr_zio_stage_pairs' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_valstr_zio_type' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_version_kernel' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_version_nvlist' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_version_print' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_version_userland' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_wait_status' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_zpl_version_map' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_add' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_add_propname' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_checkpoint' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_clear' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_clear_label' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_close' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_collect_leaves' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_collect_unsup_feat' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_create' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_ddt_prune' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_default_search_paths' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_destroy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_disable_datasets' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_disable_datasets_os' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_disable_volume_os' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_discard_checkpoint' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_disk_wait' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_dump_ddt' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_enable_datasets' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_events_clear' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_events_next' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_events_seek' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_expand_proplist' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_explain_recover' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_export' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_export_force' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_feature_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_find_config' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_find_parent_vdev' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_find_vdev' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_find_vdev_by_physpath' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_free_handles' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_get_all_vdev_props' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_get_bootenv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_get_config' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_get_errlog' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_get_features' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_get_handle' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_get_history' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_get_load_policy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_get_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_get_prop' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_get_prop_int' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_get_state' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_get_state_str' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_get_status' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_get_userprop' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_get_vdev_prop' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_get_vdev_prop_value' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_getenv_int' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_history_unpack' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_import' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_import_props' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_import_status' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_in_use' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_initialize' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_initialize_one' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_initialize_wait' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_is_draid_spare' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_iter' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_label_disk' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_label_disk_wait' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_load_compat' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_log_history' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_name_to_prop' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_obj_to_path' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_obj_to_path_ds' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_open' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_open_canfail' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_pool_state_to_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_prefetch' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_prepare_and_label_disk' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_prepare_disk' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_prop_align_right' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_prop_column_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_prop_default_numeric' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_prop_default_string' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_prop_feature' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_prop_get_feature' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_prop_get_table' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_prop_get_type' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_prop_index_to_string' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_prop_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_prop_random_value' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_prop_readonly' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_prop_setonce' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_prop_string_to_index' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_prop_to_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_prop_unsupported' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_prop_values' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_prop_vdev' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_props_refresh' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_read_label' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_refresh_stats' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_refresh_stats_from_handle' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_reguid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_reopen_one' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_scan' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_scan_range' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_search_import' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_set_bootenv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_set_guid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_set_prop' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_set_vdev_prop' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_skip_pool' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_state_to_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_sync_one' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_trim' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_trim_one' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_upgrade' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_vdev_attach' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_vdev_clear' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_vdev_degrade' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_vdev_detach' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_vdev_fault' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_vdev_indirect_size' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_vdev_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_vdev_offline' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_vdev_online' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_vdev_path_to_guid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_vdev_remove' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_vdev_remove_cancel' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_vdev_remove_wanted' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_vdev_script_alloc_env' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_vdev_script_free_env' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_vdev_set_removed_state' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_vdev_split' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_wait' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zpool_wait_status' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zprop_collect_property' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zprop_free_list' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zprop_get_list' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zprop_index_to_string' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zprop_iter' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zprop_iter_common' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zprop_name_to_prop' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zprop_nvlist_one_property' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zprop_print_one_property' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zprop_random_value' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zprop_register_hidden' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zprop_register_impl' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zprop_register_index' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zprop_register_number' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zprop_register_string' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zprop_string_to_index' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zprop_valid_char' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zprop_valid_for_type' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zprop_values' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zprop_width' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zvol_volsize_to_reservation' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - </elf-function-symbols> - <elf-variable-symbols> - <elf-symbol name='efi_debug' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='fletcher_4_abd_ops' size='24' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='fletcher_4_avx2_ops' size='128' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='fletcher_4_avx512bw_ops' size='128' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='fletcher_4_avx512f_ops' size='128' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='fletcher_4_sse2_ops' size='128' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='fletcher_4_ssse3_ops' size='128' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='fletcher_4_superscalar4_ops' size='128' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='fletcher_4_superscalar_ops' size='128' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='libzfs_config_ops' size='16' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='sa_protocol_names' size='16' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='spa_feature_table' size='2632' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfeature_checks_disable' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_deleg_perm_tab' size='544' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_history_event_names' size='328' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_max_dataset_nesting' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_userquota_prop_prefixes' size='96' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - </elf-variable-symbols> - <abi-instr address-size='64' path='lib/libefi/rdwr_efi.c' language='LANG_C99'> - <typedef-decl name='uInt' type-id='f0981eeb' id='09110a74'/> - <var-decl name='efi_debug' type-id='95e97e5e' mangled-name='efi_debug' visibility='default' elf-symbol-id='efi_debug'/> - <function-decl name='uuid_generate' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='cf536864'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='uuid_is_null' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='354f7eb9'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='crc32' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5bbcce85'/> - <parameter type-id='e8cb3e0e'/> - <parameter type-id='09110a74'/> - <return type-id='5bbcce85'/> - </function-decl> - <function-decl name='efi_err_check' mangled-name='efi_err_check' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='efi_err_check'> - <parameter type-id='0d8119a8' name='vtoc'/> - <return type-id='48b5725f'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='lib/libshare/libshare.c' language='LANG_C99'> - <array-type-def dimensions='1' type-id='b99c00c9' size-in-bits='128' id='2d6895a3'> - <subrange length='2' type-id='7359adad' id='52efc4ef'/> - </array-type-def> - <var-decl name='sa_protocol_names' type-id='2d6895a3' mangled-name='sa_protocol_names' visibility='default' elf-symbol-id='sa_protocol_names'/> - <type-decl name='unsigned long int' size-in-bits='64' id='7359adad'/> - </abi-instr> - <abi-instr address-size='64' path='lib/libshare/nfs.c' language='LANG_C99'> - <function-decl name='rename' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='memchr' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='eaa32e2f'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='b59d7dce'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='flock' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='fchmod' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <parameter type-id='e1c52942'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='mkdir' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='e1c52942'/> - <return type-id='95e97e5e'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='lib/libshare/os/linux/nfs.c' language='LANG_C99'> - <class-decl name='sa_share_impl' size-in-bits='192' is-struct='yes' visibility='default' id='72b09bf8'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='sa_zfsname' type-id='80f4b756' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='sa_mountpoint' type-id='80f4b756' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='sa_shareopts' type-id='80f4b756' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='sa_share_impl_t' type-id='946a2c6b' id='a48b47d0'/> - <class-decl name='sa_fstype_t' size-in-bits='384' is-struct='yes' naming-typedef-id='639af739' visibility='default' id='944afa86'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='enable_share' type-id='2f78a9c1' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='disable_share' type-id='2f78a9c1' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='is_shared' type-id='81020bc2' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='validate_shareopts' type-id='f194a8fb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='commit_shares' type-id='797ee7da' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='truncate_shares' type-id='5d51038b' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='sa_fstype_t' type-id='944afa86' id='639af739'/> - <qualified-type-def type-id='639af739' const='yes' id='d19dbca9'/> - <qualified-type-def type-id='72b09bf8' const='yes' id='484950e3'/> - <pointer-type-def type-id='484950e3' size-in-bits='64' id='946a2c6b'/> - <pointer-type-def type-id='276427e1' size-in-bits='64' id='1db260e5'/> - <qualified-type-def type-id='1db260e5' const='yes' id='797ee7da'/> - <pointer-type-def type-id='5113b296' size-in-bits='64' id='70487b28'/> - <qualified-type-def type-id='70487b28' const='yes' id='f194a8fb'/> - <pointer-type-def type-id='c13578bc' size-in-bits='64' id='fa1f29ce'/> - <qualified-type-def type-id='fa1f29ce' const='yes' id='2f78a9c1'/> - <pointer-type-def type-id='723e6cf2' size-in-bits='64' id='1d99e49c'/> - <pointer-type-def type-id='86373eb1' size-in-bits='64' id='f337456d'/> - <qualified-type-def type-id='f337456d' const='yes' id='81020bc2'/> - <qualified-type-def type-id='953b12f8' const='yes' id='5d51038b'/> - <var-decl name='libshare_nfs_type' type-id='d19dbca9' visibility='default'/> - <function-decl name='nfs_escape_mountpoint' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='9b23c9ad'/> - <parameter type-id='37e3bd22'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='nfs_is_shared_impl' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='a48b47d0'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='nfs_toggle_share' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <parameter type-id='a48b47d0'/> - <parameter type-id='1d99e49c'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='nfs_reset_shares' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <return type-id='48b5725f'/> - </function-decl> - <function-type size-in-bits='64' id='276427e1'> - <return type-id='95e97e5e'/> - </function-type> - <function-type size-in-bits='64' id='5113b296'> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-type> - <function-type size-in-bits='64' id='c13578bc'> - <parameter type-id='a48b47d0'/> - <return type-id='95e97e5e'/> - </function-type> - <function-type size-in-bits='64' id='723e6cf2'> - <parameter type-id='a48b47d0'/> - <parameter type-id='822cd80b'/> - <return type-id='95e97e5e'/> - </function-type> - <function-type size-in-bits='64' id='86373eb1'> - <parameter type-id='a48b47d0'/> - <return type-id='c19b74c3'/> - </function-type> - <function-type size-in-bits='64' id='ee076206'> - <return type-id='48b5725f'/> - </function-type> - </abi-instr> - <abi-instr address-size='64' path='lib/libshare/os/linux/smb.c' language='LANG_C99'> - <var-decl name='libshare_smb_type' type-id='d19dbca9' visibility='default'/> - <function-decl name='__fgets_chk' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='266fe297'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='e75a27e9'/> - <return type-id='26a90f95'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='lib/libspl/assert.c' language='LANG_C99'> - <function-decl name='libspl_backtrace' mangled-name='libspl_backtrace' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_backtrace'> - <parameter type-id='95e97e5e'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='gettid' visibility='default' binding='global' size-in-bits='64'> - <return type-id='3629bad8'/> - </function-decl> - <function-decl name='prctl' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <parameter is-variadic='yes'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='libspl_set_assert_ok' mangled-name='libspl_set_assert_ok' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_set_assert_ok'> - <parameter type-id='c19b74c3' name='val'/> - <return type-id='48b5725f'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='lib/libspl/atomic.c' language='LANG_C99'> - <typedef-decl name='int8_t' type-id='2171a512' id='ee31ee44'/> - <typedef-decl name='__int8_t' type-id='28577a57' id='2171a512'/> - <qualified-type-def type-id='149c6638' volatile='yes' id='5120c5f7'/> - <pointer-type-def type-id='5120c5f7' size-in-bits='64' id='93977ae7'/> - <qualified-type-def type-id='b96825af' volatile='yes' id='84ff7d66'/> - <pointer-type-def type-id='84ff7d66' size-in-bits='64' id='aa323ea4'/> - <qualified-type-def type-id='ee1f298e' volatile='yes' id='6f7e09cb'/> - <pointer-type-def type-id='6f7e09cb' size-in-bits='64' id='64698d33'/> - <function-decl name='atomic_inc_8' mangled-name='atomic_inc_8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_inc_8'> - <parameter type-id='aa323ea4' name='target'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='atomic_inc_16' mangled-name='atomic_inc_16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_inc_16'> - <parameter type-id='93977ae7' name='target'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='atomic_inc_32' mangled-name='atomic_inc_32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_inc_32'> - <parameter type-id='3a147f31' name='target'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='atomic_inc_ulong' mangled-name='atomic_inc_ulong' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_inc_ulong'> - <parameter type-id='64698d33' name='target'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='atomic_dec_8' mangled-name='atomic_dec_8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_dec_8'> - <parameter type-id='aa323ea4' name='target'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='atomic_dec_16' mangled-name='atomic_dec_16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_dec_16'> - <parameter type-id='93977ae7' name='target'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='atomic_dec_32' mangled-name='atomic_dec_32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_dec_32'> - <parameter type-id='3a147f31' name='target'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='atomic_dec_ulong' mangled-name='atomic_dec_ulong' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_dec_ulong'> - <parameter type-id='64698d33' name='target'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='atomic_add_ptr' mangled-name='atomic_add_ptr' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_add_ptr'> - <parameter type-id='fe09dd29' name='target'/> - <parameter type-id='79a0948f' name='bits'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='atomic_add_8' mangled-name='atomic_add_8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_add_8'> - <parameter type-id='aa323ea4' name='target'/> - <parameter type-id='ee31ee44' name='bits'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='atomic_add_16' mangled-name='atomic_add_16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_add_16'> - <parameter type-id='93977ae7' name='target'/> - <parameter type-id='23bd8cb5' name='bits'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='atomic_add_32' mangled-name='atomic_add_32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_add_32'> - <parameter type-id='3a147f31' name='target'/> - <parameter type-id='3ff5601b' name='bits'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='atomic_sub_ptr' mangled-name='atomic_sub_ptr' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_sub_ptr'> - <parameter type-id='fe09dd29' name='target'/> - <parameter type-id='79a0948f' name='bits'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='atomic_sub_8' mangled-name='atomic_sub_8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_sub_8'> - <parameter type-id='aa323ea4' name='target'/> - <parameter type-id='ee31ee44' name='bits'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='atomic_sub_16' mangled-name='atomic_sub_16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_sub_16'> - <parameter type-id='93977ae7' name='target'/> - <parameter type-id='23bd8cb5' name='bits'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='atomic_sub_32' mangled-name='atomic_sub_32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_sub_32'> - <parameter type-id='3a147f31' name='target'/> - <parameter type-id='3ff5601b' name='bits'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='atomic_or_8' mangled-name='atomic_or_8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_or_8'> - <parameter type-id='aa323ea4' name='target'/> - <parameter type-id='b96825af' name='bits'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='atomic_or_16' mangled-name='atomic_or_16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_or_16'> - <parameter type-id='93977ae7' name='target'/> - <parameter type-id='149c6638' name='bits'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='atomic_or_32' mangled-name='atomic_or_32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_or_32'> - <parameter type-id='3a147f31' name='target'/> - <parameter type-id='8f92235e' name='bits'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='atomic_or_ulong' mangled-name='atomic_or_ulong' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_or_ulong'> - <parameter type-id='64698d33' name='target'/> - <parameter type-id='ee1f298e' name='bits'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='atomic_and_8' mangled-name='atomic_and_8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_and_8'> - <parameter type-id='aa323ea4' name='target'/> - <parameter type-id='b96825af' name='bits'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='atomic_and_16' mangled-name='atomic_and_16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_and_16'> - <parameter type-id='93977ae7' name='target'/> - <parameter type-id='149c6638' name='bits'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='atomic_and_32' mangled-name='atomic_and_32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_and_32'> - <parameter type-id='3a147f31' name='target'/> - <parameter type-id='8f92235e' name='bits'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='atomic_and_ulong' mangled-name='atomic_and_ulong' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_and_ulong'> - <parameter type-id='64698d33' name='target'/> - <parameter type-id='ee1f298e' name='bits'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='atomic_inc_8_nv' mangled-name='atomic_inc_8_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_inc_8_nv'> - <parameter type-id='aa323ea4' name='target'/> - <return type-id='b96825af'/> - </function-decl> - <function-decl name='atomic_inc_16_nv' mangled-name='atomic_inc_16_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_inc_16_nv'> - <parameter type-id='93977ae7' name='target'/> - <return type-id='149c6638'/> - </function-decl> - <function-decl name='atomic_inc_32_nv' mangled-name='atomic_inc_32_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_inc_32_nv'> - <parameter type-id='3a147f31' name='target'/> - <return type-id='8f92235e'/> - </function-decl> - <function-decl name='atomic_inc_ulong_nv' mangled-name='atomic_inc_ulong_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_inc_ulong_nv'> - <parameter type-id='64698d33' name='target'/> - <return type-id='ee1f298e'/> - </function-decl> - <function-decl name='atomic_dec_8_nv' mangled-name='atomic_dec_8_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_dec_8_nv'> - <parameter type-id='aa323ea4' name='target'/> - <return type-id='b96825af'/> - </function-decl> - <function-decl name='atomic_dec_16_nv' mangled-name='atomic_dec_16_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_dec_16_nv'> - <parameter type-id='93977ae7' name='target'/> - <return type-id='149c6638'/> - </function-decl> - <function-decl name='atomic_dec_32_nv' mangled-name='atomic_dec_32_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_dec_32_nv'> - <parameter type-id='3a147f31' name='target'/> - <return type-id='8f92235e'/> - </function-decl> - <function-decl name='atomic_dec_ulong_nv' mangled-name='atomic_dec_ulong_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_dec_ulong_nv'> - <parameter type-id='64698d33' name='target'/> - <return type-id='ee1f298e'/> - </function-decl> - <function-decl name='atomic_add_ptr_nv' mangled-name='atomic_add_ptr_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_add_ptr_nv'> - <parameter type-id='fe09dd29' name='target'/> - <parameter type-id='79a0948f' name='bits'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='atomic_add_8_nv' mangled-name='atomic_add_8_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_add_8_nv'> - <parameter type-id='aa323ea4' name='target'/> - <parameter type-id='ee31ee44' name='bits'/> - <return type-id='b96825af'/> - </function-decl> - <function-decl name='atomic_add_16_nv' mangled-name='atomic_add_16_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_add_16_nv'> - <parameter type-id='93977ae7' name='target'/> - <parameter type-id='23bd8cb5' name='bits'/> - <return type-id='149c6638'/> - </function-decl> - <function-decl name='atomic_add_32_nv' mangled-name='atomic_add_32_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_add_32_nv'> - <parameter type-id='3a147f31' name='target'/> - <parameter type-id='3ff5601b' name='bits'/> - <return type-id='8f92235e'/> - </function-decl> - <function-decl name='atomic_add_long_nv' mangled-name='atomic_add_long_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_add_long_nv'> - <parameter type-id='64698d33' name='target'/> - <parameter type-id='bd54fe1a' name='bits'/> - <return type-id='ee1f298e'/> - </function-decl> - <function-decl name='atomic_sub_ptr_nv' mangled-name='atomic_sub_ptr_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_sub_ptr_nv'> - <parameter type-id='fe09dd29' name='target'/> - <parameter type-id='79a0948f' name='bits'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='atomic_sub_8_nv' mangled-name='atomic_sub_8_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_sub_8_nv'> - <parameter type-id='aa323ea4' name='target'/> - <parameter type-id='ee31ee44' name='bits'/> - <return type-id='b96825af'/> - </function-decl> - <function-decl name='atomic_sub_16_nv' mangled-name='atomic_sub_16_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_sub_16_nv'> - <parameter type-id='93977ae7' name='target'/> - <parameter type-id='23bd8cb5' name='bits'/> - <return type-id='149c6638'/> - </function-decl> - <function-decl name='atomic_sub_32_nv' mangled-name='atomic_sub_32_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_sub_32_nv'> - <parameter type-id='3a147f31' name='target'/> - <parameter type-id='3ff5601b' name='bits'/> - <return type-id='8f92235e'/> - </function-decl> - <function-decl name='atomic_sub_long_nv' mangled-name='atomic_sub_long_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_sub_long_nv'> - <parameter type-id='64698d33' name='target'/> - <parameter type-id='bd54fe1a' name='bits'/> - <return type-id='ee1f298e'/> - </function-decl> - <function-decl name='atomic_or_8_nv' mangled-name='atomic_or_8_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_or_8_nv'> - <parameter type-id='aa323ea4' name='target'/> - <parameter type-id='b96825af' name='bits'/> - <return type-id='b96825af'/> - </function-decl> - <function-decl name='atomic_or_16_nv' mangled-name='atomic_or_16_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_or_16_nv'> - <parameter type-id='93977ae7' name='target'/> - <parameter type-id='149c6638' name='bits'/> - <return type-id='149c6638'/> - </function-decl> - <function-decl name='atomic_or_32_nv' mangled-name='atomic_or_32_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_or_32_nv'> - <parameter type-id='3a147f31' name='target'/> - <parameter type-id='8f92235e' name='bits'/> - <return type-id='8f92235e'/> - </function-decl> - <function-decl name='atomic_or_ulong_nv' mangled-name='atomic_or_ulong_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_or_ulong_nv'> - <parameter type-id='64698d33' name='target'/> - <parameter type-id='ee1f298e' name='bits'/> - <return type-id='ee1f298e'/> - </function-decl> - <function-decl name='atomic_and_8_nv' mangled-name='atomic_and_8_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_and_8_nv'> - <parameter type-id='aa323ea4' name='target'/> - <parameter type-id='b96825af' name='bits'/> - <return type-id='b96825af'/> - </function-decl> - <function-decl name='atomic_and_16_nv' mangled-name='atomic_and_16_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_and_16_nv'> - <parameter type-id='93977ae7' name='target'/> - <parameter type-id='149c6638' name='bits'/> - <return type-id='149c6638'/> - </function-decl> - <function-decl name='atomic_and_32_nv' mangled-name='atomic_and_32_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_and_32_nv'> - <parameter type-id='3a147f31' name='target'/> - <parameter type-id='8f92235e' name='bits'/> - <return type-id='8f92235e'/> - </function-decl> - <function-decl name='atomic_and_ulong_nv' mangled-name='atomic_and_ulong_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_and_ulong_nv'> - <parameter type-id='64698d33' name='target'/> - <parameter type-id='ee1f298e' name='bits'/> - <return type-id='ee1f298e'/> - </function-decl> - <function-decl name='atomic_cas_ptr' mangled-name='atomic_cas_ptr' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_cas_ptr'> - <parameter type-id='fe09dd29' name='target'/> - <parameter type-id='eaa32e2f' name='exp'/> - <parameter type-id='eaa32e2f' name='des'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='atomic_cas_8' mangled-name='atomic_cas_8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_cas_8'> - <parameter type-id='aa323ea4' name='target'/> - <parameter type-id='b96825af' name='exp'/> - <parameter type-id='b96825af' name='des'/> - <return type-id='b96825af'/> - </function-decl> - <function-decl name='atomic_cas_16' mangled-name='atomic_cas_16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_cas_16'> - <parameter type-id='93977ae7' name='target'/> - <parameter type-id='149c6638' name='exp'/> - <parameter type-id='149c6638' name='des'/> - <return type-id='149c6638'/> - </function-decl> - <function-decl name='atomic_cas_32' mangled-name='atomic_cas_32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_cas_32'> - <parameter type-id='3a147f31' name='target'/> - <parameter type-id='8f92235e' name='exp'/> - <parameter type-id='8f92235e' name='des'/> - <return type-id='8f92235e'/> - </function-decl> - <function-decl name='atomic_cas_ulong' mangled-name='atomic_cas_ulong' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_cas_ulong'> - <parameter type-id='64698d33' name='target'/> - <parameter type-id='ee1f298e' name='exp'/> - <parameter type-id='ee1f298e' name='des'/> - <return type-id='ee1f298e'/> - </function-decl> - <function-decl name='atomic_swap_8' mangled-name='atomic_swap_8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_swap_8'> - <parameter type-id='aa323ea4' name='target'/> - <parameter type-id='b96825af' name='bits'/> - <return type-id='b96825af'/> - </function-decl> - <function-decl name='atomic_swap_16' mangled-name='atomic_swap_16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_swap_16'> - <parameter type-id='93977ae7' name='target'/> - <parameter type-id='149c6638' name='bits'/> - <return type-id='149c6638'/> - </function-decl> - <function-decl name='atomic_swap_ulong' mangled-name='atomic_swap_ulong' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_swap_ulong'> - <parameter type-id='64698d33' name='target'/> - <parameter type-id='ee1f298e' name='bits'/> - <return type-id='ee1f298e'/> - </function-decl> - <function-decl name='atomic_swap_ptr' mangled-name='atomic_swap_ptr' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_swap_ptr'> - <parameter type-id='fe09dd29' name='target'/> - <parameter type-id='eaa32e2f' name='bits'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='atomic_set_long_excl' mangled-name='atomic_set_long_excl' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_set_long_excl'> - <parameter type-id='64698d33' name='target'/> - <parameter type-id='3502e3ff' name='value'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='atomic_clear_long_excl' mangled-name='atomic_clear_long_excl' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_clear_long_excl'> - <parameter type-id='64698d33' name='target'/> - <parameter type-id='3502e3ff' name='value'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='membar_enter' mangled-name='membar_enter' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='membar_enter'> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='membar_consumer' mangled-name='membar_consumer' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='membar_consumer'> - <return type-id='48b5725f'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='lib/libspl/backtrace.c' language='LANG_C99'> - <array-type-def dimensions='1' type-id='62f1140c' size-in-bits='768' id='b80f3d9b'> - <subrange length='24' type-id='7359adad' id='fdd3342b'/> - </array-type-def> - <array-type-def dimensions='1' type-id='62f1140c' size-in-bits='128' id='bc19e735'> - <subrange length='4' type-id='7359adad' id='16fe7105'/> - </array-type-def> - <array-type-def dimensions='1' type-id='22c546af' size-in-bits='1024' id='498c040b'> - <subrange length='8' type-id='7359adad' id='56e0c0b1'/> - </array-type-def> - <array-type-def dimensions='1' type-id='4ea07cdb' size-in-bits='2048' id='4811c35e'> - <subrange length='16' type-id='7359adad' id='848d0938'/> - </array-type-def> - <array-type-def dimensions='1' type-id='de572c22' size-in-bits='1472' id='6d3c2f42'> - <subrange length='23' type-id='7359adad' id='fdd0f594'/> - </array-type-def> - <array-type-def dimensions='1' type-id='3a47d82b' size-in-bits='256' id='a133ec23'> - <subrange length='4' type-id='7359adad' id='16fe7105'/> - </array-type-def> - <array-type-def dimensions='1' type-id='3a47d82b' size-in-bits='512' id='a13e797f'> - <subrange length='8' type-id='7359adad' id='56e0c0b1'/> - </array-type-def> - <array-type-def dimensions='1' type-id='8efea9e5' size-in-bits='48' id='ff2536e2'> - <subrange length='3' type-id='7359adad' id='56f209d2'/> - </array-type-def> - <array-type-def dimensions='1' type-id='8efea9e5' size-in-bits='64' id='3f30d495'> - <subrange length='4' type-id='7359adad' id='16fe7105'/> - </array-type-def> - <array-type-def dimensions='1' type-id='73d941c6' size-in-bits='8128' id='dc70ec0b'> - <subrange length='127' type-id='7359adad' id='5ed08de5'/> - </array-type-def> - <class-decl name='stack_t' size-in-bits='192' is-struct='yes' naming-typedef-id='ac5e685f' visibility='default' id='380f9954'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='ss_sp' type-id='eaa32e2f' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='ss_flags' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='ss_size' type-id='b59d7dce' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='stack_t' type-id='380f9954' id='ac5e685f'/> - <typedef-decl name='unw_regnum_t' type-id='95e97e5e' id='c53620f0'/> - <class-decl name='unw_cursor' size-in-bits='8128' is-struct='yes' visibility='default' id='384a1f22'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='opaque' type-id='dc70ec0b' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='unw_cursor_t' type-id='384a1f22' id='1203d35c'/> - <typedef-decl name='unw_context_t' type-id='190d09ef' id='8f527367'/> - <typedef-decl name='unw_word_t' type-id='9c313c2d' id='73d941c6'/> - <typedef-decl name='unw_tdep_context_t' type-id='c4daa689' id='190d09ef'/> - <typedef-decl name='greg_t' type-id='1eb56b1e' id='de572c22'/> - <typedef-decl name='gregset_t' type-id='6d3c2f42' id='a66f139c'/> - <class-decl name='_libc_fpxreg' size-in-bits='128' is-struct='yes' visibility='default' id='22c546af'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='significand' type-id='3f30d495' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='exponent' type-id='8efea9e5' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='80'> - <var-decl name='__glibc_reserved1' type-id='ff2536e2' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='_libc_xmmreg' size-in-bits='128' is-struct='yes' visibility='default' id='4ea07cdb'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='element' type-id='bc19e735' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='_libc_fpstate' size-in-bits='4096' is-struct='yes' visibility='default' id='81cbe5ca'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='cwd' type-id='253c2d2a' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='16'> - <var-decl name='swd' type-id='253c2d2a' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32'> - <var-decl name='ftw' type-id='253c2d2a' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='48'> - <var-decl name='fop' type-id='253c2d2a' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='rip' type-id='8910171f' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='rdp' type-id='8910171f' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='mxcsr' type-id='62f1140c' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='224'> - <var-decl name='mxcr_mask' type-id='62f1140c' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='_st' type-id='498c040b' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1280'> - <var-decl name='_xmm' type-id='4811c35e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='3328'> - <var-decl name='__glibc_reserved1' type-id='b80f3d9b' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='fpregset_t' type-id='5b1ab9a8' id='6e5851bb'/> - <class-decl name='mcontext_t' size-in-bits='2048' is-struct='yes' naming-typedef-id='bacab071' visibility='default' id='76fab990'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='gregs' type-id='a66f139c' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1472'> - <var-decl name='fpregs' type-id='6e5851bb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1536'> - <var-decl name='__reserved1' type-id='a13e797f' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='mcontext_t' type-id='76fab990' id='bacab071'/> - <class-decl name='ucontext_t' size-in-bits='7744' is-struct='yes' visibility='default' id='1ba65dc8'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='uc_flags' type-id='7359adad' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='uc_link' type-id='4ed508de' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='uc_stack' type-id='ac5e685f' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='uc_mcontext' type-id='bacab071' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2368'> - <var-decl name='uc_sigmask' type-id='daf33c64' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='3392'> - <var-decl name='__fpregs_mem' type-id='81cbe5ca' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='7488'> - <var-decl name='__ssp' type-id='a133ec23' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='ucontext_t' type-id='1ba65dc8' id='c4daa689'/> - <pointer-type-def type-id='81cbe5ca' size-in-bits='64' id='5b1ab9a8'/> - <pointer-type-def type-id='1ba65dc8' size-in-bits='64' id='4ed508de'/> - <pointer-type-def type-id='8f527367' size-in-bits='64' id='2e408b96'/> - <pointer-type-def type-id='1203d35c' size-in-bits='64' id='3946e4d1'/> - <pointer-type-def type-id='190d09ef' size-in-bits='64' id='3e0601f0'/> - <pointer-type-def type-id='73d941c6' size-in-bits='64' id='42f5faab'/> - <function-decl name='_Ux86_64_regname' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='c53620f0'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='_ULx86_64_init_local' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='3946e4d1'/> - <parameter type-id='2e408b96'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='_ULx86_64_step' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='3946e4d1'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='_ULx86_64_get_reg' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='3946e4d1'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='42f5faab'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='_ULx86_64_get_proc_name' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='3946e4d1'/> - <parameter type-id='26a90f95'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='42f5faab'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='_Ux86_64_getcontext' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='3e0601f0'/> - <return type-id='95e97e5e'/> - </function-decl> - <type-decl name='unsigned short int' size-in-bits='16' id='8efea9e5'/> - </abi-instr> - <abi-instr address-size='64' path='lib/libspl/getexecname.c' language='LANG_C99'> - <function-decl name='getexecname' mangled-name='getexecname' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getexecname'> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='getexecname_impl' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='26a90f95'/> - <return type-id='79a0948f'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='lib/libspl/list.c' language='LANG_C99'> - <typedef-decl name='list_node_t' type-id='b0b5e45e' id='b21843b2'/> - <typedef-decl name='list_t' type-id='e824dae9' id='0899125f'/> - <class-decl name='list_node' size-in-bits='128' is-struct='yes' visibility='default' id='b0b5e45e'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='next' type-id='b03eadb4' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='prev' type-id='b03eadb4' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='list' size-in-bits='192' is-struct='yes' visibility='default' id='e824dae9'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='list_offset' type-id='b59d7dce' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='list_head' type-id='b0b5e45e' visibility='default'/> - </data-member> - </class-decl> - <pointer-type-def type-id='b0b5e45e' size-in-bits='64' id='b03eadb4'/> - <pointer-type-def type-id='b21843b2' size-in-bits='64' id='ccc38265'/> - <pointer-type-def type-id='0899125f' size-in-bits='64' id='352ec160'/> - <function-decl name='list_create' mangled-name='list_create' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='list_create'> - <parameter type-id='352ec160' name='list'/> - <parameter type-id='b59d7dce' name='size'/> - <parameter type-id='b59d7dce' name='offset'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='list_destroy' mangled-name='list_destroy' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='list_destroy'> - <parameter type-id='352ec160' name='list'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='list_insert_after' mangled-name='list_insert_after' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='list_insert_after'> - <parameter type-id='352ec160' name='list'/> - <parameter type-id='eaa32e2f' name='object'/> - <parameter type-id='eaa32e2f' name='nobject'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='list_insert_before' mangled-name='list_insert_before' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='list_insert_before'> - <parameter type-id='352ec160' name='list'/> - <parameter type-id='eaa32e2f' name='object'/> - <parameter type-id='eaa32e2f' name='nobject'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='list_insert_head' mangled-name='list_insert_head' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='list_insert_head'> - <parameter type-id='352ec160' name='list'/> - <parameter type-id='eaa32e2f' name='object'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='list_insert_tail' mangled-name='list_insert_tail' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='list_insert_tail'> - <parameter type-id='352ec160' name='list'/> - <parameter type-id='eaa32e2f' name='object'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='list_remove' mangled-name='list_remove' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='list_remove'> - <parameter type-id='352ec160' name='list'/> - <parameter type-id='eaa32e2f' name='object'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='list_remove_head' mangled-name='list_remove_head' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='list_remove_head'> - <parameter type-id='352ec160' name='list'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='list_remove_tail' mangled-name='list_remove_tail' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='list_remove_tail'> - <parameter type-id='352ec160' name='list'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='list_head' mangled-name='list_head' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='list_head'> - <parameter type-id='352ec160' name='list'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='list_tail' mangled-name='list_tail' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='list_tail'> - <parameter type-id='352ec160' name='list'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='list_next' mangled-name='list_next' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='list_next'> - <parameter type-id='352ec160' name='list'/> - <parameter type-id='eaa32e2f' name='object'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='list_prev' mangled-name='list_prev' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='list_prev'> - <parameter type-id='352ec160' name='list'/> - <parameter type-id='eaa32e2f' name='object'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='list_move_tail' mangled-name='list_move_tail' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='list_move_tail'> - <parameter type-id='352ec160' name='dst'/> - <parameter type-id='352ec160' name='src'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='list_link_replace' mangled-name='list_link_replace' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='list_link_replace'> - <parameter type-id='ccc38265' name='lold'/> - <parameter type-id='ccc38265' name='lnew'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='list_link_init' mangled-name='list_link_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='list_link_init'> - <parameter type-id='ccc38265' name='ln'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='list_link_active' mangled-name='list_link_active' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='list_link_active'> - <parameter type-id='ccc38265' name='ln'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='list_is_empty' mangled-name='list_is_empty' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='list_is_empty'> - <parameter type-id='352ec160' name='list'/> - <return type-id='95e97e5e'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='lib/libspl/mkdirp.c' language='LANG_C99'> - <typedef-decl name='wchar_t' type-id='95e97e5e' id='928221d2'/> - <qualified-type-def type-id='928221d2' const='yes' id='effb3702'/> - <pointer-type-def type-id='effb3702' size-in-bits='64' id='f077d3f8'/> - <qualified-type-def type-id='f077d3f8' restrict='yes' id='598aab80'/> - <pointer-type-def type-id='928221d2' size-in-bits='64' id='323d93c1'/> - <qualified-type-def type-id='323d93c1' restrict='yes' id='f1358bc3'/> - <function-decl name='__mbstowcs_chk' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='f1358bc3'/> - <parameter type-id='9d26089a'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='b59d7dce'/> - <return type-id='b59d7dce'/> - </function-decl> - <function-decl name='__wcstombs_chk' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='266fe297'/> - <parameter type-id='598aab80'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='b59d7dce'/> - <return type-id='b59d7dce'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='lib/libspl/os/linux/getmntany.c' language='LANG_C99'> - <pointer-type-def type-id='56fe4a37' size-in-bits='64' id='b6b61d2f'/> - <qualified-type-def type-id='b6b61d2f' restrict='yes' id='3cad23cd'/> - <function-decl name='getmntent_r' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='e75a27e9'/> - <parameter type-id='3cad23cd'/> - <parameter type-id='266fe297'/> - <parameter type-id='95e97e5e'/> - <return type-id='b6b61d2f'/> - </function-decl> - <function-decl name='feof' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='822cd80b'/> - <return type-id='95e97e5e'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='lib/libspl/timestamp.c' language='LANG_C99'> - <typedef-decl name='nl_item' type-id='95e97e5e' id='03b79a94'/> - <function-decl name='nl_langinfo' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='03b79a94'/> - <return type-id='26a90f95'/> - </function-decl> - <function-decl name='print_timestamp' mangled-name='print_timestamp' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='print_timestamp'> - <parameter type-id='3502e3ff' name='timestamp_fmt'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='get_timestamp' mangled-name='get_timestamp' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='get_timestamp'> - <parameter type-id='3502e3ff' name='timestamp_fmt'/> - <parameter type-id='26a90f95' name='buf'/> - <parameter type-id='95e97e5e' name='len'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='format_timestamp' mangled-name='format_timestamp' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='format_timestamp'> - <parameter type-id='c9d12d66' name='t'/> - <parameter type-id='26a90f95' name='buf'/> - <parameter type-id='95e97e5e' name='len'/> - <return type-id='48b5725f'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='lib/libspl/tunables.c' language='LANG_C99'> - <enum-decl name='zfs_tunable_type_t' naming-typedef-id='f50b1525' id='56905369'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='ZFS_TUNABLE_TYPE_INT' value='0'/> - <enumerator name='ZFS_TUNABLE_TYPE_UINT' value='1'/> - <enumerator name='ZFS_TUNABLE_TYPE_ULONG' value='2'/> - <enumerator name='ZFS_TUNABLE_TYPE_U64' value='3'/> - <enumerator name='ZFS_TUNABLE_TYPE_STRING' value='4'/> - </enum-decl> - <typedef-decl name='zfs_tunable_type_t' type-id='56905369' id='f50b1525'/> - <enum-decl name='zfs_tunable_perm_t' naming-typedef-id='ada7336b' id='e80e6ebf'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='ZFS_TUNABLE_PERM_ZMOD_RW' value='0'/> - <enumerator name='ZFS_TUNABLE_PERM_ZMOD_RD' value='1'/> - </enum-decl> - <typedef-decl name='zfs_tunable_perm_t' type-id='e80e6ebf' id='ada7336b'/> - <class-decl name='zfs_tunable' size-in-bits='320' is-struct='yes' visibility='default' id='1a97ee0e'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='zt_name' type-id='80f4b756' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='zt_varp' type-id='eaa32e2f' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='zt_varsz' type-id='b59d7dce' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='zt_type' type-id='f50b1525' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='224'> - <var-decl name='zt_perm' type-id='ada7336b' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='zt_desc' type-id='80f4b756' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='zfs_tunable_t' type-id='1a97ee0e' id='12bf5c5e'/> - <typedef-decl name='zfs_tunable_iter_t' type-id='7ef33f92' id='d8d5f4ab'/> - <typedef-decl name='intmax_t' type-id='5b475db0' id='e104d842'/> - <typedef-decl name='uintmax_t' type-id='04d82f4b' id='f8b828c9'/> - <typedef-decl name='__intmax_t' type-id='bd54fe1a' id='5b475db0'/> - <typedef-decl name='__uintmax_t' type-id='7359adad' id='04d82f4b'/> - <qualified-type-def type-id='12bf5c5e' const='yes' id='180e47ee'/> - <pointer-type-def type-id='180e47ee' size-in-bits='64' id='a27af98c'/> - <pointer-type-def type-id='92f86508' size-in-bits='64' id='7ef33f92'/> - <function-decl name='strtoimax' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='9d26089a'/> - <parameter type-id='8c85230f'/> - <parameter type-id='95e97e5e'/> - <return type-id='e104d842'/> - </function-decl> - <function-decl name='strtoumax' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='9d26089a'/> - <parameter type-id='8c85230f'/> - <parameter type-id='95e97e5e'/> - <return type-id='f8b828c9'/> - </function-decl> - <function-decl name='zfs_tunable_lookup' mangled-name='zfs_tunable_lookup' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_lookup'> - <parameter type-id='80f4b756' name='name'/> - <return type-id='a27af98c'/> - </function-decl> - <function-decl name='zfs_tunable_iter' mangled-name='zfs_tunable_iter' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_iter'> - <parameter type-id='d8d5f4ab' name='cb'/> - <parameter type-id='eaa32e2f' name='arg'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zfs_tunable_set' mangled-name='zfs_tunable_set' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_set'> - <parameter type-id='a27af98c' name='zt'/> - <parameter type-id='80f4b756' name='val'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_tunable_get' mangled-name='zfs_tunable_get' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_get'> - <parameter type-id='a27af98c' name='zt'/> - <parameter type-id='26a90f95' name='val'/> - <parameter type-id='b59d7dce' name='valsz'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-type size-in-bits='64' id='92f86508'> - <parameter type-id='a27af98c'/> - <parameter type-id='eaa32e2f'/> - <return type-id='95e97e5e'/> - </function-type> - </abi-instr> - <abi-instr address-size='64' path='lib/libtpool/thread_pool.c' language='LANG_C99'> - <array-type-def dimensions='1' type-id='49ef3ffd' size-in-bits='1024' id='a14403f5'> - <subrange length='16' type-id='7359adad' id='848d0938'/> - </array-type-def> - <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='384' id='36d7f119'> - <subrange length='48' type-id='7359adad' id='8f6d2a81'/> - </array-type-def> - <array-type-def dimensions='1' type-id='f0981eeb' size-in-bits='64' id='0d532ec1'> - <subrange length='2' type-id='7359adad' id='52efc4ef'/> - </array-type-def> - <union-decl name='__atomic_wide_counter' size-in-bits='64' naming-typedef-id='f3b40860' visibility='default' id='613ce450'> - <data-member access='public'> - <var-decl name='__value64' type-id='3a47d82b' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='__value32' type-id='e7f43f72' visibility='default'/> - </data-member> - </union-decl> - <class-decl name='__anonymous_struct__' size-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f72'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='__low' type-id='f0981eeb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32'> - <var-decl name='__high' type-id='f0981eeb' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='__atomic_wide_counter' type-id='613ce450' id='f3b40860'/> - <typedef-decl name='__cpu_mask' type-id='7359adad' id='49ef3ffd'/> - <class-decl name='cpu_set_t' size-in-bits='1024' is-struct='yes' naming-typedef-id='8037c762' visibility='default' id='1f20d231'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='__bits' type-id='a14403f5' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='cpu_set_t' type-id='1f20d231' id='8037c762'/> - <union-decl name='pthread_condattr_t' size-in-bits='32' naming-typedef-id='836265dd' visibility='default' id='33dd3aad'> - <data-member access='public'> - <var-decl name='__size' type-id='8e0573fd' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='__align' type-id='95e97e5e' visibility='default'/> - </data-member> - </union-decl> - <typedef-decl name='pthread_condattr_t' type-id='33dd3aad' id='836265dd'/> - <union-decl name='pthread_cond_t' size-in-bits='384' naming-typedef-id='62fab762' visibility='default' id='cbb12c12'> - <data-member access='public'> - <var-decl name='__data' type-id='c987b47c' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='__size' type-id='36d7f119' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='__align' type-id='1eb56b1e' visibility='default'/> - </data-member> - </union-decl> - <typedef-decl name='pthread_cond_t' type-id='cbb12c12' id='62fab762'/> - <class-decl name='__pthread_cond_s' size-in-bits='384' is-struct='yes' visibility='default' id='c987b47c'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='__wseq' type-id='f3b40860' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='__g1_start' type-id='f3b40860' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='__g_refs' type-id='0d532ec1' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='__g_size' type-id='0d532ec1' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='__g1_orig_size' type-id='f0981eeb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='288'> - <var-decl name='__wrefs' type-id='f0981eeb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='__g_signals' type-id='0d532ec1' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='sched_param' size-in-bits='32' is-struct='yes' visibility='default' id='0897719a'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='sched_priority' type-id='95e97e5e' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='tpool_job_t' type-id='3b8579e5' id='66a0afc9'/> - <class-decl name='tpool_job' size-in-bits='192' is-struct='yes' visibility='default' id='3b8579e5'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='tpj_next' type-id='f32b30e4' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='tpj_func' type-id='b7f9d8e6' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='tpj_arg' type-id='eaa32e2f' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='tpool_active_t' type-id='c8d086f4' id='6fcda10e'/> - <class-decl name='tpool_active' size-in-bits='128' is-struct='yes' visibility='default' id='c8d086f4'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='tpa_next' type-id='ad33e5e7' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='tpa_tid' type-id='4051f5e7' visibility='default'/> - </data-member> - </class-decl> - <qualified-type-def type-id='8037c762' const='yes' id='f50ea9b2'/> - <pointer-type-def type-id='f50ea9b2' size-in-bits='64' id='5e14fa48'/> - <qualified-type-def type-id='836265dd' const='yes' id='7d24c58d'/> - <pointer-type-def type-id='7d24c58d' size-in-bits='64' id='a7e325e5'/> - <qualified-type-def type-id='a7e325e5' restrict='yes' id='4c428e67'/> - <qualified-type-def type-id='0897719a' const='yes' id='c4a7b189'/> - <pointer-type-def type-id='c4a7b189' size-in-bits='64' id='36fca399'/> - <qualified-type-def type-id='36fca399' restrict='yes' id='37e4897b'/> - <qualified-type-def type-id='e05e8614' restrict='yes' id='0be2e71c'/> - <pointer-type-def type-id='8037c762' size-in-bits='64' id='d74a6869'/> - <qualified-type-def type-id='7292109c' restrict='yes' id='6942f6a4'/> - <qualified-type-def type-id='7347a39e' restrict='yes' id='578ba182'/> - <pointer-type-def type-id='62fab762' size-in-bits='64' id='db285b03'/> - <qualified-type-def type-id='db285b03' restrict='yes' id='2a468b41'/> - <qualified-type-def type-id='18c91f9e' restrict='yes' id='6e745582'/> - <pointer-type-def type-id='0897719a' size-in-bits='64' id='23cbcb08'/> - <qualified-type-def type-id='23cbcb08' restrict='yes' id='b09b2050'/> - <pointer-type-def type-id='6fcda10e' size-in-bits='64' id='ad33e5e7'/> - <pointer-type-def type-id='66a0afc9' size-in-bits='64' id='f32b30e4'/> - <qualified-type-def type-id='63e171df' restrict='yes' id='9e7a3a7d'/> - <function-decl name='pthread_self' visibility='default' binding='global' size-in-bits='64'> - <return type-id='4051f5e7'/> - </function-decl> - <function-decl name='pthread_attr_init' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='7347a39e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_attr_destroy' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='7347a39e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_attr_getdetachstate' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='540db505'/> - <parameter type-id='7292109c'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_attr_setdetachstate' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='7347a39e'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_attr_getguardsize' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='540db505'/> - <parameter type-id='78c01427'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_attr_setguardsize' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='7347a39e'/> - <parameter type-id='b59d7dce'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_attr_getschedparam' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='e1815e87'/> - <parameter type-id='b09b2050'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_attr_setschedparam' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='578ba182'/> - <parameter type-id='37e4897b'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_attr_getschedpolicy' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='e1815e87'/> - <parameter type-id='6942f6a4'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_attr_setschedpolicy' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='7347a39e'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_attr_getinheritsched' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='e1815e87'/> - <parameter type-id='6942f6a4'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_attr_setinheritsched' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='7347a39e'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_attr_getscope' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='e1815e87'/> - <parameter type-id='6942f6a4'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_attr_setscope' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='7347a39e'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_attr_getstack' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='e1815e87'/> - <parameter type-id='9e7a3a7d'/> - <parameter type-id='d19b2c25'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_attr_setstack' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='7347a39e'/> - <parameter type-id='eaa32e2f'/> - <parameter type-id='b59d7dce'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_attr_setaffinity_np' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='7347a39e'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='5e14fa48'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_attr_getaffinity_np' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='540db505'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='d74a6869'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_setcancelstate' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <parameter type-id='7292109c'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_setcanceltype' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <parameter type-id='7292109c'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='__pthread_unregister_cancel' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='ba7c727c'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='pthread_cond_init' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='2a468b41'/> - <parameter type-id='4c428e67'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_cond_signal' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='db285b03'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_cond_broadcast' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='db285b03'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_cond_wait' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='2a468b41'/> - <parameter type-id='6e745582'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_cond_timedwait' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='2a468b41'/> - <parameter type-id='6e745582'/> - <parameter type-id='0be2e71c'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='__sysconf' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <return type-id='bd54fe1a'/> - </function-decl> - <function-decl name='tpool_abandon' mangled-name='tpool_abandon' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_abandon'> - <parameter type-id='9cf59a50' name='tpool'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='tpool_suspend' mangled-name='tpool_suspend' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_suspend'> - <parameter type-id='9cf59a50' name='tpool'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='tpool_suspended' mangled-name='tpool_suspended' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_suspended'> - <parameter type-id='9cf59a50' name='tpool'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='tpool_resume' mangled-name='tpool_resume' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_resume'> - <parameter type-id='9cf59a50' name='tpool'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='tpool_member' mangled-name='tpool_member' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_member'> - <parameter type-id='9cf59a50' name='tpool'/> - <return type-id='95e97e5e'/> - </function-decl> - <pointer-type-def type-id='b1bbf10d' size-in-bits='64' id='9cf59a50'/> - <typedef-decl name='tpool_t' type-id='88d1b7f9' id='b1bbf10d'/> - <class-decl name='tpool' size-in-bits='2496' is-struct='yes' visibility='default' id='88d1b7f9'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='tp_forw' type-id='9cf59a50' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='tp_back' type-id='9cf59a50' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='tp_mutex' type-id='7a6844eb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='448'> - <var-decl name='tp_busycv' type-id='62fab762' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='832'> - <var-decl name='tp_workcv' type-id='62fab762' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1216'> - <var-decl name='tp_waitcv' type-id='62fab762' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1600'> - <var-decl name='tp_active' type-id='ad33e5e7' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1664'> - <var-decl name='tp_head' type-id='f32b30e4' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1728'> - <var-decl name='tp_tail' type-id='f32b30e4' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1792'> - <var-decl name='tp_attr' type-id='7d8569fd' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2240'> - <var-decl name='tp_flags' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2272'> - <var-decl name='tp_linger' type-id='3502e3ff' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2304'> - <var-decl name='tp_njobs' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2336'> - <var-decl name='tp_minimum' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2368'> - <var-decl name='tp_maximum' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2400'> - <var-decl name='tp_current' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2432'> - <var-decl name='tp_idle' type-id='95e97e5e' visibility='default'/> - </data-member> - </class-decl> - <function-type size-in-bits='64' id='c5c76c9c'> - <parameter type-id='eaa32e2f'/> - <return type-id='48b5725f'/> - </function-type> - </abi-instr> - <abi-instr address-size='64' path='lib/libzfs/libzfs_changelist.c' language='LANG_C99'> - <array-type-def dimensions='1' type-id='bf311473' size-in-bits='128' id='f0f65199'> - <subrange length='2' type-id='7359adad' id='52efc4ef'/> - </array-type-def> - <type-decl name='char' size-in-bits='8' id='a84c031d'/> - <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='8192' id='b54ce520'> - <subrange length='1024' type-id='7359adad' id='c60446f8'/> - </array-type-def> - <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='2048' id='d1617432'> - <subrange length='256' type-id='7359adad' id='36e5b9fa'/> - </array-type-def> - <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='320' id='36c46961'> - <subrange length='40' type-id='7359adad' id='8f80b239'/> - </array-type-def> - <class-decl name='re_dfa_t' is-struct='yes' visibility='default' is-declaration-only='yes' id='b48d2441'/> - <class-decl name='uu_avl' is-struct='yes' visibility='default' is-declaration-only='yes' id='4af029d1'/> - <class-decl name='uu_avl_pool' is-struct='yes' visibility='default' is-declaration-only='yes' id='12a530a8'/> - <class-decl name='uu_avl_walk' is-struct='yes' visibility='default' is-declaration-only='yes' id='e70a39e3'/> - <array-type-def dimensions='1' type-id='80f4b756' size-in-bits='256' id='71dc54ac'> - <subrange length='4' type-id='7359adad' id='16fe7105'/> - </array-type-def> - <type-decl name='int' size-in-bits='32' id='95e97e5e'/> - <type-decl name='long int' size-in-bits='64' id='bd54fe1a'/> - <type-decl name='long long int' size-in-bits='64' id='1eb56b1e'/> - <type-decl name='short int' size-in-bits='16' id='a2185560'/> - <array-type-def dimensions='1' type-id='e475ab95' size-in-bits='192' id='0ce65a8b'> - <subrange length='3' type-id='7359adad' id='56f209d2'/> - </array-type-def> - <type-decl name='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='9cac1fee'/> - <type-decl name='unsigned char' size-in-bits='8' id='002ac4a6'/> - <type-decl name='unsigned int' size-in-bits='32' id='f0981eeb'/> - <type-decl name='unsigned long int' size-in-bits='64' id='7359adad'/> - <type-decl name='void' id='48b5725f'/> - <typedef-decl name='uu_compare_fn_t' type-id='add6e811' id='40f93560'/> - <typedef-decl name='uu_avl_pool_t' type-id='12a530a8' id='7f84e390'/> - <typedef-decl name='uu_avl_t' type-id='4af029d1' id='bb7f0973'/> - <class-decl name='uu_avl_node' size-in-bits='192' is-struct='yes' visibility='default' id='f65f4326'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='uan_opaque' type-id='0ce65a8b' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='uu_avl_node_t' type-id='f65f4326' id='73a65116'/> - <typedef-decl name='uu_avl_walk_t' type-id='e70a39e3' id='edd8457b'/> - <typedef-decl name='uu_avl_index_t' type-id='e475ab95' id='5d7f5fc8'/> - <typedef-decl name='zfs_handle_t' type-id='f6ee4445' id='775509eb'/> - <typedef-decl name='zpool_handle_t' type-id='67002a8a' id='b1efc708'/> - <typedef-decl name='libzfs_handle_t' type-id='c8a9d9d8' id='95942d0c'/> - <typedef-decl name='zfs_iter_f' type-id='5571cde4' id='d8e49ab9'/> - <typedef-decl name='avl_tree_t' type-id='b351119f' id='f20fbd51'/> - <class-decl name='avl_node' size-in-bits='192' is-struct='yes' visibility='default' id='428b67b3'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='avl_child' type-id='f0f65199' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='avl_pcb' type-id='e475ab95' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='avl_tree' size-in-bits='320' is-struct='yes' visibility='default' id='b351119f'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='avl_root' type-id='bf311473' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='avl_compar' type-id='585e1de9' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='avl_offset' type-id='b59d7dce' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='avl_numnodes' type-id='ee1f298e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='avl_pad' type-id='b59d7dce' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='dmu_objset_stats' size-in-bits='2304' is-struct='yes' visibility='default' id='098f0221'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='dds_num_clones' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='dds_creation_txg' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='dds_guid' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='dds_type' type-id='230f1e16' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='224'> - <var-decl name='dds_is_snapshot' type-id='b96825af' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='232'> - <var-decl name='dds_inconsistent' type-id='b96825af' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='240'> - <var-decl name='dds_redacted' type-id='b96825af' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='248'> - <var-decl name='dds_origin' type-id='d1617432' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2296'> - <var-decl name='dds_flags' type-id='b96825af' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='dmu_objset_stats_t' type-id='098f0221' id='b2c14f17'/> - <enum-decl name='zfs_type_t' naming-typedef-id='2e45de5d' id='5d8f7321'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='ZFS_TYPE_INVALID' value='0'/> - <enumerator name='ZFS_TYPE_FILESYSTEM' value='1'/> - <enumerator name='ZFS_TYPE_SNAPSHOT' value='2'/> - <enumerator name='ZFS_TYPE_VOLUME' value='4'/> - <enumerator name='ZFS_TYPE_POOL' value='8'/> - <enumerator name='ZFS_TYPE_BOOKMARK' value='16'/> - <enumerator name='ZFS_TYPE_VDEV' value='32'/> - </enum-decl> - <typedef-decl name='zfs_type_t' type-id='5d8f7321' id='2e45de5d'/> - <enum-decl name='dmu_objset_type' id='6b1b19f9'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='DMU_OST_NONE' value='0'/> - <enumerator name='DMU_OST_META' value='1'/> - <enumerator name='DMU_OST_ZFS' value='2'/> - <enumerator name='DMU_OST_ZVOL' value='3'/> - <enumerator name='DMU_OST_OTHER' value='4'/> - <enumerator name='DMU_OST_ANY' value='5'/> - <enumerator name='DMU_OST_NUMTYPES' value='6'/> - </enum-decl> - <typedef-decl name='dmu_objset_type_t' type-id='6b1b19f9' id='230f1e16'/> - <enum-decl name='zfs_prop_t' naming-typedef-id='58603c44' id='4b000d60'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='ZPROP_CONT' value='-2'/> - <enumerator name='ZPROP_INVAL' value='-1'/> - <enumerator name='ZPROP_USERPROP' value='-1'/> - <enumerator name='ZFS_PROP_TYPE' value='0'/> - <enumerator name='ZFS_PROP_CREATION' value='1'/> - <enumerator name='ZFS_PROP_USED' value='2'/> - <enumerator name='ZFS_PROP_AVAILABLE' value='3'/> - <enumerator name='ZFS_PROP_REFERENCED' value='4'/> - <enumerator name='ZFS_PROP_COMPRESSRATIO' value='5'/> - <enumerator name='ZFS_PROP_MOUNTED' value='6'/> - <enumerator name='ZFS_PROP_ORIGIN' value='7'/> - <enumerator name='ZFS_PROP_QUOTA' value='8'/> - <enumerator name='ZFS_PROP_RESERVATION' value='9'/> - <enumerator name='ZFS_PROP_VOLSIZE' value='10'/> - <enumerator name='ZFS_PROP_VOLBLOCKSIZE' value='11'/> - <enumerator name='ZFS_PROP_RECORDSIZE' value='12'/> - <enumerator name='ZFS_PROP_MOUNTPOINT' value='13'/> - <enumerator name='ZFS_PROP_SHARENFS' value='14'/> - <enumerator name='ZFS_PROP_CHECKSUM' value='15'/> - <enumerator name='ZFS_PROP_COMPRESSION' value='16'/> - <enumerator name='ZFS_PROP_ATIME' value='17'/> - <enumerator name='ZFS_PROP_DEVICES' value='18'/> - <enumerator name='ZFS_PROP_EXEC' value='19'/> - <enumerator name='ZFS_PROP_SETUID' value='20'/> - <enumerator name='ZFS_PROP_READONLY' value='21'/> - <enumerator name='ZFS_PROP_ZONED' value='22'/> - <enumerator name='ZFS_PROP_SNAPDIR' value='23'/> - <enumerator name='ZFS_PROP_ACLMODE' value='24'/> - <enumerator name='ZFS_PROP_ACLINHERIT' value='25'/> - <enumerator name='ZFS_PROP_CREATETXG' value='26'/> - <enumerator name='ZFS_PROP_NAME' value='27'/> - <enumerator name='ZFS_PROP_CANMOUNT' value='28'/> - <enumerator name='ZFS_PROP_ISCSIOPTIONS' value='29'/> - <enumerator name='ZFS_PROP_XATTR' value='30'/> - <enumerator name='ZFS_PROP_NUMCLONES' value='31'/> - <enumerator name='ZFS_PROP_COPIES' value='32'/> - <enumerator name='ZFS_PROP_VERSION' value='33'/> - <enumerator name='ZFS_PROP_UTF8ONLY' value='34'/> - <enumerator name='ZFS_PROP_NORMALIZE' value='35'/> - <enumerator name='ZFS_PROP_CASE' value='36'/> - <enumerator name='ZFS_PROP_VSCAN' value='37'/> - <enumerator name='ZFS_PROP_NBMAND' value='38'/> - <enumerator name='ZFS_PROP_SHARESMB' value='39'/> - <enumerator name='ZFS_PROP_REFQUOTA' value='40'/> - <enumerator name='ZFS_PROP_REFRESERVATION' value='41'/> - <enumerator name='ZFS_PROP_GUID' value='42'/> - <enumerator name='ZFS_PROP_PRIMARYCACHE' value='43'/> - <enumerator name='ZFS_PROP_SECONDARYCACHE' value='44'/> - <enumerator name='ZFS_PROP_USEDSNAP' value='45'/> - <enumerator name='ZFS_PROP_USEDDS' value='46'/> - <enumerator name='ZFS_PROP_USEDCHILD' value='47'/> - <enumerator name='ZFS_PROP_USEDREFRESERV' value='48'/> - <enumerator name='ZFS_PROP_USERACCOUNTING' value='49'/> - <enumerator name='ZFS_PROP_STMF_SHAREINFO' value='50'/> - <enumerator name='ZFS_PROP_DEFER_DESTROY' value='51'/> - <enumerator name='ZFS_PROP_USERREFS' value='52'/> - <enumerator name='ZFS_PROP_LOGBIAS' value='53'/> - <enumerator name='ZFS_PROP_UNIQUE' value='54'/> - <enumerator name='ZFS_PROP_OBJSETID' value='55'/> - <enumerator name='ZFS_PROP_DEDUP' value='56'/> - <enumerator name='ZFS_PROP_MLSLABEL' value='57'/> - <enumerator name='ZFS_PROP_SYNC' value='58'/> - <enumerator name='ZFS_PROP_DNODESIZE' value='59'/> - <enumerator name='ZFS_PROP_REFRATIO' value='60'/> - <enumerator name='ZFS_PROP_WRITTEN' value='61'/> - <enumerator name='ZFS_PROP_CLONES' value='62'/> - <enumerator name='ZFS_PROP_LOGICALUSED' value='63'/> - <enumerator name='ZFS_PROP_LOGICALREFERENCED' value='64'/> - <enumerator name='ZFS_PROP_INCONSISTENT' value='65'/> - <enumerator name='ZFS_PROP_VOLMODE' value='66'/> - <enumerator name='ZFS_PROP_FILESYSTEM_LIMIT' value='67'/> - <enumerator name='ZFS_PROP_SNAPSHOT_LIMIT' value='68'/> - <enumerator name='ZFS_PROP_FILESYSTEM_COUNT' value='69'/> - <enumerator name='ZFS_PROP_SNAPSHOT_COUNT' value='70'/> - <enumerator name='ZFS_PROP_SNAPDEV' value='71'/> - <enumerator name='ZFS_PROP_ACLTYPE' value='72'/> - <enumerator name='ZFS_PROP_SELINUX_CONTEXT' value='73'/> - <enumerator name='ZFS_PROP_SELINUX_FSCONTEXT' value='74'/> - <enumerator name='ZFS_PROP_SELINUX_DEFCONTEXT' value='75'/> - <enumerator name='ZFS_PROP_SELINUX_ROOTCONTEXT' value='76'/> - <enumerator name='ZFS_PROP_RELATIME' value='77'/> - <enumerator name='ZFS_PROP_REDUNDANT_METADATA' value='78'/> - <enumerator name='ZFS_PROP_OVERLAY' value='79'/> - <enumerator name='ZFS_PROP_PREV_SNAP' value='80'/> - <enumerator name='ZFS_PROP_RECEIVE_RESUME_TOKEN' value='81'/> - <enumerator name='ZFS_PROP_ENCRYPTION' value='82'/> - <enumerator name='ZFS_PROP_KEYLOCATION' value='83'/> - <enumerator name='ZFS_PROP_KEYFORMAT' value='84'/> - <enumerator name='ZFS_PROP_PBKDF2_SALT' value='85'/> - <enumerator name='ZFS_PROP_PBKDF2_ITERS' value='86'/> - <enumerator name='ZFS_PROP_ENCRYPTION_ROOT' value='87'/> - <enumerator name='ZFS_PROP_KEY_GUID' value='88'/> - <enumerator name='ZFS_PROP_KEYSTATUS' value='89'/> - <enumerator name='ZFS_PROP_REMAPTXG' value='90'/> - <enumerator name='ZFS_PROP_SPECIAL_SMALL_BLOCKS' value='91'/> - <enumerator name='ZFS_PROP_IVSET_GUID' value='92'/> - <enumerator name='ZFS_PROP_REDACTED' value='93'/> - <enumerator name='ZFS_PROP_REDACT_SNAPS' value='94'/> - <enumerator name='ZFS_PROP_SNAPSHOTS_CHANGED' value='95'/> - <enumerator name='ZFS_PROP_PREFETCH' value='96'/> - <enumerator name='ZFS_PROP_VOLTHREADING' value='97'/> - <enumerator name='ZFS_PROP_DIRECT' value='98'/> - <enumerator name='ZFS_PROP_LONGNAME' value='99'/> - <enumerator name='ZFS_PROP_DEFAULTUSERQUOTA' value='100'/> - <enumerator name='ZFS_PROP_DEFAULTGROUPQUOTA' value='101'/> - <enumerator name='ZFS_PROP_DEFAULTPROJECTQUOTA' value='102'/> - <enumerator name='ZFS_PROP_DEFAULTUSEROBJQUOTA' value='103'/> - <enumerator name='ZFS_PROP_DEFAULTGROUPOBJQUOTA' value='104'/> - <enumerator name='ZFS_PROP_DEFAULTPROJECTOBJQUOTA' value='105'/> - <enumerator name='ZFS_NUM_PROPS' value='106'/> - </enum-decl> - <typedef-decl name='zfs_prop_t' type-id='4b000d60' id='58603c44'/> - <enum-decl name='zprop_source_t' naming-typedef-id='a2256d42' id='5903f80e'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='ZPROP_SRC_NONE' value='1'/> - <enumerator name='ZPROP_SRC_DEFAULT' value='2'/> - <enumerator name='ZPROP_SRC_TEMPORARY' value='4'/> - <enumerator name='ZPROP_SRC_LOCAL' value='8'/> - <enumerator name='ZPROP_SRC_INHERITED' value='16'/> - <enumerator name='ZPROP_SRC_RECEIVED' value='32'/> - </enum-decl> - <typedef-decl name='zprop_source_t' type-id='5903f80e' id='a2256d42'/> - <class-decl name='nvlist' size-in-bits='192' is-struct='yes' visibility='default' id='ac266fd9'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='nvl_version' type-id='3ff5601b' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32'> - <var-decl name='nvl_nvflag' type-id='8f92235e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='nvl_priv' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='nvl_flag' type-id='8f92235e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='160'> - <var-decl name='nvl_pad' type-id='3ff5601b' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='nvlist_t' type-id='ac266fd9' id='8e8d4be3'/> - <enum-decl name='sa_protocol' id='9155d4b5'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='SA_PROTOCOL_NFS' value='0'/> - <enumerator name='SA_PROTOCOL_SMB' value='1'/> - <enumerator name='SA_PROTOCOL_COUNT' value='2'/> - </enum-decl> - <enum-decl name='boolean_t' naming-typedef-id='c19b74c3' id='f58c8277'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='B_FALSE' value='0'/> - <enumerator name='B_TRUE' value='1'/> - </enum-decl> - <typedef-decl name='boolean_t' type-id='f58c8277' id='c19b74c3'/> - <typedef-decl name='uint_t' type-id='f0981eeb' id='3502e3ff'/> - <typedef-decl name='ulong_t' type-id='7359adad' id='ee1f298e'/> - <typedef-decl name='longlong_t' type-id='1eb56b1e' id='9b3ff54f'/> - <typedef-decl name='diskaddr_t' type-id='9b3ff54f' id='804dc465'/> - <typedef-decl name='zoneid_t' type-id='3502e3ff' id='4da03624'/> - <typedef-decl name='__re_long_size_t' type-id='7359adad' id='ba516949'/> - <typedef-decl name='reg_syntax_t' type-id='7359adad' id='1b72c3b3'/> - <class-decl name='re_pattern_buffer' size-in-bits='512' is-struct='yes' visibility='default' id='19fc9a8c'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='buffer' type-id='33976309' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='allocated' type-id='ba516949' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='used' type-id='ba516949' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='syntax' type-id='1b72c3b3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='fastmap' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='translate' type-id='cf536864' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='384'> - <var-decl name='re_nsub' type-id='b59d7dce' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='448'> - <var-decl name='can_be_null' type-id='f0981eeb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='449'> - <var-decl name='regs_allocated' type-id='f0981eeb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='451'> - <var-decl name='fastmap_accurate' type-id='f0981eeb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='452'> - <var-decl name='no_sub' type-id='f0981eeb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='453'> - <var-decl name='not_bol' type-id='f0981eeb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='454'> - <var-decl name='not_eol' type-id='f0981eeb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='455'> - <var-decl name='newline_anchor' type-id='f0981eeb' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='regex_t' type-id='19fc9a8c' id='aca3bac8'/> - <typedef-decl name='uintptr_t' type-id='7359adad' id='e475ab95'/> - <union-decl name='pthread_mutex_t' size-in-bits='320' naming-typedef-id='7a6844eb' visibility='default' id='70681f9b'> - <data-member access='public'> - <var-decl name='__data' type-id='4c734837' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='__size' type-id='36c46961' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='__align' type-id='bd54fe1a' visibility='default'/> - </data-member> - </union-decl> - <typedef-decl name='pthread_mutex_t' type-id='70681f9b' id='7a6844eb'/> - <typedef-decl name='int32_t' type-id='33f57a65' id='3ff5601b'/> - <typedef-decl name='uint8_t' type-id='c51d6389' id='b96825af'/> - <typedef-decl name='uint32_t' type-id='62f1140c' id='8f92235e'/> - <typedef-decl name='uint64_t' type-id='8910171f' id='9c313c2d'/> - <class-decl name='__pthread_mutex_s' size-in-bits='320' is-struct='yes' visibility='default' id='4c734837'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='__lock' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32'> - <var-decl name='__count' type-id='f0981eeb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='__owner' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='96'> - <var-decl name='__nusers' type-id='f0981eeb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='__kind' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='160'> - <var-decl name='__spins' type-id='a2185560' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='176'> - <var-decl name='__elision' type-id='a2185560' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='__list' type-id='518fb49c' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='__pthread_internal_list' size-in-bits='128' is-struct='yes' visibility='default' id='0e01899c'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='__prev' type-id='4d98cd5a' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='__next' type-id='4d98cd5a' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='__pthread_list_t' type-id='0e01899c' id='518fb49c'/> - <typedef-decl name='__uint8_t' type-id='002ac4a6' id='c51d6389'/> - <typedef-decl name='__int32_t' type-id='95e97e5e' id='33f57a65'/> - <typedef-decl name='__uint32_t' type-id='f0981eeb' id='62f1140c'/> - <typedef-decl name='__uint64_t' type-id='7359adad' id='8910171f'/> - <typedef-decl name='size_t' type-id='7359adad' id='b59d7dce'/> - <class-decl name='libzfs_handle' size-in-bits='18240' is-struct='yes' visibility='default' id='c8a9d9d8'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='libzfs_error' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32'> - <var-decl name='libzfs_fd' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='libzfs_pool_handles' type-id='4c81de99' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='libzfs_ns_avlpool' type-id='de82c773' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='libzfs_ns_avl' type-id='a5c21a38' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='libzfs_ns_gen' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='libzfs_desc_active' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='352'> - <var-decl name='libzfs_action' type-id='b54ce520' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='8544'> - <var-decl name='libzfs_desc' type-id='b54ce520' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='16736'> - <var-decl name='libzfs_printerr' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='16768'> - <var-decl name='libzfs_mnttab_enable' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='16832'> - <var-decl name='libzfs_mnttab_cache_lock' type-id='7a6844eb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='17152'> - <var-decl name='libzfs_mnttab_cache' type-id='f20fbd51' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='17472'> - <var-decl name='libzfs_pool_iter' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='17504'> - <var-decl name='libzfs_prop_debug' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='17536'> - <var-decl name='libzfs_urire' type-id='aca3bac8' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='18048'> - <var-decl name='libzfs_max_nvlist' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='18112'> - <var-decl name='libfetch' type-id='eaa32e2f' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='18176'> - <var-decl name='libfetch_load_error' type-id='26a90f95' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='zfs_handle' size-in-bits='4928' is-struct='yes' visibility='default' id='f6ee4445'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='zfs_hdl' type-id='b0382bb3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='zpool_hdl' type-id='4c81de99' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='zfs_name' type-id='d1617432' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2176'> - <var-decl name='zfs_type' type-id='2e45de5d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2208'> - <var-decl name='zfs_head_type' type-id='2e45de5d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2240'> - <var-decl name='zfs_dmustats' type-id='b2c14f17' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='4544'> - <var-decl name='zfs_props' type-id='5ce45b60' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='4608'> - <var-decl name='zfs_user_props' type-id='5ce45b60' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='4672'> - <var-decl name='zfs_recvd_props' type-id='5ce45b60' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='4736'> - <var-decl name='zfs_mntcheck' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='4800'> - <var-decl name='zfs_mntopts' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='4864'> - <var-decl name='zfs_props_table' type-id='ae3e8ca6' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='zpool_handle' size-in-bits='2816' is-struct='yes' visibility='default' id='67002a8a'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='zpool_hdl' type-id='b0382bb3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='zpool_next' type-id='4c81de99' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='zpool_name' type-id='d1617432' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2176'> - <var-decl name='zpool_state' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2208'> - <var-decl name='zpool_n_propnames' type-id='f0981eeb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2240'> - <var-decl name='zpool_propnames' type-id='71dc54ac' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2496'> - <var-decl name='zpool_config_size' type-id='b59d7dce' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2560'> - <var-decl name='zpool_config' type-id='5ce45b60' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2624'> - <var-decl name='zpool_old_config' type-id='5ce45b60' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2688'> - <var-decl name='zpool_props' type-id='5ce45b60' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2752'> - <var-decl name='zpool_start_block' type-id='804dc465' visibility='default'/> - </data-member> - </class-decl> - <pointer-type-def type-id='0e01899c' size-in-bits='64' id='4d98cd5a'/> - <pointer-type-def type-id='428b67b3' size-in-bits='64' id='bf311473'/> - <pointer-type-def type-id='a84c031d' size-in-bits='64' id='26a90f95'/> - <pointer-type-def type-id='26a90f95' size-in-bits='64' id='9b23c9ad'/> - <qualified-type-def type-id='a84c031d' const='yes' id='9b45d938'/> - <pointer-type-def type-id='9b45d938' size-in-bits='64' id='80f4b756'/> - <qualified-type-def type-id='9155d4b5' const='yes' id='9f2c1699'/> - <pointer-type-def type-id='9f2c1699' size-in-bits='64' id='4567bbc9'/> - <qualified-type-def type-id='775509eb' const='yes' id='5eadf2db'/> - <pointer-type-def type-id='5eadf2db' size-in-bits='64' id='fcd57163'/> - <pointer-type-def type-id='96ee24a5' size-in-bits='64' id='585e1de9'/> - <pointer-type-def type-id='cb9628fa' size-in-bits='64' id='5571cde4'/> - <pointer-type-def type-id='95942d0c' size-in-bits='64' id='b0382bb3'/> - <pointer-type-def type-id='8e8d4be3' size-in-bits='64' id='5ce45b60'/> - <pointer-type-def type-id='b48d2441' size-in-bits='64' id='33976309'/> - <pointer-type-def type-id='b96825af' size-in-bits='64' id='ae3e8ca6'/> - <pointer-type-def type-id='002ac4a6' size-in-bits='64' id='cf536864'/> - <pointer-type-def type-id='5d7f5fc8' size-in-bits='64' id='813a2225'/> - <pointer-type-def type-id='73a65116' size-in-bits='64' id='2dc35b9d'/> - <pointer-type-def type-id='7f84e390' size-in-bits='64' id='de82c773'/> - <pointer-type-def type-id='bb7f0973' size-in-bits='64' id='a5c21a38'/> - <pointer-type-def type-id='edd8457b' size-in-bits='64' id='5842d146'/> - <pointer-type-def type-id='40f93560' size-in-bits='64' id='d502b39f'/> - <pointer-type-def type-id='48b5725f' size-in-bits='64' id='eaa32e2f'/> - <pointer-type-def type-id='775509eb' size-in-bits='64' id='9200a744'/> - <pointer-type-def type-id='b1efc708' size-in-bits='64' id='4c81de99'/> - <pointer-type-def type-id='a2256d42' size-in-bits='64' id='debc6aa3'/> - <class-decl name='re_dfa_t' is-struct='yes' visibility='default' is-declaration-only='yes' id='b48d2441'/> - <class-decl name='uu_avl' is-struct='yes' visibility='default' is-declaration-only='yes' id='4af029d1'/> - <class-decl name='uu_avl_pool' is-struct='yes' visibility='default' is-declaration-only='yes' id='12a530a8'/> - <class-decl name='uu_avl_walk' is-struct='yes' visibility='default' is-declaration-only='yes' id='e70a39e3'/> - <function-decl name='uu_avl_pool_create' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='d502b39f'/> - <parameter type-id='8f92235e'/> - <return type-id='de82c773'/> - </function-decl> - <function-decl name='uu_avl_pool_destroy' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='de82c773'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='uu_avl_node_init' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='eaa32e2f'/> - <parameter type-id='2dc35b9d'/> - <parameter type-id='de82c773'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='uu_avl_create' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='de82c773'/> - <parameter type-id='eaa32e2f'/> - <parameter type-id='8f92235e'/> - <return type-id='a5c21a38'/> - </function-decl> - <function-decl name='uu_avl_destroy' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='a5c21a38'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='uu_avl_last' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='a5c21a38'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='uu_avl_walk_start' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='a5c21a38'/> - <parameter type-id='8f92235e'/> - <return type-id='5842d146'/> - </function-decl> - <function-decl name='uu_avl_walk_next' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5842d146'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='uu_avl_walk_end' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5842d146'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='uu_avl_find' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='a5c21a38'/> - <parameter type-id='eaa32e2f'/> - <parameter type-id='eaa32e2f'/> - <parameter type-id='813a2225'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='uu_avl_insert' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='a5c21a38'/> - <parameter type-id='eaa32e2f'/> - <parameter type-id='5d7f5fc8'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='uu_avl_remove' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='a5c21a38'/> - <parameter type-id='eaa32e2f'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zfs_get_handle' mangled-name='zfs_get_handle' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_get_handle'> - <parameter type-id='9200a744'/> - <return type-id='b0382bb3'/> - </function-decl> - <function-decl name='zfs_open' mangled-name='zfs_open' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_open'> - <parameter type-id='b0382bb3'/> - <parameter type-id='80f4b756'/> - <parameter type-id='95e97e5e'/> - <return type-id='9200a744'/> - </function-decl> - <function-decl name='zfs_close' mangled-name='zfs_close' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_close'> - <parameter type-id='9200a744'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zfs_get_name' mangled-name='zfs_get_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_get_name'> - <parameter type-id='fcd57163'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='zfs_prop_get' mangled-name='zfs_prop_get' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_get'> - <parameter type-id='9200a744'/> - <parameter type-id='58603c44'/> - <parameter type-id='26a90f95'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='debc6aa3'/> - <parameter type-id='26a90f95'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='c19b74c3'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_prop_get_int' mangled-name='zfs_prop_get_int' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_get_int'> - <parameter type-id='9200a744'/> - <parameter type-id='58603c44'/> - <return type-id='9c313c2d'/> - </function-decl> - <function-decl name='zfs_iter_children_v2' mangled-name='zfs_iter_children_v2' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_children_v2'> - <parameter type-id='9200a744'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='d8e49ab9'/> - <parameter type-id='eaa32e2f'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_iter_dependents_v2' mangled-name='zfs_iter_dependents_v2' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_dependents_v2'> - <parameter type-id='9200a744'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='c19b74c3'/> - <parameter type-id='d8e49ab9'/> - <parameter type-id='eaa32e2f'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_iter_filesystems_v2' mangled-name='zfs_iter_filesystems_v2' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_filesystems_v2'> - <parameter type-id='9200a744'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='d8e49ab9'/> - <parameter type-id='eaa32e2f'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_iter_mounted' mangled-name='zfs_iter_mounted' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_mounted'> - <parameter type-id='9200a744'/> - <parameter type-id='d8e49ab9'/> - <parameter type-id='eaa32e2f'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_refresh_properties' mangled-name='zfs_refresh_properties' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_refresh_properties'> - <parameter type-id='9200a744'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zfs_is_mounted' mangled-name='zfs_is_mounted' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_is_mounted'> - <parameter type-id='9200a744'/> - <parameter type-id='9b23c9ad'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zfs_mount' mangled-name='zfs_mount' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_mount'> - <parameter type-id='9200a744'/> - <parameter type-id='80f4b756'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_unmount' mangled-name='zfs_unmount' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_unmount'> - <parameter type-id='9200a744'/> - <parameter type-id='80f4b756'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_is_shared' mangled-name='zfs_is_shared' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_is_shared'> - <parameter type-id='9200a744'/> - <parameter type-id='9b23c9ad'/> - <parameter type-id='4567bbc9'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zfs_share' mangled-name='zfs_share' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_share'> - <parameter type-id='9200a744'/> - <parameter type-id='4567bbc9'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_unshare' mangled-name='zfs_unshare' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_unshare'> - <parameter type-id='9200a744'/> - <parameter type-id='80f4b756'/> - <parameter type-id='4567bbc9'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_commit_shares' mangled-name='zfs_commit_shares' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_commit_shares'> - <parameter type-id='4567bbc9'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='getzoneid' mangled-name='getzoneid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getzoneid'> - <return type-id='4da03624'/> - </function-decl> - <function-decl name='sa_commit_shares' mangled-name='sa_commit_shares' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='sa_commit_shares'> - <parameter type-id='9155d4b5'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='strlcat' mangled-name='strlcat' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='strlcat'> - <parameter type-id='26a90f95'/> - <parameter type-id='80f4b756'/> - <parameter type-id='b59d7dce'/> - <return type-id='b59d7dce'/> - </function-decl> - <function-decl name='strlcpy' mangled-name='strlcpy' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='strlcpy'> - <parameter type-id='26a90f95'/> - <parameter type-id='80f4b756'/> - <parameter type-id='b59d7dce'/> - <return type-id='b59d7dce'/> - </function-decl> - <function-decl name='free' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='eaa32e2f'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='strcmp' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='strncmp' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <parameter type-id='b59d7dce'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='strlen' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <return type-id='b59d7dce'/> - </function-decl> - <function-decl name='zfs_error' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_alloc' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <parameter type-id='b59d7dce'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='remove_mountpoint' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='9200a744'/> - <return type-id='48b5725f'/> - </function-decl> - <function-type size-in-bits='64' id='96ee24a5'> - <parameter type-id='eaa32e2f'/> - <parameter type-id='eaa32e2f'/> - <return type-id='95e97e5e'/> - </function-type> - <function-type size-in-bits='64' id='add6e811'> - <parameter type-id='eaa32e2f'/> - <parameter type-id='eaa32e2f'/> - <parameter type-id='eaa32e2f'/> - <return type-id='95e97e5e'/> - </function-type> - <function-type size-in-bits='64' id='cb9628fa'> - <parameter type-id='9200a744'/> - <parameter type-id='eaa32e2f'/> - <return type-id='95e97e5e'/> - </function-type> - </abi-instr> - <abi-instr address-size='64' path='lib/libzfs/libzfs_config.c' language='LANG_C99'> - <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='2816' id='514368c7'> - <subrange length='352' type-id='7359adad' id='b715cd6f'/> - </array-type-def> - <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='32768' id='d16c6df4'> - <subrange length='4096' type-id='7359adad' id='bc1b5ddc'/> - </array-type-def> - <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='65536' id='163f6aa5'> - <subrange length='8192' type-id='7359adad' id='c88f397d'/> - </array-type-def> - <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='infinite' id='e84913bd'> - <subrange length='infinite' type-id='7359adad' id='031f2035'/> - </array-type-def> - <array-type-def dimensions='1' type-id='9c313c2d' size-in-bits='128' id='c1c22e6c'> - <subrange length='2' type-id='7359adad' id='52efc4ef'/> - </array-type-def> - <array-type-def dimensions='1' type-id='b96825af' size-in-bits='24' id='d3490169'> - <subrange length='3' type-id='7359adad' id='56f209d2'/> - </array-type-def> - <type-decl name='variadic parameter type' id='2c1145c5'/> - <typedef-decl name='zpool_iter_f' type-id='3aebb66f' id='fa476e62'/> - <enum-decl name='data_type_t' naming-typedef-id='8d0687d2' id='aeeae136'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='DATA_TYPE_DONTCARE' value='-1'/> - <enumerator name='DATA_TYPE_UNKNOWN' value='0'/> - <enumerator name='DATA_TYPE_BOOLEAN' value='1'/> - <enumerator name='DATA_TYPE_BYTE' value='2'/> - <enumerator name='DATA_TYPE_INT16' value='3'/> - <enumerator name='DATA_TYPE_UINT16' value='4'/> - <enumerator name='DATA_TYPE_INT32' value='5'/> - <enumerator name='DATA_TYPE_UINT32' value='6'/> - <enumerator name='DATA_TYPE_INT64' value='7'/> - <enumerator name='DATA_TYPE_UINT64' value='8'/> - <enumerator name='DATA_TYPE_STRING' value='9'/> - <enumerator name='DATA_TYPE_BYTE_ARRAY' value='10'/> - <enumerator name='DATA_TYPE_INT16_ARRAY' value='11'/> - <enumerator name='DATA_TYPE_UINT16_ARRAY' value='12'/> - <enumerator name='DATA_TYPE_INT32_ARRAY' value='13'/> - <enumerator name='DATA_TYPE_UINT32_ARRAY' value='14'/> - <enumerator name='DATA_TYPE_INT64_ARRAY' value='15'/> - <enumerator name='DATA_TYPE_UINT64_ARRAY' value='16'/> - <enumerator name='DATA_TYPE_STRING_ARRAY' value='17'/> - <enumerator name='DATA_TYPE_HRTIME' value='18'/> - <enumerator name='DATA_TYPE_NVLIST' value='19'/> - <enumerator name='DATA_TYPE_NVLIST_ARRAY' value='20'/> - <enumerator name='DATA_TYPE_BOOLEAN_VALUE' value='21'/> - <enumerator name='DATA_TYPE_INT8' value='22'/> - <enumerator name='DATA_TYPE_UINT8' value='23'/> - <enumerator name='DATA_TYPE_BOOLEAN_ARRAY' value='24'/> - <enumerator name='DATA_TYPE_INT8_ARRAY' value='25'/> - <enumerator name='DATA_TYPE_UINT8_ARRAY' value='26'/> - <enumerator name='DATA_TYPE_DOUBLE' value='27'/> - </enum-decl> - <typedef-decl name='data_type_t' type-id='aeeae136' id='8d0687d2'/> - <class-decl name='nvpair' size-in-bits='128' is-struct='yes' visibility='default' id='1c34e459'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='nvp_size' type-id='3ff5601b' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32'> - <var-decl name='nvp_name_sz' type-id='23bd8cb5' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='48'> - <var-decl name='nvp_reserve' type-id='23bd8cb5' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='nvp_value_elem' type-id='3ff5601b' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='96'> - <var-decl name='nvp_type' type-id='8d0687d2' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='nvp_name' type-id='e84913bd' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='nvpair_t' type-id='1c34e459' id='57928edf'/> - <class-decl name='drr_begin' size-in-bits='2432' is-struct='yes' visibility='default' id='09fcdc01'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='drr_magic' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='drr_versioninfo' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='drr_creation_time' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='drr_type' type-id='230f1e16' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='224'> - <var-decl name='drr_flags' type-id='8f92235e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='drr_toguid' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='drr_fromguid' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='384'> - <var-decl name='drr_toname' type-id='d1617432' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='zinject_record' size-in-bits='2944' is-struct='yes' visibility='default' id='3216f820'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='zi_objset' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='zi_object' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='zi_start' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='zi_end' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='zi_guid' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='zi_level' type-id='8f92235e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='352'> - <var-decl name='zi_error' type-id='8f92235e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='384'> - <var-decl name='zi_type' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='448'> - <var-decl name='zi_freq' type-id='8f92235e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='480'> - <var-decl name='zi_failfast' type-id='8f92235e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='512'> - <var-decl name='zi_func' type-id='d1617432' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2560'> - <var-decl name='zi_iotype' type-id='8f92235e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2592'> - <var-decl name='zi_duration' type-id='3ff5601b' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2624'> - <var-decl name='zi_timer' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2688'> - <var-decl name='zi_nlanes' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2752'> - <var-decl name='zi_cmd' type-id='8f92235e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2784'> - <var-decl name='zi_dvas' type-id='8f92235e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2816'> - <var-decl name='zi_match_count' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2880'> - <var-decl name='zi_inject_count' type-id='9c313c2d' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='zinject_record_t' type-id='3216f820' id='a4301ca6'/> - <class-decl name='zfs_share' size-in-bits='256' is-struct='yes' visibility='default' id='feb6f2da'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='z_exportdata' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='z_sharedata' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='z_sharetype' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='z_sharemax' type-id='9c313c2d' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='zfs_share_t' type-id='feb6f2da' id='ee5cec36'/> - <class-decl name='zfs_cmd' size-in-bits='109952' is-struct='yes' visibility='default' id='3522cd69'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='zc_name' type-id='d16c6df4' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32768'> - <var-decl name='zc_nvlist_src' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32832'> - <var-decl name='zc_nvlist_src_size' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32896'> - <var-decl name='zc_nvlist_dst' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32960'> - <var-decl name='zc_nvlist_dst_size' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='33024'> - <var-decl name='zc_nvlist_dst_filled' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='33056'> - <var-decl name='zc_pad2' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='33088'> - <var-decl name='zc_history' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='33152'> - <var-decl name='zc_value' type-id='163f6aa5' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='98688'> - <var-decl name='zc_string' type-id='d1617432' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='100736'> - <var-decl name='zc_guid' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='100800'> - <var-decl name='zc_nvlist_conf' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='100864'> - <var-decl name='zc_nvlist_conf_size' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='100928'> - <var-decl name='zc_cookie' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='100992'> - <var-decl name='zc_objset_type' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='101056'> - <var-decl name='zc_perm_action' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='101120'> - <var-decl name='zc_history_len' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='101184'> - <var-decl name='zc_history_offset' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='101248'> - <var-decl name='zc_obj' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='101312'> - <var-decl name='zc_iflags' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='101376'> - <var-decl name='zc_share' type-id='ee5cec36' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='101632'> - <var-decl name='zc_objset_stats' type-id='b2c14f17' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='103936'> - <var-decl name='zc_begin_record' type-id='09fcdc01' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='106368'> - <var-decl name='' type-id='ac5ab595' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='109312'> - <var-decl name='zc_cleanup_fd' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='109344'> - <var-decl name='zc_simple' type-id='b96825af' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='109352'> - <var-decl name='zc_pad' type-id='d3490169' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='109376'> - <var-decl name='zc_sendobj' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='109440'> - <var-decl name='zc_fromobj' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='109504'> - <var-decl name='zc_createtxg' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='109568'> - <var-decl name='zc_stat' type-id='0371a9c7' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='109888'> - <var-decl name='zc_zoneid' type-id='9c313c2d' visibility='default'/> - </data-member> - </class-decl> - <union-decl name='__anonymous_union__' size-in-bits='2944' is-anonymous='yes' visibility='default' id='ac5ab595'> - <data-member access='public'> - <var-decl name='zc_inject_record' type-id='a4301ca6' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='' type-id='e7f43f73' visibility='default'/> - </data-member> - </union-decl> - <class-decl name='__anonymous_struct__' size-in-bits='2944' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f73'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='zc_pad1' type-id='514368c7' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2816'> - <var-decl name='zc_defer_destroy' type-id='8f92235e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2848'> - <var-decl name='zc_flags' type-id='8f92235e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2880'> - <var-decl name='zc_action_handle' type-id='9c313c2d' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='zfs_cmd_t' type-id='3522cd69' id='a5559cdd'/> - <class-decl name='zfs_stat' size-in-bits='320' is-struct='yes' visibility='default' id='6417f0b9'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='zs_gen' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='zs_mode' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='zs_links' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='zs_ctime' type-id='c1c22e6c' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='zfs_stat_t' type-id='6417f0b9' id='0371a9c7'/> - <typedef-decl name='int16_t' type-id='03896e23' id='23bd8cb5'/> - <typedef-decl name='__int16_t' type-id='a2185560' id='03896e23'/> - <pointer-type-def type-id='c19b74c3' size-in-bits='64' id='37e3bd22'/> - <qualified-type-def type-id='8e8d4be3' const='yes' id='693c3853'/> - <pointer-type-def type-id='693c3853' size-in-bits='64' id='22cce67b'/> - <qualified-type-def type-id='57928edf' const='yes' id='642ee20f'/> - <pointer-type-def type-id='642ee20f' size-in-bits='64' id='dace003f'/> - <pointer-type-def type-id='2bce87e3' size-in-bits='64' id='3aebb66f'/> - <pointer-type-def type-id='95e97e5e' size-in-bits='64' id='7292109c'/> - <pointer-type-def type-id='5ce45b60' size-in-bits='64' id='857bb57e'/> - <pointer-type-def type-id='57928edf' size-in-bits='64' id='3fa542f0'/> - <pointer-type-def type-id='eaa32e2f' size-in-bits='64' id='63e171df'/> - <pointer-type-def type-id='3522cd69' size-in-bits='64' id='b65f7fd1'/> - <pointer-type-def type-id='a5559cdd' size-in-bits='64' id='e4ec4540'/> - <pointer-type-def type-id='4c81de99' size-in-bits='64' id='237193c9'/> - <function-decl name='uu_avl_first' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='a5c21a38'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='uu_avl_next' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='a5c21a38'/> - <parameter type-id='eaa32e2f'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='uu_avl_teardown' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='a5c21a38'/> - <parameter type-id='63e171df'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='zfs_standard_error' mangled-name='zfs_standard_error' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_standard_error'> - <parameter type-id='b0382bb3'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_ioctl' mangled-name='zfs_ioctl' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_ioctl'> - <parameter type-id='b0382bb3'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='b65f7fd1'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='nvlist_free' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='nvlist_dup' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='22cce67b'/> - <parameter type-id='857bb57e'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='nvlist_lookup_nvlist' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='80f4b756'/> - <parameter type-id='857bb57e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='nvlist_exists' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='22cce67b'/> - <parameter type-id='80f4b756'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='nvlist_next_nvpair' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='dace003f'/> - <return type-id='3fa542f0'/> - </function-decl> - <function-decl name='nvpair_name' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='dace003f'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='fnvlist_dup' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='22cce67b'/> - <return type-id='5ce45b60'/> - </function-decl> - <function-decl name='fnvpair_value_nvlist' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='3fa542f0'/> - <return type-id='5ce45b60'/> - </function-decl> - <function-decl name='libspl_assertf' mangled-name='libspl_assertf' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_assertf'> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='80f4b756'/> - <parameter is-variadic='yes'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='__errno_location' visibility='default' binding='global' size-in-bits='64'> - <return type-id='7292109c'/> - </function-decl> - <function-decl name='dcgettext' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <parameter type-id='95e97e5e'/> - <return type-id='26a90f95'/> - </function-decl> - <function-decl name='getenv' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <return type-id='26a90f95'/> - </function-decl> - <function-decl name='strchr' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='95e97e5e'/> - <return type-id='26a90f95'/> - </function-decl> - <function-decl name='zpool_get_config' mangled-name='zpool_get_config' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_config'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='857bb57e' name='oldconfig'/> - <return type-id='5ce45b60'/> - </function-decl> - <function-decl name='zpool_get_features' mangled-name='zpool_get_features' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_features'> - <parameter type-id='4c81de99' name='zhp'/> - <return type-id='5ce45b60'/> - </function-decl> - <function-decl name='zpool_refresh_stats' mangled-name='zpool_refresh_stats' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_refresh_stats'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='37e3bd22' name='missing'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_refresh_stats_from_handle' mangled-name='zpool_refresh_stats_from_handle' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_refresh_stats_from_handle'> - <parameter type-id='4c81de99' name='dzhp'/> - <parameter type-id='4c81de99' name='szhp'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zpool_skip_pool' mangled-name='zpool_skip_pool' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_skip_pool'> - <parameter type-id='80f4b756' name='poolname'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zpool_iter' mangled-name='zpool_iter' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_iter'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='fa476e62' name='func'/> - <parameter type-id='eaa32e2f' name='data'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_iter_root' mangled-name='zfs_iter_root' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_root'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='d8e49ab9' name='func'/> - <parameter type-id='eaa32e2f' name='data'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_strdup' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <parameter type-id='80f4b756'/> - <return type-id='26a90f95'/> - </function-decl> - <function-decl name='no_memory' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zcmd_alloc_dst_nvlist' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <parameter type-id='e4ec4540'/> - <parameter type-id='b59d7dce'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zcmd_expand_dst_nvlist' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <parameter type-id='e4ec4540'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zcmd_read_dst_nvlist' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <parameter type-id='e4ec4540'/> - <parameter type-id='857bb57e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zcmd_free_nvlists' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='e4ec4540'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='make_dataset_handle' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <parameter type-id='80f4b756'/> - <return type-id='9200a744'/> - </function-decl> - <function-decl name='zpool_open_silent' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <parameter type-id='80f4b756'/> - <parameter type-id='237193c9'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-type size-in-bits='64' id='2bce87e3'> - <parameter type-id='4c81de99'/> - <parameter type-id='eaa32e2f'/> - <return type-id='95e97e5e'/> - </function-type> - </abi-instr> - <abi-instr address-size='64' path='lib/libzfs/libzfs_crypto.c' language='LANG_C99'> - <array-type-def dimensions='1' type-id='fb7c6451' size-in-bits='256' id='64177143'> - <subrange length='32' type-id='7359adad' id='ae5bde82'/> - </array-type-def> - <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='8' id='89feb1ec'> - <subrange length='1' type-id='7359adad' id='52f813b4'/> - </array-type-def> - <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='160' id='664ac0b7'> - <subrange length='20' type-id='7359adad' id='fdca39cf'/> - </array-type-def> - <class-decl name='_IO_codecvt' is-struct='yes' visibility='default' is-declaration-only='yes' id='a4036571'/> - <class-decl name='_IO_marker' is-struct='yes' visibility='default' is-declaration-only='yes' id='010ae0b9'/> - <class-decl name='_IO_wide_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='79bd3751'/> - <array-type-def dimensions='1' type-id='95e97e5e' size-in-bits='896' id='47394ee0'> - <subrange length='28' type-id='7359adad' id='3db583d7'/> - </array-type-def> - <type-decl name='signed char' size-in-bits='8' id='28577a57'/> - <array-type-def dimensions='1' type-id='7359adad' size-in-bits='1024' id='d2baa450'> - <subrange length='16' type-id='7359adad' id='848d0938'/> - </array-type-def> - <type-decl name='unsigned short int' size-in-bits='16' id='8efea9e5'/> - <enum-decl name='zpool_prop_t' naming-typedef-id='5d0c23fb' id='af1ba157'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='ZPOOL_PROP_INVAL' value='-1'/> - <enumerator name='ZPOOL_PROP_NAME' value='0'/> - <enumerator name='ZPOOL_PROP_SIZE' value='1'/> - <enumerator name='ZPOOL_PROP_CAPACITY' value='2'/> - <enumerator name='ZPOOL_PROP_ALTROOT' value='3'/> - <enumerator name='ZPOOL_PROP_HEALTH' value='4'/> - <enumerator name='ZPOOL_PROP_GUID' value='5'/> - <enumerator name='ZPOOL_PROP_VERSION' value='6'/> - <enumerator name='ZPOOL_PROP_BOOTFS' value='7'/> - <enumerator name='ZPOOL_PROP_DELEGATION' value='8'/> - <enumerator name='ZPOOL_PROP_AUTOREPLACE' value='9'/> - <enumerator name='ZPOOL_PROP_CACHEFILE' value='10'/> - <enumerator name='ZPOOL_PROP_FAILUREMODE' value='11'/> - <enumerator name='ZPOOL_PROP_LISTSNAPS' value='12'/> - <enumerator name='ZPOOL_PROP_AUTOEXPAND' value='13'/> - <enumerator name='ZPOOL_PROP_DEDUPDITTO' value='14'/> - <enumerator name='ZPOOL_PROP_DEDUPRATIO' value='15'/> - <enumerator name='ZPOOL_PROP_FREE' value='16'/> - <enumerator name='ZPOOL_PROP_ALLOCATED' value='17'/> - <enumerator name='ZPOOL_PROP_READONLY' value='18'/> - <enumerator name='ZPOOL_PROP_ASHIFT' value='19'/> - <enumerator name='ZPOOL_PROP_COMMENT' value='20'/> - <enumerator name='ZPOOL_PROP_EXPANDSZ' value='21'/> - <enumerator name='ZPOOL_PROP_FREEING' value='22'/> - <enumerator name='ZPOOL_PROP_FRAGMENTATION' value='23'/> - <enumerator name='ZPOOL_PROP_LEAKED' value='24'/> - <enumerator name='ZPOOL_PROP_MAXBLOCKSIZE' value='25'/> - <enumerator name='ZPOOL_PROP_TNAME' value='26'/> - <enumerator name='ZPOOL_PROP_MAXDNODESIZE' value='27'/> - <enumerator name='ZPOOL_PROP_MULTIHOST' value='28'/> - <enumerator name='ZPOOL_PROP_CHECKPOINT' value='29'/> - <enumerator name='ZPOOL_PROP_LOAD_GUID' value='30'/> - <enumerator name='ZPOOL_PROP_AUTOTRIM' value='31'/> - <enumerator name='ZPOOL_PROP_COMPATIBILITY' value='32'/> - <enumerator name='ZPOOL_PROP_BCLONEUSED' value='33'/> - <enumerator name='ZPOOL_PROP_BCLONESAVED' value='34'/> - <enumerator name='ZPOOL_PROP_BCLONERATIO' value='35'/> - <enumerator name='ZPOOL_PROP_DEDUP_TABLE_SIZE' value='36'/> - <enumerator name='ZPOOL_PROP_DEDUP_TABLE_QUOTA' value='37'/> - <enumerator name='ZPOOL_PROP_DEDUPCACHED' value='38'/> - <enumerator name='ZPOOL_PROP_LAST_SCRUBBED_TXG' value='39'/> - <enumerator name='ZPOOL_NUM_PROPS' value='40'/> - </enum-decl> - <typedef-decl name='zpool_prop_t' type-id='af1ba157' id='5d0c23fb'/> - <typedef-decl name='regoff_t' type-id='95e97e5e' id='54a2a2a8'/> - <class-decl name='regmatch_t' size-in-bits='64' is-struct='yes' naming-typedef-id='1b941664' visibility='default' id='4f932615'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='rm_so' type-id='54a2a2a8' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32'> - <var-decl name='rm_eo' type-id='54a2a2a8' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='regmatch_t' type-id='4f932615' id='1b941664'/> - <typedef-decl name='__sighandler_t' type-id='03347643' id='8cdd9566'/> - <typedef-decl name='ssize_t' type-id='41060289' id='79a0948f'/> - <class-decl name='sigaction' size-in-bits='1216' is-struct='yes' visibility='default' id='fe391c48'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='__sigaction_handler' type-id='ac5ab596' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='sa_mask' type-id='b9c97942' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1088'> - <var-decl name='sa_flags' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1152'> - <var-decl name='sa_restorer' type-id='953b12f8' visibility='default'/> - </data-member> - </class-decl> - <union-decl name='__anonymous_union__' size-in-bits='64' is-anonymous='yes' visibility='default' id='ac5ab596'> - <data-member access='public'> - <var-decl name='sa_handler' type-id='8cdd9566' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='sa_sigaction' type-id='6e756877' visibility='default'/> - </data-member> - </union-decl> - <class-decl name='termios' size-in-bits='480' is-struct='yes' visibility='default' id='ad55d2bc'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='c_iflag' type-id='241ce6f8' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32'> - <var-decl name='c_oflag' type-id='241ce6f8' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='c_cflag' type-id='241ce6f8' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='96'> - <var-decl name='c_lflag' type-id='241ce6f8' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='c_line' type-id='fb7c6451' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='136'> - <var-decl name='c_cc' type-id='64177143' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='416'> - <var-decl name='c_ispeed' type-id='6a8e8a14' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='448'> - <var-decl name='c_ospeed' type-id='6a8e8a14' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='cc_t' type-id='002ac4a6' id='fb7c6451'/> - <typedef-decl name='speed_t' type-id='f0981eeb' id='6a8e8a14'/> - <typedef-decl name='tcflag_t' type-id='f0981eeb' id='241ce6f8'/> - <typedef-decl name='__uid_t' type-id='f0981eeb' id='cc5fcceb'/> - <typedef-decl name='__off_t' type-id='bd54fe1a' id='79989e9c'/> - <typedef-decl name='__off64_t' type-id='bd54fe1a' id='724e4de6'/> - <typedef-decl name='__pid_t' type-id='95e97e5e' id='3629bad8'/> - <typedef-decl name='__clock_t' type-id='bd54fe1a' id='4d66c6d7'/> - <typedef-decl name='__ssize_t' type-id='bd54fe1a' id='41060289'/> - <typedef-decl name='FILE' type-id='ec1ed955' id='aa12d1ba'/> - <class-decl name='__sigset_t' size-in-bits='1024' is-struct='yes' naming-typedef-id='b9c97942' visibility='default' id='2616147f'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='__val' type-id='d2baa450' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='__sigset_t' type-id='2616147f' id='b9c97942'/> - <union-decl name='sigval' size-in-bits='64' visibility='default' id='a094b870'> - <data-member access='public'> - <var-decl name='sival_int' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='sival_ptr' type-id='eaa32e2f' visibility='default'/> - </data-member> - </union-decl> - <typedef-decl name='__sigval_t' type-id='a094b870' id='eabacd01'/> - <class-decl name='siginfo_t' size-in-bits='1024' is-struct='yes' naming-typedef-id='cb681f62' visibility='default' id='d8149419'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='si_signo' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32'> - <var-decl name='si_errno' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='si_code' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='96'> - <var-decl name='__pad0' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='_sifields' type-id='ac5ab597' visibility='default'/> - </data-member> - </class-decl> - <union-decl name='__anonymous_union__1' size-in-bits='896' is-anonymous='yes' visibility='default' id='ac5ab597'> - <data-member access='public'> - <var-decl name='_pad' type-id='47394ee0' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='_kill' type-id='e7f43f74' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='_timer' type-id='e7f43f75' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='_rt' type-id='e7f43f76' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='_sigchld' type-id='e7f43f77' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='_sigfault' type-id='e7f43f78' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='_sigpoll' type-id='e7f43f79' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='_sigsys' type-id='e7f43f7a' visibility='default'/> - </data-member> - </union-decl> - <class-decl name='__anonymous_struct__1' size-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f74'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='si_pid' type-id='3629bad8' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32'> - <var-decl name='si_uid' type-id='cc5fcceb' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='__anonymous_struct__2' size-in-bits='128' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f75'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='si_tid' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32'> - <var-decl name='si_overrun' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='si_sigval' type-id='eabacd01' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='__anonymous_struct__3' size-in-bits='128' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f76'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='si_pid' type-id='3629bad8' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32'> - <var-decl name='si_uid' type-id='cc5fcceb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='si_sigval' type-id='eabacd01' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='__anonymous_struct__4' size-in-bits='256' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f77'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='si_pid' type-id='3629bad8' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32'> - <var-decl name='si_uid' type-id='cc5fcceb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='si_status' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='si_utime' type-id='4d66c6d7' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='si_stime' type-id='4d66c6d7' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='__anonymous_struct__5' size-in-bits='256' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f78'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='si_addr' type-id='eaa32e2f' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='si_addr_lsb' type-id='a2185560' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='_bounds' type-id='ac5ab598' visibility='default'/> - </data-member> - </class-decl> - <union-decl name='__anonymous_union__2' size-in-bits='128' is-anonymous='yes' visibility='default' id='ac5ab598'> - <data-member access='public'> - <var-decl name='_addr_bnd' type-id='e7f43f7b' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='_pkey' type-id='62f1140c' visibility='default'/> - </data-member> - </union-decl> - <class-decl name='__anonymous_struct__6' size-in-bits='128' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f7b'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='_lower' type-id='eaa32e2f' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='_upper' type-id='eaa32e2f' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='__anonymous_struct__7' size-in-bits='128' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f79'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='si_band' type-id='bd54fe1a' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='si_fd' type-id='95e97e5e' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='__anonymous_struct__8' size-in-bits='128' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f7a'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='_call_addr' type-id='eaa32e2f' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='_syscall' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='96'> - <var-decl name='_arch' type-id='f0981eeb' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='siginfo_t' type-id='d8149419' id='cb681f62'/> - <typedef-decl name='sigset_t' type-id='b9c97942' id='daf33c64'/> - <typedef-decl name='_IO_lock_t' type-id='48b5725f' id='bb4788fa'/> - <class-decl name='_IO_FILE' size-in-bits='1728' is-struct='yes' visibility='default' id='ec1ed955'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='_flags' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='_IO_read_ptr' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='_IO_read_end' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='_IO_read_base' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='_IO_write_base' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='_IO_write_ptr' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='384'> - <var-decl name='_IO_write_end' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='448'> - <var-decl name='_IO_buf_base' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='512'> - <var-decl name='_IO_buf_end' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='576'> - <var-decl name='_IO_save_base' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='640'> - <var-decl name='_IO_backup_base' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='704'> - <var-decl name='_IO_save_end' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='768'> - <var-decl name='_markers' type-id='e4c6fa61' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='832'> - <var-decl name='_chain' type-id='dca988a5' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='896'> - <var-decl name='_fileno' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='928'> - <var-decl name='_flags2' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='960'> - <var-decl name='_old_offset' type-id='79989e9c' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1024'> - <var-decl name='_cur_column' type-id='8efea9e5' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1040'> - <var-decl name='_vtable_offset' type-id='28577a57' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1048'> - <var-decl name='_shortbuf' type-id='89feb1ec' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1088'> - <var-decl name='_lock' type-id='cecf4ea7' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1152'> - <var-decl name='_offset' type-id='724e4de6' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1216'> - <var-decl name='_codecvt' type-id='570f8c59' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1280'> - <var-decl name='_wide_data' type-id='c65a1f29' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1344'> - <var-decl name='_freeres_list' type-id='dca988a5' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1408'> - <var-decl name='_freeres_buf' type-id='eaa32e2f' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1472'> - <var-decl name='__pad5' type-id='b59d7dce' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1536'> - <var-decl name='_mode' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1568'> - <var-decl name='_unused2' type-id='664ac0b7' visibility='default'/> - </data-member> - </class-decl> - <pointer-type-def type-id='aa12d1ba' size-in-bits='64' id='822cd80b'/> - <qualified-type-def type-id='822cd80b' restrict='yes' id='e75a27e9'/> - <pointer-type-def type-id='ec1ed955' size-in-bits='64' id='dca988a5'/> - <pointer-type-def type-id='a4036571' size-in-bits='64' id='570f8c59'/> - <pointer-type-def type-id='bb4788fa' size-in-bits='64' id='cecf4ea7'/> - <pointer-type-def type-id='010ae0b9' size-in-bits='64' id='e4c6fa61'/> - <pointer-type-def type-id='79bd3751' size-in-bits='64' id='c65a1f29'/> - <qualified-type-def type-id='9b23c9ad' restrict='yes' id='8c85230f'/> - <qualified-type-def type-id='80f4b756' restrict='yes' id='9d26089a'/> - <pointer-type-def type-id='80f4b756' size-in-bits='64' id='7d3cd834'/> - <qualified-type-def type-id='aca3bac8' const='yes' id='2498fd78'/> - <pointer-type-def type-id='2498fd78' size-in-bits='64' id='eed6c816'/> - <qualified-type-def type-id='eed6c816' restrict='yes' id='a431a9da'/> - <qualified-type-def type-id='fe391c48' const='yes' id='14a93b33'/> - <pointer-type-def type-id='14a93b33' size-in-bits='64' id='9f68085b'/> - <qualified-type-def type-id='9f68085b' restrict='yes' id='e2a5e6f9'/> - <qualified-type-def type-id='ad55d2bc' const='yes' id='a46bf13f'/> - <pointer-type-def type-id='a46bf13f' size-in-bits='64' id='eaec840f'/> - <qualified-type-def type-id='002ac4a6' const='yes' id='ea86de29'/> - <pointer-type-def type-id='ea86de29' size-in-bits='64' id='354f7eb9'/> - <qualified-type-def type-id='8efea9e5' const='yes' id='3beb2af4'/> - <pointer-type-def type-id='3beb2af4' size-in-bits='64' id='31347b7a'/> - <pointer-type-def type-id='31347b7a' size-in-bits='64' id='c59e1ef0'/> - <pointer-type-def type-id='7a6844eb' size-in-bits='64' id='18c91f9e'/> - <pointer-type-def type-id='1b941664' size-in-bits='64' id='7e2979d5'/> - <qualified-type-def type-id='7e2979d5' restrict='yes' id='fc212857'/> - <pointer-type-def type-id='fe391c48' size-in-bits='64' id='568dd84e'/> - <qualified-type-def type-id='568dd84e' restrict='yes' id='3d8ee6f2'/> - <pointer-type-def type-id='cb681f62' size-in-bits='64' id='185869c1'/> - <pointer-type-def type-id='daf33c64' size-in-bits='64' id='9e80f729'/> - <pointer-type-def type-id='b59d7dce' size-in-bits='64' id='78c01427'/> - <qualified-type-def type-id='78c01427' restrict='yes' id='d19b2c25'/> - <pointer-type-def type-id='ad55d2bc' size-in-bits='64' id='665a4eda'/> - <pointer-type-def type-id='9c313c2d' size-in-bits='64' id='5d6479ae'/> - <pointer-type-def type-id='ae3e8ca6' size-in-bits='64' id='d8774064'/> - <pointer-type-def type-id='3502e3ff' size-in-bits='64' id='4dd26a40'/> - <pointer-type-def type-id='ee076206' size-in-bits='64' id='953b12f8'/> - <pointer-type-def type-id='f712e2b7' size-in-bits='64' id='03347643'/> - <pointer-type-def type-id='ef70d893' size-in-bits='64' id='6e756877'/> - <qualified-type-def type-id='eaa32e2f' restrict='yes' id='1b7446cd'/> - <class-decl name='_IO_codecvt' is-struct='yes' visibility='default' is-declaration-only='yes' id='a4036571'/> - <class-decl name='_IO_marker' is-struct='yes' visibility='default' is-declaration-only='yes' id='010ae0b9'/> - <class-decl name='_IO_wide_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='79bd3751'/> - <function-decl name='zpool_get_prop_int' mangled-name='zpool_get_prop_int' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_prop_int'> - <parameter type-id='4c81de99'/> - <parameter type-id='5d0c23fb'/> - <parameter type-id='debc6aa3'/> - <return type-id='9c313c2d'/> - </function-decl> - <function-decl name='zfs_handle_dup' mangled-name='zfs_handle_dup' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_handle_dup'> - <parameter type-id='9200a744'/> - <return type-id='9200a744'/> - </function-decl> - <function-decl name='zfs_valid_proplist' mangled-name='zfs_valid_proplist' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_valid_proplist'> - <parameter type-id='b0382bb3'/> - <parameter type-id='2e45de5d'/> - <parameter type-id='5ce45b60'/> - <parameter type-id='9c313c2d'/> - <parameter type-id='9200a744'/> - <parameter type-id='4c81de99'/> - <parameter type-id='c19b74c3'/> - <parameter type-id='80f4b756'/> - <return type-id='5ce45b60'/> - </function-decl> - <function-decl name='zfs_prop_to_name' mangled-name='zfs_prop_to_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_to_name'> - <parameter type-id='58603c44'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='zfs_parent_name' mangled-name='zfs_parent_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_parent_name'> - <parameter type-id='9200a744'/> - <parameter type-id='26a90f95'/> - <parameter type-id='b59d7dce'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_load_key' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='c19b74c3'/> - <parameter type-id='ae3e8ca6'/> - <parameter type-id='3502e3ff'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_unload_key' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_change_key' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='9c313c2d'/> - <parameter type-id='5ce45b60'/> - <parameter type-id='ae3e8ca6'/> - <parameter type-id='3502e3ff'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_name_to_prop' mangled-name='zfs_name_to_prop' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_name_to_prop'> - <parameter type-id='80f4b756'/> - <return type-id='58603c44'/> - </function-decl> - <function-decl name='nvlist_add_uint64' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='80f4b756'/> - <parameter type-id='9c313c2d'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='nvlist_add_string' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='nvlist_lookup_uint64' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='22cce67b'/> - <parameter type-id='80f4b756'/> - <parameter type-id='5d6479ae'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='nvlist_lookup_string' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='22cce67b'/> - <parameter type-id='80f4b756'/> - <parameter type-id='7d3cd834'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='fnvlist_alloc' visibility='default' binding='global' size-in-bits='64'> - <return type-id='5ce45b60'/> - </function-decl> - <function-decl name='__ctype_b_loc' visibility='default' binding='global' size-in-bits='64'> - <return type-id='c59e1ef0'/> - </function-decl> - <function-decl name='dlopen' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='95e97e5e'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='dlsym' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='1b7446cd'/> - <parameter type-id='9d26089a'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='dlerror' visibility='default' binding='global' size-in-bits='64'> - <return type-id='26a90f95'/> - </function-decl> - <function-decl name='PKCS5_PBKDF2_HMAC_SHA1' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='354f7eb9'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='cf536864'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_mutex_lock' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='18c91f9e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_mutex_unlock' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='18c91f9e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='regexec' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='a431a9da'/> - <parameter type-id='9d26089a'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='fc212857'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='kill' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='3629bad8'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='sigemptyset' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='9e80f729'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='sigaction' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <parameter type-id='e2a5e6f9'/> - <parameter type-id='3d8ee6f2'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='fclose' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='822cd80b'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='fflush' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='822cd80b'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='fdopen' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <parameter type-id='80f4b756'/> - <return type-id='822cd80b'/> - </function-decl> - <function-decl name='fputc' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <parameter type-id='822cd80b'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='__getdelim' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='8c85230f'/> - <parameter type-id='d19b2c25'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='e75a27e9'/> - <return type-id='41060289'/> - </function-decl> - <function-decl name='rewind' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='822cd80b'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='ferror' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='822cd80b'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='fileno' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='822cd80b'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='malloc' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b59d7dce'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='calloc' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b59d7dce'/> - <parameter type-id='b59d7dce'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='strdup' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <return type-id='26a90f95'/> - </function-decl> - <function-decl name='strerror' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <return type-id='26a90f95'/> - </function-decl> - <function-decl name='tcgetattr' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <parameter type-id='665a4eda'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='tcsetattr' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='eaec840f'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='close' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='getpid' visibility='default' binding='global' size-in-bits='64'> - <return type-id='3629bad8'/> - </function-decl> - <function-decl name='isatty' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='unlink' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='__open_too_many_args' visibility='default' binding='global' size-in-bits='64'> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='__open_missing_mode' visibility='default' binding='global' size-in-bits='64'> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='__printf_chk' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <parameter type-id='80f4b756'/> - <parameter is-variadic='yes'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='__asprintf_chk' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='8c85230f'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='9d26089a'/> - <parameter is-variadic='yes'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='__fread_chk' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='1b7446cd'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='e75a27e9'/> - <return type-id='b59d7dce'/> - </function-decl> - <function-decl name='__read_chk' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <parameter type-id='eaa32e2f'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='b59d7dce'/> - <return type-id='79a0948f'/> - </function-decl> - <function-decl name='zfs_crypto_get_encryption_root' mangled-name='zfs_crypto_get_encryption_root' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_crypto_get_encryption_root'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='37e3bd22' name='is_encroot'/> - <parameter type-id='26a90f95' name='buf'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_crypto_create' mangled-name='zfs_crypto_create' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_crypto_create'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='26a90f95' name='parent_name'/> - <parameter type-id='5ce45b60' name='props'/> - <parameter type-id='5ce45b60' name='pool_props'/> - <parameter type-id='c19b74c3' name='stdin_available'/> - <parameter type-id='d8774064' name='wkeydata_out'/> - <parameter type-id='4dd26a40' name='wkeylen_out'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_crypto_clone_check' mangled-name='zfs_crypto_clone_check' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_crypto_clone_check'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='9200a744' name='origin_zhp'/> - <parameter type-id='26a90f95' name='parent_name'/> - <parameter type-id='5ce45b60' name='props'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_crypto_attempt_load_keys' mangled-name='zfs_crypto_attempt_load_keys' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_crypto_attempt_load_keys'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='80f4b756' name='fsname'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_crypto_load_key' mangled-name='zfs_crypto_load_key' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_crypto_load_key'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='c19b74c3' name='noop'/> - <parameter type-id='80f4b756' name='alt_keylocation'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_crypto_unload_key' mangled-name='zfs_crypto_unload_key' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_crypto_unload_key'> - <parameter type-id='9200a744' name='zhp'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_crypto_rewrap' mangled-name='zfs_crypto_rewrap' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_crypto_rewrap'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='5ce45b60' name='raw_props'/> - <parameter type-id='c19b74c3' name='inheritkey'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_is_encrypted' mangled-name='zfs_is_encrypted' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_is_encrypted'> - <parameter type-id='9200a744' name='zhp'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zfs_error_aux' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <parameter type-id='80f4b756'/> - <parameter is-variadic='yes'/> - <return type-id='48b5725f'/> - </function-decl> - <function-type size-in-bits='64' id='f712e2b7'> - <parameter type-id='95e97e5e'/> - <return type-id='48b5725f'/> - </function-type> - <function-type size-in-bits='64' id='ef70d893'> - <parameter type-id='95e97e5e'/> - <parameter type-id='185869c1'/> - <parameter type-id='eaa32e2f'/> - <return type-id='48b5725f'/> - </function-type> - </abi-instr> - <abi-instr address-size='64' path='lib/libzfs/libzfs_dataset.c' language='LANG_C99'> - <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='32' id='8e0573fd'> - <subrange length='4' type-id='7359adad' id='16fe7105'/> - </array-type-def> - <class-decl name='prop_changelist' is-struct='yes' visibility='default' is-declaration-only='yes' id='d86edc51'/> - <class-decl name='zprop_list' size-in-bits='448' is-struct='yes' visibility='default' id='bd9b4291'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='pl_prop' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='pl_user_prop' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='pl_next' type-id='9f1a1109' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='pl_all' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='pl_width' type-id='b59d7dce' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='pl_recvd_width' type-id='b59d7dce' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='384'> - <var-decl name='pl_fixed' type-id='c19b74c3' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='zprop_list_t' type-id='bd9b4291' id='bdb8ac4f'/> - <class-decl name='renameflags' size-in-bits='32' is-struct='yes' visibility='default' id='7aee5792'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='recursive' type-id='f0981eeb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1'> - <var-decl name='nounmount' type-id='f0981eeb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2'> - <var-decl name='forceunmount' type-id='f0981eeb' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='renameflags_t' type-id='7aee5792' id='067170c2'/> - <typedef-decl name='zfs_userspace_cb_t' type-id='bbaa4f9c' id='16c5f410'/> - <enum-decl name='lzc_dataset_type' id='bc9887f1'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='LZC_DATSET_TYPE_ZFS' value='2'/> - <enumerator name='LZC_DATSET_TYPE_ZVOL' value='3'/> - </enum-decl> - <typedef-decl name='avl_index_t' type-id='e475ab95' id='fba6cb51'/> - <enum-decl name='zfs_userquota_prop_t' naming-typedef-id='279fde6a' id='5258d2f6'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='ZFS_PROP_USERUSED' value='0'/> - <enumerator name='ZFS_PROP_USERQUOTA' value='1'/> - <enumerator name='ZFS_PROP_GROUPUSED' value='2'/> - <enumerator name='ZFS_PROP_GROUPQUOTA' value='3'/> - <enumerator name='ZFS_PROP_USEROBJUSED' value='4'/> - <enumerator name='ZFS_PROP_USEROBJQUOTA' value='5'/> - <enumerator name='ZFS_PROP_GROUPOBJUSED' value='6'/> - <enumerator name='ZFS_PROP_GROUPOBJQUOTA' value='7'/> - <enumerator name='ZFS_PROP_PROJECTUSED' value='8'/> - <enumerator name='ZFS_PROP_PROJECTQUOTA' value='9'/> - <enumerator name='ZFS_PROP_PROJECTOBJUSED' value='10'/> - <enumerator name='ZFS_PROP_PROJECTOBJQUOTA' value='11'/> - <enumerator name='ZFS_NUM_USERQUOTA_PROPS' value='12'/> - </enum-decl> - <typedef-decl name='zfs_userquota_prop_t' type-id='5258d2f6' id='279fde6a'/> - <enum-decl name='zfs_wait_activity_t' naming-typedef-id='3024501a' id='527d5dc6'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='ZFS_WAIT_DELETEQ' value='0'/> - <enumerator name='ZFS_WAIT_NUM_ACTIVITIES' value='1'/> - </enum-decl> - <typedef-decl name='zfs_wait_activity_t' type-id='527d5dc6' id='3024501a'/> - <enum-decl name='namecheck_err_t' naming-typedef-id='8e0af06e' id='f43bbcda'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='NAME_ERR_LEADING_SLASH' value='0'/> - <enumerator name='NAME_ERR_EMPTY_COMPONENT' value='1'/> - <enumerator name='NAME_ERR_TRAILING_SLASH' value='2'/> - <enumerator name='NAME_ERR_INVALCHAR' value='3'/> - <enumerator name='NAME_ERR_MULTIPLE_DELIMITERS' value='4'/> - <enumerator name='NAME_ERR_NOLETTER' value='5'/> - <enumerator name='NAME_ERR_RESERVED' value='6'/> - <enumerator name='NAME_ERR_DISKLIKE' value='7'/> - <enumerator name='NAME_ERR_TOOLONG' value='8'/> - <enumerator name='NAME_ERR_SELF_REF' value='9'/> - <enumerator name='NAME_ERR_PARENT_REF' value='10'/> - <enumerator name='NAME_ERR_NO_AT' value='11'/> - <enumerator name='NAME_ERR_NO_POUND' value='12'/> - </enum-decl> - <typedef-decl name='namecheck_err_t' type-id='f43bbcda' id='8e0af06e'/> - <enum-decl name='zprop_type_t' naming-typedef-id='31429eff' id='87676253'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='PROP_TYPE_NUMBER' value='0'/> - <enumerator name='PROP_TYPE_STRING' value='1'/> - <enumerator name='PROP_TYPE_INDEX' value='2'/> - </enum-decl> - <typedef-decl name='zprop_type_t' type-id='87676253' id='31429eff'/> - <class-decl name='mnttab' size-in-bits='256' is-struct='yes' visibility='default' id='1b055409'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='mnt_special' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='mnt_mountp' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='mnt_fstype' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='mnt_mntopts' type-id='26a90f95' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='group' size-in-bits='256' is-struct='yes' visibility='default' id='01a1b934'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='gr_name' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='gr_passwd' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='gr_gid' type-id='d94ec6d9' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='gr_mem' type-id='9b23c9ad' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='mntent' size-in-bits='320' is-struct='yes' visibility='default' id='56fe4a37'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='mnt_fsname' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='mnt_dir' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='mnt_type' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='mnt_opts' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='mnt_freq' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='288'> - <var-decl name='mnt_passno' type-id='95e97e5e' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='passwd' size-in-bits='384' is-struct='yes' visibility='default' id='a63d15a3'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='pw_name' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='pw_passwd' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='pw_uid' type-id='cc5fcceb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='160'> - <var-decl name='pw_gid' type-id='d94ec6d9' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='pw_gecos' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='pw_dir' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='pw_shell' type-id='26a90f95' visibility='default'/> - </data-member> - </class-decl> - <union-decl name='pthread_mutexattr_t' size-in-bits='32' naming-typedef-id='8afd6070' visibility='default' id='7300eb00'> - <data-member access='public'> - <var-decl name='__size' type-id='8e0573fd' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='__align' type-id='95e97e5e' visibility='default'/> - </data-member> - </union-decl> - <typedef-decl name='pthread_mutexattr_t' type-id='7300eb00' id='8afd6070'/> - <typedef-decl name='int64_t' type-id='0c9942d2' id='9da381c4'/> - <typedef-decl name='__int64_t' type-id='bd54fe1a' id='0c9942d2'/> - <typedef-decl name='__gid_t' type-id='f0981eeb' id='d94ec6d9'/> - <typedef-decl name='__time_t' type-id='bd54fe1a' id='65eda9c0'/> - <class-decl name='tm' size-in-bits='448' is-struct='yes' visibility='default' id='dddf6ca2'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='tm_sec' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32'> - <var-decl name='tm_min' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='tm_hour' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='96'> - <var-decl name='tm_mday' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='tm_mon' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='160'> - <var-decl name='tm_year' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='tm_wday' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='224'> - <var-decl name='tm_yday' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='tm_isdst' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='tm_gmtoff' type-id='bd54fe1a' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='384'> - <var-decl name='tm_zone' type-id='80f4b756' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='time_t' type-id='65eda9c0' id='c9d12d66'/> - <typedef-decl name='uid_t' type-id='cc5fcceb' id='354978ed'/> - <typedef-decl name='prop_changelist_t' type-id='d86edc51' id='eae6431d'/> - <pointer-type-def type-id='fba6cb51' size-in-bits='64' id='32adbf30'/> - <pointer-type-def type-id='f20fbd51' size-in-bits='64' id='a3681dea'/> - <qualified-type-def type-id='26a90f95' restrict='yes' id='266fe297'/> - <qualified-type-def type-id='56fe4a37' const='yes' id='a75125ce'/> - <pointer-type-def type-id='a75125ce' size-in-bits='64' id='48bea5ec'/> - <qualified-type-def type-id='8afd6070' const='yes' id='1d853360'/> - <pointer-type-def type-id='1d853360' size-in-bits='64' id='c2afbd7e'/> - <qualified-type-def type-id='c9d12d66' const='yes' id='588b3216'/> - <pointer-type-def type-id='588b3216' size-in-bits='64' id='9f201474'/> - <qualified-type-def type-id='9f201474' restrict='yes' id='d6e2847c'/> - <qualified-type-def type-id='dddf6ca2' const='yes' id='e824a34f'/> - <pointer-type-def type-id='e824a34f' size-in-bits='64' id='d6ad37ff'/> - <qualified-type-def type-id='d6ad37ff' restrict='yes' id='f8c6051d'/> - <qualified-type-def type-id='9c313c2d' const='yes' id='c3b7ba7d'/> - <pointer-type-def type-id='c3b7ba7d' size-in-bits='64' id='713a56f5'/> - <pointer-type-def type-id='01a1b934' size-in-bits='64' id='566b3f52'/> - <qualified-type-def type-id='566b3f52' restrict='yes' id='c878edd6'/> - <pointer-type-def type-id='566b3f52' size-in-bits='64' id='82d4e9e8'/> - <qualified-type-def type-id='82d4e9e8' restrict='yes' id='aa19c230'/> - <pointer-type-def type-id='02362c02' size-in-bits='64' id='bbaa4f9c'/> - <pointer-type-def type-id='9da381c4' size-in-bits='64' id='cb785ebf'/> - <pointer-type-def type-id='1b055409' size-in-bits='64' id='9d424d31'/> - <pointer-type-def type-id='8e0af06e' size-in-bits='64' id='053457bd'/> - <pointer-type-def type-id='857bb57e' size-in-bits='64' id='75be733c'/> - <pointer-type-def type-id='a63d15a3' size-in-bits='64' id='a195f4a3'/> - <qualified-type-def type-id='a195f4a3' restrict='yes' id='33518961'/> - <pointer-type-def type-id='a195f4a3' size-in-bits='64' id='e80ff3ab'/> - <qualified-type-def type-id='e80ff3ab' restrict='yes' id='8f2c7109'/> - <pointer-type-def type-id='eae6431d' size-in-bits='64' id='0d41d328'/> - <pointer-type-def type-id='dddf6ca2' size-in-bits='64' id='d915a820'/> - <qualified-type-def type-id='d915a820' restrict='yes' id='f099ad08'/> - <pointer-type-def type-id='5d6479ae' size-in-bits='64' id='892b4acc'/> - <pointer-type-def type-id='bd9b4291' size-in-bits='64' id='9f1a1109'/> - <pointer-type-def type-id='bdb8ac4f' size-in-bits='64' id='3a9b2288'/> - <pointer-type-def type-id='3a9b2288' size-in-bits='64' id='e4378506'/> - <class-decl name='prop_changelist' is-struct='yes' visibility='default' is-declaration-only='yes' id='d86edc51'/> - <function-decl name='zpool_open' mangled-name='zpool_open' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_open'> - <parameter type-id='b0382bb3'/> - <parameter type-id='80f4b756'/> - <return type-id='4c81de99'/> - </function-decl> - <function-decl name='zpool_open_canfail' mangled-name='zpool_open_canfail' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_open_canfail'> - <parameter type-id='b0382bb3'/> - <parameter type-id='80f4b756'/> - <return type-id='4c81de99'/> - </function-decl> - <function-decl name='zpool_close' mangled-name='zpool_close' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_close'> - <parameter type-id='4c81de99'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zpool_get_name' mangled-name='zpool_get_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_name'> - <parameter type-id='4c81de99'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='zpool_get_prop' mangled-name='zpool_get_prop' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_prop'> - <parameter type-id='4c81de99'/> - <parameter type-id='5d0c23fb'/> - <parameter type-id='26a90f95'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='debc6aa3'/> - <parameter type-id='c19b74c3'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_prop_default_string' mangled-name='zfs_prop_default_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_default_string'> - <parameter type-id='58603c44'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='zfs_prop_default_numeric' mangled-name='zfs_prop_default_numeric' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_default_numeric'> - <parameter type-id='58603c44'/> - <return type-id='9c313c2d'/> - </function-decl> - <function-decl name='zfs_iter_snapshots_v2' mangled-name='zfs_iter_snapshots_v2' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_snapshots_v2'> - <parameter type-id='9200a744'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='d8e49ab9'/> - <parameter type-id='eaa32e2f'/> - <parameter type-id='9c313c2d'/> - <parameter type-id='9c313c2d'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_iter_bookmarks_v2' mangled-name='zfs_iter_bookmarks_v2' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_bookmarks_v2'> - <parameter type-id='9200a744'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='d8e49ab9'/> - <parameter type-id='eaa32e2f'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_destroy_snaps_nvl_os' mangled-name='zfs_destroy_snaps_nvl_os' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_destroy_snaps_nvl_os'> - <parameter type-id='b0382bb3'/> - <parameter type-id='5ce45b60'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_nicestrtonum' mangled-name='zfs_nicestrtonum' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_nicestrtonum'> - <parameter type-id='b0382bb3'/> - <parameter type-id='80f4b756'/> - <parameter type-id='5d6479ae'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_ioctl_fd' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <parameter type-id='7359adad'/> - <parameter type-id='b65f7fd1'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_snapshot' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='5ce45b60'/> - <parameter type-id='857bb57e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_create' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='bc9887f1'/> - <parameter type-id='5ce45b60'/> - <parameter type-id='ae3e8ca6'/> - <parameter type-id='3502e3ff'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_clone' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <parameter type-id='5ce45b60'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_promote' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='26a90f95'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_destroy_snaps' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='c19b74c3'/> - <parameter type-id='857bb57e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_get_bookmarks' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='5ce45b60'/> - <parameter type-id='857bb57e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_destroy_bookmarks' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='857bb57e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_hold' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='857bb57e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_release' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='857bb57e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_get_holds' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='857bb57e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_exists' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='lzc_rollback_to' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_destroy' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_channel_program_nosync' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <parameter type-id='9c313c2d'/> - <parameter type-id='9c313c2d'/> - <parameter type-id='5ce45b60'/> - <parameter type-id='857bb57e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_wait_fs' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='3024501a'/> - <parameter type-id='37e3bd22'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_nicebytes' mangled-name='zfs_nicebytes' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_nicebytes'> - <parameter type-id='9c313c2d'/> - <parameter type-id='26a90f95'/> - <parameter type-id='b59d7dce'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zfs_nicenum' mangled-name='zfs_nicenum' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_nicenum'> - <parameter type-id='9c313c2d'/> - <parameter type-id='26a90f95'/> - <parameter type-id='b59d7dce'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='avl_create' mangled-name='avl_create' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_create'> - <parameter type-id='a3681dea'/> - <parameter type-id='585e1de9'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='b59d7dce'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='avl_find' mangled-name='avl_find' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_find'> - <parameter type-id='a3681dea'/> - <parameter type-id='eaa32e2f'/> - <parameter type-id='32adbf30'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='avl_add' mangled-name='avl_add' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_add'> - <parameter type-id='a3681dea'/> - <parameter type-id='eaa32e2f'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='avl_remove' mangled-name='avl_remove' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_remove'> - <parameter type-id='a3681dea'/> - <parameter type-id='eaa32e2f'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='avl_numnodes' mangled-name='avl_numnodes' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_numnodes'> - <parameter type-id='a3681dea'/> - <return type-id='ee1f298e'/> - </function-decl> - <function-decl name='avl_destroy_nodes' mangled-name='avl_destroy_nodes' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_destroy_nodes'> - <parameter type-id='a3681dea'/> - <parameter type-id='63e171df'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='avl_destroy' mangled-name='avl_destroy' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_destroy'> - <parameter type-id='a3681dea'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zfs_prop_readonly' mangled-name='zfs_prop_readonly' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_readonly'> - <parameter type-id='58603c44'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zfs_prop_inheritable' mangled-name='zfs_prop_inheritable' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_inheritable'> - <parameter type-id='58603c44'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zfs_prop_setonce' mangled-name='zfs_prop_setonce' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_setonce'> - <parameter type-id='58603c44'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zfs_prop_encryption_key_param' mangled-name='zfs_prop_encryption_key_param' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_encryption_key_param'> - <parameter type-id='58603c44'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zfs_prop_valid_keylocation' mangled-name='zfs_prop_valid_keylocation' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_valid_keylocation'> - <parameter type-id='80f4b756'/> - <parameter type-id='c19b74c3'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zfs_prop_user' mangled-name='zfs_prop_user' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_user'> - <parameter type-id='80f4b756'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zfs_prop_userquota' mangled-name='zfs_prop_userquota' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_userquota'> - <parameter type-id='80f4b756'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zfs_prop_written' mangled-name='zfs_prop_written' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_written'> - <parameter type-id='80f4b756'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zfs_prop_index_to_string' mangled-name='zfs_prop_index_to_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_index_to_string'> - <parameter type-id='58603c44'/> - <parameter type-id='9c313c2d'/> - <parameter type-id='7d3cd834'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_prop_valid_for_type' mangled-name='zfs_prop_valid_for_type' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_valid_for_type'> - <parameter type-id='95e97e5e'/> - <parameter type-id='2e45de5d'/> - <parameter type-id='c19b74c3'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='nvlist_alloc' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='857bb57e'/> - <parameter type-id='3502e3ff'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='nvlist_size' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='78c01427'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='nvlist_pack' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='9b23c9ad'/> - <parameter type-id='78c01427'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='nvlist_unpack' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='26a90f95'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='857bb57e'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='nvlist_add_nvlist' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='80f4b756'/> - <parameter type-id='22cce67b'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='nvlist_add_uint64_array' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='80f4b756'/> - <parameter type-id='713a56f5'/> - <parameter type-id='3502e3ff'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='nvlist_remove' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='80f4b756'/> - <parameter type-id='8d0687d2'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='nvlist_remove_all' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='nvlist_lookup_int64' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='22cce67b'/> - <parameter type-id='80f4b756'/> - <parameter type-id='cb785ebf'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='nvlist_lookup_uint64_array' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='80f4b756'/> - <parameter type-id='892b4acc'/> - <parameter type-id='4dd26a40'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='nvlist_lookup_nvlist_array' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='80f4b756'/> - <parameter type-id='75be733c'/> - <parameter type-id='4dd26a40'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='nvlist_empty' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='22cce67b'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='nvpair_type' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='dace003f'/> - <return type-id='8d0687d2'/> - </function-decl> - <function-decl name='nvpair_value_uint64' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='dace003f'/> - <parameter type-id='5d6479ae'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='nvpair_value_string' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='dace003f'/> - <parameter type-id='7d3cd834'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='fnvlist_free' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='fnvlist_add_boolean' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='80f4b756'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='fnvlist_add_uint64' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='80f4b756'/> - <parameter type-id='9c313c2d'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='fnvlist_add_string' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='fnvlist_add_nvlist' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='80f4b756'/> - <parameter type-id='5ce45b60'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='fnvlist_lookup_uint64' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='22cce67b'/> - <parameter type-id='80f4b756'/> - <return type-id='9c313c2d'/> - </function-decl> - <function-decl name='fnvlist_lookup_string' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='22cce67b'/> - <parameter type-id='80f4b756'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='fnvlist_lookup_nvlist' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='80f4b756'/> - <return type-id='5ce45b60'/> - </function-decl> - <function-decl name='fnvpair_value_int32' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='dace003f'/> - <return type-id='3ff5601b'/> - </function-decl> - <function-decl name='fnvpair_value_uint64' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='dace003f'/> - <return type-id='9c313c2d'/> - </function-decl> - <function-decl name='entity_namecheck' mangled-name='entity_namecheck' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='entity_namecheck'> - <parameter type-id='80f4b756'/> - <parameter type-id='053457bd'/> - <parameter type-id='26a90f95'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='dataset_nestcheck' mangled-name='dataset_nestcheck' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='dataset_nestcheck'> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='mountpoint_namecheck' mangled-name='mountpoint_namecheck' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='mountpoint_namecheck'> - <parameter type-id='80f4b756'/> - <parameter type-id='053457bd'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_prop_get_type' mangled-name='zfs_prop_get_type' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_get_type'> - <parameter type-id='58603c44'/> - <return type-id='31429eff'/> - </function-decl> - <function-decl name='sa_validate_shareopts' mangled-name='sa_validate_shareopts' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='sa_validate_shareopts'> - <parameter type-id='80f4b756'/> - <parameter type-id='9155d4b5'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='getmntany' mangled-name='getmntany' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getmntany'> - <parameter type-id='822cd80b'/> - <parameter type-id='9d424d31'/> - <parameter type-id='9d424d31'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='_sol_getmntent' mangled-name='_sol_getmntent' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='_sol_getmntent'> - <parameter type-id='822cd80b'/> - <parameter type-id='9d424d31'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='getgrnam_r' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='9d26089a'/> - <parameter type-id='c878edd6'/> - <parameter type-id='266fe297'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='aa19c230'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='hasmntopt' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='48bea5ec'/> - <parameter type-id='80f4b756'/> - <return type-id='26a90f95'/> - </function-decl> - <function-decl name='pthread_mutex_init' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='18c91f9e'/> - <parameter type-id='c2afbd7e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_mutex_destroy' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='18c91f9e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='getpwnam_r' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='9d26089a'/> - <parameter type-id='33518961'/> - <parameter type-id='266fe297'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='8f2c7109'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='strtol' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='9d26089a'/> - <parameter type-id='8c85230f'/> - <parameter type-id='95e97e5e'/> - <return type-id='bd54fe1a'/> - </function-decl> - <function-decl name='strtoul' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='9d26089a'/> - <parameter type-id='8c85230f'/> - <parameter type-id='95e97e5e'/> - <return type-id='7359adad'/> - </function-decl> - <function-decl name='abort' visibility='default' binding='global' size-in-bits='64'> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='strrchr' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='95e97e5e'/> - <return type-id='26a90f95'/> - </function-decl> - <function-decl name='strcspn' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <return type-id='b59d7dce'/> - </function-decl> - <function-decl name='strstr' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <return type-id='26a90f95'/> - </function-decl> - <function-decl name='strsep' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='8c85230f'/> - <parameter type-id='9d26089a'/> - <return type-id='26a90f95'/> - </function-decl> - <function-decl name='strftime' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='266fe297'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='9d26089a'/> - <parameter type-id='f8c6051d'/> - <return type-id='b59d7dce'/> - </function-decl> - <function-decl name='localtime_r' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='d6e2847c'/> - <parameter type-id='f099ad08'/> - <return type-id='d915a820'/> - </function-decl> - <function-decl name='__fprintf_chk' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='e75a27e9'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='9d26089a'/> - <parameter is-variadic='yes'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_type_to_name' mangled-name='zfs_type_to_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_type_to_name'> - <parameter type-id='2e45de5d' name='type'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='zfs_name_valid' mangled-name='zfs_name_valid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_name_valid'> - <parameter type-id='80f4b756' name='name'/> - <parameter type-id='2e45de5d' name='type'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_free_handles' mangled-name='zpool_free_handles' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_free_handles'> - <parameter type-id='b0382bb3' name='hdl'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zfs_bookmark_exists' mangled-name='zfs_bookmark_exists' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_bookmark_exists'> - <parameter type-id='80f4b756' name='path'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='libzfs_mnttab_init' mangled-name='libzfs_mnttab_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_mnttab_init'> - <parameter type-id='b0382bb3' name='hdl'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='libzfs_mnttab_fini' mangled-name='libzfs_mnttab_fini' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_mnttab_fini'> - <parameter type-id='b0382bb3' name='hdl'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='libzfs_mnttab_cache' mangled-name='libzfs_mnttab_cache' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_mnttab_cache'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='c19b74c3' name='enable'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='libzfs_mnttab_find' mangled-name='libzfs_mnttab_find' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_mnttab_find'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='80f4b756' name='fsname'/> - <parameter type-id='9d424d31' name='entry'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='libzfs_mnttab_add' mangled-name='libzfs_mnttab_add' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_mnttab_add'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='80f4b756' name='special'/> - <parameter type-id='80f4b756' name='mountp'/> - <parameter type-id='80f4b756' name='mntopts'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='libzfs_mnttab_remove' mangled-name='libzfs_mnttab_remove' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_mnttab_remove'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='80f4b756' name='fsname'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zfs_spa_version' mangled-name='zfs_spa_version' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_spa_version'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='7292109c' name='spa_version'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_prop_set' mangled-name='zfs_prop_set' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_set'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='80f4b756' name='propname'/> - <parameter type-id='80f4b756' name='propval'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_prop_set_list' mangled-name='zfs_prop_set_list' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_set_list'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='5ce45b60' name='props'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_prop_set_list_flags' mangled-name='zfs_prop_set_list_flags' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_set_list_flags'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='5ce45b60' name='props'/> - <parameter type-id='95e97e5e' name='flags'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_prop_inherit' mangled-name='zfs_prop_inherit' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_inherit'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='80f4b756' name='propname'/> - <parameter type-id='c19b74c3' name='received'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='getprop_uint64' mangled-name='getprop_uint64' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getprop_uint64'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='58603c44' name='prop'/> - <parameter type-id='7d3cd834' name='source'/> - <return type-id='9c313c2d'/> - </function-decl> - <function-decl name='zfs_prop_get_recvd' mangled-name='zfs_prop_get_recvd' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_get_recvd'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='80f4b756' name='propname'/> - <parameter type-id='26a90f95' name='propbuf'/> - <parameter type-id='b59d7dce' name='proplen'/> - <parameter type-id='c19b74c3' name='literal'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_get_clones_nvl' mangled-name='zfs_get_clones_nvl' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_get_clones_nvl'> - <parameter type-id='9200a744' name='zhp'/> - <return type-id='5ce45b60'/> - </function-decl> - <function-decl name='zfs_prop_get_numeric' mangled-name='zfs_prop_get_numeric' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_get_numeric'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='58603c44' name='prop'/> - <parameter type-id='5d6479ae' name='value'/> - <parameter type-id='debc6aa3' name='src'/> - <parameter type-id='26a90f95' name='statbuf'/> - <parameter type-id='b59d7dce' name='statlen'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_prop_get_userquota_int' mangled-name='zfs_prop_get_userquota_int' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_get_userquota_int'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='80f4b756' name='propname'/> - <parameter type-id='5d6479ae' name='propvalue'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_prop_get_userquota' mangled-name='zfs_prop_get_userquota' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_get_userquota'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='80f4b756' name='propname'/> - <parameter type-id='26a90f95' name='propbuf'/> - <parameter type-id='95e97e5e' name='proplen'/> - <parameter type-id='c19b74c3' name='literal'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_prop_get_written_int' mangled-name='zfs_prop_get_written_int' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_get_written_int'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='80f4b756' name='propname'/> - <parameter type-id='5d6479ae' name='propvalue'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_prop_get_written' mangled-name='zfs_prop_get_written' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_get_written'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='80f4b756' name='propname'/> - <parameter type-id='26a90f95' name='propbuf'/> - <parameter type-id='95e97e5e' name='proplen'/> - <parameter type-id='c19b74c3' name='literal'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_get_pool_name' mangled-name='zfs_get_pool_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_get_pool_name'> - <parameter type-id='fcd57163' name='zhp'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='zfs_get_type' mangled-name='zfs_get_type' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_get_type'> - <parameter type-id='fcd57163' name='zhp'/> - <return type-id='2e45de5d'/> - </function-decl> - <function-decl name='zfs_get_underlying_type' mangled-name='zfs_get_underlying_type' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_get_underlying_type'> - <parameter type-id='fcd57163' name='zhp'/> - <return type-id='2e45de5d'/> - </function-decl> - <function-decl name='zfs_dataset_exists' mangled-name='zfs_dataset_exists' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_dataset_exists'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='80f4b756' name='path'/> - <parameter type-id='2e45de5d' name='types'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zfs_create_ancestors' mangled-name='zfs_create_ancestors' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_create_ancestors'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='80f4b756' name='path'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_create' mangled-name='zfs_create' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_create'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='80f4b756' name='path'/> - <parameter type-id='2e45de5d' name='type'/> - <parameter type-id='5ce45b60' name='props'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_destroy' mangled-name='zfs_destroy' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_destroy'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='c19b74c3' name='defer'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_destroy_snaps' mangled-name='zfs_destroy_snaps' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_destroy_snaps'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='26a90f95' name='snapname'/> - <parameter type-id='c19b74c3' name='defer'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_destroy_snaps_nvl' mangled-name='zfs_destroy_snaps_nvl' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_destroy_snaps_nvl'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='5ce45b60' name='snaps'/> - <parameter type-id='c19b74c3' name='defer'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_clone' mangled-name='zfs_clone' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_clone'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='80f4b756' name='target'/> - <parameter type-id='5ce45b60' name='props'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_promote' mangled-name='zfs_promote' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_promote'> - <parameter type-id='9200a744' name='zhp'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_snapshot_nvl' mangled-name='zfs_snapshot_nvl' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_snapshot_nvl'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='5ce45b60' name='snaps'/> - <parameter type-id='5ce45b60' name='props'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_snapshot' mangled-name='zfs_snapshot' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_snapshot'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='80f4b756' name='path'/> - <parameter type-id='c19b74c3' name='recursive'/> - <parameter type-id='5ce45b60' name='props'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_rollback' mangled-name='zfs_rollback' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_rollback'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='9200a744' name='snap'/> - <parameter type-id='c19b74c3' name='force'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_rename' mangled-name='zfs_rename' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_rename'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='80f4b756' name='target'/> - <parameter type-id='067170c2' name='flags'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_get_all_props' mangled-name='zfs_get_all_props' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_get_all_props'> - <parameter type-id='9200a744' name='zhp'/> - <return type-id='5ce45b60'/> - </function-decl> - <function-decl name='zfs_get_recvd_props' mangled-name='zfs_get_recvd_props' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_get_recvd_props'> - <parameter type-id='9200a744' name='zhp'/> - <return type-id='5ce45b60'/> - </function-decl> - <function-decl name='zfs_get_user_props' mangled-name='zfs_get_user_props' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_get_user_props'> - <parameter type-id='9200a744' name='zhp'/> - <return type-id='5ce45b60'/> - </function-decl> - <function-decl name='zfs_expand_proplist' mangled-name='zfs_expand_proplist' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_expand_proplist'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='e4378506' name='plp'/> - <parameter type-id='c19b74c3' name='received'/> - <parameter type-id='c19b74c3' name='literal'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_prune_proplist' mangled-name='zfs_prune_proplist' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prune_proplist'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='ae3e8ca6' name='props'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zfs_smb_acl_add' mangled-name='zfs_smb_acl_add' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_smb_acl_add'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='26a90f95' name='dataset'/> - <parameter type-id='26a90f95' name='path'/> - <parameter type-id='26a90f95' name='resource'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_smb_acl_remove' mangled-name='zfs_smb_acl_remove' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_smb_acl_remove'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='26a90f95' name='dataset'/> - <parameter type-id='26a90f95' name='path'/> - <parameter type-id='26a90f95' name='resource'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_smb_acl_purge' mangled-name='zfs_smb_acl_purge' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_smb_acl_purge'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='26a90f95' name='dataset'/> - <parameter type-id='26a90f95' name='path'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_smb_acl_rename' mangled-name='zfs_smb_acl_rename' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_smb_acl_rename'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='26a90f95' name='dataset'/> - <parameter type-id='26a90f95' name='path'/> - <parameter type-id='26a90f95' name='oldname'/> - <parameter type-id='26a90f95' name='newname'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_userspace' mangled-name='zfs_userspace' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_userspace'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='279fde6a' name='type'/> - <parameter type-id='16c5f410' name='func'/> - <parameter type-id='eaa32e2f' name='arg'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_hold' mangled-name='zfs_hold' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_hold'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='80f4b756' name='snapname'/> - <parameter type-id='80f4b756' name='tag'/> - <parameter type-id='c19b74c3' name='recursive'/> - <parameter type-id='95e97e5e' name='cleanup_fd'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_hold_nvl' mangled-name='zfs_hold_nvl' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_hold_nvl'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='95e97e5e' name='cleanup_fd'/> - <parameter type-id='5ce45b60' name='holds'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_release' mangled-name='zfs_release' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_release'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='80f4b756' name='snapname'/> - <parameter type-id='80f4b756' name='tag'/> - <parameter type-id='c19b74c3' name='recursive'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_get_fsacl' mangled-name='zfs_get_fsacl' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_get_fsacl'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='857bb57e' name='nvl'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_set_fsacl' mangled-name='zfs_set_fsacl' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_set_fsacl'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='c19b74c3' name='un'/> - <parameter type-id='5ce45b60' name='nvl'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_get_holds' mangled-name='zfs_get_holds' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_get_holds'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='857bb57e' name='nvl'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zvol_volsize_to_reservation' mangled-name='zvol_volsize_to_reservation' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zvol_volsize_to_reservation'> - <parameter type-id='4c81de99' name='zph'/> - <parameter type-id='9c313c2d' name='volsize'/> - <parameter type-id='5ce45b60' name='props'/> - <return type-id='9c313c2d'/> - </function-decl> - <function-decl name='zfs_wait_status' mangled-name='zfs_wait_status' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_wait_status'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='3024501a' name='activity'/> - <parameter type-id='37e3bd22' name='missing'/> - <parameter type-id='37e3bd22' name='waited'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_error_fmt' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='80f4b756'/> - <parameter is-variadic='yes'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_standard_error_fmt' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='80f4b756'/> - <parameter is-variadic='yes'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_setprop_error' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <parameter type-id='58603c44'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='26a90f95'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zprop_parse_value' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <parameter type-id='3fa542f0'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='2e45de5d'/> - <parameter type-id='5ce45b60'/> - <parameter type-id='7d3cd834'/> - <parameter type-id='5d6479ae'/> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zprop_expand_list' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <parameter type-id='e4378506'/> - <parameter type-id='2e45de5d'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zcmd_write_src_nvlist' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <parameter type-id='e4ec4540'/> - <parameter type-id='5ce45b60'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='changelist_prefix' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='0d41d328'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='changelist_postfix' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='0d41d328'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='changelist_rename' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='0d41d328'/> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='changelist_remove' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='0d41d328'/> - <parameter type-id='80f4b756'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='changelist_free' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='0d41d328'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='changelist_gather' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='9200a744'/> - <parameter type-id='58603c44'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='95e97e5e'/> - <return type-id='0d41d328'/> - </function-decl> - <function-decl name='changelist_haszonedchild' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='0d41d328'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_name_valid' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <parameter type-id='c19b74c3'/> - <parameter type-id='80f4b756'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-type size-in-bits='64' id='02362c02'> - <parameter type-id='eaa32e2f'/> - <parameter type-id='80f4b756'/> - <parameter type-id='354978ed'/> - <parameter type-id='9c313c2d'/> - <parameter type-id='9c313c2d'/> - <return type-id='95e97e5e'/> - </function-type> - </abi-instr> - <abi-instr address-size='64' path='lib/libzfs/libzfs_diff.c' language='LANG_C99'> - <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='448' id='6093ff7c'> - <subrange length='56' type-id='7359adad' id='f8137894'/> - </array-type-def> - <typedef-decl name='pthread_t' type-id='7359adad' id='4051f5e7'/> - <union-decl name='pthread_attr_t' size-in-bits='448' visibility='default' id='b63afacd'> - <data-member access='public'> - <var-decl name='__size' type-id='6093ff7c' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='__align' type-id='bd54fe1a' visibility='default'/> - </data-member> - </union-decl> - <typedef-decl name='pthread_attr_t' type-id='b63afacd' id='7d8569fd'/> - <class-decl name='differ_info' size-in-bits='9088' is-struct='yes' visibility='default' id='d41965ee'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='zhp' type-id='9200a744' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='fromsnap' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='frommnt' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='tosnap' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='tomnt' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='ds' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='384'> - <var-decl name='dsmnt' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='448'> - <var-decl name='tmpsnap' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='512'> - <var-decl name='errbuf' type-id='b54ce520' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='8704'> - <var-decl name='isclone' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='8736'> - <var-decl name='scripted' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='8768'> - <var-decl name='classify' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='8800'> - <var-decl name='timestamped' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='8832'> - <var-decl name='no_mangle' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='8896'> - <var-decl name='shares' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='8960'> - <var-decl name='zerr' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='8992'> - <var-decl name='cleanupfd' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='9024'> - <var-decl name='outputfd' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='9056'> - <var-decl name='datafd' type-id='95e97e5e' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='differ_info_t' type-id='d41965ee' id='e8525f0e'/> - <qualified-type-def type-id='7d8569fd' const='yes' id='e06dee2d'/> - <pointer-type-def type-id='e06dee2d' size-in-bits='64' id='540db505'/> - <qualified-type-def type-id='540db505' restrict='yes' id='e1815e87'/> - <pointer-type-def type-id='e8525f0e' size-in-bits='64' id='ee78f675'/> - <pointer-type-def type-id='4051f5e7' size-in-bits='64' id='e01b5462'/> - <qualified-type-def type-id='e01b5462' restrict='yes' id='cc338b26'/> - <pointer-type-def type-id='cd5d79f4' size-in-bits='64' id='5ad9edb6'/> - <function-decl name='is_mounted' mangled-name='is_mounted' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='is_mounted'> - <parameter type-id='b0382bb3'/> - <parameter type-id='80f4b756'/> - <parameter type-id='9b23c9ad'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='color_start' mangled-name='color_start' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='color_start'> - <parameter type-id='80f4b756'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='color_end' mangled-name='color_end' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='color_end'> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='pthread_create' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='cc338b26'/> - <parameter type-id='e1815e87'/> - <parameter type-id='5ad9edb6'/> - <parameter type-id='1b7446cd'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_join' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='4051f5e7'/> - <parameter type-id='63e171df'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_cancel' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='4051f5e7'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='fputs' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='9d26089a'/> - <parameter type-id='e75a27e9'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pipe2' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='7292109c'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_show_diffs' mangled-name='zfs_show_diffs' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_show_diffs'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='95e97e5e' name='outfd'/> - <parameter type-id='80f4b756' name='fromsnap'/> - <parameter type-id='80f4b756' name='tosnap'/> - <parameter type-id='95e97e5e' name='flags'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_asprintf' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <parameter type-id='80f4b756'/> - <parameter is-variadic='yes'/> - <return type-id='26a90f95'/> - </function-decl> - <function-decl name='zfs_validate_name' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <parameter type-id='80f4b756'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='c19b74c3'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='find_shares_object' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='ee78f675'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-type size-in-bits='64' id='cd5d79f4'> - <parameter type-id='eaa32e2f'/> - <return type-id='eaa32e2f'/> - </function-type> - </abi-instr> - <abi-instr address-size='64' path='lib/libzfs/libzfs_import.c' language='LANG_C99'> - <array-type-def dimensions='1' type-id='03085adc' size-in-bits='192' id='083f8d58'> - <subrange length='3' type-id='7359adad' id='56f209d2'/> - </array-type-def> - <typedef-decl name='refresh_config_func_t' type-id='29f040d2' id='b7c58eaa'/> - <typedef-decl name='pool_active_func_t' type-id='baa42fef' id='de5d1d8f'/> - <class-decl name='pool_config_ops' size-in-bits='128' is-struct='yes' visibility='default' id='8b092c69'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='pco_refresh_config' type-id='e7c00489' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='pco_pool_active' type-id='9eadf5e0' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='pool_config_ops_t' type-id='1a21babe' id='b1e62775'/> - <enum-decl name='pool_state' id='4871ac24'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='POOL_STATE_ACTIVE' value='0'/> - <enumerator name='POOL_STATE_EXPORTED' value='1'/> - <enumerator name='POOL_STATE_DESTROYED' value='2'/> - <enumerator name='POOL_STATE_SPARE' value='3'/> - <enumerator name='POOL_STATE_L2CACHE' value='4'/> - <enumerator name='POOL_STATE_UNINITIALIZED' value='5'/> - <enumerator name='POOL_STATE_UNAVAIL' value='6'/> - <enumerator name='POOL_STATE_POTENTIALLY_ACTIVE' value='7'/> - </enum-decl> - <typedef-decl name='pool_state_t' type-id='4871ac24' id='084a08a3'/> - <class-decl name='stat64' size-in-bits='1152' is-struct='yes' visibility='default' id='0bbec9cd'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='st_dev' type-id='35ed8932' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='st_ino' type-id='71288a47' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='st_nlink' type-id='80f0b9df' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='st_mode' type-id='e1c52942' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='224'> - <var-decl name='st_uid' type-id='cc5fcceb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='st_gid' type-id='d94ec6d9' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='288'> - <var-decl name='__pad0' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='st_rdev' type-id='35ed8932' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='384'> - <var-decl name='st_size' type-id='79989e9c' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='448'> - <var-decl name='st_blksize' type-id='d3f10a7f' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='512'> - <var-decl name='st_blocks' type-id='4e711bf1' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='576'> - <var-decl name='st_atim' type-id='a9c79a1f' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='704'> - <var-decl name='st_mtim' type-id='a9c79a1f' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='832'> - <var-decl name='st_ctim' type-id='a9c79a1f' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='960'> - <var-decl name='__glibc_reserved' type-id='083f8d58' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='__dev_t' type-id='7359adad' id='35ed8932'/> - <typedef-decl name='__ino64_t' type-id='7359adad' id='71288a47'/> - <typedef-decl name='__mode_t' type-id='f0981eeb' id='e1c52942'/> - <typedef-decl name='__nlink_t' type-id='7359adad' id='80f0b9df'/> - <typedef-decl name='__blksize_t' type-id='bd54fe1a' id='d3f10a7f'/> - <typedef-decl name='__blkcnt64_t' type-id='bd54fe1a' id='4e711bf1'/> - <typedef-decl name='__syscall_slong_t' type-id='bd54fe1a' id='03085adc'/> - <class-decl name='timespec' size-in-bits='128' is-struct='yes' visibility='default' id='a9c79a1f'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='tv_sec' type-id='65eda9c0' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='tv_nsec' type-id='03085adc' visibility='default'/> - </data-member> - </class-decl> - <qualified-type-def type-id='8b092c69' const='yes' id='1a21babe'/> - <pointer-type-def type-id='de5d1d8f' size-in-bits='64' id='9eadf5e0'/> - <pointer-type-def type-id='084a08a3' size-in-bits='64' id='b9ea57b8'/> - <pointer-type-def type-id='b7c58eaa' size-in-bits='64' id='e7c00489'/> - <pointer-type-def type-id='0bbec9cd' size-in-bits='64' id='62f7a03d'/> - <var-decl name='libzfs_config_ops' type-id='b1e62775' mangled-name='libzfs_config_ops' visibility='default' elf-symbol-id='libzfs_config_ops'/> - <function-decl name='zpool_read_label' mangled-name='zpool_read_label' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_read_label'> - <parameter type-id='95e97e5e'/> - <parameter type-id='857bb57e'/> - <parameter type-id='7292109c'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pwrite64' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <parameter type-id='eaa32e2f'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='724e4de6'/> - <return type-id='79a0948f'/> - </function-decl> - <function-decl name='__pread64_chk' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <parameter type-id='eaa32e2f'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='724e4de6'/> - <parameter type-id='b59d7dce'/> - <return type-id='79a0948f'/> - </function-decl> - <function-decl name='ioctl' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <parameter type-id='7359adad'/> - <parameter is-variadic='yes'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='fstat64' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <parameter type-id='62f7a03d'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zcmd_write_conf_nvlist' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <parameter type-id='e4ec4540'/> - <parameter type-id='5ce45b60'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zpool_clear_label' mangled-name='zpool_clear_label' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_clear_label'> - <parameter type-id='95e97e5e' name='fd'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_in_use' mangled-name='zpool_in_use' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_in_use'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='95e97e5e' name='fd'/> - <parameter type-id='b9ea57b8' name='state'/> - <parameter type-id='9b23c9ad' name='namestr'/> - <parameter type-id='37e3bd22' name='inuse'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-type size-in-bits='64' id='baa42fef'> - <parameter type-id='eaa32e2f'/> - <parameter type-id='80f4b756'/> - <parameter type-id='9c313c2d'/> - <parameter type-id='37e3bd22'/> - <return type-id='95e97e5e'/> - </function-type> - <function-type size-in-bits='64' id='29f040d2'> - <parameter type-id='eaa32e2f'/> - <parameter type-id='5ce45b60'/> - <return type-id='5ce45b60'/> - </function-type> - </abi-instr> - <abi-instr address-size='64' path='lib/libzfs/libzfs_iter.c' language='LANG_C99'> - <pointer-type-def type-id='b351119f' size-in-bits='64' id='716943c7'/> - <function-decl name='avl_first' mangled-name='avl_first' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_first'> - <parameter type-id='a3681dea'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='avl_walk' mangled-name='avl_walk' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_walk'> - <parameter type-id='716943c7'/> - <parameter type-id='eaa32e2f'/> - <parameter type-id='95e97e5e'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='make_dataset_handle_zc' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <parameter type-id='e4ec4540'/> - <return type-id='9200a744'/> - </function-decl> - <function-decl name='make_dataset_simple_handle_zc' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='9200a744'/> - <parameter type-id='e4ec4540'/> - <return type-id='9200a744'/> - </function-decl> - <function-decl name='make_bookmark_handle' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='9200a744'/> - <parameter type-id='80f4b756'/> - <parameter type-id='5ce45b60'/> - <return type-id='9200a744'/> - </function-decl> - <function-decl name='zfs_iter_filesystems' mangled-name='zfs_iter_filesystems' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_filesystems'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='d8e49ab9' name='func'/> - <parameter type-id='eaa32e2f' name='data'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_iter_snapshots' mangled-name='zfs_iter_snapshots' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_snapshots'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='c19b74c3' name='simple'/> - <parameter type-id='d8e49ab9' name='func'/> - <parameter type-id='eaa32e2f' name='data'/> - <parameter type-id='9c313c2d' name='min_txg'/> - <parameter type-id='9c313c2d' name='max_txg'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_iter_bookmarks' mangled-name='zfs_iter_bookmarks' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_bookmarks'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='d8e49ab9' name='func'/> - <parameter type-id='eaa32e2f' name='data'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_iter_snapshots_sorted' mangled-name='zfs_iter_snapshots_sorted' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_snapshots_sorted'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='d8e49ab9' name='callback'/> - <parameter type-id='eaa32e2f' name='data'/> - <parameter type-id='9c313c2d' name='min_txg'/> - <parameter type-id='9c313c2d' name='max_txg'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_iter_snapshots_sorted_v2' mangled-name='zfs_iter_snapshots_sorted_v2' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_snapshots_sorted_v2'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='95e97e5e' name='flags'/> - <parameter type-id='d8e49ab9' name='callback'/> - <parameter type-id='eaa32e2f' name='data'/> - <parameter type-id='9c313c2d' name='min_txg'/> - <parameter type-id='9c313c2d' name='max_txg'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_iter_snapspec' mangled-name='zfs_iter_snapspec' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_snapspec'> - <parameter type-id='9200a744' name='fs_zhp'/> - <parameter type-id='80f4b756' name='spec_orig'/> - <parameter type-id='d8e49ab9' name='func'/> - <parameter type-id='eaa32e2f' name='arg'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_iter_snapspec_v2' mangled-name='zfs_iter_snapspec_v2' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_snapspec_v2'> - <parameter type-id='9200a744' name='fs_zhp'/> - <parameter type-id='95e97e5e' name='flags'/> - <parameter type-id='80f4b756' name='spec_orig'/> - <parameter type-id='d8e49ab9' name='func'/> - <parameter type-id='eaa32e2f' name='arg'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_iter_children' mangled-name='zfs_iter_children' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_children'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='d8e49ab9' name='func'/> - <parameter type-id='eaa32e2f' name='data'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_iter_dependents' mangled-name='zfs_iter_dependents' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_dependents'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='c19b74c3' name='allowrecursion'/> - <parameter type-id='d8e49ab9' name='func'/> - <parameter type-id='eaa32e2f' name='data'/> - <return type-id='95e97e5e'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='lib/libzfs/libzfs_mount.c' language='LANG_C99'> - <array-type-def dimensions='1' type-id='6028cbfe' size-in-bits='256' id='b39b9aa7'> - <subrange length='4' type-id='7359adad' id='16fe7105'/> - </array-type-def> - <class-decl name='__dirstream' is-struct='yes' visibility='default' is-declaration-only='yes' id='20cd73f2'/> - <class-decl name='tpool' size-in-bits='2496' is-struct='yes' visibility='default' id='88d1b7f9'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='tp_forw' type-id='9cf59a50' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='tp_back' type-id='9cf59a50' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='tp_mutex' type-id='7a6844eb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='448'> - <var-decl name='tp_busycv' type-id='62fab762' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='832'> - <var-decl name='tp_workcv' type-id='62fab762' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1216'> - <var-decl name='tp_waitcv' type-id='62fab762' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1600'> - <var-decl name='tp_active' type-id='ad33e5e7' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1664'> - <var-decl name='tp_head' type-id='f32b30e4' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1728'> - <var-decl name='tp_tail' type-id='f32b30e4' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1792'> - <var-decl name='tp_attr' type-id='7d8569fd' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2240'> - <var-decl name='tp_flags' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2272'> - <var-decl name='tp_linger' type-id='3502e3ff' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2304'> - <var-decl name='tp_njobs' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2336'> - <var-decl name='tp_minimum' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2368'> - <var-decl name='tp_maximum' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2400'> - <var-decl name='tp_current' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2432'> - <var-decl name='tp_idle' type-id='95e97e5e' visibility='default'/> - </data-member> - </class-decl> - <array-type-def dimensions='1' type-id='95e97e5e' size-in-bits='64' id='e4266c7e'> - <subrange length='2' type-id='7359adad' id='52efc4ef'/> - </array-type-def> - <class-decl name='get_all_cb' size-in-bits='192' is-struct='yes' visibility='default' id='803dac95'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='cb_handles' type-id='4507922a' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='cb_alloc' type-id='b59d7dce' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='cb_used' type-id='b59d7dce' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='get_all_cb_t' type-id='803dac95' id='9b293607'/> - <typedef-decl name='tpool_t' type-id='88d1b7f9' id='b1bbf10d'/> - <typedef-decl name='DIR' type-id='20cd73f2' id='54a5d683'/> - <typedef-decl name='mode_t' type-id='e1c52942' id='d50d396c'/> - <typedef-decl name='__compar_fn_t' type-id='585e1de9' id='aba7edd8'/> - <class-decl name='dirent64' size-in-bits='2240' is-struct='yes' visibility='default' id='5725d813'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='d_ino' type-id='71288a47' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='d_off' type-id='724e4de6' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='d_reclen' type-id='8efea9e5' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='144'> - <var-decl name='d_type' type-id='002ac4a6' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='152'> - <var-decl name='d_name' type-id='d1617432' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='statfs64' size-in-bits='960' is-struct='yes' visibility='default' id='a2a6be1a'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='f_type' type-id='6028cbfe' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='f_bsize' type-id='6028cbfe' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='f_blocks' type-id='95fe1a02' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='f_bfree' type-id='95fe1a02' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='f_bavail' type-id='95fe1a02' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='f_files' type-id='0c3a4dde' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='384'> - <var-decl name='f_ffree' type-id='0c3a4dde' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='448'> - <var-decl name='f_fsid' type-id='0f35d263' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='512'> - <var-decl name='f_namelen' type-id='6028cbfe' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='576'> - <var-decl name='f_frsize' type-id='6028cbfe' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='640'> - <var-decl name='f_flags' type-id='6028cbfe' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='704'> - <var-decl name='f_spare' type-id='b39b9aa7' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='stat' size-in-bits='1152' is-struct='yes' visibility='default' id='aafc373f'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='st_dev' type-id='35ed8932' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='st_ino' type-id='e43e523d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='st_nlink' type-id='80f0b9df' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='st_mode' type-id='e1c52942' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='224'> - <var-decl name='st_uid' type-id='cc5fcceb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='st_gid' type-id='d94ec6d9' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='288'> - <var-decl name='__pad0' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='st_rdev' type-id='35ed8932' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='384'> - <var-decl name='st_size' type-id='79989e9c' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='448'> - <var-decl name='st_blksize' type-id='d3f10a7f' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='512'> - <var-decl name='st_blocks' type-id='dbc43803' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='576'> - <var-decl name='st_atim' type-id='a9c79a1f' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='704'> - <var-decl name='st_mtim' type-id='a9c79a1f' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='832'> - <var-decl name='st_ctim' type-id='a9c79a1f' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='960'> - <var-decl name='__glibc_reserved' type-id='083f8d58' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='__ino_t' type-id='7359adad' id='e43e523d'/> - <class-decl name='__fsid_t' size-in-bits='64' is-struct='yes' naming-typedef-id='0f35d263' visibility='default' id='ea35c84a'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='__val' type-id='e4266c7e' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='__fsid_t' type-id='ea35c84a' id='0f35d263'/> - <typedef-decl name='__blkcnt_t' type-id='bd54fe1a' id='dbc43803'/> - <typedef-decl name='__fsblkcnt64_t' type-id='7359adad' id='95fe1a02'/> - <typedef-decl name='__fsfilcnt64_t' type-id='7359adad' id='0c3a4dde'/> - <typedef-decl name='__fsword_t' type-id='bd54fe1a' id='6028cbfe'/> - <pointer-type-def type-id='54a5d683' size-in-bits='64' id='f09217ba'/> - <pointer-type-def type-id='5725d813' size-in-bits='64' id='07b96073'/> - <pointer-type-def type-id='9b293607' size-in-bits='64' id='77bf1784'/> - <pointer-type-def type-id='7d8569fd' size-in-bits='64' id='7347a39e'/> - <pointer-type-def type-id='aafc373f' size-in-bits='64' id='4330df87'/> - <qualified-type-def type-id='4330df87' restrict='yes' id='73665405'/> - <pointer-type-def type-id='a2a6be1a' size-in-bits='64' id='7fd094c8'/> - <pointer-type-def type-id='b1bbf10d' size-in-bits='64' id='9cf59a50'/> - <pointer-type-def type-id='c5c76c9c' size-in-bits='64' id='b7f9d8e6'/> - <pointer-type-def type-id='9200a744' size-in-bits='64' id='4507922a'/> - <class-decl name='__dirstream' is-struct='yes' visibility='default' is-declaration-only='yes' id='20cd73f2'/> - <function-decl name='zpool_disable_datasets_os' mangled-name='zpool_disable_datasets_os' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_disable_datasets_os'> - <parameter type-id='4c81de99'/> - <parameter type-id='c19b74c3'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zpool_disable_volume_os' mangled-name='zpool_disable_volume_os' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_disable_volume_os'> - <parameter type-id='80f4b756'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='tpool_create' mangled-name='tpool_create' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_create'> - <parameter type-id='3502e3ff'/> - <parameter type-id='3502e3ff'/> - <parameter type-id='3502e3ff'/> - <parameter type-id='7347a39e'/> - <return type-id='9cf59a50'/> - </function-decl> - <function-decl name='tpool_dispatch' mangled-name='tpool_dispatch' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_dispatch'> - <parameter type-id='9cf59a50'/> - <parameter type-id='b7f9d8e6'/> - <parameter type-id='eaa32e2f'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='tpool_destroy' mangled-name='tpool_destroy' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_destroy'> - <parameter type-id='9cf59a50'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='tpool_wait' mangled-name='tpool_wait' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_wait'> - <parameter type-id='9cf59a50'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='mkdirp' mangled-name='mkdirp' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='mkdirp'> - <parameter type-id='80f4b756'/> - <parameter type-id='d50d396c'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='sa_errorstr' mangled-name='sa_errorstr' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='sa_errorstr'> - <parameter type-id='95e97e5e'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='sa_enable_share' mangled-name='sa_enable_share' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='sa_enable_share'> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <parameter type-id='9155d4b5'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='sa_disable_share' mangled-name='sa_disable_share' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='sa_disable_share'> - <parameter type-id='80f4b756'/> - <parameter type-id='9155d4b5'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='sa_is_shared' mangled-name='sa_is_shared' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='sa_is_shared'> - <parameter type-id='80f4b756'/> - <parameter type-id='9155d4b5'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='sa_truncate_shares' mangled-name='sa_truncate_shares' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='sa_truncate_shares'> - <parameter type-id='9155d4b5'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='fdopendir' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <return type-id='f09217ba'/> - </function-decl> - <function-decl name='closedir' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='f09217ba'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='readdir64' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='f09217ba'/> - <return type-id='07b96073'/> - </function-decl> - <function-decl name='qsort' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='eaa32e2f'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='aba7edd8'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='rmdir' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='__openat_too_many_args' visibility='default' binding='global' size-in-bits='64'> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='__openat_missing_mode' visibility='default' binding='global' size-in-bits='64'> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='statfs64' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='7fd094c8'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_realloc' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <parameter type-id='eaa32e2f'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='b59d7dce'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='changelist_unshare' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='0d41d328'/> - <parameter type-id='4567bbc9'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='do_mount' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='9200a744'/> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='do_unmount' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='9200a744'/> - <parameter type-id='80f4b756'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_mount_at' mangled-name='zfs_mount_at' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_mount_at'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='80f4b756' name='options'/> - <parameter type-id='95e97e5e' name='flags'/> - <parameter type-id='80f4b756' name='mountpoint'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_unmountall' mangled-name='zfs_unmountall' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_unmountall'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='95e97e5e' name='flags'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_truncate_shares' mangled-name='zfs_truncate_shares' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_truncate_shares'> - <parameter type-id='4567bbc9' name='proto'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zfs_unshareall' mangled-name='zfs_unshareall' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_unshareall'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='4567bbc9' name='proto'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='libzfs_add_handle' mangled-name='libzfs_add_handle' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_add_handle'> - <parameter type-id='77bf1784' name='cbp'/> - <parameter type-id='9200a744' name='zhp'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zfs_foreach_mountpoint' mangled-name='zfs_foreach_mountpoint' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_foreach_mountpoint'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='4507922a' name='handles'/> - <parameter type-id='b59d7dce' name='num_handles'/> - <parameter type-id='d8e49ab9' name='func'/> - <parameter type-id='eaa32e2f' name='data'/> - <parameter type-id='3502e3ff' name='nthr'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zpool_enable_datasets' mangled-name='zpool_enable_datasets' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_enable_datasets'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='80f4b756' name='mntopts'/> - <parameter type-id='95e97e5e' name='flags'/> - <parameter type-id='3502e3ff' name='nthr'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_disable_datasets' mangled-name='zpool_disable_datasets' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_disable_datasets'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='c19b74c3' name='force'/> - <return type-id='95e97e5e'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='lib/libzfs/libzfs_pool.c' language='LANG_C99'> - <type-decl name='long long unsigned int' size-in-bits='64' id='3a47d82b'/> - <class-decl name='splitflags' size-in-bits='64' is-struct='yes' visibility='default' id='dc01bf52'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='dryrun' type-id='f0981eeb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1'> - <var-decl name='import' type-id='f0981eeb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32'> - <var-decl name='name_flags' type-id='95e97e5e' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='splitflags_t' type-id='dc01bf52' id='325c1e34'/> - <class-decl name='trimflags' size-in-bits='192' is-struct='yes' visibility='default' id='8ef58008'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='fullpool' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32'> - <var-decl name='secure' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='wait' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='rate' type-id='9c313c2d' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='trimflags_t' type-id='8ef58008' id='a093cbb8'/> - <enum-decl name='zpool_status_t' naming-typedef-id='d3dd6294' id='5e770b40'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='ZPOOL_STATUS_CORRUPT_CACHE' value='0'/> - <enumerator name='ZPOOL_STATUS_MISSING_DEV_R' value='1'/> - <enumerator name='ZPOOL_STATUS_MISSING_DEV_NR' value='2'/> - <enumerator name='ZPOOL_STATUS_CORRUPT_LABEL_R' value='3'/> - <enumerator name='ZPOOL_STATUS_CORRUPT_LABEL_NR' value='4'/> - <enumerator name='ZPOOL_STATUS_BAD_GUID_SUM' value='5'/> - <enumerator name='ZPOOL_STATUS_CORRUPT_POOL' value='6'/> - <enumerator name='ZPOOL_STATUS_CORRUPT_DATA' value='7'/> - <enumerator name='ZPOOL_STATUS_FAILING_DEV' value='8'/> - <enumerator name='ZPOOL_STATUS_VERSION_NEWER' value='9'/> - <enumerator name='ZPOOL_STATUS_HOSTID_MISMATCH' value='10'/> - <enumerator name='ZPOOL_STATUS_HOSTID_ACTIVE' value='11'/> - <enumerator name='ZPOOL_STATUS_HOSTID_REQUIRED' value='12'/> - <enumerator name='ZPOOL_STATUS_IO_FAILURE_WAIT' value='13'/> - <enumerator name='ZPOOL_STATUS_IO_FAILURE_CONTINUE' value='14'/> - <enumerator name='ZPOOL_STATUS_IO_FAILURE_MMP' value='15'/> - <enumerator name='ZPOOL_STATUS_BAD_LOG' value='16'/> - <enumerator name='ZPOOL_STATUS_ERRATA' value='17'/> - <enumerator name='ZPOOL_STATUS_UNSUP_FEAT_READ' value='18'/> - <enumerator name='ZPOOL_STATUS_UNSUP_FEAT_WRITE' value='19'/> - <enumerator name='ZPOOL_STATUS_FAULTED_DEV_R' value='20'/> - <enumerator name='ZPOOL_STATUS_FAULTED_DEV_NR' value='21'/> - <enumerator name='ZPOOL_STATUS_VERSION_OLDER' value='22'/> - <enumerator name='ZPOOL_STATUS_FEAT_DISABLED' value='23'/> - <enumerator name='ZPOOL_STATUS_RESILVERING' value='24'/> - <enumerator name='ZPOOL_STATUS_OFFLINE_DEV' value='25'/> - <enumerator name='ZPOOL_STATUS_REMOVED_DEV' value='26'/> - <enumerator name='ZPOOL_STATUS_REBUILDING' value='27'/> - <enumerator name='ZPOOL_STATUS_REBUILD_SCRUB' value='28'/> - <enumerator name='ZPOOL_STATUS_NON_NATIVE_ASHIFT' value='29'/> - <enumerator name='ZPOOL_STATUS_COMPATIBILITY_ERR' value='30'/> - <enumerator name='ZPOOL_STATUS_INCOMPATIBLE_FEAT' value='31'/> - <enumerator name='ZPOOL_STATUS_OK' value='32'/> - </enum-decl> - <typedef-decl name='zpool_status_t' type-id='5e770b40' id='d3dd6294'/> - <enum-decl name='zpool_compat_status_t' naming-typedef-id='901b78d1' id='20676925'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='ZPOOL_COMPATIBILITY_OK' value='0'/> - <enumerator name='ZPOOL_COMPATIBILITY_WARNTOKEN' value='1'/> - <enumerator name='ZPOOL_COMPATIBILITY_BADTOKEN' value='2'/> - <enumerator name='ZPOOL_COMPATIBILITY_BADFILE' value='3'/> - <enumerator name='ZPOOL_COMPATIBILITY_NOFILES' value='4'/> - </enum-decl> - <typedef-decl name='zpool_compat_status_t' type-id='20676925' id='901b78d1'/> - <enum-decl name='vdev_prop_t' naming-typedef-id='5aa5c90c' id='1573bec8'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='VDEV_PROP_INVAL' value='-1'/> - <enumerator name='VDEV_PROP_USERPROP' value='-1'/> - <enumerator name='VDEV_PROP_NAME' value='0'/> - <enumerator name='VDEV_PROP_CAPACITY' value='1'/> - <enumerator name='VDEV_PROP_STATE' value='2'/> - <enumerator name='VDEV_PROP_GUID' value='3'/> - <enumerator name='VDEV_PROP_ASIZE' value='4'/> - <enumerator name='VDEV_PROP_PSIZE' value='5'/> - <enumerator name='VDEV_PROP_ASHIFT' value='6'/> - <enumerator name='VDEV_PROP_SIZE' value='7'/> - <enumerator name='VDEV_PROP_FREE' value='8'/> - <enumerator name='VDEV_PROP_ALLOCATED' value='9'/> - <enumerator name='VDEV_PROP_COMMENT' value='10'/> - <enumerator name='VDEV_PROP_EXPANDSZ' value='11'/> - <enumerator name='VDEV_PROP_FRAGMENTATION' value='12'/> - <enumerator name='VDEV_PROP_BOOTSIZE' value='13'/> - <enumerator name='VDEV_PROP_PARITY' value='14'/> - <enumerator name='VDEV_PROP_PATH' value='15'/> - <enumerator name='VDEV_PROP_DEVID' value='16'/> - <enumerator name='VDEV_PROP_PHYS_PATH' value='17'/> - <enumerator name='VDEV_PROP_ENC_PATH' value='18'/> - <enumerator name='VDEV_PROP_FRU' value='19'/> - <enumerator name='VDEV_PROP_PARENT' value='20'/> - <enumerator name='VDEV_PROP_CHILDREN' value='21'/> - <enumerator name='VDEV_PROP_NUMCHILDREN' value='22'/> - <enumerator name='VDEV_PROP_READ_ERRORS' value='23'/> - <enumerator name='VDEV_PROP_WRITE_ERRORS' value='24'/> - <enumerator name='VDEV_PROP_CHECKSUM_ERRORS' value='25'/> - <enumerator name='VDEV_PROP_INITIALIZE_ERRORS' value='26'/> - <enumerator name='VDEV_PROP_OPS_NULL' value='27'/> - <enumerator name='VDEV_PROP_OPS_READ' value='28'/> - <enumerator name='VDEV_PROP_OPS_WRITE' value='29'/> - <enumerator name='VDEV_PROP_OPS_FREE' value='30'/> - <enumerator name='VDEV_PROP_OPS_CLAIM' value='31'/> - <enumerator name='VDEV_PROP_OPS_TRIM' value='32'/> - <enumerator name='VDEV_PROP_BYTES_NULL' value='33'/> - <enumerator name='VDEV_PROP_BYTES_READ' value='34'/> - <enumerator name='VDEV_PROP_BYTES_WRITE' value='35'/> - <enumerator name='VDEV_PROP_BYTES_FREE' value='36'/> - <enumerator name='VDEV_PROP_BYTES_CLAIM' value='37'/> - <enumerator name='VDEV_PROP_BYTES_TRIM' value='38'/> - <enumerator name='VDEV_PROP_REMOVING' value='39'/> - <enumerator name='VDEV_PROP_ALLOCATING' value='40'/> - <enumerator name='VDEV_PROP_FAILFAST' value='41'/> - <enumerator name='VDEV_PROP_CHECKSUM_N' value='42'/> - <enumerator name='VDEV_PROP_CHECKSUM_T' value='43'/> - <enumerator name='VDEV_PROP_IO_N' value='44'/> - <enumerator name='VDEV_PROP_IO_T' value='45'/> - <enumerator name='VDEV_PROP_RAIDZ_EXPANDING' value='46'/> - <enumerator name='VDEV_PROP_SLOW_IO_N' value='47'/> - <enumerator name='VDEV_PROP_SLOW_IO_T' value='48'/> - <enumerator name='VDEV_PROP_TRIM_SUPPORT' value='49'/> - <enumerator name='VDEV_PROP_TRIM_ERRORS' value='50'/> - <enumerator name='VDEV_PROP_SLOW_IOS' value='51'/> - <enumerator name='VDEV_PROP_SIT_OUT' value='52'/> - <enumerator name='VDEV_PROP_AUTOSIT' value='53'/> - <enumerator name='VDEV_NUM_PROPS' value='54'/> - </enum-decl> - <typedef-decl name='vdev_prop_t' type-id='1573bec8' id='5aa5c90c'/> - <class-decl name='zpool_load_policy' size-in-bits='256' is-struct='yes' visibility='default' id='2f65b36f'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='zlp_rewind' type-id='8f92235e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='zlp_maxmeta' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='zlp_maxdata' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='zlp_txg' type-id='9c313c2d' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='zpool_load_policy_t' type-id='2f65b36f' id='d11b7617'/> - <enum-decl name='vdev_state' id='21566197'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='VDEV_STATE_UNKNOWN' value='0'/> - <enumerator name='VDEV_STATE_CLOSED' value='1'/> - <enumerator name='VDEV_STATE_OFFLINE' value='2'/> - <enumerator name='VDEV_STATE_REMOVED' value='3'/> - <enumerator name='VDEV_STATE_CANT_OPEN' value='4'/> - <enumerator name='VDEV_STATE_FAULTED' value='5'/> - <enumerator name='VDEV_STATE_DEGRADED' value='6'/> - <enumerator name='VDEV_STATE_HEALTHY' value='7'/> - </enum-decl> - <typedef-decl name='vdev_state_t' type-id='21566197' id='35acf840'/> - <enum-decl name='vdev_aux' id='7f5bcca4'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='VDEV_AUX_NONE' value='0'/> - <enumerator name='VDEV_AUX_OPEN_FAILED' value='1'/> - <enumerator name='VDEV_AUX_CORRUPT_DATA' value='2'/> - <enumerator name='VDEV_AUX_NO_REPLICAS' value='3'/> - <enumerator name='VDEV_AUX_BAD_GUID_SUM' value='4'/> - <enumerator name='VDEV_AUX_TOO_SMALL' value='5'/> - <enumerator name='VDEV_AUX_BAD_LABEL' value='6'/> - <enumerator name='VDEV_AUX_VERSION_NEWER' value='7'/> - <enumerator name='VDEV_AUX_VERSION_OLDER' value='8'/> - <enumerator name='VDEV_AUX_UNSUP_FEAT' value='9'/> - <enumerator name='VDEV_AUX_SPARED' value='10'/> - <enumerator name='VDEV_AUX_ERR_EXCEEDED' value='11'/> - <enumerator name='VDEV_AUX_IO_FAILURE' value='12'/> - <enumerator name='VDEV_AUX_BAD_LOG' value='13'/> - <enumerator name='VDEV_AUX_EXTERNAL' value='14'/> - <enumerator name='VDEV_AUX_SPLIT_POOL' value='15'/> - <enumerator name='VDEV_AUX_BAD_ASHIFT' value='16'/> - <enumerator name='VDEV_AUX_EXTERNAL_PERSIST' value='17'/> - <enumerator name='VDEV_AUX_ACTIVE' value='18'/> - <enumerator name='VDEV_AUX_CHILDREN_OFFLINE' value='19'/> - <enumerator name='VDEV_AUX_ASHIFT_TOO_BIG' value='20'/> - </enum-decl> - <typedef-decl name='vdev_aux_t' type-id='7f5bcca4' id='9d774e0b'/> - <enum-decl name='pool_scan_func' id='1b092565'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='POOL_SCAN_NONE' value='0'/> - <enumerator name='POOL_SCAN_SCRUB' value='1'/> - <enumerator name='POOL_SCAN_RESILVER' value='2'/> - <enumerator name='POOL_SCAN_ERRORSCRUB' value='3'/> - <enumerator name='POOL_SCAN_FUNCS' value='4'/> - </enum-decl> - <typedef-decl name='pool_scan_func_t' type-id='1b092565' id='7313fbe2'/> - <enum-decl name='pool_scrub_cmd' id='a1474cbd'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='POOL_SCRUB_NORMAL' value='0'/> - <enumerator name='POOL_SCRUB_PAUSE' value='1'/> - <enumerator name='POOL_SCRUB_FROM_LAST_TXG' value='2'/> - <enumerator name='POOL_SCRUB_FLAGS_END' value='3'/> - </enum-decl> - <typedef-decl name='pool_scrub_cmd_t' type-id='a1474cbd' id='b51cf3c2'/> - <enum-decl name='zpool_errata' id='d9abbf54'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='ZPOOL_ERRATA_NONE' value='0'/> - <enumerator name='ZPOOL_ERRATA_ZOL_2094_SCRUB' value='1'/> - <enumerator name='ZPOOL_ERRATA_ZOL_2094_ASYNC_DESTROY' value='2'/> - <enumerator name='ZPOOL_ERRATA_ZOL_6845_ENCRYPTION' value='3'/> - <enumerator name='ZPOOL_ERRATA_ZOL_8308_ENCRYPTION' value='4'/> - </enum-decl> - <typedef-decl name='zpool_errata_t' type-id='d9abbf54' id='688c495b'/> - <enum-decl name='pool_initialize_func' id='5c246ad4'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='POOL_INITIALIZE_START' value='0'/> - <enumerator name='POOL_INITIALIZE_CANCEL' value='1'/> - <enumerator name='POOL_INITIALIZE_SUSPEND' value='2'/> - <enumerator name='POOL_INITIALIZE_UNINIT' value='3'/> - <enumerator name='POOL_INITIALIZE_FUNCS' value='4'/> - </enum-decl> - <typedef-decl name='pool_initialize_func_t' type-id='5c246ad4' id='7063e1ab'/> - <enum-decl name='pool_trim_func' id='54ed608a'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='POOL_TRIM_START' value='0'/> - <enumerator name='POOL_TRIM_CANCEL' value='1'/> - <enumerator name='POOL_TRIM_SUSPEND' value='2'/> - <enumerator name='POOL_TRIM_FUNCS' value='3'/> - </enum-decl> - <typedef-decl name='pool_trim_func_t' type-id='54ed608a' id='b1146b8d'/> - <enum-decl name='zfs_ioc' id='12033f13'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='ZFS_IOC_FIRST' value='23040'/> - <enumerator name='ZFS_IOC' value='23040'/> - <enumerator name='ZFS_IOC_POOL_CREATE' value='23040'/> - <enumerator name='ZFS_IOC_POOL_DESTROY' value='23041'/> - <enumerator name='ZFS_IOC_POOL_IMPORT' value='23042'/> - <enumerator name='ZFS_IOC_POOL_EXPORT' value='23043'/> - <enumerator name='ZFS_IOC_POOL_CONFIGS' value='23044'/> - <enumerator name='ZFS_IOC_POOL_STATS' value='23045'/> - <enumerator name='ZFS_IOC_POOL_TRYIMPORT' value='23046'/> - <enumerator name='ZFS_IOC_POOL_SCAN' value='23047'/> - <enumerator name='ZFS_IOC_POOL_FREEZE' value='23048'/> - <enumerator name='ZFS_IOC_POOL_UPGRADE' value='23049'/> - <enumerator name='ZFS_IOC_POOL_GET_HISTORY' value='23050'/> - <enumerator name='ZFS_IOC_VDEV_ADD' value='23051'/> - <enumerator name='ZFS_IOC_VDEV_REMOVE' value='23052'/> - <enumerator name='ZFS_IOC_VDEV_SET_STATE' value='23053'/> - <enumerator name='ZFS_IOC_VDEV_ATTACH' value='23054'/> - <enumerator name='ZFS_IOC_VDEV_DETACH' value='23055'/> - <enumerator name='ZFS_IOC_VDEV_SETPATH' value='23056'/> - <enumerator name='ZFS_IOC_VDEV_SETFRU' value='23057'/> - <enumerator name='ZFS_IOC_OBJSET_STATS' value='23058'/> - <enumerator name='ZFS_IOC_OBJSET_ZPLPROPS' value='23059'/> - <enumerator name='ZFS_IOC_DATASET_LIST_NEXT' value='23060'/> - <enumerator name='ZFS_IOC_SNAPSHOT_LIST_NEXT' value='23061'/> - <enumerator name='ZFS_IOC_SET_PROP' value='23062'/> - <enumerator name='ZFS_IOC_CREATE' value='23063'/> - <enumerator name='ZFS_IOC_DESTROY' value='23064'/> - <enumerator name='ZFS_IOC_ROLLBACK' value='23065'/> - <enumerator name='ZFS_IOC_RENAME' value='23066'/> - <enumerator name='ZFS_IOC_RECV' value='23067'/> - <enumerator name='ZFS_IOC_SEND' value='23068'/> - <enumerator name='ZFS_IOC_INJECT_FAULT' value='23069'/> - <enumerator name='ZFS_IOC_CLEAR_FAULT' value='23070'/> - <enumerator name='ZFS_IOC_INJECT_LIST_NEXT' value='23071'/> - <enumerator name='ZFS_IOC_ERROR_LOG' value='23072'/> - <enumerator name='ZFS_IOC_CLEAR' value='23073'/> - <enumerator name='ZFS_IOC_PROMOTE' value='23074'/> - <enumerator name='ZFS_IOC_SNAPSHOT' value='23075'/> - <enumerator name='ZFS_IOC_DSOBJ_TO_DSNAME' value='23076'/> - <enumerator name='ZFS_IOC_OBJ_TO_PATH' value='23077'/> - <enumerator name='ZFS_IOC_POOL_SET_PROPS' value='23078'/> - <enumerator name='ZFS_IOC_POOL_GET_PROPS' value='23079'/> - <enumerator name='ZFS_IOC_SET_FSACL' value='23080'/> - <enumerator name='ZFS_IOC_GET_FSACL' value='23081'/> - <enumerator name='ZFS_IOC_SHARE' value='23082'/> - <enumerator name='ZFS_IOC_INHERIT_PROP' value='23083'/> - <enumerator name='ZFS_IOC_SMB_ACL' value='23084'/> - <enumerator name='ZFS_IOC_USERSPACE_ONE' value='23085'/> - <enumerator name='ZFS_IOC_USERSPACE_MANY' value='23086'/> - <enumerator name='ZFS_IOC_USERSPACE_UPGRADE' value='23087'/> - <enumerator name='ZFS_IOC_HOLD' value='23088'/> - <enumerator name='ZFS_IOC_RELEASE' value='23089'/> - <enumerator name='ZFS_IOC_GET_HOLDS' value='23090'/> - <enumerator name='ZFS_IOC_OBJSET_RECVD_PROPS' value='23091'/> - <enumerator name='ZFS_IOC_VDEV_SPLIT' value='23092'/> - <enumerator name='ZFS_IOC_NEXT_OBJ' value='23093'/> - <enumerator name='ZFS_IOC_DIFF' value='23094'/> - <enumerator name='ZFS_IOC_TMP_SNAPSHOT' value='23095'/> - <enumerator name='ZFS_IOC_OBJ_TO_STATS' value='23096'/> - <enumerator name='ZFS_IOC_SPACE_WRITTEN' value='23097'/> - <enumerator name='ZFS_IOC_SPACE_SNAPS' value='23098'/> - <enumerator name='ZFS_IOC_DESTROY_SNAPS' value='23099'/> - <enumerator name='ZFS_IOC_POOL_REGUID' value='23100'/> - <enumerator name='ZFS_IOC_POOL_REOPEN' value='23101'/> - <enumerator name='ZFS_IOC_SEND_PROGRESS' value='23102'/> - <enumerator name='ZFS_IOC_LOG_HISTORY' value='23103'/> - <enumerator name='ZFS_IOC_SEND_NEW' value='23104'/> - <enumerator name='ZFS_IOC_SEND_SPACE' value='23105'/> - <enumerator name='ZFS_IOC_CLONE' value='23106'/> - <enumerator name='ZFS_IOC_BOOKMARK' value='23107'/> - <enumerator name='ZFS_IOC_GET_BOOKMARKS' value='23108'/> - <enumerator name='ZFS_IOC_DESTROY_BOOKMARKS' value='23109'/> - <enumerator name='ZFS_IOC_RECV_NEW' value='23110'/> - <enumerator name='ZFS_IOC_POOL_SYNC' value='23111'/> - <enumerator name='ZFS_IOC_CHANNEL_PROGRAM' value='23112'/> - <enumerator name='ZFS_IOC_LOAD_KEY' value='23113'/> - <enumerator name='ZFS_IOC_UNLOAD_KEY' value='23114'/> - <enumerator name='ZFS_IOC_CHANGE_KEY' value='23115'/> - <enumerator name='ZFS_IOC_REMAP' value='23116'/> - <enumerator name='ZFS_IOC_POOL_CHECKPOINT' value='23117'/> - <enumerator name='ZFS_IOC_POOL_DISCARD_CHECKPOINT' value='23118'/> - <enumerator name='ZFS_IOC_POOL_INITIALIZE' value='23119'/> - <enumerator name='ZFS_IOC_POOL_TRIM' value='23120'/> - <enumerator name='ZFS_IOC_REDACT' value='23121'/> - <enumerator name='ZFS_IOC_GET_BOOKMARK_PROPS' value='23122'/> - <enumerator name='ZFS_IOC_WAIT' value='23123'/> - <enumerator name='ZFS_IOC_WAIT_FS' value='23124'/> - <enumerator name='ZFS_IOC_VDEV_GET_PROPS' value='23125'/> - <enumerator name='ZFS_IOC_VDEV_SET_PROPS' value='23126'/> - <enumerator name='ZFS_IOC_POOL_SCRUB' value='23127'/> - <enumerator name='ZFS_IOC_POOL_PREFETCH' value='23128'/> - <enumerator name='ZFS_IOC_DDT_PRUNE' value='23129'/> - <enumerator name='ZFS_IOC_PLATFORM' value='23168'/> - <enumerator name='ZFS_IOC_EVENTS_NEXT' value='23169'/> - <enumerator name='ZFS_IOC_EVENTS_CLEAR' value='23170'/> - <enumerator name='ZFS_IOC_EVENTS_SEEK' value='23171'/> - <enumerator name='ZFS_IOC_NEXTBOOT' value='23172'/> - <enumerator name='ZFS_IOC_JAIL' value='23173'/> - <enumerator name='ZFS_IOC_USERNS_ATTACH' value='23173'/> - <enumerator name='ZFS_IOC_UNJAIL' value='23174'/> - <enumerator name='ZFS_IOC_USERNS_DETACH' value='23174'/> - <enumerator name='ZFS_IOC_SET_BOOTENV' value='23175'/> - <enumerator name='ZFS_IOC_GET_BOOTENV' value='23176'/> - <enumerator name='ZFS_IOC_LAST' value='23177'/> - </enum-decl> - <typedef-decl name='zfs_ioc_t' type-id='12033f13' id='5b35941c'/> - <enum-decl name='zpool_wait_activity_t' naming-typedef-id='73446457' id='849338e3'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='ZPOOL_WAIT_CKPT_DISCARD' value='0'/> - <enumerator name='ZPOOL_WAIT_FREE' value='1'/> - <enumerator name='ZPOOL_WAIT_INITIALIZE' value='2'/> - <enumerator name='ZPOOL_WAIT_REPLACE' value='3'/> - <enumerator name='ZPOOL_WAIT_REMOVE' value='4'/> - <enumerator name='ZPOOL_WAIT_RESILVER' value='5'/> - <enumerator name='ZPOOL_WAIT_SCRUB' value='6'/> - <enumerator name='ZPOOL_WAIT_TRIM' value='7'/> - <enumerator name='ZPOOL_WAIT_RAIDZ_EXPAND' value='8'/> - <enumerator name='ZPOOL_WAIT_NUM_ACTIVITIES' value='9'/> - </enum-decl> - <typedef-decl name='zpool_wait_activity_t' type-id='849338e3' id='73446457'/> - <enum-decl name='zpool_prefetch_type_t' naming-typedef-id='e55ff6bc' id='0299ab50'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='ZPOOL_PREFETCH_NONE' value='0'/> - <enumerator name='ZPOOL_PREFETCH_DDT' value='1'/> - </enum-decl> - <typedef-decl name='zpool_prefetch_type_t' type-id='0299ab50' id='e55ff6bc'/> - <enum-decl name='zpool_ddt_prune_unit_t' naming-typedef-id='02e25ab0' id='509ae11c'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='ZPOOL_DDT_PRUNE_NONE' value='0'/> - <enumerator name='ZPOOL_DDT_PRUNE_AGE' value='1'/> - <enumerator name='ZPOOL_DDT_PRUNE_PERCENTAGE' value='2'/> - </enum-decl> - <typedef-decl name='zpool_ddt_prune_unit_t' type-id='509ae11c' id='02e25ab0'/> - <enum-decl name='spa_feature' id='33ecb627'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='SPA_FEATURE_NONE' value='-1'/> - <enumerator name='SPA_FEATURE_ASYNC_DESTROY' value='0'/> - <enumerator name='SPA_FEATURE_EMPTY_BPOBJ' value='1'/> - <enumerator name='SPA_FEATURE_LZ4_COMPRESS' value='2'/> - <enumerator name='SPA_FEATURE_MULTI_VDEV_CRASH_DUMP' value='3'/> - <enumerator name='SPA_FEATURE_SPACEMAP_HISTOGRAM' value='4'/> - <enumerator name='SPA_FEATURE_ENABLED_TXG' value='5'/> - <enumerator name='SPA_FEATURE_HOLE_BIRTH' value='6'/> - <enumerator name='SPA_FEATURE_EXTENSIBLE_DATASET' value='7'/> - <enumerator name='SPA_FEATURE_EMBEDDED_DATA' value='8'/> - <enumerator name='SPA_FEATURE_BOOKMARKS' value='9'/> - <enumerator name='SPA_FEATURE_FS_SS_LIMIT' value='10'/> - <enumerator name='SPA_FEATURE_LARGE_BLOCKS' value='11'/> - <enumerator name='SPA_FEATURE_LARGE_DNODE' value='12'/> - <enumerator name='SPA_FEATURE_SHA512' value='13'/> - <enumerator name='SPA_FEATURE_SKEIN' value='14'/> - <enumerator name='SPA_FEATURE_EDONR' value='15'/> - <enumerator name='SPA_FEATURE_USEROBJ_ACCOUNTING' value='16'/> - <enumerator name='SPA_FEATURE_ENCRYPTION' value='17'/> - <enumerator name='SPA_FEATURE_PROJECT_QUOTA' value='18'/> - <enumerator name='SPA_FEATURE_DEVICE_REMOVAL' value='19'/> - <enumerator name='SPA_FEATURE_OBSOLETE_COUNTS' value='20'/> - <enumerator name='SPA_FEATURE_POOL_CHECKPOINT' value='21'/> - <enumerator name='SPA_FEATURE_SPACEMAP_V2' value='22'/> - <enumerator name='SPA_FEATURE_ALLOCATION_CLASSES' value='23'/> - <enumerator name='SPA_FEATURE_RESILVER_DEFER' value='24'/> - <enumerator name='SPA_FEATURE_BOOKMARK_V2' value='25'/> - <enumerator name='SPA_FEATURE_REDACTION_BOOKMARKS' value='26'/> - <enumerator name='SPA_FEATURE_REDACTED_DATASETS' value='27'/> - <enumerator name='SPA_FEATURE_BOOKMARK_WRITTEN' value='28'/> - <enumerator name='SPA_FEATURE_LOG_SPACEMAP' value='29'/> - <enumerator name='SPA_FEATURE_LIVELIST' value='30'/> - <enumerator name='SPA_FEATURE_DEVICE_REBUILD' value='31'/> - <enumerator name='SPA_FEATURE_ZSTD_COMPRESS' value='32'/> - <enumerator name='SPA_FEATURE_DRAID' value='33'/> - <enumerator name='SPA_FEATURE_ZILSAXATTR' value='34'/> - <enumerator name='SPA_FEATURE_HEAD_ERRLOG' value='35'/> - <enumerator name='SPA_FEATURE_BLAKE3' value='36'/> - <enumerator name='SPA_FEATURE_BLOCK_CLONING' value='37'/> - <enumerator name='SPA_FEATURE_AVZ_V2' value='38'/> - <enumerator name='SPA_FEATURE_REDACTION_LIST_SPILL' value='39'/> - <enumerator name='SPA_FEATURE_RAIDZ_EXPANSION' value='40'/> - <enumerator name='SPA_FEATURE_FAST_DEDUP' value='41'/> - <enumerator name='SPA_FEATURE_LONGNAME' value='42'/> - <enumerator name='SPA_FEATURE_LARGE_MICROZAP' value='43'/> - <enumerator name='SPA_FEATURE_DYNAMIC_GANG_HEADER' value='44'/> - <enumerator name='SPA_FEATURE_BLOCK_CLONING_ENDIAN' value='45'/> - <enumerator name='SPA_FEATURE_PHYSICAL_REWRITE' value='46'/> - <enumerator name='SPA_FEATURES' value='47'/> - </enum-decl> - <typedef-decl name='spa_feature_t' type-id='33ecb627' id='d6618c78'/> - <qualified-type-def type-id='80f4b756' const='yes' id='b99c00c9'/> - <pointer-type-def type-id='b99c00c9' size-in-bits='64' id='13956559'/> - <qualified-type-def type-id='22cce67b' const='yes' id='d2816df0'/> - <pointer-type-def type-id='d2816df0' size-in-bits='64' id='3bbfee2e'/> - <qualified-type-def type-id='b96825af' const='yes' id='2b61797f'/> - <pointer-type-def type-id='2b61797f' size-in-bits='64' id='9f7200cf'/> - <pointer-type-def type-id='d6618c78' size-in-bits='64' id='a8425263'/> - <qualified-type-def type-id='62f7a03d' restrict='yes' id='f1cadedf'/> - <pointer-type-def type-id='a093cbb8' size-in-bits='64' id='b13f38c3'/> - <pointer-type-def type-id='35acf840' size-in-bits='64' id='17f3480d'/> - <pointer-type-def type-id='688c495b' size-in-bits='64' id='cec6f2e4'/> - <pointer-type-def type-id='d11b7617' size-in-bits='64' id='23432aaa'/> - <function-decl name='zpool_get_handle' mangled-name='zpool_get_handle' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_handle'> - <parameter type-id='4c81de99'/> - <return type-id='b0382bb3'/> - </function-decl> - <function-decl name='zpool_prop_to_name' mangled-name='zpool_prop_to_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_to_name'> - <parameter type-id='5d0c23fb'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='vdev_prop_to_name' mangled-name='vdev_prop_to_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_to_name'> - <parameter type-id='5aa5c90c'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='vdev_prop_user' mangled-name='vdev_prop_user' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_user'> - <parameter type-id='80f4b756'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zpool_get_status' mangled-name='zpool_get_status' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_status'> - <parameter type-id='4c81de99'/> - <parameter type-id='7d3cd834'/> - <parameter type-id='cec6f2e4'/> - <return type-id='d3dd6294'/> - </function-decl> - <function-decl name='zpool_prop_default_string' mangled-name='zpool_prop_default_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_default_string'> - <parameter type-id='5d0c23fb'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='zpool_prop_default_numeric' mangled-name='zpool_prop_default_numeric' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_default_numeric'> - <parameter type-id='5d0c23fb'/> - <return type-id='9c313c2d'/> - </function-decl> - <function-decl name='libzfs_envvar_is_set' mangled-name='libzfs_envvar_is_set' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_envvar_is_set'> - <parameter type-id='80f4b756'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='lzc_initialize' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='7063e1ab'/> - <parameter type-id='5ce45b60'/> - <parameter type-id='857bb57e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_trim' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='b1146b8d'/> - <parameter type-id='9c313c2d'/> - <parameter type-id='c19b74c3'/> - <parameter type-id='5ce45b60'/> - <parameter type-id='857bb57e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_sync' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='5ce45b60'/> - <parameter type-id='857bb57e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_reopen' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='c19b74c3'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_pool_checkpoint' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_pool_checkpoint_discard' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_wait' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='73446457'/> - <parameter type-id='37e3bd22'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_wait_tag' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='73446457'/> - <parameter type-id='9c313c2d'/> - <parameter type-id='37e3bd22'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_pool_prefetch' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='e55ff6bc'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_set_bootenv' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='22cce67b'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_get_bootenv' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='857bb57e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_get_vdev_prop' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='5ce45b60'/> - <parameter type-id='857bb57e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_set_vdev_prop' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='5ce45b60'/> - <parameter type-id='857bb57e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_scrub' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5b35941c'/> - <parameter type-id='80f4b756'/> - <parameter type-id='5ce45b60'/> - <parameter type-id='857bb57e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_ddt_prune' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='02e25ab0'/> - <parameter type-id='9c313c2d'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_resolve_shortname' mangled-name='zfs_resolve_shortname' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_resolve_shortname'> - <parameter type-id='80f4b756'/> - <parameter type-id='26a90f95'/> - <parameter type-id='b59d7dce'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_strip_partition' mangled-name='zfs_strip_partition' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_strip_partition'> - <parameter type-id='80f4b756'/> - <return type-id='26a90f95'/> - </function-decl> - <function-decl name='zfs_strip_path' mangled-name='zfs_strip_path' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_strip_path'> - <parameter type-id='80f4b756'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='zfs_strcmp_pathname' mangled-name='zfs_strcmp_pathname' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_strcmp_pathname'> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_history_unpack' mangled-name='zpool_history_unpack' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_history_unpack'> - <parameter type-id='26a90f95'/> - <parameter type-id='9c313c2d'/> - <parameter type-id='5d6479ae'/> - <parameter type-id='75be733c'/> - <parameter type-id='4dd26a40'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_basename' mangled-name='zfs_basename' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_basename'> - <parameter type-id='80f4b756'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='zpool_name_to_prop' mangled-name='zpool_name_to_prop' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_name_to_prop'> - <parameter type-id='80f4b756'/> - <return type-id='5d0c23fb'/> - </function-decl> - <function-decl name='zpool_prop_readonly' mangled-name='zpool_prop_readonly' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_readonly'> - <parameter type-id='5d0c23fb'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zpool_prop_setonce' mangled-name='zpool_prop_setonce' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_setonce'> - <parameter type-id='5d0c23fb'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zpool_prop_feature' mangled-name='zpool_prop_feature' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_feature'> - <parameter type-id='80f4b756'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zpool_prop_index_to_string' mangled-name='zpool_prop_index_to_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_index_to_string'> - <parameter type-id='5d0c23fb'/> - <parameter type-id='9c313c2d'/> - <parameter type-id='7d3cd834'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='vdev_name_to_prop' mangled-name='vdev_name_to_prop' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_name_to_prop'> - <parameter type-id='80f4b756'/> - <return type-id='5aa5c90c'/> - </function-decl> - <function-decl name='vdev_prop_default_string' mangled-name='vdev_prop_default_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_default_string'> - <parameter type-id='5aa5c90c'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='vdev_prop_default_numeric' mangled-name='vdev_prop_default_numeric' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_default_numeric'> - <parameter type-id='5aa5c90c'/> - <return type-id='9c313c2d'/> - </function-decl> - <function-decl name='vdev_prop_readonly' mangled-name='vdev_prop_readonly' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_readonly'> - <parameter type-id='5aa5c90c'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='vdev_prop_index_to_string' mangled-name='vdev_prop_index_to_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_index_to_string'> - <parameter type-id='5aa5c90c'/> - <parameter type-id='9c313c2d'/> - <parameter type-id='7d3cd834'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_prop_vdev' mangled-name='zpool_prop_vdev' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_vdev'> - <parameter type-id='80f4b756'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='nvlist_add_nvpair' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='3fa542f0'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='nvlist_add_uint8_array' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='80f4b756'/> - <parameter type-id='9f7200cf'/> - <parameter type-id='3502e3ff'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='nvlist_add_nvlist_array' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='80f4b756'/> - <parameter type-id='3bbfee2e'/> - <parameter type-id='3502e3ff'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='nvpair_value_nvlist' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='3fa542f0'/> - <parameter type-id='857bb57e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='fnvlist_add_boolean_value' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='80f4b756'/> - <parameter type-id='c19b74c3'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='fnvlist_add_int64' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='80f4b756'/> - <parameter type-id='9da381c4'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='fnvlist_add_string_array' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='80f4b756'/> - <parameter type-id='13956559'/> - <parameter type-id='3502e3ff'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='fnvlist_add_nvlist_array' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='80f4b756'/> - <parameter type-id='3bbfee2e'/> - <parameter type-id='3502e3ff'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='fnvlist_lookup_uint64_array' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='80f4b756'/> - <parameter type-id='4dd26a40'/> - <return type-id='5d6479ae'/> - </function-decl> - <function-decl name='fnvpair_value_int64' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='dace003f'/> - <return type-id='9da381c4'/> - </function-decl> - <function-decl name='fnvpair_value_string' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='dace003f'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='zfeature_is_supported' mangled-name='zfeature_is_supported' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfeature_is_supported'> - <parameter type-id='80f4b756'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zfeature_lookup_guid' mangled-name='zfeature_lookup_guid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfeature_lookup_guid'> - <parameter type-id='80f4b756'/> - <parameter type-id='a8425263'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfeature_lookup_name' mangled-name='zfeature_lookup_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfeature_lookup_name'> - <parameter type-id='80f4b756'/> - <parameter type-id='a8425263'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_get_load_policy' mangled-name='zpool_get_load_policy' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_load_policy'> - <parameter type-id='5ce45b60'/> - <parameter type-id='23432aaa'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='pool_namecheck' mangled-name='pool_namecheck' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='pool_namecheck'> - <parameter type-id='80f4b756'/> - <parameter type-id='053457bd'/> - <parameter type-id='26a90f95'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_prop_get_type' mangled-name='zpool_prop_get_type' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_get_type'> - <parameter type-id='5d0c23fb'/> - <return type-id='31429eff'/> - </function-decl> - <function-decl name='vdev_prop_get_type' mangled-name='vdev_prop_get_type' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_get_type'> - <parameter type-id='5aa5c90c'/> - <return type-id='31429eff'/> - </function-decl> - <function-decl name='get_system_hostid' mangled-name='get_system_hostid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='get_system_hostid'> - <return type-id='7359adad'/> - </function-decl> - <function-decl name='strtoull' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='9d26089a'/> - <parameter type-id='8c85230f'/> - <parameter type-id='95e97e5e'/> - <return type-id='3a47d82b'/> - </function-decl> - <function-decl name='memcmp' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='eaa32e2f'/> - <parameter type-id='eaa32e2f'/> - <parameter type-id='b59d7dce'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='strtok_r' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='266fe297'/> - <parameter type-id='9d26089a'/> - <parameter type-id='8c85230f'/> - <return type-id='26a90f95'/> - </function-decl> - <function-decl name='ctime_r' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='d6e2847c'/> - <parameter type-id='266fe297'/> - <return type-id='26a90f95'/> - </function-decl> - <function-decl name='__realpath_chk' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='9d26089a'/> - <parameter type-id='266fe297'/> - <parameter type-id='b59d7dce'/> - <return type-id='26a90f95'/> - </function-decl> - <function-decl name='munmap' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='eaa32e2f'/> - <parameter type-id='b59d7dce'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='stat64' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='9d26089a'/> - <parameter type-id='f1cadedf'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_standard_error' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_standard_error_fmt' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='80f4b756'/> - <parameter is-variadic='yes'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_relabel_disk' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_props_refresh' mangled-name='zpool_props_refresh' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_props_refresh'> - <parameter type-id='4c81de99' name='zhp'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_state_to_name' mangled-name='zpool_state_to_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_state_to_name'> - <parameter type-id='35acf840' name='state'/> - <parameter type-id='9d774e0b' name='aux'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='zpool_pool_state_to_name' mangled-name='zpool_pool_state_to_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_pool_state_to_name'> - <parameter type-id='084a08a3' name='state'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='zpool_get_state_str' mangled-name='zpool_get_state_str' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_state_str'> - <parameter type-id='4c81de99' name='zhp'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='zpool_get_userprop' mangled-name='zpool_get_userprop' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_userprop'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='80f4b756' name='propname'/> - <parameter type-id='26a90f95' name='buf'/> - <parameter type-id='b59d7dce' name='len'/> - <parameter type-id='debc6aa3' name='srctype'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_set_prop' mangled-name='zpool_set_prop' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_set_prop'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='80f4b756' name='propname'/> - <parameter type-id='80f4b756' name='propval'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_expand_proplist' mangled-name='zpool_expand_proplist' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_expand_proplist'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='e4378506' name='plp'/> - <parameter type-id='2e45de5d' name='type'/> - <parameter type-id='c19b74c3' name='literal'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='vdev_expand_proplist' mangled-name='vdev_expand_proplist' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_expand_proplist'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='80f4b756' name='vdevname'/> - <parameter type-id='e4378506' name='plp'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_prop_get_feature' mangled-name='zpool_prop_get_feature' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_get_feature'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='80f4b756' name='propname'/> - <parameter type-id='26a90f95' name='buf'/> - <parameter type-id='b59d7dce' name='len'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_get_state' mangled-name='zpool_get_state' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_state'> - <parameter type-id='4c81de99' name='zhp'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_is_draid_spare' mangled-name='zpool_is_draid_spare' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_is_draid_spare'> - <parameter type-id='80f4b756' name='name'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zpool_create' mangled-name='zpool_create' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_create'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='80f4b756' name='pool'/> - <parameter type-id='5ce45b60' name='nvroot'/> - <parameter type-id='5ce45b60' name='props'/> - <parameter type-id='5ce45b60' name='fsprops'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_destroy' mangled-name='zpool_destroy' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_destroy'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='80f4b756' name='log_str'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_checkpoint' mangled-name='zpool_checkpoint' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_checkpoint'> - <parameter type-id='4c81de99' name='zhp'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_discard_checkpoint' mangled-name='zpool_discard_checkpoint' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_discard_checkpoint'> - <parameter type-id='4c81de99' name='zhp'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_prefetch' mangled-name='zpool_prefetch' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prefetch'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='e55ff6bc' name='type'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_add' mangled-name='zpool_add' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_add'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='5ce45b60' name='nvroot'/> - <parameter type-id='c19b74c3' name='check_ashift'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_export' mangled-name='zpool_export' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_export'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='c19b74c3' name='force'/> - <parameter type-id='80f4b756' name='log_str'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_export_force' mangled-name='zpool_export_force' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_export_force'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='80f4b756' name='log_str'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_explain_recover' mangled-name='zpool_explain_recover' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_explain_recover'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='80f4b756' name='name'/> - <parameter type-id='95e97e5e' name='reason'/> - <parameter type-id='5ce45b60' name='config'/> - <parameter type-id='26a90f95' name='buf'/> - <parameter type-id='b59d7dce' name='size'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zpool_import' mangled-name='zpool_import' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_import'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='5ce45b60' name='config'/> - <parameter type-id='80f4b756' name='newname'/> - <parameter type-id='26a90f95' name='altroot'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_collect_unsup_feat' mangled-name='zpool_collect_unsup_feat' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_collect_unsup_feat'> - <parameter type-id='5ce45b60' name='config'/> - <parameter type-id='26a90f95' name='buf'/> - <parameter type-id='b59d7dce' name='size'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zpool_import_props' mangled-name='zpool_import_props' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_import_props'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='5ce45b60' name='config'/> - <parameter type-id='80f4b756' name='newname'/> - <parameter type-id='5ce45b60' name='props'/> - <parameter type-id='95e97e5e' name='flags'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_initialize_one' mangled-name='zpool_initialize_one' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_initialize_one'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='eaa32e2f' name='data'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_initialize' mangled-name='zpool_initialize' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_initialize'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='7063e1ab' name='cmd_type'/> - <parameter type-id='5ce45b60' name='vds'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_initialize_wait' mangled-name='zpool_initialize_wait' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_initialize_wait'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='7063e1ab' name='cmd_type'/> - <parameter type-id='5ce45b60' name='vds'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_collect_leaves' mangled-name='zpool_collect_leaves' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_collect_leaves'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='5ce45b60' name='nvroot'/> - <parameter type-id='5ce45b60' name='res'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zpool_trim_one' mangled-name='zpool_trim_one' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_trim_one'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='eaa32e2f' name='data'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_trim' mangled-name='zpool_trim' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_trim'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='b1146b8d' name='cmd_type'/> - <parameter type-id='5ce45b60' name='vds'/> - <parameter type-id='b13f38c3' name='trim_flags'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_scan' mangled-name='zpool_scan' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_scan'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='7313fbe2' name='func'/> - <parameter type-id='b51cf3c2' name='cmd'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_scan_range' mangled-name='zpool_scan_range' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_scan_range'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='7313fbe2' name='func'/> - <parameter type-id='b51cf3c2' name='cmd'/> - <parameter type-id='c9d12d66' name='date_start'/> - <parameter type-id='c9d12d66' name='date_end'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_find_vdev_by_physpath' mangled-name='zpool_find_vdev_by_physpath' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_find_vdev_by_physpath'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='80f4b756' name='ppath'/> - <parameter type-id='37e3bd22' name='avail_spare'/> - <parameter type-id='37e3bd22' name='l2cache'/> - <parameter type-id='37e3bd22' name='log'/> - <return type-id='5ce45b60'/> - </function-decl> - <function-decl name='zpool_find_vdev' mangled-name='zpool_find_vdev' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_find_vdev'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='80f4b756' name='path'/> - <parameter type-id='37e3bd22' name='avail_spare'/> - <parameter type-id='37e3bd22' name='l2cache'/> - <parameter type-id='37e3bd22' name='log'/> - <return type-id='5ce45b60'/> - </function-decl> - <function-decl name='zpool_find_parent_vdev' mangled-name='zpool_find_parent_vdev' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_find_parent_vdev'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='80f4b756' name='path'/> - <parameter type-id='37e3bd22' name='avail_spare'/> - <parameter type-id='37e3bd22' name='l2cache'/> - <parameter type-id='37e3bd22' name='log'/> - <return type-id='5ce45b60'/> - </function-decl> - <function-decl name='zpool_vdev_path_to_guid' mangled-name='zpool_vdev_path_to_guid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_path_to_guid'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='80f4b756' name='path'/> - <return type-id='9c313c2d'/> - </function-decl> - <function-decl name='zpool_vdev_online' mangled-name='zpool_vdev_online' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_online'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='80f4b756' name='path'/> - <parameter type-id='95e97e5e' name='flags'/> - <parameter type-id='17f3480d' name='newstate'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_vdev_offline' mangled-name='zpool_vdev_offline' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_offline'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='80f4b756' name='path'/> - <parameter type-id='c19b74c3' name='istmp'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_vdev_remove_wanted' mangled-name='zpool_vdev_remove_wanted' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_remove_wanted'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='80f4b756' name='path'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_vdev_fault' mangled-name='zpool_vdev_fault' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_fault'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='9c313c2d' name='guid'/> - <parameter type-id='9d774e0b' name='aux'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_vdev_degrade' mangled-name='zpool_vdev_degrade' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_degrade'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='9c313c2d' name='guid'/> - <parameter type-id='9d774e0b' name='aux'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_vdev_set_removed_state' mangled-name='zpool_vdev_set_removed_state' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_set_removed_state'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='9c313c2d' name='guid'/> - <parameter type-id='9d774e0b' name='aux'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_vdev_attach' mangled-name='zpool_vdev_attach' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_attach'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='80f4b756' name='old_disk'/> - <parameter type-id='80f4b756' name='new_disk'/> - <parameter type-id='5ce45b60' name='nvroot'/> - <parameter type-id='95e97e5e' name='replacing'/> - <parameter type-id='c19b74c3' name='rebuild'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_vdev_detach' mangled-name='zpool_vdev_detach' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_detach'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='80f4b756' name='path'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_vdev_split' mangled-name='zpool_vdev_split' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_split'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='26a90f95' name='newname'/> - <parameter type-id='857bb57e' name='newroot'/> - <parameter type-id='5ce45b60' name='props'/> - <parameter type-id='325c1e34' name='flags'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_vdev_remove' mangled-name='zpool_vdev_remove' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_remove'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='80f4b756' name='path'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_vdev_remove_cancel' mangled-name='zpool_vdev_remove_cancel' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_remove_cancel'> - <parameter type-id='4c81de99' name='zhp'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_vdev_indirect_size' mangled-name='zpool_vdev_indirect_size' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_indirect_size'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='80f4b756' name='path'/> - <parameter type-id='5d6479ae' name='sizep'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_clear' mangled-name='zpool_clear' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_clear'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='80f4b756' name='path'/> - <parameter type-id='5ce45b60' name='rewindnvl'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_vdev_clear' mangled-name='zpool_vdev_clear' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_clear'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='9c313c2d' name='guid'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_set_guid' mangled-name='zpool_set_guid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_set_guid'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='713a56f5' name='guid'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_reguid' mangled-name='zpool_reguid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_reguid'> - <parameter type-id='4c81de99' name='zhp'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_reopen_one' mangled-name='zpool_reopen_one' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_reopen_one'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='eaa32e2f' name='data'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_sync_one' mangled-name='zpool_sync_one' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_sync_one'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='eaa32e2f' name='data'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_vdev_name' mangled-name='zpool_vdev_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_name'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='5ce45b60' name='nv'/> - <parameter type-id='95e97e5e' name='name_flags'/> - <return type-id='26a90f95'/> - </function-decl> - <function-decl name='zpool_add_propname' mangled-name='zpool_add_propname' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_add_propname'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='80f4b756' name='propname'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zpool_get_errlog' mangled-name='zpool_get_errlog' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_errlog'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='857bb57e' name='nverrlistp'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_upgrade' mangled-name='zpool_upgrade' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_upgrade'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='9c313c2d' name='new_version'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_save_arguments' mangled-name='zfs_save_arguments' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_save_arguments'> - <parameter type-id='95e97e5e' name='argc'/> - <parameter type-id='9b23c9ad' name='argv'/> - <parameter type-id='26a90f95' name='string'/> - <parameter type-id='95e97e5e' name='len'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zpool_log_history' mangled-name='zpool_log_history' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_log_history'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='80f4b756' name='message'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_get_history' mangled-name='zpool_get_history' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_history'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='857bb57e' name='nvhisp'/> - <parameter type-id='5d6479ae' name='off'/> - <parameter type-id='37e3bd22' name='eof'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_events_next' mangled-name='zpool_events_next' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_events_next'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='857bb57e' name='nvp'/> - <parameter type-id='7292109c' name='dropped'/> - <parameter type-id='f0981eeb' name='flags'/> - <parameter type-id='95e97e5e' name='zevent_fd'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_events_clear' mangled-name='zpool_events_clear' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_events_clear'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='7292109c' name='count'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_events_seek' mangled-name='zpool_events_seek' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_events_seek'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='9c313c2d' name='eid'/> - <parameter type-id='95e97e5e' name='zevent_fd'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_obj_to_path' mangled-name='zpool_obj_to_path' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_obj_to_path'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='9c313c2d' name='dsobj'/> - <parameter type-id='9c313c2d' name='obj'/> - <parameter type-id='26a90f95' name='pathname'/> - <parameter type-id='b59d7dce' name='len'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zpool_obj_to_path_ds' mangled-name='zpool_obj_to_path_ds' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_obj_to_path_ds'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='9c313c2d' name='dsobj'/> - <parameter type-id='9c313c2d' name='obj'/> - <parameter type-id='26a90f95' name='pathname'/> - <parameter type-id='b59d7dce' name='len'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zpool_wait' mangled-name='zpool_wait' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_wait'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='73446457' name='activity'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_wait_status' mangled-name='zpool_wait_status' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_wait_status'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='73446457' name='activity'/> - <parameter type-id='37e3bd22' name='missing'/> - <parameter type-id='37e3bd22' name='waited'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_set_bootenv' mangled-name='zpool_set_bootenv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_set_bootenv'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='22cce67b' name='envmap'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_get_bootenv' mangled-name='zpool_get_bootenv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_bootenv'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='857bb57e' name='nvlp'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_load_compat' mangled-name='zpool_load_compat' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_load_compat'> - <parameter type-id='80f4b756' name='compat'/> - <parameter type-id='37e3bd22' name='features'/> - <parameter type-id='26a90f95' name='report'/> - <parameter type-id='b59d7dce' name='rlen'/> - <return type-id='901b78d1'/> - </function-decl> - <function-decl name='zpool_get_vdev_prop_value' mangled-name='zpool_get_vdev_prop_value' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_vdev_prop_value'> - <parameter type-id='5ce45b60' name='nvprop'/> - <parameter type-id='5aa5c90c' name='prop'/> - <parameter type-id='26a90f95' name='prop_name'/> - <parameter type-id='26a90f95' name='buf'/> - <parameter type-id='b59d7dce' name='len'/> - <parameter type-id='debc6aa3' name='srctype'/> - <parameter type-id='c19b74c3' name='literal'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_get_vdev_prop' mangled-name='zpool_get_vdev_prop' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_vdev_prop'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='80f4b756' name='vdevname'/> - <parameter type-id='5aa5c90c' name='prop'/> - <parameter type-id='26a90f95' name='prop_name'/> - <parameter type-id='26a90f95' name='buf'/> - <parameter type-id='b59d7dce' name='len'/> - <parameter type-id='debc6aa3' name='srctype'/> - <parameter type-id='c19b74c3' name='literal'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_get_all_vdev_props' mangled-name='zpool_get_all_vdev_props' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_all_vdev_props'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='80f4b756' name='vdevname'/> - <parameter type-id='857bb57e' name='outnvl'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_set_vdev_prop' mangled-name='zpool_set_vdev_prop' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_set_vdev_prop'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='80f4b756' name='vdevname'/> - <parameter type-id='80f4b756' name='propname'/> - <parameter type-id='80f4b756' name='propval'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_ddt_prune' mangled-name='zpool_ddt_prune' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_ddt_prune'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='02e25ab0' name='unit'/> - <parameter type-id='9c313c2d' name='amount'/> - <return type-id='95e97e5e'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='lib/libzfs/libzfs_sendrecv.c' language='LANG_C99'> - <array-type-def dimensions='1' type-id='8901473c' size-in-bits='576' id='f5da478b'> - <subrange length='1' type-id='7359adad' id='52f813b4'/> - </array-type-def> - <array-type-def dimensions='1' type-id='95e97e5e' size-in-bits='384' id='73b82f0f'> - <subrange length='12' type-id='7359adad' id='84827bdc'/> - </array-type-def> - <array-type-def dimensions='1' type-id='bd54fe1a' size-in-bits='512' id='5d4efd44'> - <subrange length='8' type-id='7359adad' id='56e0c0b1'/> - </array-type-def> - <array-type-def dimensions='1' type-id='9c313c2d' size-in-bits='2176' id='8c2bcad1'> - <subrange length='34' type-id='7359adad' id='6a6a7e00'/> - </array-type-def> - <array-type-def dimensions='1' type-id='9c313c2d' size-in-bits='256' id='85c64d26'> - <subrange length='4' type-id='7359adad' id='16fe7105'/> - </array-type-def> - <array-type-def dimensions='1' type-id='b96825af' size-in-bits='96' id='fa8ef949'> - <subrange length='12' type-id='7359adad' id='84827bdc'/> - </array-type-def> - <array-type-def dimensions='1' type-id='b96825af' size-in-bits='128' id='fa9986a5'> - <subrange length='16' type-id='7359adad' id='848d0938'/> - </array-type-def> - <array-type-def dimensions='1' type-id='b96825af' size-in-bits='40' id='0f4ddd0b'> - <subrange length='5' type-id='7359adad' id='53010e10'/> - </array-type-def> - <array-type-def dimensions='1' type-id='b96825af' size-in-bits='48' id='0f562bd0'> - <subrange length='6' type-id='7359adad' id='52fa524b'/> - </array-type-def> - <array-type-def dimensions='1' type-id='b96825af' size-in-bits='64' id='13339fda'> - <subrange length='8' type-id='7359adad' id='56e0c0b1'/> - </array-type-def> - <array-type-def dimensions='1' type-id='eaa32e2f' size-in-bits='256' id='209ef23f'> - <subrange length='4' type-id='7359adad' id='16fe7105'/> - </array-type-def> - <class-decl name='sendflags' size-in-bits='576' is-struct='yes' visibility='default' id='f6aa15be'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='verbosity' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32'> - <var-decl name='replicate' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='skipmissing' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='96'> - <var-decl name='doall' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='fromorigin' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='160'> - <var-decl name='pad' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='props' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='224'> - <var-decl name='dryrun' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='parsable' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='288'> - <var-decl name='progress' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='progressastitle' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='352'> - <var-decl name='largeblock' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='384'> - <var-decl name='embed_data' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='416'> - <var-decl name='compress' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='448'> - <var-decl name='raw' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='480'> - <var-decl name='backup' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='512'> - <var-decl name='holds' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='544'> - <var-decl name='saved' type-id='c19b74c3' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='sendflags_t' type-id='f6aa15be' id='945467e6'/> - <typedef-decl name='snapfilter_cb_t' type-id='d2a5e211' id='3d3ffb69'/> - <class-decl name='recvflags' size-in-bits='448' is-struct='yes' visibility='default' id='34a384dc'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='verbose' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32'> - <var-decl name='isprefix' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='istail' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='96'> - <var-decl name='dryrun' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='force' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='160'> - <var-decl name='canmountoff' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='resumable' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='224'> - <var-decl name='byteswap' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='nomount' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='288'> - <var-decl name='holds' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='skipholds' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='352'> - <var-decl name='domount' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='384'> - <var-decl name='forceunmount' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='416'> - <var-decl name='heal' type-id='c19b74c3' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='recvflags_t' type-id='34a384dc' id='9e59d1d4'/> - <enum-decl name='lzc_send_flags' id='bfbd3c8e'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='LZC_SEND_FLAG_EMBED_DATA' value='1'/> - <enumerator name='LZC_SEND_FLAG_LARGE_BLOCK' value='2'/> - <enumerator name='LZC_SEND_FLAG_COMPRESS' value='4'/> - <enumerator name='LZC_SEND_FLAG_RAW' value='8'/> - <enumerator name='LZC_SEND_FLAG_SAVED' value='16'/> - </enum-decl> - <class-decl name='ddt_key_t' size-in-bits='320' is-struct='yes' naming-typedef-id='67f6d2cf' visibility='default' id='5fae1718'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='ddk_cksum' type-id='39730d0b' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='ddk_prop' type-id='9c313c2d' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='ddt_key_t' type-id='5fae1718' id='67f6d2cf'/> - <enum-decl name='dmu_object_type' id='04b3b0b9'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='DMU_OT_NONE' value='0'/> - <enumerator name='DMU_OT_OBJECT_DIRECTORY' value='1'/> - <enumerator name='DMU_OT_OBJECT_ARRAY' value='2'/> - <enumerator name='DMU_OT_PACKED_NVLIST' value='3'/> - <enumerator name='DMU_OT_PACKED_NVLIST_SIZE' value='4'/> - <enumerator name='DMU_OT_BPOBJ' value='5'/> - <enumerator name='DMU_OT_BPOBJ_HDR' value='6'/> - <enumerator name='DMU_OT_SPACE_MAP_HEADER' value='7'/> - <enumerator name='DMU_OT_SPACE_MAP' value='8'/> - <enumerator name='DMU_OT_INTENT_LOG' value='9'/> - <enumerator name='DMU_OT_DNODE' value='10'/> - <enumerator name='DMU_OT_OBJSET' value='11'/> - <enumerator name='DMU_OT_DSL_DIR' value='12'/> - <enumerator name='DMU_OT_DSL_DIR_CHILD_MAP' value='13'/> - <enumerator name='DMU_OT_DSL_DS_SNAP_MAP' value='14'/> - <enumerator name='DMU_OT_DSL_PROPS' value='15'/> - <enumerator name='DMU_OT_DSL_DATASET' value='16'/> - <enumerator name='DMU_OT_ZNODE' value='17'/> - <enumerator name='DMU_OT_OLDACL' value='18'/> - <enumerator name='DMU_OT_PLAIN_FILE_CONTENTS' value='19'/> - <enumerator name='DMU_OT_DIRECTORY_CONTENTS' value='20'/> - <enumerator name='DMU_OT_MASTER_NODE' value='21'/> - <enumerator name='DMU_OT_UNLINKED_SET' value='22'/> - <enumerator name='DMU_OT_ZVOL' value='23'/> - <enumerator name='DMU_OT_ZVOL_PROP' value='24'/> - <enumerator name='DMU_OT_PLAIN_OTHER' value='25'/> - <enumerator name='DMU_OT_UINT64_OTHER' value='26'/> - <enumerator name='DMU_OT_ZAP_OTHER' value='27'/> - <enumerator name='DMU_OT_ERROR_LOG' value='28'/> - <enumerator name='DMU_OT_SPA_HISTORY' value='29'/> - <enumerator name='DMU_OT_SPA_HISTORY_OFFSETS' value='30'/> - <enumerator name='DMU_OT_POOL_PROPS' value='31'/> - <enumerator name='DMU_OT_DSL_PERMS' value='32'/> - <enumerator name='DMU_OT_ACL' value='33'/> - <enumerator name='DMU_OT_SYSACL' value='34'/> - <enumerator name='DMU_OT_FUID' value='35'/> - <enumerator name='DMU_OT_FUID_SIZE' value='36'/> - <enumerator name='DMU_OT_NEXT_CLONES' value='37'/> - <enumerator name='DMU_OT_SCAN_QUEUE' value='38'/> - <enumerator name='DMU_OT_USERGROUP_USED' value='39'/> - <enumerator name='DMU_OT_USERGROUP_QUOTA' value='40'/> - <enumerator name='DMU_OT_USERREFS' value='41'/> - <enumerator name='DMU_OT_DDT_ZAP' value='42'/> - <enumerator name='DMU_OT_DDT_STATS' value='43'/> - <enumerator name='DMU_OT_SA' value='44'/> - <enumerator name='DMU_OT_SA_MASTER_NODE' value='45'/> - <enumerator name='DMU_OT_SA_ATTR_REGISTRATION' value='46'/> - <enumerator name='DMU_OT_SA_ATTR_LAYOUTS' value='47'/> - <enumerator name='DMU_OT_SCAN_XLATE' value='48'/> - <enumerator name='DMU_OT_DEDUP' value='49'/> - <enumerator name='DMU_OT_DEADLIST' value='50'/> - <enumerator name='DMU_OT_DEADLIST_HDR' value='51'/> - <enumerator name='DMU_OT_DSL_CLONES' value='52'/> - <enumerator name='DMU_OT_BPOBJ_SUBOBJ' value='53'/> - <enumerator name='DMU_OT_NUMTYPES' value='54'/> - <enumerator name='DMU_OTN_UINT8_DATA' value='128'/> - <enumerator name='DMU_OTN_UINT8_METADATA' value='192'/> - <enumerator name='DMU_OTN_UINT16_DATA' value='129'/> - <enumerator name='DMU_OTN_UINT16_METADATA' value='193'/> - <enumerator name='DMU_OTN_UINT32_DATA' value='130'/> - <enumerator name='DMU_OTN_UINT32_METADATA' value='194'/> - <enumerator name='DMU_OTN_UINT64_DATA' value='131'/> - <enumerator name='DMU_OTN_UINT64_METADATA' value='195'/> - <enumerator name='DMU_OTN_ZAP_DATA' value='132'/> - <enumerator name='DMU_OTN_ZAP_METADATA' value='196'/> - <enumerator name='DMU_OTN_UINT8_ENC_DATA' value='160'/> - <enumerator name='DMU_OTN_UINT8_ENC_METADATA' value='224'/> - <enumerator name='DMU_OTN_UINT16_ENC_DATA' value='161'/> - <enumerator name='DMU_OTN_UINT16_ENC_METADATA' value='225'/> - <enumerator name='DMU_OTN_UINT32_ENC_DATA' value='162'/> - <enumerator name='DMU_OTN_UINT32_ENC_METADATA' value='226'/> - <enumerator name='DMU_OTN_UINT64_ENC_DATA' value='163'/> - <enumerator name='DMU_OTN_UINT64_ENC_METADATA' value='227'/> - <enumerator name='DMU_OTN_ZAP_ENC_DATA' value='164'/> - <enumerator name='DMU_OTN_ZAP_ENC_METADATA' value='228'/> - </enum-decl> - <typedef-decl name='dmu_object_type_t' type-id='04b3b0b9' id='5c9d8906'/> - <class-decl name='zio_cksum' size-in-bits='256' is-struct='yes' visibility='default' id='1d53e28b'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='zc_word' type-id='85c64d26' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='zio_cksum_t' type-id='1d53e28b' id='39730d0b'/> - <class-decl name='dmu_replay_record' size-in-bits='2496' is-struct='yes' visibility='default' id='781a52d7'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='drr_type' type-id='08f5ca17' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32'> - <var-decl name='drr_payloadlen' type-id='8f92235e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='drr_u' type-id='ac5ab599' visibility='default'/> - </data-member> - </class-decl> - <enum-decl name='__anonymous_enum__' is-anonymous='yes' id='08f5ca17'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='DRR_BEGIN' value='0'/> - <enumerator name='DRR_OBJECT' value='1'/> - <enumerator name='DRR_FREEOBJECTS' value='2'/> - <enumerator name='DRR_WRITE' value='3'/> - <enumerator name='DRR_FREE' value='4'/> - <enumerator name='DRR_END' value='5'/> - <enumerator name='DRR_WRITE_BYREF' value='6'/> - <enumerator name='DRR_SPILL' value='7'/> - <enumerator name='DRR_WRITE_EMBEDDED' value='8'/> - <enumerator name='DRR_OBJECT_RANGE' value='9'/> - <enumerator name='DRR_REDACT' value='10'/> - <enumerator name='DRR_NUMTYPES' value='11'/> - </enum-decl> - <union-decl name='__anonymous_union__' size-in-bits='2432' is-anonymous='yes' visibility='default' id='ac5ab599'> - <data-member access='public'> - <var-decl name='drr_begin' type-id='09fcdc01' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='drr_end' type-id='6ee25631' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='drr_object' type-id='f9ad530b' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='drr_freeobjects' type-id='a27d958e' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='drr_write' type-id='4cc69e4b' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='drr_free' type-id='c836cfd2' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='drr_write_byref' type-id='e511cdce' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='drr_spill' type-id='1e69a80a' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='drr_write_embedded' type-id='98b1345e' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='drr_object_range' type-id='aba1f9e1' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='drr_redact' type-id='50389039' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='drr_checksum' type-id='a5fe3647' visibility='default'/> - </data-member> - </union-decl> - <class-decl name='drr_end' size-in-bits='320' is-struct='yes' visibility='default' id='6ee25631'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='drr_checksum' type-id='39730d0b' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='drr_toguid' type-id='9c313c2d' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='drr_object' size-in-bits='448' is-struct='yes' visibility='default' id='f9ad530b'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='drr_object' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='drr_type' type-id='5c9d8906' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='96'> - <var-decl name='drr_bonustype' type-id='5c9d8906' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='drr_blksz' type-id='8f92235e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='160'> - <var-decl name='drr_bonuslen' type-id='8f92235e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='drr_checksumtype' type-id='b96825af' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='200'> - <var-decl name='drr_compress' type-id='b96825af' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='208'> - <var-decl name='drr_dn_slots' type-id='b96825af' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='216'> - <var-decl name='drr_flags' type-id='b96825af' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='224'> - <var-decl name='drr_raw_bonuslen' type-id='8f92235e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='drr_toguid' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='drr_indblkshift' type-id='b96825af' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='328'> - <var-decl name='drr_nlevels' type-id='b96825af' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='336'> - <var-decl name='drr_nblkptr' type-id='b96825af' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='344'> - <var-decl name='drr_pad' type-id='0f4ddd0b' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='384'> - <var-decl name='drr_maxblkid' type-id='9c313c2d' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='drr_freeobjects' size-in-bits='192' is-struct='yes' visibility='default' id='a27d958e'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='drr_firstobj' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='drr_numobjs' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='drr_toguid' type-id='9c313c2d' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='drr_write' size-in-bits='1088' is-struct='yes' visibility='default' id='4cc69e4b'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='drr_object' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='drr_type' type-id='5c9d8906' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='96'> - <var-decl name='drr_pad' type-id='8f92235e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='drr_offset' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='drr_logical_size' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='drr_toguid' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='drr_checksumtype' type-id='b96825af' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='328'> - <var-decl name='drr_flags' type-id='b96825af' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='336'> - <var-decl name='drr_compressiontype' type-id='b96825af' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='344'> - <var-decl name='drr_pad2' type-id='0f4ddd0b' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='384'> - <var-decl name='drr_key' type-id='67f6d2cf' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='704'> - <var-decl name='drr_compressed_size' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='768'> - <var-decl name='drr_salt' type-id='13339fda' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='832'> - <var-decl name='drr_iv' type-id='fa8ef949' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='928'> - <var-decl name='drr_mac' type-id='fa9986a5' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='drr_free' size-in-bits='256' is-struct='yes' visibility='default' id='c836cfd2'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='drr_object' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='drr_offset' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='drr_length' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='drr_toguid' type-id='9c313c2d' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='drr_write_byref' size-in-bits='832' is-struct='yes' visibility='default' id='e511cdce'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='drr_object' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='drr_offset' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='drr_length' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='drr_toguid' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='drr_refguid' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='drr_refobject' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='384'> - <var-decl name='drr_refoffset' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='448'> - <var-decl name='drr_checksumtype' type-id='b96825af' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='456'> - <var-decl name='drr_flags' type-id='b96825af' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='464'> - <var-decl name='drr_pad2' type-id='0f562bd0' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='512'> - <var-decl name='drr_key' type-id='67f6d2cf' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='drr_spill' size-in-bits='640' is-struct='yes' visibility='default' id='1e69a80a'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='drr_object' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='drr_length' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='drr_toguid' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='drr_flags' type-id='b96825af' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='200'> - <var-decl name='drr_compressiontype' type-id='b96825af' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='208'> - <var-decl name='drr_pad' type-id='0f562bd0' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='drr_compressed_size' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='drr_salt' type-id='13339fda' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='384'> - <var-decl name='drr_iv' type-id='fa8ef949' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='480'> - <var-decl name='drr_mac' type-id='fa9986a5' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='608'> - <var-decl name='drr_type' type-id='5c9d8906' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='drr_write_embedded' size-in-bits='384' is-struct='yes' visibility='default' id='98b1345e'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='drr_object' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='drr_offset' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='drr_length' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='drr_toguid' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='drr_compression' type-id='b96825af' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='264'> - <var-decl name='drr_etype' type-id='b96825af' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='272'> - <var-decl name='drr_pad' type-id='0f562bd0' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='drr_lsize' type-id='8f92235e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='352'> - <var-decl name='drr_psize' type-id='8f92235e' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='drr_object_range' size-in-bits='512' is-struct='yes' visibility='default' id='aba1f9e1'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='drr_firstobj' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='drr_numslots' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='drr_toguid' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='drr_salt' type-id='13339fda' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='drr_iv' type-id='fa8ef949' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='352'> - <var-decl name='drr_mac' type-id='fa9986a5' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='480'> - <var-decl name='drr_flags' type-id='b96825af' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='488'> - <var-decl name='drr_pad' type-id='d3490169' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='drr_redact' size-in-bits='256' is-struct='yes' visibility='default' id='50389039'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='drr_object' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='drr_offset' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='drr_length' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='drr_toguid' type-id='9c313c2d' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='drr_checksum' size-in-bits='2432' is-struct='yes' visibility='default' id='a5fe3647'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='drr_pad' type-id='8c2bcad1' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='2176'> - <var-decl name='drr_checksum' type-id='39730d0b' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='__cancel_jmp_buf_tag' size-in-bits='576' is-struct='yes' visibility='default' id='8901473c'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='__cancel_jmp_buf' type-id='379a1ab7' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='512'> - <var-decl name='__mask_was_saved' type-id='95e97e5e' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='__pthread_unwind_buf_t' size-in-bits='832' is-struct='yes' naming-typedef-id='4423cf7f' visibility='default' id='a0abc656'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='__cancel_jmp_buf' type-id='f5da478b' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='576'> - <var-decl name='__pad' type-id='209ef23f' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='__pthread_unwind_buf_t' type-id='a0abc656' id='4423cf7f'/> - <typedef-decl name='__jmp_buf' type-id='5d4efd44' id='379a1ab7'/> - <typedef-decl name='__clockid_t' type-id='95e97e5e' id='08f9a87a'/> - <typedef-decl name='__timer_t' type-id='eaa32e2f' id='df209b60'/> - <typedef-decl name='clockid_t' type-id='08f9a87a' id='a1c3b834'/> - <class-decl name='sigevent' size-in-bits='512' is-struct='yes' visibility='default' id='519bc206'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='sigev_value' type-id='eabacd01' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='sigev_signo' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='96'> - <var-decl name='sigev_notify' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='_sigev_un' type-id='ac5ab59a' visibility='default'/> - </data-member> - </class-decl> - <union-decl name='__anonymous_union__1' size-in-bits='384' is-anonymous='yes' visibility='default' id='ac5ab59a'> - <data-member access='public'> - <var-decl name='_pad' type-id='73b82f0f' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='_tid' type-id='3629bad8' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='_sigev_thread' type-id='e7f43f7c' visibility='default'/> - </data-member> - </union-decl> - <class-decl name='__anonymous_struct__' size-in-bits='128' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f7c'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='_function' type-id='5f147c28' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='_attribute' type-id='7347a39e' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='itimerspec' size-in-bits='256' is-struct='yes' visibility='default' id='acbdbcc6'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='it_interval' type-id='a9c79a1f' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='it_value' type-id='a9c79a1f' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='timer_t' type-id='df209b60' id='b07ae406'/> - <typedef-decl name='Byte' type-id='002ac4a6' id='efb9ba06'/> - <typedef-decl name='uLong' type-id='7359adad' id='5bbcce85'/> - <typedef-decl name='Bytef' type-id='efb9ba06' id='c1606520'/> - <typedef-decl name='uLongf' type-id='5bbcce85' id='4d39af59'/> - <pointer-type-def type-id='c1606520' size-in-bits='64' id='4c667223'/> - <pointer-type-def type-id='8901473c' size-in-bits='64' id='eb91b7ea'/> - <pointer-type-def type-id='4423cf7f' size-in-bits='64' id='ba7c727c'/> - <pointer-type-def type-id='b9c97942' size-in-bits='64' id='bbf06c47'/> - <qualified-type-def type-id='bbf06c47' restrict='yes' id='65e6ec45'/> - <qualified-type-def type-id='c1606520' const='yes' id='a6124a50'/> - <pointer-type-def type-id='a6124a50' size-in-bits='64' id='e8cb3e0e'/> - <qualified-type-def type-id='b9c97942' const='yes' id='191f6b72'/> - <pointer-type-def type-id='191f6b72' size-in-bits='64' id='e475fb88'/> - <qualified-type-def type-id='e475fb88' restrict='yes' id='5a8729d0'/> - <qualified-type-def type-id='781a52d7' const='yes' id='413ab2b8'/> - <pointer-type-def type-id='413ab2b8' size-in-bits='64' id='41671bd6'/> - <qualified-type-def type-id='acbdbcc6' const='yes' id='4ba62af7'/> - <pointer-type-def type-id='4ba62af7' size-in-bits='64' id='f39579e7'/> - <qualified-type-def type-id='f39579e7' restrict='yes' id='9b23e165'/> - <pointer-type-def type-id='c70fa2e8' size-in-bits='64' id='2e711a2a'/> - <pointer-type-def type-id='3ff5601b' size-in-bits='64' id='4aafb922'/> - <pointer-type-def type-id='acbdbcc6' size-in-bits='64' id='116842ac'/> - <qualified-type-def type-id='116842ac' restrict='yes' id='3d3c4cf4'/> - <pointer-type-def type-id='9e59d1d4' size-in-bits='64' id='4ea84b4f'/> - <pointer-type-def type-id='945467e6' size-in-bits='64' id='8def7735'/> - <pointer-type-def type-id='519bc206' size-in-bits='64' id='ef2f159c'/> - <qualified-type-def type-id='ef2f159c' restrict='yes' id='de0eb5a4'/> - <pointer-type-def type-id='3d3ffb69' size-in-bits='64' id='72a26210'/> - <pointer-type-def type-id='c9d12d66' size-in-bits='64' id='b2eb2c3f'/> - <pointer-type-def type-id='b07ae406' size-in-bits='64' id='36e89359'/> - <qualified-type-def type-id='36e89359' restrict='yes' id='de98c2bb'/> - <pointer-type-def type-id='a9c79a1f' size-in-bits='64' id='3d83ba87'/> - <pointer-type-def type-id='4d39af59' size-in-bits='64' id='60db3356'/> - <pointer-type-def type-id='f1abb096' size-in-bits='64' id='5f147c28'/> - <pointer-type-def type-id='39730d0b' size-in-bits='64' id='c24fc2ee'/> - <function-decl name='nvlist_print' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='822cd80b'/> - <parameter type-id='5ce45b60'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zfs_get_pool_handle' mangled-name='zfs_get_pool_handle' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_get_pool_handle'> - <parameter type-id='fcd57163'/> - <return type-id='4c81de99'/> - </function-decl> - <function-decl name='lzc_send_wrapper' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='2e711a2a'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='eaa32e2f'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_send_redacted' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='bfbd3c8e'/> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_send_resume_redacted' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='bfbd3c8e'/> - <parameter type-id='9c313c2d'/> - <parameter type-id='9c313c2d'/> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_receive_with_cmdprops' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='5ce45b60'/> - <parameter type-id='5ce45b60'/> - <parameter type-id='ae3e8ca6'/> - <parameter type-id='3502e3ff'/> - <parameter type-id='80f4b756'/> - <parameter type-id='c19b74c3'/> - <parameter type-id='c19b74c3'/> - <parameter type-id='c19b74c3'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='41671bd6'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='5d6479ae'/> - <parameter type-id='5d6479ae'/> - <parameter type-id='5d6479ae'/> - <parameter type-id='857bb57e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_receive_with_heal' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='5ce45b60'/> - <parameter type-id='5ce45b60'/> - <parameter type-id='ae3e8ca6'/> - <parameter type-id='3502e3ff'/> - <parameter type-id='80f4b756'/> - <parameter type-id='c19b74c3'/> - <parameter type-id='c19b74c3'/> - <parameter type-id='c19b74c3'/> - <parameter type-id='c19b74c3'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='41671bd6'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='5d6479ae'/> - <parameter type-id='5d6479ae'/> - <parameter type-id='5d6479ae'/> - <parameter type-id='857bb57e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_send_space' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <parameter type-id='bfbd3c8e'/> - <parameter type-id='5d6479ae'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_send_space_resume_redacted' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <parameter type-id='bfbd3c8e'/> - <parameter type-id='9c313c2d'/> - <parameter type-id='9c313c2d'/> - <parameter type-id='9c313c2d'/> - <parameter type-id='80f4b756'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='5d6479ae'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='lzc_rename' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_setproctitle' mangled-name='zfs_setproctitle' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_setproctitle'> - <parameter type-id='80f4b756'/> - <parameter is-variadic='yes'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='avl_insert' mangled-name='avl_insert' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_insert'> - <parameter type-id='a3681dea'/> - <parameter type-id='eaa32e2f'/> - <parameter type-id='fba6cb51'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='nvlist_add_boolean' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='nvlist_lookup_boolean' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='22cce67b'/> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='nvpair_value_int32' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='dace003f'/> - <parameter type-id='4aafb922'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='fnvlist_size' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <return type-id='b59d7dce'/> - </function-decl> - <function-decl name='fnvlist_merge' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='5ce45b60'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='fnvlist_remove' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='80f4b756'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='fnvlist_lookup_boolean_value' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='22cce67b'/> - <parameter type-id='80f4b756'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='fletcher_4_native_varsize' mangled-name='fletcher_4_native_varsize' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_4_native_varsize'> - <parameter type-id='eaa32e2f'/> - <parameter type-id='9c313c2d'/> - <parameter type-id='c24fc2ee'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='fletcher_4_incremental_native' mangled-name='fletcher_4_incremental_native' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_4_incremental_native'> - <parameter type-id='eaa32e2f'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='eaa32e2f'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='fletcher_4_incremental_byteswap' mangled-name='fletcher_4_incremental_byteswap' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_4_incremental_byteswap'> - <parameter type-id='eaa32e2f'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='eaa32e2f'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_exit' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='eaa32e2f'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='__pthread_register_cancel' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='ba7c727c'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='__pthread_unwind_next' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='ba7c727c'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='sigaddset' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='9e80f729'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='perror' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='strndup' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='b59d7dce'/> - <return type-id='26a90f95'/> - </function-decl> - <function-decl name='time' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b2eb2c3f'/> - <return type-id='c9d12d66'/> - </function-decl> - <function-decl name='clock_gettime' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='a1c3b834'/> - <parameter type-id='3d83ba87'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='timer_create' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='a1c3b834'/> - <parameter type-id='de0eb5a4'/> - <parameter type-id='de98c2bb'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='timer_delete' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b07ae406'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='timer_settime' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b07ae406'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='9b23e165'/> - <parameter type-id='3d3c4cf4'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='write' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <parameter type-id='eaa32e2f'/> - <parameter type-id='b59d7dce'/> - <return type-id='79a0948f'/> - </function-decl> - <function-decl name='pause' visibility='default' binding='global' size-in-bits='64'> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_sigmask' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <parameter type-id='5a8729d0'/> - <parameter type-id='65e6ec45'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='uncompress' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='4c667223'/> - <parameter type-id='60db3356'/> - <parameter type-id='e8cb3e0e'/> - <parameter type-id='5bbcce85'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='create_parents' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <parameter type-id='26a90f95'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_send_progress' mangled-name='zfs_send_progress' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_send_progress'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='95e97e5e' name='fd'/> - <parameter type-id='5d6479ae' name='bytes_written'/> - <parameter type-id='5d6479ae' name='blocks_visited'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_send_resume_token_to_nvlist' mangled-name='zfs_send_resume_token_to_nvlist' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_send_resume_token_to_nvlist'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='80f4b756' name='token'/> - <return type-id='5ce45b60'/> - </function-decl> - <function-decl name='zfs_send_resume' mangled-name='zfs_send_resume' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_send_resume'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='8def7735' name='flags'/> - <parameter type-id='95e97e5e' name='outfd'/> - <parameter type-id='80f4b756' name='resume_token'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_send_saved' mangled-name='zfs_send_saved' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_send_saved'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='8def7735' name='flags'/> - <parameter type-id='95e97e5e' name='outfd'/> - <parameter type-id='80f4b756' name='resume_token'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_send' mangled-name='zfs_send' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_send'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='80f4b756' name='fromsnap'/> - <parameter type-id='80f4b756' name='tosnap'/> - <parameter type-id='8def7735' name='flags'/> - <parameter type-id='95e97e5e' name='outfd'/> - <parameter type-id='72a26210' name='filter_func'/> - <parameter type-id='eaa32e2f' name='cb_arg'/> - <parameter type-id='857bb57e' name='debugnvp'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_send_one' mangled-name='zfs_send_one' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_send_one'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='80f4b756' name='from'/> - <parameter type-id='95e97e5e' name='fd'/> - <parameter type-id='8def7735' name='flags'/> - <parameter type-id='80f4b756' name='redactbook'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_receive' mangled-name='zfs_receive' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_receive'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='80f4b756' name='tosnap'/> - <parameter type-id='5ce45b60' name='props'/> - <parameter type-id='4ea84b4f' name='flags'/> - <parameter type-id='95e97e5e' name='infd'/> - <parameter type-id='a3681dea' name='stream_avl'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-type size-in-bits='64' id='c70fa2e8'> - <parameter type-id='95e97e5e'/> - <parameter type-id='eaa32e2f'/> - <return type-id='95e97e5e'/> - </function-type> - <function-type size-in-bits='64' id='d2a5e211'> - <parameter type-id='9200a744'/> - <parameter type-id='eaa32e2f'/> - <return type-id='c19b74c3'/> - </function-type> - <function-type size-in-bits='64' id='f1abb096'> - <parameter type-id='eabacd01'/> - <return type-id='48b5725f'/> - </function-type> - </abi-instr> - <abi-instr address-size='64' path='lib/libzfs/libzfs_status.c' language='LANG_C99'> - <function-decl name='zpool_import_status' mangled-name='zpool_import_status' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_import_status'> - <parameter type-id='5ce45b60' name='config'/> - <parameter type-id='7d3cd834' name='msgid'/> - <parameter type-id='cec6f2e4' name='errata'/> - <return type-id='d3dd6294'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='lib/libzfs/libzfs_util.c' language='LANG_C99'> - <class-decl name='__va_list_tag' size-in-bits='192' is-struct='yes' visibility='default' id='d5027220'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='gp_offset' type-id='f0981eeb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32'> - <var-decl name='fp_offset' type-id='f0981eeb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='overflow_arg_area' type-id='eaa32e2f' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='reg_save_area' type-id='eaa32e2f' visibility='default'/> - </data-member> - </class-decl> - <type-decl name='double' size-in-bits='64' id='a0eb0f08'/> - <array-type-def dimensions='1' type-id='95e97e5e' size-in-bits='192' id='e41bdf22'> - <subrange length='6' type-id='7359adad' id='52fa524b'/> - </array-type-def> - <array-type-def dimensions='1' type-id='19cefcee' size-in-bits='160' alignment-in-bits='32' id='3fcf57d2'> - <subrange length='5' type-id='7359adad' id='53010e10'/> - </array-type-def> - <enum-decl name='zfs_get_column_t' naming-typedef-id='19cefcee' id='223bdcaa'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='GET_COL_NONE' value='0'/> - <enumerator name='GET_COL_NAME' value='1'/> - <enumerator name='GET_COL_PROPERTY' value='2'/> - <enumerator name='GET_COL_VALUE' value='3'/> - <enumerator name='GET_COL_RECVD' value='4'/> - <enumerator name='GET_COL_SOURCE' value='5'/> - </enum-decl> - <typedef-decl name='zfs_get_column_t' type-id='223bdcaa' id='19cefcee'/> - <class-decl name='vdev_cbdata' size-in-bits='192' is-struct='yes' visibility='default' id='b8006be8'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='cb_name_flags' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='cb_names' type-id='9b23c9ad' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='cb_names_count' type-id='f0981eeb' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='vdev_cbdata_t' type-id='b8006be8' id='a9679c94'/> - <class-decl name='zprop_get_cbdata' size-in-bits='960' is-struct='yes' visibility='default' id='f3d3c319'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='cb_sources' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32'> - <var-decl name='cb_columns' type-id='3fcf57d2' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='cb_colwidths' type-id='e41bdf22' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='384'> - <var-decl name='cb_scripted' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='416'> - <var-decl name='cb_literal' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='448'> - <var-decl name='cb_first' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='480'> - <var-decl name='cb_json' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='512'> - <var-decl name='cb_proplist' type-id='3a9b2288' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='576'> - <var-decl name='cb_type' type-id='2e45de5d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='640'> - <var-decl name='cb_vdevs' type-id='a9679c94' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='832'> - <var-decl name='cb_jsobj' type-id='5ce45b60' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='896'> - <var-decl name='cb_json_as_int' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='928'> - <var-decl name='cb_json_pool_key_guid' type-id='c19b74c3' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='zprop_get_cbdata_t' type-id='f3d3c319' id='f3d87113'/> - <typedef-decl name='zprop_func' type-id='2e711a2a' id='1ec3747a'/> - <enum-decl name='zprop_attr_t' naming-typedef-id='999701cc' id='77d05200'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='PROP_DEFAULT' value='0'/> - <enumerator name='PROP_READONLY' value='1'/> - <enumerator name='PROP_INHERIT' value='2'/> - <enumerator name='PROP_ONETIME' value='3'/> - <enumerator name='PROP_ONETIME_DEFAULT' value='4'/> - </enum-decl> - <typedef-decl name='zprop_attr_t' type-id='77d05200' id='999701cc'/> - <class-decl name='zfs_index' size-in-bits='128' is-struct='yes' visibility='default' id='87957af9'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='pi_name' type-id='80f4b756' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='pi_value' type-id='9c313c2d' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='zprop_index_t' type-id='87957af9' id='64636ce3'/> - <class-decl name='zprop_desc_t' size-in-bits='640' is-struct='yes' naming-typedef-id='ffa52b96' visibility='default' id='bbff5e4b'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='pd_name' type-id='80f4b756' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='pd_propnum' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='96'> - <var-decl name='pd_proptype' type-id='31429eff' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='pd_strdefault' type-id='80f4b756' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='pd_numdefault' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='pd_attr' type-id='999701cc' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='288'> - <var-decl name='pd_types' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='pd_values' type-id='80f4b756' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='384'> - <var-decl name='pd_colname' type-id='80f4b756' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='448'> - <var-decl name='pd_rightalign' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='449'> - <var-decl name='pd_visible' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='450'> - <var-decl name='pd_zfs_mod_supported' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='451'> - <var-decl name='pd_always_flex' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='512'> - <var-decl name='pd_table' type-id='c8bc397b' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='576'> - <var-decl name='pd_table_size' type-id='b59d7dce' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='zprop_desc_t' type-id='bbff5e4b' id='ffa52b96'/> - <class-decl name='extmnttab' size-in-bits='320' is-struct='yes' visibility='default' id='0c544dc0'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='mnt_special' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='mnt_mountp' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='mnt_fstype' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='mnt_mntopts' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='mnt_major' type-id='3502e3ff' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='288'> - <var-decl name='mnt_minor' type-id='3502e3ff' visibility='default'/> - </data-member> - </class-decl> - <pointer-type-def type-id='d5027220' size-in-bits='64' id='b7f2d5e6'/> - <qualified-type-def type-id='26a90f95' const='yes' id='57de658a'/> - <pointer-type-def type-id='57de658a' size-in-bits='64' id='f319fae0'/> - <pointer-type-def type-id='9b23c9ad' size-in-bits='64' id='c0563f85'/> - <qualified-type-def type-id='33f57a65' const='yes' id='21fd6035'/> - <pointer-type-def type-id='21fd6035' size-in-bits='64' id='a0de50cd'/> - <pointer-type-def type-id='a0de50cd' size-in-bits='64' id='24f95ba5'/> - <qualified-type-def type-id='64636ce3' const='yes' id='072f7953'/> - <pointer-type-def type-id='072f7953' size-in-bits='64' id='c8bc397b'/> - <pointer-type-def type-id='0c544dc0' size-in-bits='64' id='394fc496'/> - <pointer-type-def type-id='aca3bac8' size-in-bits='64' id='d33f11cb'/> - <qualified-type-def type-id='d33f11cb' restrict='yes' id='5c53ba29'/> - <pointer-type-def type-id='ffa52b96' size-in-bits='64' id='76c8174b'/> - <pointer-type-def type-id='f3d87113' size-in-bits='64' id='0d2a0670'/> - <function-decl name='nvlist_print_json' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='822cd80b'/> - <parameter type-id='5ce45b60'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_label_disk' mangled-name='zpool_label_disk' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_label_disk'> - <parameter type-id='b0382bb3'/> - <parameter type-id='4c81de99'/> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_version_kernel' mangled-name='zfs_version_kernel' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_version_kernel'> - <return type-id='26a90f95'/> - </function-decl> - <function-decl name='libzfs_core_init' visibility='default' binding='global' size-in-bits='64'> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='libzfs_core_fini' visibility='default' binding='global' size-in-bits='64'> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zfs_get_underlying_path' mangled-name='zfs_get_underlying_path' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_get_underlying_path'> - <parameter type-id='80f4b756'/> - <return type-id='26a90f95'/> - </function-decl> - <function-decl name='zpool_prop_unsupported' mangled-name='zpool_prop_unsupported' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_unsupported'> - <parameter type-id='80f4b756'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zpool_feature_init' mangled-name='zpool_feature_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_feature_init'> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='fletcher_4_init' mangled-name='fletcher_4_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_4_init'> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='fletcher_4_fini' mangled-name='fletcher_4_fini' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_4_fini'> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zfs_prop_init' mangled-name='zfs_prop_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_init'> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zfs_prop_get_table' mangled-name='zfs_prop_get_table' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_get_table'> - <return type-id='76c8174b'/> - </function-decl> - <function-decl name='zpool_prop_init' mangled-name='zpool_prop_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_init'> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zpool_prop_get_table' mangled-name='zpool_prop_get_table' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_get_table'> - <return type-id='76c8174b'/> - </function-decl> - <function-decl name='vdev_prop_init' mangled-name='vdev_prop_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_init'> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zprop_iter_common' mangled-name='zprop_iter_common' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_iter_common'> - <parameter type-id='1ec3747a'/> - <parameter type-id='eaa32e2f'/> - <parameter type-id='c19b74c3'/> - <parameter type-id='c19b74c3'/> - <parameter type-id='2e45de5d'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zprop_name_to_prop' mangled-name='zprop_name_to_prop' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_name_to_prop'> - <parameter type-id='80f4b756'/> - <parameter type-id='2e45de5d'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zprop_string_to_index' mangled-name='zprop_string_to_index' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_string_to_index'> - <parameter type-id='95e97e5e'/> - <parameter type-id='80f4b756'/> - <parameter type-id='5d6479ae'/> - <parameter type-id='2e45de5d'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zprop_values' mangled-name='zprop_values' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_values'> - <parameter type-id='95e97e5e'/> - <parameter type-id='2e45de5d'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='zprop_width' mangled-name='zprop_width' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_width'> - <parameter type-id='95e97e5e'/> - <parameter type-id='37e3bd22'/> - <parameter type-id='2e45de5d'/> - <return type-id='b59d7dce'/> - </function-decl> - <function-decl name='zprop_valid_for_type' mangled-name='zprop_valid_for_type' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_valid_for_type'> - <parameter type-id='95e97e5e'/> - <parameter type-id='2e45de5d'/> - <parameter type-id='c19b74c3'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='getextmntent' mangled-name='getextmntent' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getextmntent'> - <parameter type-id='80f4b756'/> - <parameter type-id='394fc496'/> - <parameter type-id='62f7a03d'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='__ctype_toupper_loc' visibility='default' binding='global' size-in-bits='64'> - <return type-id='24f95ba5'/> - </function-decl> - <function-decl name='dlclose' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='eaa32e2f'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='regcomp' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5c53ba29'/> - <parameter type-id='9d26089a'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='regfree' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='d33f11cb'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='putc' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <parameter type-id='822cd80b'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='puts' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='strtod' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='9d26089a'/> - <parameter type-id='8c85230f'/> - <return type-id='a0eb0f08'/> - </function-decl> - <function-decl name='realloc' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='eaa32e2f'/> - <parameter type-id='b59d7dce'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='exit' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='strspn' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <return type-id='b59d7dce'/> - </function-decl> - <function-decl name='strnlen' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='b59d7dce'/> - <return type-id='b59d7dce'/> - </function-decl> - <function-decl name='strncasecmp' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <parameter type-id='b59d7dce'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='access' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='dup2' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='execve' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='f319fae0'/> - <parameter type-id='f319fae0'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='execv' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='f319fae0'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='execvp' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='f319fae0'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='execvpe' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='f319fae0'/> - <parameter type-id='f319fae0'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='_exit' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='setpgid' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='3629bad8'/> - <parameter type-id='3629bad8'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='fork' visibility='default' binding='global' size-in-bits='64'> - <return type-id='3629bad8'/> - </function-decl> - <function-decl name='pow' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='a0eb0f08'/> - <parameter type-id='a0eb0f08'/> - <return type-id='a0eb0f08'/> - </function-decl> - <function-decl name='__vfprintf_chk' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='e75a27e9'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='9d26089a'/> - <parameter type-id='b7f2d5e6'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='__vasprintf_chk' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='8c85230f'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='9d26089a'/> - <parameter type-id='b7f2d5e6'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='waitpid' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='3629bad8'/> - <parameter type-id='7292109c'/> - <parameter type-id='95e97e5e'/> - <return type-id='3629bad8'/> - </function-decl> - <function-decl name='namespace_clear' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b0382bb3'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='libzfs_load_module' visibility='default' binding='global' size-in-bits='64'> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='libzfs_errno' mangled-name='libzfs_errno' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_errno'> - <parameter type-id='b0382bb3' name='hdl'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='libzfs_error_action' mangled-name='libzfs_error_action' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_error_action'> - <parameter type-id='b0382bb3' name='hdl'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='libzfs_error_description' mangled-name='libzfs_error_description' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_error_description'> - <parameter type-id='b0382bb3' name='hdl'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='libzfs_print_on_error' mangled-name='libzfs_print_on_error' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_print_on_error'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='c19b74c3' name='printerr'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='libzfs_run_process' mangled-name='libzfs_run_process' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_run_process'> - <parameter type-id='80f4b756' name='path'/> - <parameter type-id='9b23c9ad' name='argv'/> - <parameter type-id='95e97e5e' name='flags'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='libzfs_run_process_get_stdout' mangled-name='libzfs_run_process_get_stdout' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_run_process_get_stdout'> - <parameter type-id='80f4b756' name='path'/> - <parameter type-id='9b23c9ad' name='argv'/> - <parameter type-id='9b23c9ad' name='env'/> - <parameter type-id='c0563f85' name='lines'/> - <parameter type-id='7292109c' name='lines_cnt'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='libzfs_run_process_get_stdout_nopath' mangled-name='libzfs_run_process_get_stdout_nopath' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_run_process_get_stdout_nopath'> - <parameter type-id='80f4b756' name='path'/> - <parameter type-id='9b23c9ad' name='argv'/> - <parameter type-id='9b23c9ad' name='env'/> - <parameter type-id='c0563f85' name='lines'/> - <parameter type-id='7292109c' name='lines_cnt'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='libzfs_free_str_array' mangled-name='libzfs_free_str_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_free_str_array'> - <parameter type-id='9b23c9ad' name='strs'/> - <parameter type-id='95e97e5e' name='count'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='libzfs_init' mangled-name='libzfs_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_init'> - <return type-id='b0382bb3'/> - </function-decl> - <function-decl name='libzfs_fini' mangled-name='libzfs_fini' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_fini'> - <parameter type-id='b0382bb3' name='hdl'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zfs_path_to_zhandle' mangled-name='zfs_path_to_zhandle' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_path_to_zhandle'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='80f4b756' name='path'/> - <parameter type-id='2e45de5d' name='argtype'/> - <return type-id='9200a744'/> - </function-decl> - <function-decl name='zcmd_print_json' mangled-name='zcmd_print_json' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zcmd_print_json'> - <parameter type-id='5ce45b60' name='nvl'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zprop_nvlist_one_property' mangled-name='zprop_nvlist_one_property' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_nvlist_one_property'> - <parameter type-id='80f4b756' name='propname'/> - <parameter type-id='80f4b756' name='value'/> - <parameter type-id='a2256d42' name='sourcetype'/> - <parameter type-id='80f4b756' name='source'/> - <parameter type-id='80f4b756' name='recvd_value'/> - <parameter type-id='5ce45b60' name='nvl'/> - <parameter type-id='c19b74c3' name='as_int'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zprop_print_one_property' mangled-name='zprop_print_one_property' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_print_one_property'> - <parameter type-id='80f4b756' name='name'/> - <parameter type-id='0d2a0670' name='cbp'/> - <parameter type-id='80f4b756' name='propname'/> - <parameter type-id='80f4b756' name='value'/> - <parameter type-id='a2256d42' name='sourcetype'/> - <parameter type-id='80f4b756' name='source'/> - <parameter type-id='80f4b756' name='recvd_value'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zprop_collect_property' mangled-name='zprop_collect_property' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_collect_property'> - <parameter type-id='80f4b756' name='name'/> - <parameter type-id='0d2a0670' name='cbp'/> - <parameter type-id='80f4b756' name='propname'/> - <parameter type-id='80f4b756' name='value'/> - <parameter type-id='a2256d42' name='sourcetype'/> - <parameter type-id='80f4b756' name='source'/> - <parameter type-id='80f4b756' name='recvd_value'/> - <parameter type-id='5ce45b60' name='nvl'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zprop_get_list' mangled-name='zprop_get_list' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_get_list'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='26a90f95' name='props'/> - <parameter type-id='e4378506' name='listp'/> - <parameter type-id='2e45de5d' name='type'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zprop_free_list' mangled-name='zprop_free_list' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_free_list'> - <parameter type-id='3a9b2288' name='pl'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zprop_iter' mangled-name='zprop_iter' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_iter'> - <parameter type-id='1ec3747a' name='func'/> - <parameter type-id='eaa32e2f' name='cb'/> - <parameter type-id='c19b74c3' name='show_all'/> - <parameter type-id='c19b74c3' name='ordered'/> - <parameter type-id='2e45de5d' name='type'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_version_userland' mangled-name='zfs_version_userland' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_version_userland'> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='zfs_version_print' mangled-name='zfs_version_print' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_version_print'> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_version_nvlist' mangled-name='zfs_version_nvlist' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_version_nvlist'> - <return type-id='5ce45b60'/> - </function-decl> - <function-decl name='use_color' mangled-name='use_color' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='use_color'> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='printf_color' mangled-name='printf_color' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='printf_color'> - <parameter type-id='80f4b756' name='color'/> - <parameter type-id='80f4b756' name='format'/> - <parameter is-variadic='yes'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_vdev_script_alloc_env' mangled-name='zpool_vdev_script_alloc_env' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_script_alloc_env'> - <parameter type-id='80f4b756' name='pool_name'/> - <parameter type-id='80f4b756' name='vdev_path'/> - <parameter type-id='80f4b756' name='vdev_upath'/> - <parameter type-id='80f4b756' name='vdev_enc_sysfs_path'/> - <parameter type-id='80f4b756' name='opt_key'/> - <parameter type-id='80f4b756' name='opt_val'/> - <return type-id='9b23c9ad'/> - </function-decl> - <function-decl name='zpool_vdev_script_free_env' mangled-name='zpool_vdev_script_free_env' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_script_free_env'> - <parameter type-id='9b23c9ad' name='env'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zpool_prepare_disk' mangled-name='zpool_prepare_disk' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prepare_disk'> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='5ce45b60' name='vdev_nv'/> - <parameter type-id='80f4b756' name='prepare_str'/> - <parameter type-id='c0563f85' name='lines'/> - <parameter type-id='7292109c' name='lines_cnt'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_prepare_and_label_disk' mangled-name='zpool_prepare_and_label_disk' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prepare_and_label_disk'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='4c81de99' name='zhp'/> - <parameter type-id='80f4b756' name='name'/> - <parameter type-id='5ce45b60' name='vdev_nv'/> - <parameter type-id='80f4b756' name='prepare_str'/> - <parameter type-id='c0563f85' name='lines'/> - <parameter type-id='7292109c' name='lines_cnt'/> - <return type-id='95e97e5e'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='lib/libzfs/os/linux/libzfs_mount_os.c' language='LANG_C99'> - <pointer-type-def type-id='7359adad' size-in-bits='64' id='1d2c2b85'/> - <function-decl name='geteuid' visibility='default' binding='global' size-in-bits='64'> - <return type-id='cc5fcceb'/> - </function-decl> - <function-decl name='mount' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <parameter type-id='7359adad'/> - <parameter type-id='eaa32e2f'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='umount2' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_parse_mount_options' mangled-name='zfs_parse_mount_options' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_parse_mount_options'> - <parameter type-id='80f4b756' name='mntopts'/> - <parameter type-id='1d2c2b85' name='mntflags'/> - <parameter type-id='1d2c2b85' name='zfsflags'/> - <parameter type-id='95e97e5e' name='sloppy'/> - <parameter type-id='26a90f95' name='badopt'/> - <parameter type-id='26a90f95' name='mtabopt'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_adjust_mount_options' mangled-name='zfs_adjust_mount_options' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_adjust_mount_options'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='80f4b756' name='mntpoint'/> - <parameter type-id='26a90f95' name='mntopts'/> - <parameter type-id='26a90f95' name='mtabopt'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zfs_mount_delegation_check' mangled-name='zfs_mount_delegation_check' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_mount_delegation_check'> - <return type-id='95e97e5e'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='lib/libzfs/os/linux/libzfs_pool_os.c' language='LANG_C99'> - <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='288' id='16e6f2c6'> - <subrange length='36' type-id='7359adad' id='ae666bde'/> - </array-type-def> - <array-type-def dimensions='1' type-id='a65ae39c' size-in-bits='960' id='fa198beb'> - <subrange length='1' type-id='7359adad' id='52f813b4'/> - </array-type-def> - <array-type-def dimensions='1' type-id='3502e3ff' size-in-bits='384' id='dba89ba3'> - <subrange length='12' type-id='7359adad' id='84827bdc'/> - </array-type-def> - <array-type-def dimensions='1' type-id='3502e3ff' size-in-bits='256' id='01d84ed4'> - <subrange length='8' type-id='7359adad' id='56e0c0b1'/> - </array-type-def> - <class-decl name='dk_part' size-in-bits='960' is-struct='yes' visibility='default' id='a65ae39c'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='p_start' type-id='804dc465' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='p_size' type-id='804dc465' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='p_guid' type-id='214f32ea' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='p_tag' type-id='d908a348' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='272'> - <var-decl name='p_flag' type-id='d908a348' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='288'> - <var-decl name='p_name' type-id='16e6f2c6' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='576'> - <var-decl name='p_uguid' type-id='214f32ea' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='704'> - <var-decl name='p_resv' type-id='01d84ed4' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='dk_gpt' size-in-bits='1920' is-struct='yes' visibility='default' id='dd4a2e5a'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='efi_version' type-id='3502e3ff' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32'> - <var-decl name='efi_nparts' type-id='3502e3ff' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='efi_part_size' type-id='3502e3ff' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='96'> - <var-decl name='efi_lbasize' type-id='3502e3ff' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='efi_last_lba' type-id='804dc465' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='efi_first_u_lba' type-id='804dc465' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='efi_last_u_lba' type-id='804dc465' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='efi_disk_uguid' type-id='214f32ea' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='448'> - <var-decl name='efi_flags' type-id='3502e3ff' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='480'> - <var-decl name='efi_reserved1' type-id='3502e3ff' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='512'> - <var-decl name='efi_altern_lba' type-id='804dc465' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='576'> - <var-decl name='efi_reserved' type-id='dba89ba3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='960'> - <var-decl name='efi_parts' type-id='fa198beb' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='uuid' size-in-bits='128' is-struct='yes' visibility='default' id='214f32ea'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='time_low' type-id='8f92235e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32'> - <var-decl name='time_mid' type-id='149c6638' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='48'> - <var-decl name='time_hi_and_version' type-id='149c6638' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='clock_seq_hi_and_reserved' type-id='b96825af' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='72'> - <var-decl name='clock_seq_low' type-id='b96825af' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='80'> - <var-decl name='node_addr' type-id='0f562bd0' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='ushort_t' type-id='8efea9e5' id='d908a348'/> - <typedef-decl name='uint16_t' type-id='253c2d2a' id='149c6638'/> - <typedef-decl name='__uint16_t' type-id='8efea9e5' id='253c2d2a'/> - <pointer-type-def type-id='dd4a2e5a' size-in-bits='64' id='0d8119a8'/> - <pointer-type-def type-id='0d8119a8' size-in-bits='64' id='c43b27a6'/> - <function-decl name='zpool_label_disk_wait' mangled-name='zpool_label_disk_wait' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_label_disk_wait'> - <parameter type-id='80f4b756'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_append_partition' mangled-name='zfs_append_partition' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_append_partition'> - <parameter type-id='26a90f95'/> - <parameter type-id='b59d7dce'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='efi_alloc_and_init' mangled-name='efi_alloc_and_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='efi_alloc_and_init'> - <parameter type-id='95e97e5e'/> - <parameter type-id='8f92235e'/> - <parameter type-id='c43b27a6'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='efi_alloc_and_read' mangled-name='efi_alloc_and_read' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='efi_alloc_and_read'> - <parameter type-id='95e97e5e'/> - <parameter type-id='c43b27a6'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='efi_write' mangled-name='efi_write' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='efi_write'> - <parameter type-id='95e97e5e'/> - <parameter type-id='0d8119a8'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='efi_rescan' mangled-name='efi_rescan' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='efi_rescan'> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='efi_free' mangled-name='efi_free' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='efi_free'> - <parameter type-id='0d8119a8'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='efi_use_whole_disk' mangled-name='efi_use_whole_disk' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='efi_use_whole_disk'> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='rand' visibility='default' binding='global' size-in-bits='64'> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='fsync' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='lib/libzfs/os/linux/libzfs_util_os.c' language='LANG_C99'> - <typedef-decl name='nfds_t' type-id='7359adad' id='555eef66'/> - <class-decl name='pollfd' size-in-bits='64' is-struct='yes' visibility='default' id='b440e872'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='fd' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32'> - <var-decl name='events' type-id='a2185560' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='48'> - <var-decl name='revents' type-id='a2185560' visibility='default'/> - </data-member> - </class-decl> - <pointer-type-def type-id='b440e872' size-in-bits='64' id='3ac36db0'/> - <function-decl name='__poll_chk' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='3ac36db0'/> - <parameter type-id='555eef66'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='7359adad'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='inotify_init1' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='inotify_add_watch' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <parameter type-id='80f4b756'/> - <parameter type-id='8f92235e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='timerfd_create' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='08f9a87a'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='timerfd_settime' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='f39579e7'/> - <parameter type-id='116842ac'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='libzfs_error_init' mangled-name='libzfs_error_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_error_init'> - <parameter type-id='95e97e5e' name='error'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='zfs_userns' mangled-name='zfs_userns' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_userns'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='80f4b756' name='nspath'/> - <parameter type-id='95e97e5e' name='attach'/> - <return type-id='95e97e5e'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='lib/libzutil/os/linux/zutil_device_path_os.c' language='LANG_C99'> - <class-decl name='udev' is-struct='yes' visibility='default' is-declaration-only='yes' id='e4a7fb7f'/> - <class-decl name='udev_device' is-struct='yes' visibility='default' is-declaration-only='yes' id='640b33ca'/> - <pointer-type-def type-id='e4a7fb7f' size-in-bits='64' id='025eefe7'/> - <pointer-type-def type-id='640b33ca' size-in-bits='64' id='b32bae08'/> - <class-decl name='udev' is-struct='yes' visibility='default' is-declaration-only='yes' id='e4a7fb7f'/> - <class-decl name='udev_device' is-struct='yes' visibility='default' is-declaration-only='yes' id='640b33ca'/> - <function-decl name='udev_new' visibility='default' binding='global' size-in-bits='64'> - <return type-id='025eefe7'/> - </function-decl> - <function-decl name='udev_device_unref' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b32bae08'/> - <return type-id='b32bae08'/> - </function-decl> - <function-decl name='udev_device_new_from_subsystem_sysname' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='025eefe7'/> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <return type-id='b32bae08'/> - </function-decl> - <function-decl name='udev_device_get_property_value' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b32bae08'/> - <parameter type-id='80f4b756'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='__readlink_chk' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='9d26089a'/> - <parameter type-id='266fe297'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='b59d7dce'/> - <return type-id='79a0948f'/> - </function-decl> - <function-decl name='zfs_get_enclosure_sysfs_path' mangled-name='zfs_get_enclosure_sysfs_path' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_get_enclosure_sysfs_path'> - <parameter type-id='80f4b756' name='dev_name'/> - <return type-id='26a90f95'/> - </function-decl> - <function-decl name='zfs_dev_is_dm' mangled-name='zfs_dev_is_dm' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_dev_is_dm'> - <parameter type-id='80f4b756' name='dev_name'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zfs_dev_is_whole_disk' mangled-name='zfs_dev_is_whole_disk' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_dev_is_whole_disk'> - <parameter type-id='80f4b756' name='dev_name'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='is_mpath_whole_disk' mangled-name='is_mpath_whole_disk' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='is_mpath_whole_disk'> - <parameter type-id='80f4b756' name='path'/> - <return type-id='c19b74c3'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='lib/libzutil/os/linux/zutil_import_os.c' language='LANG_C99'> - <class-decl name='blkid_struct_cache' is-struct='yes' visibility='default' is-declaration-only='yes' id='09286066'/> - <class-decl name='blkid_struct_dev' is-struct='yes' visibility='default' is-declaration-only='yes' id='86223623'/> - <class-decl name='blkid_struct_dev_iterate' is-struct='yes' visibility='default' is-declaration-only='yes' id='d88420d6'/> - <class-decl name='udev_list_entry' is-struct='yes' visibility='default' is-declaration-only='yes' id='e7dbdca3'/> - <typedef-decl name='pool_vdev_iter_f' type-id='6c16a6c8' id='dff793e0'/> - <typedef-decl name='blkid_dev' type-id='8433f053' id='f47b023a'/> - <typedef-decl name='blkid_cache' type-id='940e3afc' id='0882dfdf'/> - <typedef-decl name='blkid_dev_iterate' type-id='b8fa2efc' id='f4760fa7'/> - <typedef-decl name='__useconds_t' type-id='f0981eeb' id='4e80d4b1'/> - <pointer-type-def type-id='0882dfdf' size-in-bits='64' id='2e3e7caa'/> - <pointer-type-def type-id='f47b023a' size-in-bits='64' id='d87f9b75'/> - <pointer-type-def type-id='09286066' size-in-bits='64' id='940e3afc'/> - <pointer-type-def type-id='86223623' size-in-bits='64' id='8433f053'/> - <pointer-type-def type-id='d88420d6' size-in-bits='64' id='b8fa2efc'/> - <pointer-type-def type-id='2ec2411e' size-in-bits='64' id='6c16a6c8'/> - <pointer-type-def type-id='e7dbdca3' size-in-bits='64' id='deabd0d3'/> - <class-decl name='blkid_struct_cache' is-struct='yes' visibility='default' is-declaration-only='yes' id='09286066'/> - <class-decl name='blkid_struct_dev' is-struct='yes' visibility='default' is-declaration-only='yes' id='86223623'/> - <class-decl name='blkid_struct_dev_iterate' is-struct='yes' visibility='default' is-declaration-only='yes' id='d88420d6'/> - <class-decl name='udev_list_entry' is-struct='yes' visibility='default' is-declaration-only='yes' id='e7dbdca3'/> - <function-decl name='for_each_vdev_in_nvlist' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <parameter type-id='dff793e0'/> - <parameter type-id='eaa32e2f'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='label_paths' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5507783b'/> - <parameter type-id='5ce45b60'/> - <parameter type-id='7d3cd834'/> - <parameter type-id='7d3cd834'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zutil_alloc' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5507783b'/> - <parameter type-id='b59d7dce'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='zutil_strdup' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5507783b'/> - <parameter type-id='80f4b756'/> - <return type-id='26a90f95'/> - </function-decl> - <function-decl name='slice_cache_compare' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='eaa32e2f'/> - <parameter type-id='eaa32e2f'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='blkid_put_cache' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='0882dfdf'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='blkid_get_cache' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='2e3e7caa'/> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='blkid_dev_devname' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='f47b023a'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='blkid_dev_iterate_begin' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='0882dfdf'/> - <return type-id='f4760fa7'/> - </function-decl> - <function-decl name='blkid_dev_set_search' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='f4760fa7'/> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='blkid_dev_next' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='f4760fa7'/> - <parameter type-id='d87f9b75'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='blkid_dev_iterate_end' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='f4760fa7'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='blkid_probe_all_new' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='0882dfdf'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='udev_unref' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='025eefe7'/> - <return type-id='025eefe7'/> - </function-decl> - <function-decl name='udev_list_entry_get_next' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='deabd0d3'/> - <return type-id='deabd0d3'/> - </function-decl> - <function-decl name='udev_list_entry_get_name' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='deabd0d3'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='udev_device_get_parent_with_subsystem_devtype' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b32bae08'/> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <return type-id='b32bae08'/> - </function-decl> - <function-decl name='udev_device_get_devlinks_list_entry' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='b32bae08'/> - <return type-id='deabd0d3'/> - </function-decl> - <function-decl name='sched_yield' visibility='default' binding='global' size-in-bits='64'> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='usleep' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='4e80d4b1'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_dev_flush' mangled-name='zfs_dev_flush' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_dev_flush'> - <parameter type-id='95e97e5e' name='fd'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_device_get_devid' mangled-name='zfs_device_get_devid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_device_get_devid'> - <parameter type-id='b32bae08' name='dev'/> - <parameter type-id='26a90f95' name='bufptr'/> - <parameter type-id='b59d7dce' name='buflen'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_device_get_physical' mangled-name='zfs_device_get_physical' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_device_get_physical'> - <parameter type-id='b32bae08' name='dev'/> - <parameter type-id='26a90f95' name='bufptr'/> - <parameter type-id='b59d7dce' name='buflen'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_disk_wait' mangled-name='zpool_disk_wait' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_disk_wait'> - <parameter type-id='80f4b756' name='path'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='update_vdev_config_dev_sysfs_path' mangled-name='update_vdev_config_dev_sysfs_path' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='update_vdev_config_dev_sysfs_path'> - <parameter type-id='5ce45b60' name='nv'/> - <parameter type-id='80f4b756' name='path'/> - <parameter type-id='80f4b756' name='key'/> - <return type-id='48b5725f'/> - </function-decl> - <function-type size-in-bits='64' id='2ec2411e'> - <parameter type-id='eaa32e2f'/> - <parameter type-id='5ce45b60'/> - <parameter type-id='eaa32e2f'/> - <return type-id='95e97e5e'/> - </function-type> - </abi-instr> - <abi-instr address-size='64' path='lib/libzutil/os/linux/zutil_setproctitle.c' language='LANG_C99'> - <function-decl name='warnx' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter is-variadic='yes'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='setenv' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <parameter type-id='95e97e5e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='clearenv' visibility='default' binding='global' size-in-bits='64'> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_setproctitle_init' mangled-name='zfs_setproctitle_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_setproctitle_init'> - <parameter type-id='95e97e5e' name='argc'/> - <parameter type-id='9b23c9ad' name='argv'/> - <parameter type-id='9b23c9ad' name='envp'/> - <return type-id='48b5725f'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='lib/libzutil/zutil_device_path.c' language='LANG_C99'> - <function-decl name='zpool_default_search_paths' mangled-name='zpool_default_search_paths' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_default_search_paths'> - <parameter type-id='78c01427'/> - <return type-id='13956559'/> - </function-decl> - <function-decl name='zfs_dirnamelen' mangled-name='zfs_dirnamelen' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_dirnamelen'> - <parameter type-id='80f4b756' name='path'/> - <return type-id='79a0948f'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='lib/libzutil/zutil_import.c' language='LANG_C99'> - <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='256' id='16dc656a'> - <subrange length='32' type-id='7359adad' id='ae5bde82'/> - </array-type-def> - <class-decl name='importargs' size-in-bits='512' is-struct='yes' visibility='default' id='7ac83801'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='path' type-id='9b23c9ad' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='paths' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='poolname' type-id='80f4b756' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='guid' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='cachefile' type-id='80f4b756' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='can_be_active' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='352'> - <var-decl name='scan' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='384'> - <var-decl name='policy' type-id='5ce45b60' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='448'> - <var-decl name='do_destroyed' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='480'> - <var-decl name='do_all' type-id='c19b74c3' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='importargs_t' type-id='7ac83801' id='7a842a6b'/> - <class-decl name='libpc_handle' size-in-bits='8448' is-struct='yes' visibility='default' id='7c8737f0'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='lpc_error' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32'> - <var-decl name='lpc_printerr' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='lpc_open_access_error' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='96'> - <var-decl name='lpc_desc_active' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='lpc_desc' type-id='b54ce520' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='8320'> - <var-decl name='lpc_ops' type-id='f095e320' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='8384'> - <var-decl name='lpc_lib_handle' type-id='eaa32e2f' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='libpc_handle_t' type-id='7c8737f0' id='8a70a786'/> - <class-decl name='aiocb' size-in-bits='1344' is-struct='yes' visibility='default' id='e4957c49'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='aio_fildes' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='32'> - <var-decl name='aio_lio_opcode' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='aio_reqprio' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='aio_buf' type-id='fe09dd29' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='aio_nbytes' type-id='b59d7dce' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='aio_sigevent' type-id='519bc206' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='768'> - <var-decl name='__next_prio' type-id='924bbc81' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='832'> - <var-decl name='__abs_prio' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='864'> - <var-decl name='__policy' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='896'> - <var-decl name='__error_code' type-id='95e97e5e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='960'> - <var-decl name='__return_value' type-id='41060289' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1024'> - <var-decl name='aio_offset' type-id='724e4de6' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='1088'> - <var-decl name='__glibc_reserved' type-id='16dc656a' visibility='default'/> - </data-member> - </class-decl> - <pointer-type-def type-id='e4957c49' size-in-bits='64' id='924bbc81'/> - <qualified-type-def type-id='924bbc81' const='yes' id='5499dcde'/> - <pointer-type-def type-id='5499dcde' size-in-bits='64' id='2236d41c'/> - <qualified-type-def type-id='2236d41c' restrict='yes' id='31488924'/> - <pointer-type-def type-id='a3681dea' size-in-bits='64' id='fce6d540'/> - <qualified-type-def type-id='e4957c49' const='yes' id='fced9da2'/> - <pointer-type-def type-id='fced9da2' size-in-bits='64' id='b20efd18'/> - <pointer-type-def type-id='7a842a6b' size-in-bits='64' id='07ee4a58'/> - <pointer-type-def type-id='8a70a786' size-in-bits='64' id='5507783b'/> - <pointer-type-def type-id='b1e62775' size-in-bits='64' id='f095e320'/> - <qualified-type-def type-id='48b5725f' volatile='yes' id='b0b3cbf9'/> - <pointer-type-def type-id='b0b3cbf9' size-in-bits='64' id='fe09dd29'/> - <function-decl name='update_vdev_config_dev_strs' mangled-name='update_vdev_config_dev_strs' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='update_vdev_config_dev_strs'> - <parameter type-id='5ce45b60'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='update_vdevs_config_dev_sysfs_path' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5ce45b60'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='spl_pagesize' mangled-name='spl_pagesize' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='spl_pagesize'> - <return type-id='b59d7dce'/> - </function-decl> - <function-decl name='posix_memalign' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='63e171df'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='b59d7dce'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='sysconf' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='95e97e5e'/> - <return type-id='bd54fe1a'/> - </function-decl> - <function-decl name='libpc_error_description' mangled-name='libpc_error_description' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libpc_error_description'> - <parameter type-id='5507783b' name='hdl'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='zpool_search_import' mangled-name='zpool_search_import' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_search_import'> - <parameter type-id='5507783b' name='hdl'/> - <parameter type-id='07ee4a58' name='import'/> - <return type-id='5ce45b60'/> - </function-decl> - <function-decl name='zpool_find_config' mangled-name='zpool_find_config' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_find_config'> - <parameter type-id='5507783b' name='hdl'/> - <parameter type-id='80f4b756' name='target'/> - <parameter type-id='857bb57e' name='configp'/> - <parameter type-id='07ee4a58' name='args'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_find_import_blkid' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='5507783b'/> - <parameter type-id='18c91f9e'/> - <parameter type-id='fce6d540'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_open_func' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='eaa32e2f'/> - <return type-id='48b5725f'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='lib/libzutil/zutil_nicenum.c' language='LANG_C99'> - <type-decl name='long double' size-in-bits='128' id='e095c704'/> - <enum-decl name='zfs_nicenum_format' id='29cf1969'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='ZFS_NICENUM_1024' value='0'/> - <enumerator name='ZFS_NICENUM_BYTES' value='1'/> - <enumerator name='ZFS_NICENUM_TIME' value='2'/> - <enumerator name='ZFS_NICENUM_RAW' value='3'/> - <enumerator name='ZFS_NICENUM_RAWTIME' value='4'/> - </enum-decl> - <function-decl name='powl' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='e095c704'/> - <parameter type-id='e095c704'/> - <return type-id='e095c704'/> - </function-decl> - <function-decl name='floor' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='a0eb0f08'/> - <return type-id='a0eb0f08'/> - </function-decl> - <function-decl name='zfs_isnumber' mangled-name='zfs_isnumber' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_isnumber'> - <parameter type-id='80f4b756' name='str'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zfs_nicenum_format' mangled-name='zfs_nicenum_format' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_nicenum_format'> - <parameter type-id='9c313c2d' name='num'/> - <parameter type-id='26a90f95' name='buf'/> - <parameter type-id='b59d7dce' name='buflen'/> - <parameter type-id='29cf1969' name='format'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zfs_nicetime' mangled-name='zfs_nicetime' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_nicetime'> - <parameter type-id='9c313c2d' name='num'/> - <parameter type-id='26a90f95' name='buf'/> - <parameter type-id='b59d7dce' name='buflen'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zfs_niceraw' mangled-name='zfs_niceraw' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_niceraw'> - <parameter type-id='9c313c2d' name='num'/> - <parameter type-id='26a90f95' name='buf'/> - <parameter type-id='b59d7dce' name='buflen'/> - <return type-id='48b5725f'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='lib/libzutil/zutil_pool.c' language='LANG_C99'> - <array-type-def dimensions='1' type-id='853fd5dc' size-in-bits='32768' id='b505fc2f'> - <subrange length='64' type-id='7359adad' id='b10be967'/> - </array-type-def> - <type-decl name='float' size-in-bits='32' id='a6c45d85'/> - <class-decl name='ddt_stat' size-in-bits='512' is-struct='yes' visibility='default' id='65242dfe'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='dds_blocks' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='dds_lsize' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='dds_psize' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='dds_dsize' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='dds_ref_blocks' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='dds_ref_lsize' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='384'> - <var-decl name='dds_ref_psize' type-id='9c313c2d' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='448'> - <var-decl name='dds_ref_dsize' type-id='9c313c2d' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='ddt_stat_t' type-id='65242dfe' id='853fd5dc'/> - <class-decl name='ddt_histogram' size-in-bits='32768' is-struct='yes' visibility='default' id='bc2b3086'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='ddh_stat' type-id='b505fc2f' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='ddt_histogram_t' type-id='bc2b3086' id='2d7fe832'/> - <qualified-type-def type-id='2d7fe832' const='yes' id='ec92d602'/> - <pointer-type-def type-id='ec92d602' size-in-bits='64' id='932720f8'/> - <qualified-type-def type-id='853fd5dc' const='yes' id='764c298c'/> - <pointer-type-def type-id='764c298c' size-in-bits='64' id='dfe59052'/> - <qualified-type-def type-id='a9c79a1f' const='yes' id='cd087e36'/> - <pointer-type-def type-id='cd087e36' size-in-bits='64' id='e05e8614'/> - <function-decl name='nanosleep' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='e05e8614'/> - <parameter type-id='3d83ba87'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_dump_ddt' mangled-name='zpool_dump_ddt' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_dump_ddt'> - <parameter type-id='dfe59052' name='dds_total'/> - <parameter type-id='932720f8' name='ddh'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='fsleep' mangled-name='fsleep' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fsleep'> - <parameter type-id='a6c45d85' name='sec'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zpool_getenv_int' mangled-name='zpool_getenv_int' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_getenv_int'> - <parameter type-id='80f4b756' name='env'/> - <parameter type-id='95e97e5e' name='default_val'/> - <return type-id='95e97e5e'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='module/avl/avl.c' language='LANG_C99'> - <function-decl name='avl_last' mangled-name='avl_last' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_last'> - <parameter type-id='a3681dea' name='tree'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='avl_nearest' mangled-name='avl_nearest' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_nearest'> - <parameter type-id='a3681dea' name='tree'/> - <parameter type-id='fba6cb51' name='where'/> - <parameter type-id='95e97e5e' name='direction'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='avl_insert_here' mangled-name='avl_insert_here' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_insert_here'> - <parameter type-id='a3681dea' name='tree'/> - <parameter type-id='eaa32e2f' name='new_data'/> - <parameter type-id='eaa32e2f' name='here'/> - <parameter type-id='95e97e5e' name='direction'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='avl_update_lt' mangled-name='avl_update_lt' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_update_lt'> - <parameter type-id='a3681dea' name='t'/> - <parameter type-id='eaa32e2f' name='obj'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='avl_update_gt' mangled-name='avl_update_gt' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_update_gt'> - <parameter type-id='a3681dea' name='t'/> - <parameter type-id='eaa32e2f' name='obj'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='avl_update' mangled-name='avl_update' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_update'> - <parameter type-id='a3681dea' name='t'/> - <parameter type-id='eaa32e2f' name='obj'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='avl_swap' mangled-name='avl_swap' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_swap'> - <parameter type-id='a3681dea' name='tree1'/> - <parameter type-id='a3681dea' name='tree2'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='avl_is_empty' mangled-name='avl_is_empty' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_is_empty'> - <parameter type-id='a3681dea' name='tree'/> - <return type-id='c19b74c3'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='module/zcommon/cityhash.c' language='LANG_C99'> - <function-decl name='cityhash1' mangled-name='cityhash1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='cityhash1'> - <parameter type-id='9c313c2d' name='w'/> - <return type-id='9c313c2d'/> - </function-decl> - <function-decl name='cityhash2' mangled-name='cityhash2' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='cityhash2'> - <parameter type-id='9c313c2d' name='w1'/> - <parameter type-id='9c313c2d' name='w2'/> - <return type-id='9c313c2d'/> - </function-decl> - <function-decl name='cityhash3' mangled-name='cityhash3' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='cityhash3'> - <parameter type-id='9c313c2d' name='w1'/> - <parameter type-id='9c313c2d' name='w2'/> - <parameter type-id='9c313c2d' name='w3'/> - <return type-id='9c313c2d'/> - </function-decl> - <function-decl name='cityhash4' mangled-name='cityhash4' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='cityhash4'> - <parameter type-id='9c313c2d' name='w1'/> - <parameter type-id='9c313c2d' name='w2'/> - <parameter type-id='9c313c2d' name='w3'/> - <parameter type-id='9c313c2d' name='w4'/> - <return type-id='9c313c2d'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='module/zcommon/zfeature_common.c' language='LANG_C99'> - <array-type-def dimensions='1' type-id='83f29ca2' size-in-bits='21056' id='fd43354e'> - <subrange length='47' type-id='7359adad' id='8f8900fe'/> - </array-type-def> - <enum-decl name='zfeature_flags' id='6db816a4'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='ZFEATURE_FLAG_READONLY_COMPAT' value='1'/> - <enumerator name='ZFEATURE_FLAG_MOS' value='2'/> - <enumerator name='ZFEATURE_FLAG_ACTIVATE_ON_ENABLE' value='4'/> - <enumerator name='ZFEATURE_FLAG_PER_DATASET' value='8'/> - <enumerator name='ZFEATURE_FLAG_NO_UPGRADE' value='16'/> - </enum-decl> - <typedef-decl name='zfeature_flags_t' type-id='6db816a4' id='fc329033'/> - <enum-decl name='zfeature_type' id='c4fa2355'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='ZFEATURE_TYPE_BOOLEAN' value='0'/> - <enumerator name='ZFEATURE_TYPE_UINT64_ARRAY' value='1'/> - <enumerator name='ZFEATURE_NUM_TYPES' value='2'/> - </enum-decl> - <typedef-decl name='zfeature_type_t' type-id='c4fa2355' id='732d2bb2'/> - <class-decl name='zfeature_info' size-in-bits='448' is-struct='yes' visibility='default' id='1178d146'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='fi_feature' type-id='d6618c78' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='fi_uname' type-id='80f4b756' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='fi_guid' type-id='80f4b756' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='fi_desc' type-id='80f4b756' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='fi_flags' type-id='fc329033' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='288'> - <var-decl name='fi_zfs_mod_supported' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='fi_type' type-id='732d2bb2' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='384'> - <var-decl name='fi_depends' type-id='1acff326' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='zfeature_info_t' type-id='1178d146' id='83f29ca2'/> - <typedef-decl name='__free_fn_t' type-id='b7f9d8e6' id='3ff5e51e'/> - <class-decl name='dirent' size-in-bits='2240' is-struct='yes' visibility='default' id='611586a1'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='d_ino' type-id='71288a47' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='d_off' type-id='724e4de6' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='d_reclen' type-id='8efea9e5' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='144'> - <var-decl name='d_type' type-id='002ac4a6' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='152'> - <var-decl name='d_name' type-id='d1617432' visibility='default'/> - </data-member> - </class-decl> - <class-decl name='zfs_mod_supported_features' size-in-bits='128' is-struct='yes' visibility='default' id='3eee3342'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='tree' type-id='eaa32e2f' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='all_features' type-id='c19b74c3' visibility='default'/> - </data-member> - </class-decl> - <qualified-type-def type-id='d6618c78' const='yes' id='81a65028'/> - <pointer-type-def type-id='81a65028' size-in-bits='64' id='1acff326'/> - <qualified-type-def type-id='3eee3342' const='yes' id='0c1d5bbb'/> - <pointer-type-def type-id='0c1d5bbb' size-in-bits='64' id='a3372543'/> - <pointer-type-def type-id='611586a1' size-in-bits='64' id='2e243169'/> - <qualified-type-def type-id='eaa32e2f' const='yes' id='83be723c'/> - <pointer-type-def type-id='83be723c' size-in-bits='64' id='7acd98a2'/> - <var-decl name='spa_feature_table' type-id='fd43354e' mangled-name='spa_feature_table' visibility='default' elf-symbol-id='spa_feature_table'/> - <var-decl name='zfeature_checks_disable' type-id='c19b74c3' mangled-name='zfeature_checks_disable' visibility='default' elf-symbol-id='zfeature_checks_disable'/> - <function-decl name='opendir' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <return type-id='f09217ba'/> - </function-decl> - <function-decl name='tsearch' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='eaa32e2f'/> - <parameter type-id='63e171df'/> - <parameter type-id='aba7edd8'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='tfind' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='eaa32e2f'/> - <parameter type-id='7acd98a2'/> - <parameter type-id='aba7edd8'/> - <return type-id='eaa32e2f'/> - </function-decl> - <function-decl name='tdestroy' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='eaa32e2f'/> - <parameter type-id='3ff5e51e'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zfeature_is_valid_guid' mangled-name='zfeature_is_valid_guid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfeature_is_valid_guid'> - <parameter type-id='80f4b756' name='name'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zfeature_depends_on' mangled-name='zfeature_depends_on' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfeature_depends_on'> - <parameter type-id='d6618c78' name='fid'/> - <parameter type-id='d6618c78' name='check'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zfs_mod_supported' mangled-name='zfs_mod_supported' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_mod_supported'> - <parameter type-id='80f4b756' name='scope'/> - <parameter type-id='80f4b756' name='name'/> - <parameter type-id='a3372543' name='sfeatures'/> - <return type-id='c19b74c3'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='module/zcommon/zfs_comutil.c' language='LANG_C99'> - <array-type-def dimensions='1' type-id='b99c00c9' size-in-bits='2624' id='5ce15418'> - <subrange length='41' type-id='7359adad' id='cb834f44'/> - </array-type-def> - <pointer-type-def type-id='8f92235e' size-in-bits='64' id='90421557'/> - <function-decl name='nvpair_value_uint32' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='dace003f'/> - <parameter type-id='90421557'/> - <return type-id='95e97e5e'/> - </function-decl> - <var-decl name='zfs_history_event_names' type-id='5ce15418' mangled-name='zfs_history_event_names' visibility='default' elf-symbol-id='zfs_history_event_names'/> - <function-decl name='strpbrk' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <return type-id='26a90f95'/> - </function-decl> - <function-decl name='zfs_allocatable_devs' mangled-name='zfs_allocatable_devs' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_allocatable_devs'> - <parameter type-id='5ce45b60' name='nv'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zfs_special_devs' mangled-name='zfs_special_devs' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_special_devs'> - <parameter type-id='5ce45b60' name='nv'/> - <parameter type-id='80f4b756' name='type'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zfs_zpl_version_map' mangled-name='zfs_zpl_version_map' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_zpl_version_map'> - <parameter type-id='95e97e5e' name='spa_version'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_spa_version_map' mangled-name='zfs_spa_version_map' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_spa_version_map'> - <parameter type-id='95e97e5e' name='zpl_version'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_dataset_name_hidden' mangled-name='zfs_dataset_name_hidden' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_dataset_name_hidden'> - <parameter type-id='80f4b756' name='name'/> - <return type-id='c19b74c3'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='module/zcommon/zfs_deleg.c' language='LANG_C99'> - <array-type-def dimensions='1' type-id='fa1870fd' size-in-bits='4352' id='55f84f08'> - <subrange length='34' type-id='7359adad' id='6a6a7e00'/> - </array-type-def> - <array-type-def dimensions='1' type-id='fa1870fd' size-in-bits='infinite' id='7c00e69d'> - <subrange length='infinite' id='031f2035'/> - </array-type-def> - <enum-decl name='zfs_deleg_who_type_t' naming-typedef-id='36d4bd5a' id='b5fa5816'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='ZFS_DELEG_WHO_UNKNOWN' value='0'/> - <enumerator name='ZFS_DELEG_USER' value='117'/> - <enumerator name='ZFS_DELEG_USER_SETS' value='85'/> - <enumerator name='ZFS_DELEG_GROUP' value='103'/> - <enumerator name='ZFS_DELEG_GROUP_SETS' value='71'/> - <enumerator name='ZFS_DELEG_EVERYONE' value='101'/> - <enumerator name='ZFS_DELEG_EVERYONE_SETS' value='69'/> - <enumerator name='ZFS_DELEG_CREATE' value='99'/> - <enumerator name='ZFS_DELEG_CREATE_SETS' value='67'/> - <enumerator name='ZFS_DELEG_NAMED_SET' value='115'/> - <enumerator name='ZFS_DELEG_NAMED_SET_SETS' value='83'/> - </enum-decl> - <typedef-decl name='zfs_deleg_who_type_t' type-id='b5fa5816' id='36d4bd5a'/> - <enum-decl name='zfs_deleg_note_t' naming-typedef-id='4613c173' id='729d4547'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='ZFS_DELEG_NOTE_CREATE' value='0'/> - <enumerator name='ZFS_DELEG_NOTE_DESTROY' value='1'/> - <enumerator name='ZFS_DELEG_NOTE_SNAPSHOT' value='2'/> - <enumerator name='ZFS_DELEG_NOTE_ROLLBACK' value='3'/> - <enumerator name='ZFS_DELEG_NOTE_CLONE' value='4'/> - <enumerator name='ZFS_DELEG_NOTE_PROMOTE' value='5'/> - <enumerator name='ZFS_DELEG_NOTE_RENAME' value='6'/> - <enumerator name='ZFS_DELEG_NOTE_SEND' value='7'/> - <enumerator name='ZFS_DELEG_NOTE_SEND_RAW' value='8'/> - <enumerator name='ZFS_DELEG_NOTE_RECEIVE' value='9'/> - <enumerator name='ZFS_DELEG_NOTE_ALLOW' value='10'/> - <enumerator name='ZFS_DELEG_NOTE_USERPROP' value='11'/> - <enumerator name='ZFS_DELEG_NOTE_MOUNT' value='12'/> - <enumerator name='ZFS_DELEG_NOTE_SHARE' value='13'/> - <enumerator name='ZFS_DELEG_NOTE_USERQUOTA' value='14'/> - <enumerator name='ZFS_DELEG_NOTE_GROUPQUOTA' value='15'/> - <enumerator name='ZFS_DELEG_NOTE_USERUSED' value='16'/> - <enumerator name='ZFS_DELEG_NOTE_GROUPUSED' value='17'/> - <enumerator name='ZFS_DELEG_NOTE_USEROBJQUOTA' value='18'/> - <enumerator name='ZFS_DELEG_NOTE_GROUPOBJQUOTA' value='19'/> - <enumerator name='ZFS_DELEG_NOTE_USEROBJUSED' value='20'/> - <enumerator name='ZFS_DELEG_NOTE_GROUPOBJUSED' value='21'/> - <enumerator name='ZFS_DELEG_NOTE_HOLD' value='22'/> - <enumerator name='ZFS_DELEG_NOTE_RELEASE' value='23'/> - <enumerator name='ZFS_DELEG_NOTE_DIFF' value='24'/> - <enumerator name='ZFS_DELEG_NOTE_BOOKMARK' value='25'/> - <enumerator name='ZFS_DELEG_NOTE_LOAD_KEY' value='26'/> - <enumerator name='ZFS_DELEG_NOTE_CHANGE_KEY' value='27'/> - <enumerator name='ZFS_DELEG_NOTE_PROJECTUSED' value='28'/> - <enumerator name='ZFS_DELEG_NOTE_PROJECTQUOTA' value='29'/> - <enumerator name='ZFS_DELEG_NOTE_PROJECTOBJUSED' value='30'/> - <enumerator name='ZFS_DELEG_NOTE_PROJECTOBJQUOTA' value='31'/> - <enumerator name='ZFS_DELEG_NOTE_NONE' value='32'/> - </enum-decl> - <typedef-decl name='zfs_deleg_note_t' type-id='729d4547' id='4613c173'/> - <class-decl name='zfs_deleg_perm_tab' size-in-bits='128' is-struct='yes' visibility='default' id='5aa05c1f'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='z_perm' type-id='80f4b756' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='z_note' type-id='4613c173' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='zfs_deleg_perm_tab_t' type-id='5aa05c1f' id='f3f851ad'/> - <qualified-type-def type-id='f3f851ad' const='yes' id='fa1870fd'/> - <var-decl name='zfs_deleg_perm_tab' type-id='7c00e69d' mangled-name='zfs_deleg_perm_tab' visibility='default' elf-symbol-id='zfs_deleg_perm_tab'/> - <function-decl name='permset_namecheck' mangled-name='permset_namecheck' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='permset_namecheck'> - <parameter type-id='80f4b756'/> - <parameter type-id='053457bd'/> - <parameter type-id='26a90f95'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_prop_delegatable' mangled-name='zfs_prop_delegatable' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_delegatable'> - <parameter type-id='58603c44'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zfs_deleg_canonicalize_perm' mangled-name='zfs_deleg_canonicalize_perm' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_deleg_canonicalize_perm'> - <parameter type-id='80f4b756' name='perm'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='zfs_deleg_verify_nvlist' mangled-name='zfs_deleg_verify_nvlist' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_deleg_verify_nvlist'> - <parameter type-id='5ce45b60' name='nvp'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_deleg_whokey' mangled-name='zfs_deleg_whokey' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_deleg_whokey'> - <parameter type-id='26a90f95' name='attr'/> - <parameter type-id='36d4bd5a' name='type'/> - <parameter type-id='a84c031d' name='inheritchr'/> - <parameter type-id='eaa32e2f' name='data'/> - <return type-id='48b5725f'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='module/zcommon/zfs_fletcher.c' language='LANG_C99'> - <array-type-def dimensions='1' type-id='9c313c2d' size-in-bits='512' id='c5d13f42'> - <subrange length='8' type-id='7359adad' id='56e0c0b1'/> - </array-type-def> - <array-type-def dimensions='1' type-id='90dbb6d6' size-in-bits='2048' id='16582e69'> - <subrange length='4' type-id='7359adad' id='16fe7105'/> - </array-type-def> - <array-type-def dimensions='1' type-id='8240361c' size-in-bits='1024' id='481f90b1'> - <subrange length='4' type-id='7359adad' id='16fe7105'/> - </array-type-def> - <array-type-def dimensions='1' type-id='7c1ab40c' size-in-bits='512' id='cbd91ec1'> - <subrange length='4' type-id='7359adad' id='16fe7105'/> - </array-type-def> - <array-type-def dimensions='1' type-id='6d059eaa' size-in-bits='1024' id='729b6ebb'> - <subrange length='4' type-id='7359adad' id='16fe7105'/> - </array-type-def> - <enum-decl name='zio_byteorder_t' naming-typedef-id='595a65ec' id='fc861be0'> - <underlying-type type-id='9cac1fee'/> - <enumerator name='ZIO_CHECKSUM_NATIVE' value='0'/> - <enumerator name='ZIO_CHECKSUM_BYTESWAP' value='1'/> - </enum-decl> - <typedef-decl name='zio_byteorder_t' type-id='fc861be0' id='595a65ec'/> - <class-decl name='zio_abd_checksum_data' size-in-bits='256' is-struct='yes' visibility='default' id='4bf4b004'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='acd_byteorder' type-id='595a65ec' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='acd_ctx' type-id='0f7df99e' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='acd_zcp' type-id='c24fc2ee' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='acd_private' type-id='eaa32e2f' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='zio_abd_checksum_data_t' type-id='4bf4b004' id='74e39470'/> - <typedef-decl name='zio_abd_checksum_init_t' type-id='a5444274' id='029a8ebe'/> - <typedef-decl name='zio_abd_checksum_fini_t' type-id='a5444274' id='d6fd5c6c'/> - <typedef-decl name='zio_abd_checksum_iter_t' type-id='f4a1892e' id='cefa0f4a'/> - <class-decl name='zio_abd_checksum_func' size-in-bits='192' is-struct='yes' visibility='default' id='aa14691a'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='acf_init' type-id='0bcca125' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='acf_fini' type-id='bfe36153' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='acf_iter' type-id='1e276399' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='zio_abd_checksum_func_t' type-id='3f8e8d11' id='c2eb138a'/> - <class-decl name='zfs_fletcher_superscalar' size-in-bits='256' is-struct='yes' visibility='default' id='28efb250'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='v' type-id='85c64d26' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='zfs_fletcher_superscalar_t' type-id='28efb250' id='6d059eaa'/> - <class-decl name='zfs_fletcher_sse' size-in-bits='128' is-struct='yes' visibility='default' id='acd4019a'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='v' type-id='c1c22e6c' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='zfs_fletcher_sse_t' type-id='acd4019a' id='7c1ab40c'/> - <class-decl name='zfs_fletcher_avx' size-in-bits='256' is-struct='yes' visibility='default' id='8c208dfa'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='v' type-id='85c64d26' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='zfs_fletcher_avx_t' type-id='8c208dfa' id='8240361c'/> - <class-decl name='zfs_fletcher_avx512' size-in-bits='512' is-struct='yes' visibility='default' id='c6d0c382'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='v' type-id='c5d13f42' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='zfs_fletcher_avx512_t' type-id='c6d0c382' id='90dbb6d6'/> - <union-decl name='fletcher_4_ctx' size-in-bits='2048' visibility='default' id='1f951ade'> - <data-member access='public'> - <var-decl name='scalar' type-id='39730d0b' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='superscalar' type-id='729b6ebb' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='sse' type-id='cbd91ec1' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='avx' type-id='481f90b1' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='avx512' type-id='16582e69' visibility='default'/> - </data-member> - </union-decl> - <typedef-decl name='fletcher_4_ctx_t' type-id='1f951ade' id='4b675395'/> - <qualified-type-def type-id='aa14691a' const='yes' id='3f8e8d11'/> - <pointer-type-def type-id='4b675395' size-in-bits='64' id='0f7df99e'/> - <qualified-type-def type-id='8f92235e' volatile='yes' id='430e0681'/> - <pointer-type-def type-id='430e0681' size-in-bits='64' id='3a147f31'/> - <pointer-type-def type-id='74e39470' size-in-bits='64' id='eefe7427'/> - <pointer-type-def type-id='d6fd5c6c' size-in-bits='64' id='bfe36153'/> - <pointer-type-def type-id='029a8ebe' size-in-bits='64' id='0bcca125'/> - <pointer-type-def type-id='cefa0f4a' size-in-bits='64' id='1e276399'/> - <var-decl name='fletcher_4_abd_ops' type-id='c2eb138a' mangled-name='fletcher_4_abd_ops' visibility='default' elf-symbol-id='fletcher_4_abd_ops'/> - <function-decl name='atomic_swap_32' mangled-name='atomic_swap_32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_swap_32'> - <parameter type-id='3a147f31'/> - <parameter type-id='8f92235e'/> - <return type-id='8f92235e'/> - </function-decl> - <function-decl name='membar_producer' mangled-name='membar_producer' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='membar_producer'> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='fletcher_init' mangled-name='fletcher_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_init'> - <parameter type-id='c24fc2ee' name='zcp'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='fletcher_2_incremental_native' mangled-name='fletcher_2_incremental_native' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_2_incremental_native'> - <parameter type-id='eaa32e2f' name='buf'/> - <parameter type-id='b59d7dce' name='size'/> - <parameter type-id='eaa32e2f' name='data'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='fletcher_2_native' mangled-name='fletcher_2_native' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_2_native'> - <parameter type-id='eaa32e2f' name='buf'/> - <parameter type-id='9c313c2d' name='size'/> - <parameter type-id='eaa32e2f' name='ctx_template'/> - <parameter type-id='c24fc2ee' name='zcp'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='fletcher_2_incremental_byteswap' mangled-name='fletcher_2_incremental_byteswap' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_2_incremental_byteswap'> - <parameter type-id='eaa32e2f' name='buf'/> - <parameter type-id='b59d7dce' name='size'/> - <parameter type-id='eaa32e2f' name='data'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='fletcher_2_byteswap' mangled-name='fletcher_2_byteswap' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_2_byteswap'> - <parameter type-id='eaa32e2f' name='buf'/> - <parameter type-id='9c313c2d' name='size'/> - <parameter type-id='eaa32e2f' name='ctx_template'/> - <parameter type-id='c24fc2ee' name='zcp'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='fletcher_4_impl_set' mangled-name='fletcher_4_impl_set' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_4_impl_set'> - <parameter type-id='80f4b756' name='val'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='fletcher_4_native' mangled-name='fletcher_4_native' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_4_native'> - <parameter type-id='eaa32e2f' name='buf'/> - <parameter type-id='9c313c2d' name='size'/> - <parameter type-id='eaa32e2f' name='ctx_template'/> - <parameter type-id='c24fc2ee' name='zcp'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='fletcher_4_byteswap' mangled-name='fletcher_4_byteswap' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_4_byteswap'> - <parameter type-id='eaa32e2f' name='buf'/> - <parameter type-id='9c313c2d' name='size'/> - <parameter type-id='eaa32e2f' name='ctx_template'/> - <parameter type-id='c24fc2ee' name='zcp'/> - <return type-id='48b5725f'/> - </function-decl> - <function-type size-in-bits='64' id='f4a1892e'> - <parameter type-id='eaa32e2f'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='eaa32e2f'/> - <return type-id='95e97e5e'/> - </function-type> - <function-type size-in-bits='64' id='a5444274'> - <parameter type-id='eefe7427'/> - <return type-id='48b5725f'/> - </function-type> - </abi-instr> - <abi-instr address-size='64' path='module/zcommon/zfs_fletcher_avx512.c' language='LANG_C99'> - <typedef-decl name='fletcher_4_init_f' type-id='173aa527' id='b9ae1656'/> - <typedef-decl name='fletcher_4_fini_f' type-id='0ad5b8a8' id='c4c1f4fc'/> - <typedef-decl name='fletcher_4_compute_f' type-id='38147eff' id='ad1dc4cb'/> - <class-decl name='fletcher_4_func' size-in-bits='1024' is-struct='yes' visibility='default' id='57f479a0'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='init_native' type-id='b9ae1656' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='fini_native' type-id='c4c1f4fc' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='compute_native' type-id='ad1dc4cb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='init_byteswap' type-id='b9ae1656' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='fini_byteswap' type-id='c4c1f4fc' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='compute_byteswap' type-id='ad1dc4cb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='384'> - <var-decl name='valid' type-id='297d38bc' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='448'> - <var-decl name='uses_fpu' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='512'> - <var-decl name='name' type-id='80f4b756' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='fletcher_4_ops_t' type-id='57f479a0' id='eba91718'/> - <qualified-type-def type-id='eba91718' const='yes' id='9eeabdc8'/> - <pointer-type-def type-id='e9e61702' size-in-bits='64' id='297d38bc'/> - <pointer-type-def type-id='fe40251b' size-in-bits='64' id='173aa527'/> - <pointer-type-def type-id='17fb1f83' size-in-bits='64' id='38147eff'/> - <pointer-type-def type-id='fb39e25e' size-in-bits='64' id='0ad5b8a8'/> - <var-decl name='fletcher_4_avx512f_ops' type-id='9eeabdc8' mangled-name='fletcher_4_avx512f_ops' visibility='default' elf-symbol-id='fletcher_4_avx512f_ops'/> - <var-decl name='fletcher_4_avx512bw_ops' type-id='9eeabdc8' mangled-name='fletcher_4_avx512bw_ops' visibility='default' elf-symbol-id='fletcher_4_avx512bw_ops'/> - <function-type size-in-bits='64' id='e9e61702'> - <return type-id='c19b74c3'/> - </function-type> - <function-type size-in-bits='64' id='fe40251b'> - <parameter type-id='0f7df99e'/> - <return type-id='48b5725f'/> - </function-type> - <function-type size-in-bits='64' id='17fb1f83'> - <parameter type-id='0f7df99e'/> - <parameter type-id='eaa32e2f'/> - <parameter type-id='9c313c2d'/> - <return type-id='48b5725f'/> - </function-type> - <function-type size-in-bits='64' id='fb39e25e'> - <parameter type-id='0f7df99e'/> - <parameter type-id='c24fc2ee'/> - <return type-id='48b5725f'/> - </function-type> - </abi-instr> - <abi-instr address-size='64' path='module/zcommon/zfs_fletcher_intel.c' language='LANG_C99'> - <var-decl name='fletcher_4_avx2_ops' type-id='9eeabdc8' mangled-name='fletcher_4_avx2_ops' visibility='default' elf-symbol-id='fletcher_4_avx2_ops'/> - </abi-instr> - <abi-instr address-size='64' path='module/zcommon/zfs_fletcher_sse.c' language='LANG_C99'> - <var-decl name='fletcher_4_sse2_ops' type-id='9eeabdc8' mangled-name='fletcher_4_sse2_ops' visibility='default' elf-symbol-id='fletcher_4_sse2_ops'/> - <var-decl name='fletcher_4_ssse3_ops' type-id='9eeabdc8' mangled-name='fletcher_4_ssse3_ops' visibility='default' elf-symbol-id='fletcher_4_ssse3_ops'/> - </abi-instr> - <abi-instr address-size='64' path='module/zcommon/zfs_fletcher_superscalar.c' language='LANG_C99'> - <var-decl name='fletcher_4_superscalar_ops' type-id='9eeabdc8' mangled-name='fletcher_4_superscalar_ops' visibility='default' elf-symbol-id='fletcher_4_superscalar_ops'/> - </abi-instr> - <abi-instr address-size='64' path='module/zcommon/zfs_fletcher_superscalar4.c' language='LANG_C99'> - <var-decl name='fletcher_4_superscalar4_ops' type-id='9eeabdc8' mangled-name='fletcher_4_superscalar4_ops' visibility='default' elf-symbol-id='fletcher_4_superscalar4_ops'/> - </abi-instr> - <abi-instr address-size='64' path='module/zcommon/zfs_namecheck.c' language='LANG_C99'> - <var-decl name='zfs_max_dataset_nesting' type-id='95e97e5e' mangled-name='zfs_max_dataset_nesting' visibility='default' elf-symbol-id='zfs_max_dataset_nesting'/> - <function-decl name='get_dataset_depth' mangled-name='get_dataset_depth' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='get_dataset_depth'> - <parameter type-id='80f4b756' name='path'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_component_namecheck' mangled-name='zfs_component_namecheck' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_component_namecheck'> - <parameter type-id='80f4b756' name='path'/> - <parameter type-id='053457bd' name='why'/> - <parameter type-id='26a90f95' name='what'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='dataset_namecheck' mangled-name='dataset_namecheck' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='dataset_namecheck'> - <parameter type-id='80f4b756' name='path'/> - <parameter type-id='053457bd' name='why'/> - <parameter type-id='26a90f95' name='what'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='bookmark_namecheck' mangled-name='bookmark_namecheck' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='bookmark_namecheck'> - <parameter type-id='80f4b756' name='path'/> - <parameter type-id='053457bd' name='why'/> - <parameter type-id='26a90f95' name='what'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='snapshot_namecheck' mangled-name='snapshot_namecheck' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='snapshot_namecheck'> - <parameter type-id='80f4b756' name='path'/> - <parameter type-id='053457bd' name='why'/> - <parameter type-id='26a90f95' name='what'/> - <return type-id='95e97e5e'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='module/zcommon/zfs_prop.c' language='LANG_C99'> - <array-type-def dimensions='1' type-id='b99c00c9' size-in-bits='768' id='bcc77e38'> - <subrange length='12' type-id='7359adad' id='84827bdc'/> - </array-type-def> - <pointer-type-def type-id='3eee3342' size-in-bits='64' id='73f8e240'/> - <var-decl name='zfs_userquota_prop_prefixes' type-id='bcc77e38' mangled-name='zfs_userquota_prop_prefixes' visibility='default' elf-symbol-id='zfs_userquota_prop_prefixes'/> - <function-decl name='zfs_mod_list_supported' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <return type-id='73f8e240'/> - </function-decl> - <function-decl name='zfs_mod_list_supported_free' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='73f8e240'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zprop_register_impl' mangled-name='zprop_register_impl' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_register_impl'> - <parameter type-id='95e97e5e'/> - <parameter type-id='80f4b756'/> - <parameter type-id='31429eff'/> - <parameter type-id='9c313c2d'/> - <parameter type-id='80f4b756'/> - <parameter type-id='999701cc'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <parameter type-id='c19b74c3'/> - <parameter type-id='c19b74c3'/> - <parameter type-id='c19b74c3'/> - <parameter type-id='c8bc397b'/> - <parameter type-id='a3372543'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zprop_register_string' mangled-name='zprop_register_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_register_string'> - <parameter type-id='95e97e5e'/> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <parameter type-id='999701cc'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <parameter type-id='a3372543'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zprop_register_number' mangled-name='zprop_register_number' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_register_number'> - <parameter type-id='95e97e5e'/> - <parameter type-id='80f4b756'/> - <parameter type-id='9c313c2d'/> - <parameter type-id='999701cc'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <parameter type-id='c19b74c3'/> - <parameter type-id='a3372543'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zprop_register_index' mangled-name='zprop_register_index' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_register_index'> - <parameter type-id='95e97e5e'/> - <parameter type-id='80f4b756'/> - <parameter type-id='9c313c2d'/> - <parameter type-id='999701cc'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <parameter type-id='c8bc397b'/> - <parameter type-id='a3372543'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zprop_register_hidden' mangled-name='zprop_register_hidden' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_register_hidden'> - <parameter type-id='95e97e5e'/> - <parameter type-id='80f4b756'/> - <parameter type-id='31429eff'/> - <parameter type-id='999701cc'/> - <parameter type-id='95e97e5e'/> - <parameter type-id='80f4b756'/> - <parameter type-id='c19b74c3'/> - <parameter type-id='a3372543'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='zprop_index_to_string' mangled-name='zprop_index_to_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_index_to_string'> - <parameter type-id='95e97e5e'/> - <parameter type-id='9c313c2d'/> - <parameter type-id='7d3cd834'/> - <parameter type-id='2e45de5d'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zprop_random_value' mangled-name='zprop_random_value' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_random_value'> - <parameter type-id='95e97e5e'/> - <parameter type-id='9c313c2d'/> - <parameter type-id='2e45de5d'/> - <return type-id='9c313c2d'/> - </function-decl> - <function-decl name='zprop_valid_char' mangled-name='zprop_valid_char' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_valid_char'> - <parameter type-id='a84c031d'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_prop_string_to_index' mangled-name='zfs_prop_string_to_index' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_string_to_index'> - <parameter type-id='58603c44' name='prop'/> - <parameter type-id='80f4b756' name='string'/> - <parameter type-id='5d6479ae' name='index'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_prop_random_value' mangled-name='zfs_prop_random_value' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_random_value'> - <parameter type-id='58603c44' name='prop'/> - <parameter type-id='9c313c2d' name='seed'/> - <return type-id='9c313c2d'/> - </function-decl> - <function-decl name='zfs_prop_visible' mangled-name='zfs_prop_visible' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_visible'> - <parameter type-id='58603c44' name='prop'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='zfs_prop_values' mangled-name='zfs_prop_values' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_values'> - <parameter type-id='58603c44' name='prop'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='zfs_prop_is_string' mangled-name='zfs_prop_is_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_is_string'> - <parameter type-id='58603c44' name='prop'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_prop_column_name' mangled-name='zfs_prop_column_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_column_name'> - <parameter type-id='58603c44' name='prop'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='zfs_prop_align_right' mangled-name='zfs_prop_align_right' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_align_right'> - <parameter type-id='58603c44' name='prop'/> - <return type-id='c19b74c3'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='module/zcommon/zfs_valstr.c' language='LANG_C99'> - <function-decl name='zfs_valstr_zio_flag' mangled-name='zfs_valstr_zio_flag' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_valstr_zio_flag'> - <parameter type-id='9c313c2d' name='bits'/> - <parameter type-id='26a90f95' name='out'/> - <parameter type-id='b59d7dce' name='outlen'/> - <return type-id='b59d7dce'/> - </function-decl> - <function-decl name='zfs_valstr_zio_flag_bits' mangled-name='zfs_valstr_zio_flag_bits' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_valstr_zio_flag_bits'> - <parameter type-id='9c313c2d' name='bits'/> - <parameter type-id='26a90f95' name='out'/> - <parameter type-id='b59d7dce' name='outlen'/> - <return type-id='b59d7dce'/> - </function-decl> - <function-decl name='zfs_valstr_zio_flag_pairs' mangled-name='zfs_valstr_zio_flag_pairs' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_valstr_zio_flag_pairs'> - <parameter type-id='9c313c2d' name='bits'/> - <parameter type-id='26a90f95' name='out'/> - <parameter type-id='b59d7dce' name='outlen'/> - <return type-id='b59d7dce'/> - </function-decl> - <function-decl name='zfs_valstr_zio_stage' mangled-name='zfs_valstr_zio_stage' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_valstr_zio_stage'> - <parameter type-id='9c313c2d' name='bits'/> - <parameter type-id='26a90f95' name='out'/> - <parameter type-id='b59d7dce' name='outlen'/> - <return type-id='b59d7dce'/> - </function-decl> - <function-decl name='zfs_valstr_zio_stage_bits' mangled-name='zfs_valstr_zio_stage_bits' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_valstr_zio_stage_bits'> - <parameter type-id='9c313c2d' name='bits'/> - <parameter type-id='26a90f95' name='out'/> - <parameter type-id='b59d7dce' name='outlen'/> - <return type-id='b59d7dce'/> - </function-decl> - <function-decl name='zfs_valstr_zio_stage_pairs' mangled-name='zfs_valstr_zio_stage_pairs' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_valstr_zio_stage_pairs'> - <parameter type-id='9c313c2d' name='bits'/> - <parameter type-id='26a90f95' name='out'/> - <parameter type-id='b59d7dce' name='outlen'/> - <return type-id='b59d7dce'/> - </function-decl> - <function-decl name='zfs_valstr_zio_type' mangled-name='zfs_valstr_zio_type' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_valstr_zio_type'> - <parameter type-id='95e97e5e' name='v'/> - <parameter type-id='26a90f95' name='out'/> - <parameter type-id='b59d7dce' name='outlen'/> - <return type-id='b59d7dce'/> - </function-decl> - <function-decl name='zfs_valstr_zio_priority' mangled-name='zfs_valstr_zio_priority' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_valstr_zio_priority'> - <parameter type-id='95e97e5e' name='v'/> - <parameter type-id='26a90f95' name='out'/> - <parameter type-id='b59d7dce' name='outlen'/> - <return type-id='b59d7dce'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='module/zcommon/zpool_prop.c' language='LANG_C99'> - <function-decl name='zpool_prop_string_to_index' mangled-name='zpool_prop_string_to_index' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_string_to_index'> - <parameter type-id='5d0c23fb' name='prop'/> - <parameter type-id='80f4b756' name='string'/> - <parameter type-id='5d6479ae' name='index'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zpool_prop_random_value' mangled-name='zpool_prop_random_value' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_random_value'> - <parameter type-id='5d0c23fb' name='prop'/> - <parameter type-id='9c313c2d' name='seed'/> - <return type-id='9c313c2d'/> - </function-decl> - <function-decl name='zpool_prop_values' mangled-name='zpool_prop_values' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_values'> - <parameter type-id='5d0c23fb' name='prop'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='zpool_prop_column_name' mangled-name='zpool_prop_column_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_column_name'> - <parameter type-id='5d0c23fb' name='prop'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='zpool_prop_align_right' mangled-name='zpool_prop_align_right' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_align_right'> - <parameter type-id='5d0c23fb' name='prop'/> - <return type-id='c19b74c3'/> - </function-decl> - <function-decl name='vdev_prop_get_table' mangled-name='vdev_prop_get_table' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_get_table'> - <return type-id='76c8174b'/> - </function-decl> - <function-decl name='vdev_prop_string_to_index' mangled-name='vdev_prop_string_to_index' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_string_to_index'> - <parameter type-id='5aa5c90c' name='prop'/> - <parameter type-id='80f4b756' name='string'/> - <parameter type-id='5d6479ae' name='index'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='vdev_prop_random_value' mangled-name='vdev_prop_random_value' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_random_value'> - <parameter type-id='5aa5c90c' name='prop'/> - <parameter type-id='9c313c2d' name='seed'/> - <return type-id='9c313c2d'/> - </function-decl> - <function-decl name='vdev_prop_values' mangled-name='vdev_prop_values' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_values'> - <parameter type-id='5aa5c90c' name='prop'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='vdev_prop_column_name' mangled-name='vdev_prop_column_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_column_name'> - <parameter type-id='5aa5c90c' name='prop'/> - <return type-id='80f4b756'/> - </function-decl> - <function-decl name='vdev_prop_align_right' mangled-name='vdev_prop_align_right' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_align_right'> - <parameter type-id='5aa5c90c' name='prop'/> - <return type-id='c19b74c3'/> - </function-decl> - </abi-instr> - <abi-instr address-size='64' path='module/zcommon/zprop_common.c' language='LANG_C99'> - <function-decl name='__ctype_tolower_loc' visibility='default' binding='global' size-in-bits='64'> - <return type-id='24f95ba5'/> - </function-decl> - </abi-instr> -</abi-corpus> diff --git a/lib/libzfs/libzfs.pc.in b/lib/libzfs/libzfs.pc.in deleted file mode 100644 index afe5635ae633..000000000000 --- a/lib/libzfs/libzfs.pc.in +++ /dev/null @@ -1,14 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: libzfs -Description: LibZFS library -Version: @VERSION@ -URL: https://github.com/openzfs/zfs -Requires: libzfs_core -Requires.private: @LIBCRYPTO_PC@ @ZLIB_PC@ -Cflags: -I${includedir}/libzfs -I${includedir}/libspl -Libs: -L${libdir} -lzfs -lnvpair -Libs.private: -luutil -lm -pthread diff --git a/lib/libzfs/libzfs.suppr b/lib/libzfs/libzfs.suppr deleted file mode 100644 index d55b5b728116..000000000000 --- a/lib/libzfs/libzfs.suppr +++ /dev/null @@ -1,13 +0,0 @@ -[suppress_type] - name = FILE* - -[suppress_type] - type_kind = typedef - name = SHA256_CTX - -[suppress_type] - type_kind = typedef - name = SHA2_CTX - -[suppress_variable] - name = zfs_deleg_perm_tab diff --git a/lib/libzfs/libzfs_changelist.c b/lib/libzfs/libzfs_changelist.c deleted file mode 100644 index d290d949f4b2..000000000000 --- a/lib/libzfs/libzfs_changelist.c +++ /dev/null @@ -1,805 +0,0 @@ -// SPDX-License-Identifier: CDDL-1.0 -/* - * 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 - */ - -/* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - * Portions Copyright 2007 Ramprakash Jelari - * Copyright (c) 2014, 2020 by Delphix. All rights reserved. - * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com> - * Copyright (c) 2018 Datto Inc. - */ - -#include <libintl.h> -#include <libuutil.h> -#include <stddef.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <zone.h> - -#include <libzfs.h> - -#include "libzfs_impl.h" - -/* - * Structure to keep track of dataset state. Before changing the 'sharenfs' or - * 'mountpoint' property, we record whether the filesystem was previously - * mounted/shared. This prior state dictates whether we remount/reshare the - * dataset after the property has been changed. - * - * The interface consists of the following sequence of functions: - * - * changelist_gather() - * changelist_prefix() - * < change property > - * changelist_postfix() - * changelist_free() - * - * Other interfaces: - * - * changelist_remove() - remove a node from a gathered list - * changelist_rename() - renames all datasets appropriately when doing a rename - * changelist_unshare() - unshares all the nodes in a given changelist - * changelist_haszonedchild() - check if there is any child exported to - * a local zone - */ -typedef struct prop_changenode { - zfs_handle_t *cn_handle; - int cn_shared; - int cn_mounted; - int cn_zoned; - boolean_t cn_needpost; /* is postfix() needed? */ - uu_avl_node_t cn_treenode; -} prop_changenode_t; - -struct prop_changelist { - zfs_prop_t cl_prop; - zfs_prop_t cl_realprop; - zfs_prop_t cl_shareprop; /* used with sharenfs/sharesmb */ - uu_avl_pool_t *cl_pool; - uu_avl_t *cl_tree; - boolean_t cl_waslegacy; - boolean_t cl_allchildren; - boolean_t cl_alldependents; - int cl_mflags; /* Mount flags */ - int cl_gflags; /* Gather request flags */ - boolean_t cl_haszonedchild; -}; - -/* - * If the property is 'mountpoint', go through and unmount filesystems as - * necessary. We don't do the same for 'sharenfs', because we can just re-share - * with different options without interrupting service. We do handle 'sharesmb' - * since there may be old resource names that need to be removed. - */ -int -changelist_prefix(prop_changelist_t *clp) -{ - prop_changenode_t *cn; - uu_avl_walk_t *walk; - int ret = 0; - const enum sa_protocol smb[] = {SA_PROTOCOL_SMB, SA_NO_PROTOCOL}; - boolean_t commit_smb_shares = B_FALSE; - - if (clp->cl_prop != ZFS_PROP_MOUNTPOINT && - clp->cl_prop != ZFS_PROP_SHARESMB) - return (0); - - /* - * If CL_GATHER_DONT_UNMOUNT is set, don't want to unmount/unshare and - * later (re)mount/(re)share the filesystem in postfix phase, so we - * return from here. If filesystem is mounted or unmounted, leave it - * as it is. - */ - if (clp->cl_gflags & CL_GATHER_DONT_UNMOUNT) - return (0); - - if ((walk = uu_avl_walk_start(clp->cl_tree, UU_WALK_ROBUST)) == NULL) - return (-1); - - while ((cn = uu_avl_walk_next(walk)) != NULL) { - - /* if a previous loop failed, set the remaining to false */ - if (ret == -1) { - cn->cn_needpost = B_FALSE; - continue; - } - - /* - * If we are in the global zone, but this dataset is exported - * to a local zone, do nothing. - */ - if (getzoneid() == GLOBAL_ZONEID && cn->cn_zoned) - continue; - - if (!ZFS_IS_VOLUME(cn->cn_handle)) { - /* - * Do the property specific processing. - */ - switch (clp->cl_prop) { - case ZFS_PROP_MOUNTPOINT: - if (zfs_unmount(cn->cn_handle, NULL, - clp->cl_mflags) != 0) { - ret = -1; - cn->cn_needpost = B_FALSE; - } - break; - case ZFS_PROP_SHARESMB: - (void) zfs_unshare(cn->cn_handle, NULL, - smb); - commit_smb_shares = B_TRUE; - break; - - default: - break; - } - } - } - - if (commit_smb_shares) - zfs_commit_shares(smb); - uu_avl_walk_end(walk); - - if (ret == -1) - (void) changelist_postfix(clp); - - return (ret); -} - -/* - * If the property is 'mountpoint' or 'sharenfs', go through and remount and/or - * reshare the filesystems as necessary. In changelist_gather() we recorded - * whether the filesystem was previously shared or mounted. The action we take - * depends on the previous state, and whether the value was previously 'legacy'. - * For non-legacy properties, we always remount/reshare the filesystem, - * if CL_GATHER_DONT_UNMOUNT is not set. - */ -int -changelist_postfix(prop_changelist_t *clp) -{ - prop_changenode_t *cn; - uu_avl_walk_t *walk; - char shareopts[ZFS_MAXPROPLEN]; - boolean_t commit_smb_shares = B_FALSE; - boolean_t commit_nfs_shares = B_FALSE; - - /* - * If CL_GATHER_DONT_UNMOUNT is set, it means we don't want to (un)mount - * or (re/un)share the filesystem, so we return from here. If filesystem - * is mounted or unmounted, leave it as it is. - */ - if (clp->cl_gflags & CL_GATHER_DONT_UNMOUNT) - return (0); - - /* - * If we're changing the mountpoint, attempt to destroy the underlying - * mountpoint. All other datasets will have inherited from this dataset - * (in which case their mountpoints exist in the filesystem in the new - * location), or have explicit mountpoints set (in which case they won't - * be in the changelist). - */ - if ((cn = uu_avl_last(clp->cl_tree)) == NULL) - return (0); - - if (clp->cl_prop == ZFS_PROP_MOUNTPOINT && - !(clp->cl_gflags & CL_GATHER_DONT_UNMOUNT)) - remove_mountpoint(cn->cn_handle); - - /* - * We walk the datasets in reverse, because we want to mount any parent - * datasets before mounting the children. We walk all datasets even if - * there are errors. - */ - if ((walk = uu_avl_walk_start(clp->cl_tree, - UU_WALK_REVERSE | UU_WALK_ROBUST)) == NULL) - return (-1); - - while ((cn = uu_avl_walk_next(walk)) != NULL) { - - boolean_t sharenfs; - boolean_t sharesmb; - boolean_t mounted; - boolean_t needs_key; - - /* - * If we are in the global zone, but this dataset is exported - * to a local zone, do nothing. - */ - if (getzoneid() == GLOBAL_ZONEID && cn->cn_zoned) - continue; - - /* Only do post-processing if it's required */ - if (!cn->cn_needpost) - continue; - cn->cn_needpost = B_FALSE; - - zfs_refresh_properties(cn->cn_handle); - - if (ZFS_IS_VOLUME(cn->cn_handle)) - continue; - - /* - * Remount if previously mounted or mountpoint was legacy, - * or sharenfs or sharesmb property is set. - */ - sharenfs = ((zfs_prop_get(cn->cn_handle, ZFS_PROP_SHARENFS, - shareopts, sizeof (shareopts), NULL, NULL, 0, - B_FALSE) == 0) && (strcmp(shareopts, "off") != 0)); - - sharesmb = ((zfs_prop_get(cn->cn_handle, ZFS_PROP_SHARESMB, - shareopts, sizeof (shareopts), NULL, NULL, 0, - B_FALSE) == 0) && (strcmp(shareopts, "off") != 0)); - - needs_key = (zfs_prop_get_int(cn->cn_handle, - ZFS_PROP_KEYSTATUS) == ZFS_KEYSTATUS_UNAVAILABLE); - - mounted = zfs_is_mounted(cn->cn_handle, NULL); - - if (!mounted && !needs_key && (cn->cn_mounted || - (((clp->cl_prop == ZFS_PROP_MOUNTPOINT && - clp->cl_prop == clp->cl_realprop) || - sharenfs || sharesmb || clp->cl_waslegacy) && - (zfs_prop_get_int(cn->cn_handle, - ZFS_PROP_CANMOUNT) == ZFS_CANMOUNT_ON)))) { - - if (zfs_mount(cn->cn_handle, NULL, 0) == 0) - mounted = TRUE; - } - - /* - * If the file system is mounted we always re-share even - * if the filesystem is currently shared, so that we can - * adopt any new options. - */ - const enum sa_protocol nfs[] = - {SA_PROTOCOL_NFS, SA_NO_PROTOCOL}; - if (sharenfs && mounted) { - zfs_share(cn->cn_handle, nfs); - commit_nfs_shares = B_TRUE; - } else if (cn->cn_shared || clp->cl_waslegacy) { - zfs_unshare(cn->cn_handle, NULL, nfs); - commit_nfs_shares = B_TRUE; - } - const enum sa_protocol smb[] = - {SA_PROTOCOL_SMB, SA_NO_PROTOCOL}; - if (sharesmb && mounted) { - zfs_share(cn->cn_handle, smb); - commit_smb_shares = B_TRUE; - } else if (cn->cn_shared || clp->cl_waslegacy) { - zfs_unshare(cn->cn_handle, NULL, smb); - commit_smb_shares = B_TRUE; - } - } - - enum sa_protocol proto[SA_PROTOCOL_COUNT + 1], *p = proto; - if (commit_nfs_shares) - *p++ = SA_PROTOCOL_NFS; - if (commit_smb_shares) - *p++ = SA_PROTOCOL_SMB; - *p++ = SA_NO_PROTOCOL; - zfs_commit_shares(proto); - uu_avl_walk_end(walk); - - return (0); -} - -/* - * Is this "dataset" a child of "parent"? - */ -static boolean_t -isa_child_of(const char *dataset, const char *parent) -{ - int len; - - len = strlen(parent); - - if (strncmp(dataset, parent, len) == 0 && - (dataset[len] == '@' || dataset[len] == '/' || - dataset[len] == '\0')) - return (B_TRUE); - else - return (B_FALSE); - -} - -/* - * If we rename a filesystem, child filesystem handles are no longer valid - * since we identify each dataset by its name in the ZFS namespace. As a - * result, we have to go through and fix up all the names appropriately. We - * could do this automatically if libzfs kept track of all open handles, but - * this is a lot less work. - */ -void -changelist_rename(prop_changelist_t *clp, const char *src, const char *dst) -{ - prop_changenode_t *cn; - uu_avl_walk_t *walk; - char newname[ZFS_MAX_DATASET_NAME_LEN]; - - if ((walk = uu_avl_walk_start(clp->cl_tree, UU_WALK_ROBUST)) == NULL) - return; - - while ((cn = uu_avl_walk_next(walk)) != NULL) { - /* - * Do not rename a clone that's not in the source hierarchy. - */ - if (!isa_child_of(cn->cn_handle->zfs_name, src)) - continue; - - /* - * Destroy the previous mountpoint if needed. - */ - remove_mountpoint(cn->cn_handle); - - (void) strlcpy(newname, dst, sizeof (newname)); - (void) strlcat(newname, cn->cn_handle->zfs_name + strlen(src), - sizeof (newname)); - - (void) strlcpy(cn->cn_handle->zfs_name, newname, - sizeof (cn->cn_handle->zfs_name)); - } - - uu_avl_walk_end(walk); -} - -/* - * Given a gathered changelist for the 'sharenfs' or 'sharesmb' property, - * unshare all the datasets in the list. - */ -int -changelist_unshare(prop_changelist_t *clp, const enum sa_protocol *proto) -{ - prop_changenode_t *cn; - uu_avl_walk_t *walk; - int ret = 0; - - if (clp->cl_prop != ZFS_PROP_SHARENFS && - clp->cl_prop != ZFS_PROP_SHARESMB) - return (0); - - if ((walk = uu_avl_walk_start(clp->cl_tree, UU_WALK_ROBUST)) == NULL) - return (-1); - - while ((cn = uu_avl_walk_next(walk)) != NULL) { - if (zfs_unshare(cn->cn_handle, NULL, proto) != 0) - ret = -1; - } - - for (const enum sa_protocol *p = proto; *p != SA_NO_PROTOCOL; ++p) - sa_commit_shares(*p); - uu_avl_walk_end(walk); - - return (ret); -} - -/* - * Check if there is any child exported to a local zone in a given changelist. - * This information has already been recorded while gathering the changelist - * via changelist_gather(). - */ -int -changelist_haszonedchild(prop_changelist_t *clp) -{ - return (clp->cl_haszonedchild); -} - -/* - * Remove a node from a gathered list. - */ -void -changelist_remove(prop_changelist_t *clp, const char *name) -{ - prop_changenode_t *cn; - uu_avl_walk_t *walk; - - if ((walk = uu_avl_walk_start(clp->cl_tree, UU_WALK_ROBUST)) == NULL) - return; - - while ((cn = uu_avl_walk_next(walk)) != NULL) { - if (strcmp(cn->cn_handle->zfs_name, name) == 0) { - uu_avl_remove(clp->cl_tree, cn); - zfs_close(cn->cn_handle); - free(cn); - uu_avl_walk_end(walk); - return; - } - } - - uu_avl_walk_end(walk); -} - -/* - * Release any memory associated with a changelist. - */ -void -changelist_free(prop_changelist_t *clp) -{ - prop_changenode_t *cn; - - if (clp->cl_tree) { - uu_avl_walk_t *walk; - - if ((walk = uu_avl_walk_start(clp->cl_tree, - UU_WALK_ROBUST)) == NULL) - return; - - while ((cn = uu_avl_walk_next(walk)) != NULL) { - uu_avl_remove(clp->cl_tree, cn); - zfs_close(cn->cn_handle); - free(cn); - } - - uu_avl_walk_end(walk); - uu_avl_destroy(clp->cl_tree); - } - if (clp->cl_pool) - uu_avl_pool_destroy(clp->cl_pool); - - free(clp); -} - -/* - * Add one dataset to changelist - */ -static int -changelist_add_mounted(zfs_handle_t *zhp, void *data) -{ - prop_changelist_t *clp = data; - prop_changenode_t *cn; - uu_avl_index_t idx; - - ASSERT3U(clp->cl_prop, ==, ZFS_PROP_MOUNTPOINT); - - cn = zfs_alloc(zfs_get_handle(zhp), sizeof (prop_changenode_t)); - cn->cn_handle = zhp; - cn->cn_mounted = zfs_is_mounted(zhp, NULL); - ASSERT3U(cn->cn_mounted, ==, B_TRUE); - cn->cn_shared = zfs_is_shared(zhp, NULL, NULL); - cn->cn_zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED); - cn->cn_needpost = B_TRUE; - - /* Indicate if any child is exported to a local zone. */ - if (getzoneid() == GLOBAL_ZONEID && cn->cn_zoned) - clp->cl_haszonedchild = B_TRUE; - - uu_avl_node_init(cn, &cn->cn_treenode, clp->cl_pool); - - if (uu_avl_find(clp->cl_tree, cn, NULL, &idx) == NULL) { - uu_avl_insert(clp->cl_tree, cn, idx); - } else { - free(cn); - zfs_close(zhp); - } - - return (0); -} - -static int -change_one(zfs_handle_t *zhp, void *data) -{ - prop_changelist_t *clp = data; - char property[ZFS_MAXPROPLEN]; - char where[64]; - prop_changenode_t *cn = NULL; - zprop_source_t sourcetype = ZPROP_SRC_NONE; - zprop_source_t share_sourcetype = ZPROP_SRC_NONE; - int ret = 0; - - /* - * We only want to unmount/unshare those filesystems that may inherit - * from the target filesystem. If we find any filesystem with a - * locally set mountpoint, we ignore any children since changing the - * property will not affect them. If this is a rename, we iterate - * over all children regardless, since we need them unmounted in - * order to do the rename. Also, if this is a volume and we're doing - * a rename, then always add it to the changelist. - */ - - if (!(ZFS_IS_VOLUME(zhp) && clp->cl_realprop == ZFS_PROP_NAME) && - zfs_prop_get(zhp, clp->cl_prop, property, - sizeof (property), &sourcetype, where, sizeof (where), - B_FALSE) != 0) { - goto out; - } - - /* - * If we are "watching" sharenfs or sharesmb - * then check out the companion property which is tracked - * in cl_shareprop - */ - if (clp->cl_shareprop != ZPROP_INVAL && - zfs_prop_get(zhp, clp->cl_shareprop, property, - sizeof (property), &share_sourcetype, where, sizeof (where), - B_FALSE) != 0) { - goto out; - } - - if (clp->cl_alldependents || clp->cl_allchildren || - sourcetype == ZPROP_SRC_DEFAULT || - sourcetype == ZPROP_SRC_INHERITED || - (clp->cl_shareprop != ZPROP_INVAL && - (share_sourcetype == ZPROP_SRC_DEFAULT || - share_sourcetype == ZPROP_SRC_INHERITED))) { - cn = zfs_alloc(zfs_get_handle(zhp), sizeof (prop_changenode_t)); - cn->cn_handle = zhp; - cn->cn_mounted = (clp->cl_gflags & CL_GATHER_MOUNT_ALWAYS) || - zfs_is_mounted(zhp, NULL); - cn->cn_shared = zfs_is_shared(zhp, NULL, NULL); - cn->cn_zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED); - cn->cn_needpost = B_TRUE; - - /* Indicate if any child is exported to a local zone. */ - if (getzoneid() == GLOBAL_ZONEID && cn->cn_zoned) - clp->cl_haszonedchild = B_TRUE; - - uu_avl_node_init(cn, &cn->cn_treenode, clp->cl_pool); - - uu_avl_index_t idx; - - if (uu_avl_find(clp->cl_tree, cn, NULL, &idx) == NULL) { - uu_avl_insert(clp->cl_tree, cn, idx); - } else { - free(cn); - cn = NULL; - } - - if (!clp->cl_alldependents) { - if (clp->cl_prop != ZFS_PROP_MOUNTPOINT) { - ret = zfs_iter_filesystems_v2(zhp, 0, - change_one, data); - } else { - ret = zfs_iter_children_v2(zhp, 0, change_one, - data); - } - } - - /* - * If we added the handle to the changelist, we will re-use it - * later so return without closing it. - */ - if (cn != NULL) - return (ret); - } - -out: - zfs_close(zhp); - return (ret); -} - -static int -compare_props(const void *a, const void *b, zfs_prop_t prop) -{ - const prop_changenode_t *ca = a; - const prop_changenode_t *cb = b; - - char propa[MAXPATHLEN]; - char propb[MAXPATHLEN]; - - boolean_t haspropa, haspropb; - - haspropa = (zfs_prop_get(ca->cn_handle, prop, propa, sizeof (propa), - NULL, NULL, 0, B_FALSE) == 0); - haspropb = (zfs_prop_get(cb->cn_handle, prop, propb, sizeof (propb), - NULL, NULL, 0, B_FALSE) == 0); - - if (!haspropa && haspropb) - return (-1); - else if (haspropa && !haspropb) - return (1); - else if (!haspropa && !haspropb) - return (0); - else - return (strcmp(propb, propa)); -} - -static int -compare_mountpoints(const void *a, const void *b, void *unused) -{ - /* - * When unsharing or unmounting filesystems, we need to do it in - * mountpoint order. This allows the user to have a mountpoint - * hierarchy that is different from the dataset hierarchy, and still - * allow it to be changed. - */ - (void) unused; - return (compare_props(a, b, ZFS_PROP_MOUNTPOINT)); -} - -static int -compare_dataset_names(const void *a, const void *b, void *unused) -{ - (void) unused; - return (compare_props(a, b, ZFS_PROP_NAME)); -} - -/* - * Given a ZFS handle and a property, construct a complete list of datasets - * that need to be modified as part of this process. For anything but the - * 'mountpoint' and 'sharenfs' properties, this just returns an empty list. - * Otherwise, we iterate over all children and look for any datasets that - * inherit the property. For each such dataset, we add it to the list and - * mark whether it was shared beforehand. - */ -prop_changelist_t * -changelist_gather(zfs_handle_t *zhp, zfs_prop_t prop, int gather_flags, - int mnt_flags) -{ - prop_changelist_t *clp; - prop_changenode_t *cn; - zfs_handle_t *temp; - char property[ZFS_MAXPROPLEN]; - boolean_t legacy = B_FALSE; - - clp = zfs_alloc(zhp->zfs_hdl, sizeof (prop_changelist_t)); - - /* - * For mountpoint-related tasks, we want to sort everything by - * mountpoint, so that we mount and unmount them in the appropriate - * order, regardless of their position in the hierarchy. - */ - if (prop == ZFS_PROP_NAME || prop == ZFS_PROP_ZONED || - prop == ZFS_PROP_MOUNTPOINT || prop == ZFS_PROP_SHARENFS || - prop == ZFS_PROP_SHARESMB) { - - if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, - property, sizeof (property), - NULL, NULL, 0, B_FALSE) == 0 && - (strcmp(property, "legacy") == 0 || - strcmp(property, "none") == 0)) { - legacy = B_TRUE; - } - } - - clp->cl_pool = uu_avl_pool_create("changelist_pool", - sizeof (prop_changenode_t), - offsetof(prop_changenode_t, cn_treenode), - legacy ? compare_dataset_names : compare_mountpoints, 0); - if (clp->cl_pool == NULL) { - assert(uu_error() == UU_ERROR_NO_MEMORY); - (void) zfs_error(zhp->zfs_hdl, EZFS_NOMEM, "internal error"); - changelist_free(clp); - return (NULL); - } - - clp->cl_tree = uu_avl_create(clp->cl_pool, NULL, UU_DEFAULT); - clp->cl_gflags = gather_flags; - clp->cl_mflags = mnt_flags; - - if (clp->cl_tree == NULL) { - assert(uu_error() == UU_ERROR_NO_MEMORY); - (void) zfs_error(zhp->zfs_hdl, EZFS_NOMEM, "internal error"); - changelist_free(clp); - return (NULL); - } - - /* - * If this is a rename or the 'zoned' property, we pretend we're - * changing the mountpoint and flag it so we can catch all children in - * change_one(). - * - * Flag cl_alldependents to catch all children plus the dependents - * (clones) that are not in the hierarchy. - */ - if (prop == ZFS_PROP_NAME) { - clp->cl_prop = ZFS_PROP_MOUNTPOINT; - clp->cl_alldependents = B_TRUE; - } else if (prop == ZFS_PROP_ZONED) { - clp->cl_prop = ZFS_PROP_MOUNTPOINT; - clp->cl_allchildren = B_TRUE; - } else if (prop == ZFS_PROP_CANMOUNT) { - clp->cl_prop = ZFS_PROP_MOUNTPOINT; - } else if (prop == ZFS_PROP_VOLSIZE) { - clp->cl_prop = ZFS_PROP_MOUNTPOINT; - } else { - clp->cl_prop = prop; - } - clp->cl_realprop = prop; - - if (clp->cl_prop != ZFS_PROP_MOUNTPOINT && - clp->cl_prop != ZFS_PROP_SHARENFS && - clp->cl_prop != ZFS_PROP_SHARESMB) - return (clp); - - /* - * If watching SHARENFS or SHARESMB then - * also watch its companion property. - */ - if (clp->cl_prop == ZFS_PROP_SHARENFS) - clp->cl_shareprop = ZFS_PROP_SHARESMB; - else if (clp->cl_prop == ZFS_PROP_SHARESMB) - clp->cl_shareprop = ZFS_PROP_SHARENFS; - - if (clp->cl_prop == ZFS_PROP_MOUNTPOINT && - (clp->cl_gflags & CL_GATHER_ITER_MOUNTED)) { - /* - * Instead of iterating through all of the dataset children we - * gather mounted dataset children from MNTTAB - */ - if (zfs_iter_mounted(zhp, changelist_add_mounted, clp) != 0) { - changelist_free(clp); - return (NULL); - } - } else if (clp->cl_alldependents) { - if (zfs_iter_dependents_v2(zhp, 0, B_TRUE, change_one, - clp) != 0) { - changelist_free(clp); - return (NULL); - } - } else if (clp->cl_prop != ZFS_PROP_MOUNTPOINT) { - if (zfs_iter_filesystems_v2(zhp, 0, change_one, clp) != 0) { - changelist_free(clp); - return (NULL); - } - } else if (zfs_iter_children_v2(zhp, 0, change_one, clp) != 0) { - changelist_free(clp); - return (NULL); - } - - /* - * We have to re-open ourselves because we auto-close all the handles - * and can't tell the difference. - */ - if ((temp = zfs_open(zhp->zfs_hdl, zfs_get_name(zhp), - ZFS_TYPE_DATASET)) == NULL) { - changelist_free(clp); - return (NULL); - } - - /* - * Always add ourself to the list. We add ourselves to the end so that - * we're the last to be unmounted. - */ - cn = zfs_alloc(zhp->zfs_hdl, sizeof (prop_changenode_t)); - cn->cn_handle = temp; - cn->cn_mounted = (clp->cl_gflags & CL_GATHER_MOUNT_ALWAYS) || - zfs_is_mounted(temp, NULL); - cn->cn_shared = zfs_is_shared(temp, NULL, NULL); - cn->cn_zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED); - cn->cn_needpost = B_TRUE; - - uu_avl_node_init(cn, &cn->cn_treenode, clp->cl_pool); - uu_avl_index_t idx; - if (uu_avl_find(clp->cl_tree, cn, NULL, &idx) == NULL) { - uu_avl_insert(clp->cl_tree, cn, idx); - } else { - free(cn); - zfs_close(temp); - } - - /* - * If the mountpoint property was previously 'legacy', or 'none', - * record it as the behavior of changelist_postfix() will be different. - */ - if ((clp->cl_prop == ZFS_PROP_MOUNTPOINT) && legacy) { - /* - * do not automatically mount ex-legacy datasets if - * we specifically set canmount to noauto - */ - if (zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT) != - ZFS_CANMOUNT_NOAUTO) - clp->cl_waslegacy = B_TRUE; - } - - return (clp); -} diff --git a/lib/libzfs/libzfs_config.c b/lib/libzfs/libzfs_config.c deleted file mode 100644 index 9d704e4303ff..000000000000 --- a/lib/libzfs/libzfs_config.c +++ /dev/null @@ -1,455 +0,0 @@ -// SPDX-License-Identifier: CDDL-1.0 -/* - * 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 - */ - -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * Copyright (c) 2012 by Delphix. All rights reserved. - * Copyright (c) 2015 by Syneto S.R.L. All rights reserved. - * Copyright 2016 Nexenta Systems, Inc. - */ - -/* - * The pool configuration repository is stored in /etc/zfs/zpool.cache as a - * single packed nvlist. While it would be nice to just read in this - * file from userland, this wouldn't work from a local zone. So we have to have - * a zpool ioctl to return the complete configuration for all pools. In the - * global zone, this will be identical to reading the file and unpacking it in - * userland. - */ - -#include <errno.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <stddef.h> -#include <string.h> -#include <unistd.h> -#include <libintl.h> -#include <libuutil.h> - -#include "libzfs_impl.h" - -typedef struct config_node { - char *cn_name; - nvlist_t *cn_config; - uu_avl_node_t cn_avl; -} config_node_t; - -static int -config_node_compare(const void *a, const void *b, void *unused) -{ - (void) unused; - const config_node_t *ca = (config_node_t *)a; - const config_node_t *cb = (config_node_t *)b; - - int ret = strcmp(ca->cn_name, cb->cn_name); - - if (ret < 0) - return (-1); - else if (ret > 0) - return (1); - else - return (0); -} - -void -namespace_clear(libzfs_handle_t *hdl) -{ - if (hdl->libzfs_ns_avl) { - config_node_t *cn; - void *cookie = NULL; - - while ((cn = uu_avl_teardown(hdl->libzfs_ns_avl, - &cookie)) != NULL) { - nvlist_free(cn->cn_config); - free(cn->cn_name); - free(cn); - } - - uu_avl_destroy(hdl->libzfs_ns_avl); - hdl->libzfs_ns_avl = NULL; - } - - if (hdl->libzfs_ns_avlpool) { - uu_avl_pool_destroy(hdl->libzfs_ns_avlpool); - hdl->libzfs_ns_avlpool = NULL; - } -} - -/* - * Loads the pool namespace, or re-loads it if the cache has changed. - */ -static int -namespace_reload(libzfs_handle_t *hdl) -{ - nvlist_t *config; - config_node_t *cn; - nvpair_t *elem; - zfs_cmd_t zc = {"\0"}; - void *cookie; - - if (hdl->libzfs_ns_gen == 0) { - /* - * This is the first time we've accessed the configuration - * cache. Initialize the AVL tree and then fall through to the - * common code. - */ - if ((hdl->libzfs_ns_avlpool = uu_avl_pool_create("config_pool", - sizeof (config_node_t), - offsetof(config_node_t, cn_avl), - config_node_compare, UU_DEFAULT)) == NULL) - return (no_memory(hdl)); - - if ((hdl->libzfs_ns_avl = uu_avl_create(hdl->libzfs_ns_avlpool, - NULL, UU_DEFAULT)) == NULL) - return (no_memory(hdl)); - } - - zcmd_alloc_dst_nvlist(hdl, &zc, 0); - - for (;;) { - zc.zc_cookie = hdl->libzfs_ns_gen; - if (zfs_ioctl(hdl, ZFS_IOC_POOL_CONFIGS, &zc) != 0) { - switch (errno) { - case EEXIST: - /* - * The namespace hasn't changed. - */ - zcmd_free_nvlists(&zc); - return (0); - - case ENOMEM: - zcmd_expand_dst_nvlist(hdl, &zc); - break; - - default: - zcmd_free_nvlists(&zc); - return (zfs_standard_error(hdl, errno, - dgettext(TEXT_DOMAIN, "failed to read " - "pool configuration"))); - } - } else { - hdl->libzfs_ns_gen = zc.zc_cookie; - break; - } - } - - if (zcmd_read_dst_nvlist(hdl, &zc, &config) != 0) { - zcmd_free_nvlists(&zc); - return (-1); - } - - zcmd_free_nvlists(&zc); - - /* - * Clear out any existing configuration information. - */ - cookie = NULL; - while ((cn = uu_avl_teardown(hdl->libzfs_ns_avl, &cookie)) != NULL) { - nvlist_free(cn->cn_config); - free(cn->cn_name); - free(cn); - } - - elem = NULL; - while ((elem = nvlist_next_nvpair(config, elem)) != NULL) { - nvlist_t *child; - uu_avl_index_t where; - - cn = zfs_alloc(hdl, sizeof (config_node_t)); - cn->cn_name = zfs_strdup(hdl, nvpair_name(elem)); - child = fnvpair_value_nvlist(elem); - if (nvlist_dup(child, &cn->cn_config, 0) != 0) { - free(cn->cn_name); - free(cn); - nvlist_free(config); - return (no_memory(hdl)); - } - verify(uu_avl_find(hdl->libzfs_ns_avl, cn, NULL, &where) - == NULL); - - uu_avl_insert(hdl->libzfs_ns_avl, cn, where); - } - - nvlist_free(config); - return (0); -} - -/* - * Retrieve the configuration for the given pool. The configuration is an nvlist - * describing the vdevs, as well as the statistics associated with each one. - */ -nvlist_t * -zpool_get_config(zpool_handle_t *zhp, nvlist_t **oldconfig) -{ - if (oldconfig) - *oldconfig = zhp->zpool_old_config; - return (zhp->zpool_config); -} - -/* - * Retrieves a list of enabled features and their refcounts and caches it in - * the pool handle. - */ -nvlist_t * -zpool_get_features(zpool_handle_t *zhp) -{ - nvlist_t *config, *features; - - config = zpool_get_config(zhp, NULL); - - if (config == NULL || !nvlist_exists(config, - ZPOOL_CONFIG_FEATURE_STATS)) { - int error; - boolean_t missing = B_FALSE; - - error = zpool_refresh_stats(zhp, &missing); - - if (error != 0 || missing) - return (NULL); - - config = zpool_get_config(zhp, NULL); - } - - if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_FEATURE_STATS, - &features) != 0) - return (NULL); - - return (features); -} - -/* - * Refresh the vdev statistics associated with the given pool. This is used in - * iostat to show configuration changes and determine the delta from the last - * time the function was called. This function can fail, in case the pool has - * been destroyed. - */ -int -zpool_refresh_stats(zpool_handle_t *zhp, boolean_t *missing) -{ - zfs_cmd_t zc = {"\0"}; - int error; - nvlist_t *config; - libzfs_handle_t *hdl = zhp->zpool_hdl; - - *missing = B_FALSE; - (void) strcpy(zc.zc_name, zhp->zpool_name); - - if (zhp->zpool_config_size == 0) - zhp->zpool_config_size = 1 << 16; - - zcmd_alloc_dst_nvlist(hdl, &zc, zhp->zpool_config_size); - - for (;;) { - if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_STATS, - &zc) == 0) { - /* - * The real error is returned in the zc_cookie field. - */ - error = zc.zc_cookie; - break; - } - - if (errno == ENOMEM) - zcmd_expand_dst_nvlist(hdl, &zc); - else { - zcmd_free_nvlists(&zc); - if (errno == ENOENT || errno == EINVAL) - *missing = B_TRUE; - zhp->zpool_state = POOL_STATE_UNAVAIL; - return (0); - } - } - - if (zcmd_read_dst_nvlist(hdl, &zc, &config) != 0) { - zcmd_free_nvlists(&zc); - return (-1); - } - - zcmd_free_nvlists(&zc); - - zhp->zpool_config_size = zc.zc_nvlist_dst_size; - - if (zhp->zpool_config != NULL) { - nvlist_free(zhp->zpool_old_config); - - zhp->zpool_old_config = zhp->zpool_config; - } - - zhp->zpool_config = config; - if (error) - zhp->zpool_state = POOL_STATE_UNAVAIL; - else - zhp->zpool_state = POOL_STATE_ACTIVE; - - return (0); -} - -/* - * Copies the pool config and state from szhp to dzhp. szhp and dzhp must - * represent the same pool. Used by pool_list_refresh() to avoid another - * round-trip into the kernel to get stats already collected earlier in the - * function. - */ -void -zpool_refresh_stats_from_handle(zpool_handle_t *dzhp, zpool_handle_t *szhp) -{ - VERIFY0(strcmp(dzhp->zpool_name, szhp->zpool_name)); - nvlist_free(dzhp->zpool_old_config); - dzhp->zpool_old_config = dzhp->zpool_config; - dzhp->zpool_config = fnvlist_dup(szhp->zpool_config); - dzhp->zpool_config_size = szhp->zpool_config_size; - dzhp->zpool_state = szhp->zpool_state; -} - -/* - * The following environment variables are undocumented - * and should be used for testing purposes only: - * - * __ZFS_POOL_EXCLUDE - don't iterate over the pools it lists - * __ZFS_POOL_RESTRICT - iterate only over the pools it lists - * - * This function returns B_TRUE if the pool should be skipped - * during iteration. - */ -boolean_t -zpool_skip_pool(const char *poolname) -{ - static boolean_t initialized = B_FALSE; - static const char *exclude = NULL; - static const char *restricted = NULL; - - const char *cur, *end; - int len; - int namelen = strlen(poolname); - - if (!initialized) { - initialized = B_TRUE; - exclude = getenv("__ZFS_POOL_EXCLUDE"); - restricted = getenv("__ZFS_POOL_RESTRICT"); - } - - if (exclude != NULL) { - cur = exclude; - do { - end = strchr(cur, ' '); - len = (NULL == end) ? strlen(cur) : (end - cur); - if (len == namelen && 0 == strncmp(cur, poolname, len)) - return (B_TRUE); - cur += (len + 1); - } while (NULL != end); - } - - if (NULL == restricted) - return (B_FALSE); - - cur = restricted; - do { - end = strchr(cur, ' '); - len = (NULL == end) ? strlen(cur) : (end - cur); - - if (len == namelen && 0 == strncmp(cur, poolname, len)) { - return (B_FALSE); - } - - cur += (len + 1); - } while (NULL != end); - - return (B_TRUE); -} - -/* - * Iterate over all pools in the system. - */ -int -zpool_iter(libzfs_handle_t *hdl, zpool_iter_f func, void *data) -{ - config_node_t *cn; - zpool_handle_t *zhp; - int ret; - - /* - * If someone makes a recursive call to zpool_iter(), we want to avoid - * refreshing the namespace because that will invalidate the parent - * context. We allow recursive calls, but simply re-use the same - * namespace AVL tree. - */ - if (!hdl->libzfs_pool_iter && namespace_reload(hdl) != 0) - return (-1); - - hdl->libzfs_pool_iter++; - for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL; - cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) { - - if (zpool_skip_pool(cn->cn_name)) - continue; - - if (zpool_open_silent(hdl, cn->cn_name, &zhp) != 0) { - hdl->libzfs_pool_iter--; - return (-1); - } - - if (zhp == NULL) - continue; - - if ((ret = func(zhp, data)) != 0) { - hdl->libzfs_pool_iter--; - return (ret); - } - } - hdl->libzfs_pool_iter--; - - return (0); -} - -/* - * Iterate over root datasets, calling the given function for each. The zfs - * handle passed each time must be explicitly closed by the callback. - */ -int -zfs_iter_root(libzfs_handle_t *hdl, zfs_iter_f func, void *data) -{ - config_node_t *cn; - zfs_handle_t *zhp; - int ret; - - if (namespace_reload(hdl) != 0) - return (-1); - - for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL; - cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) { - - if (zpool_skip_pool(cn->cn_name)) - continue; - - if ((zhp = make_dataset_handle(hdl, cn->cn_name)) == NULL) - continue; - - if ((ret = func(zhp, data)) != 0) - return (ret); - } - - return (0); -} diff --git a/lib/libzfs/libzfs_crypto.c b/lib/libzfs/libzfs_crypto.c deleted file mode 100644 index b34a44c30eb4..000000000000 --- a/lib/libzfs/libzfs_crypto.c +++ /dev/null @@ -1,1831 +0,0 @@ -// SPDX-License-Identifier: CDDL-1.0 -/* - * 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) 2017, Datto, Inc. All rights reserved. - * Copyright 2020 Joyent, Inc. - */ - -#include <sys/zfs_context.h> -#include <sys/fs/zfs.h> -#include <sys/dsl_crypt.h> -#include <libintl.h> -#include <termios.h> -#include <signal.h> -#include <errno.h> -#include <openssl/evp.h> -#if LIBFETCH_DYNAMIC -#include <dlfcn.h> -#endif -#if LIBFETCH_IS_FETCH -#include <sys/param.h> -#include <stdio.h> -#include <fetch.h> -#elif LIBFETCH_IS_LIBCURL -#include <curl/curl.h> -#endif -#include <libzfs.h> -#include <libzutil.h> -#include "libzfs_impl.h" -#include "zfeature_common.h" - -/* - * User keys are used to decrypt the master encryption keys of a dataset. This - * indirection allows a user to change his / her access key without having to - * re-encrypt the entire dataset. User keys can be provided in one of several - * ways. Raw keys are simply given to the kernel as is. Similarly, hex keys - * are converted to binary and passed into the kernel. Password based keys are - * a bit more complicated. Passwords alone do not provide suitable entropy for - * encryption and may be too short or too long to be used. In order to derive - * a more appropriate key we use a PBKDF2 function. This function is designed - * to take a (relatively) long time to calculate in order to discourage - * attackers from guessing from a list of common passwords. PBKDF2 requires - * 2 additional parameters. The first is the number of iterations to run, which - * will ultimately determine how long it takes to derive the resulting key from - * the password. The second parameter is a salt that is randomly generated for - * each dataset. The salt is used to "tweak" PBKDF2 such that a group of - * attackers cannot reasonably generate a table of commonly known passwords to - * their output keys and expect it work for all past and future PBKDF2 users. - * We store the salt as a hidden property of the dataset (although it is - * technically ok if the salt is known to the attacker). - */ - -#define MIN_PASSPHRASE_LEN 8 -#define MAX_PASSPHRASE_LEN 512 -#define MAX_KEY_PROMPT_ATTEMPTS 3 - -static int caught_interrupt; - -static int get_key_material_file(libzfs_handle_t *, const char *, const char *, - zfs_keyformat_t, boolean_t, uint8_t **, size_t *); -static int get_key_material_https(libzfs_handle_t *, const char *, const char *, - zfs_keyformat_t, boolean_t, uint8_t **, size_t *); - -static zfs_uri_handler_t uri_handlers[] = { - { "file", get_key_material_file }, - { "https", get_key_material_https }, - { "http", get_key_material_https }, - { NULL, NULL } -}; - -static int -pkcs11_get_urandom(uint8_t *buf, size_t bytes) -{ - int rand; - ssize_t bytes_read = 0; - - rand = open("/dev/urandom", O_RDONLY | O_CLOEXEC); - - if (rand < 0) - return (rand); - - while (bytes_read < bytes) { - ssize_t rc = read(rand, buf + bytes_read, bytes - bytes_read); - if (rc < 0) - break; - bytes_read += rc; - } - - (void) close(rand); - - return (bytes_read); -} - -static int -zfs_prop_parse_keylocation(libzfs_handle_t *restrict hdl, const char *str, - zfs_keylocation_t *restrict locp, char **restrict schemep) -{ - *locp = ZFS_KEYLOCATION_NONE; - *schemep = NULL; - - if (strcmp("prompt", str) == 0) { - *locp = ZFS_KEYLOCATION_PROMPT; - return (0); - } - - regmatch_t pmatch[2]; - - if (regexec(&hdl->libzfs_urire, str, ARRAY_SIZE(pmatch), - pmatch, 0) == 0) { - size_t scheme_len; - - if (pmatch[1].rm_so == -1) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Invalid URI")); - return (EINVAL); - } - - scheme_len = pmatch[1].rm_eo - pmatch[1].rm_so; - - *schemep = calloc(1, scheme_len + 1); - if (*schemep == NULL) { - int ret = errno; - - errno = 0; - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Invalid URI")); - return (ret); - } - - (void) memcpy(*schemep, str + pmatch[1].rm_so, scheme_len); - *locp = ZFS_KEYLOCATION_URI; - return (0); - } - - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "Invalid keylocation")); - return (EINVAL); -} - -static int -hex_key_to_raw(char *hex, int hexlen, uint8_t *out) -{ - int ret, i; - unsigned int c; - - for (i = 0; i < hexlen; i += 2) { - if (!isxdigit(hex[i]) || !isxdigit(hex[i + 1])) { - ret = EINVAL; - goto error; - } - - ret = sscanf(&hex[i], "%02x", &c); - if (ret != 1) { - ret = EINVAL; - goto error; - } - - out[i / 2] = c; - } - - return (0); - -error: - return (ret); -} - - -static void -catch_signal(int sig) -{ - caught_interrupt = sig; -} - -static const char * -get_format_prompt_string(zfs_keyformat_t format) -{ - switch (format) { - case ZFS_KEYFORMAT_RAW: - return ("raw key"); - case ZFS_KEYFORMAT_HEX: - return ("hex key"); - case ZFS_KEYFORMAT_PASSPHRASE: - return ("passphrase"); - default: - /* shouldn't happen */ - return (NULL); - } -} - -/* do basic validation of the key material */ -static int -validate_key(libzfs_handle_t *hdl, zfs_keyformat_t keyformat, - const char *key, size_t keylen, boolean_t do_verify) -{ - switch (keyformat) { - case ZFS_KEYFORMAT_RAW: - /* verify the key length is correct */ - if (keylen < WRAPPING_KEY_LEN) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Raw key too short (expected %u)."), - WRAPPING_KEY_LEN); - return (EINVAL); - } - - if (keylen > WRAPPING_KEY_LEN) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Raw key too long (expected %u)."), - WRAPPING_KEY_LEN); - return (EINVAL); - } - break; - case ZFS_KEYFORMAT_HEX: - /* verify the key length is correct */ - if (keylen < WRAPPING_KEY_LEN * 2) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Hex key too short (expected %u)."), - WRAPPING_KEY_LEN * 2); - return (EINVAL); - } - - if (keylen > WRAPPING_KEY_LEN * 2) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Hex key too long (expected %u)."), - WRAPPING_KEY_LEN * 2); - return (EINVAL); - } - - /* check for invalid hex digits */ - for (size_t i = 0; i < WRAPPING_KEY_LEN * 2; i++) { - if (!isxdigit(key[i])) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Invalid hex character detected.")); - return (EINVAL); - } - } - break; - case ZFS_KEYFORMAT_PASSPHRASE: - /* - * Verify the length is within bounds when setting a new key, - * but not when loading an existing key. - */ - if (!do_verify) - break; - if (keylen > MAX_PASSPHRASE_LEN) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Passphrase too long (max %u)."), - MAX_PASSPHRASE_LEN); - return (EINVAL); - } - - if (keylen < MIN_PASSPHRASE_LEN) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Passphrase too short (min %u)."), - MIN_PASSPHRASE_LEN); - return (EINVAL); - } - break; - default: - /* can't happen, checked above */ - break; - } - - return (0); -} - -static int -libzfs_getpassphrase(zfs_keyformat_t keyformat, boolean_t is_reenter, - boolean_t new_key, const char *fsname, - char **restrict res, size_t *restrict reslen) -{ - FILE *f = stdin; - size_t buflen = 0; - ssize_t bytes; - int ret = 0; - struct termios old_term, new_term; - struct sigaction act, osigint, osigtstp; - - *res = NULL; - *reslen = 0; - - /* - * handle SIGINT and ignore SIGSTP. This is necessary to - * restore the state of the terminal. - */ - caught_interrupt = 0; - act.sa_flags = 0; - (void) sigemptyset(&act.sa_mask); - act.sa_handler = catch_signal; - - (void) sigaction(SIGINT, &act, &osigint); - act.sa_handler = SIG_IGN; - (void) sigaction(SIGTSTP, &act, &osigtstp); - - (void) printf("%s %s%s", - is_reenter ? "Re-enter" : "Enter", - new_key ? "new " : "", - get_format_prompt_string(keyformat)); - if (fsname != NULL) - (void) printf(" for '%s'", fsname); - (void) fputc(':', stdout); - (void) fflush(stdout); - - /* disable the terminal echo for key input */ - (void) tcgetattr(fileno(f), &old_term); - - new_term = old_term; - new_term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); - - ret = tcsetattr(fileno(f), TCSAFLUSH, &new_term); - if (ret != 0) { - ret = errno; - errno = 0; - goto out; - } - - bytes = getline(res, &buflen, f); - if (bytes < 0) { - ret = errno; - errno = 0; - goto out; - } - - /* trim the ending newline if it exists */ - if (bytes > 0 && (*res)[bytes - 1] == '\n') { - (*res)[bytes - 1] = '\0'; - bytes--; - } - - *reslen = bytes; - -out: - /* reset the terminal */ - (void) tcsetattr(fileno(f), TCSAFLUSH, &old_term); - (void) sigaction(SIGINT, &osigint, NULL); - (void) sigaction(SIGTSTP, &osigtstp, NULL); - - /* if we caught a signal, re-throw it now */ - if (caught_interrupt != 0) - (void) kill(getpid(), caught_interrupt); - - /* print the newline that was not echo'd */ - (void) printf("\n"); - - return (ret); -} - -static int -get_key_interactive(libzfs_handle_t *restrict hdl, const char *fsname, - zfs_keyformat_t keyformat, boolean_t confirm_key, boolean_t newkey, - uint8_t **restrict outbuf, size_t *restrict len_out) -{ - char *buf = NULL, *buf2 = NULL; - size_t buflen = 0, buf2len = 0; - int ret = 0; - - ASSERT(isatty(fileno(stdin))); - - /* raw keys cannot be entered on the terminal */ - if (keyformat == ZFS_KEYFORMAT_RAW) { - ret = EINVAL; - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Cannot enter raw keys on the terminal")); - goto out; - } - - /* prompt for the key */ - if ((ret = libzfs_getpassphrase(keyformat, B_FALSE, newkey, fsname, - &buf, &buflen)) != 0) { - free(buf); - buf = NULL; - buflen = 0; - goto out; - } - - if (!confirm_key) - goto out; - - if ((ret = validate_key(hdl, keyformat, buf, buflen, confirm_key)) != - 0) { - free(buf); - return (ret); - } - - ret = libzfs_getpassphrase(keyformat, B_TRUE, newkey, fsname, &buf2, - &buf2len); - if (ret != 0) { - free(buf); - free(buf2); - buf = buf2 = NULL; - buflen = buf2len = 0; - goto out; - } - - if (buflen != buf2len || strcmp(buf, buf2) != 0) { - free(buf); - buf = NULL; - buflen = 0; - - ret = EINVAL; - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Provided keys do not match.")); - } - - free(buf2); - -out: - *outbuf = (uint8_t *)buf; - *len_out = buflen; - return (ret); -} - -static int -get_key_material_raw(FILE *fd, zfs_keyformat_t keyformat, - uint8_t **buf, size_t *len_out) -{ - int ret = 0; - size_t buflen = 0; - - *len_out = 0; - - /* read the key material */ - if (keyformat != ZFS_KEYFORMAT_RAW) { - ssize_t bytes; - - bytes = getline((char **)buf, &buflen, fd); - if (bytes < 0) { - ret = errno; - errno = 0; - goto out; - } - - /* trim the ending newline if it exists */ - if (bytes > 0 && (*buf)[bytes - 1] == '\n') { - (*buf)[bytes - 1] = '\0'; - bytes--; - } - - *len_out = bytes; - } else { - size_t n; - - /* - * Raw keys may have newline characters in them and so can't - * use getline(). Here we attempt to read 33 bytes so that we - * can properly check the key length (the file should only have - * 32 bytes). - */ - *buf = malloc((WRAPPING_KEY_LEN + 1) * sizeof (uint8_t)); - if (*buf == NULL) { - ret = ENOMEM; - goto out; - } - - n = fread(*buf, 1, WRAPPING_KEY_LEN + 1, fd); - if (n == 0 || ferror(fd)) { - /* size errors are handled by the calling function */ - free(*buf); - *buf = NULL; - ret = errno; - errno = 0; - goto out; - } - - *len_out = n; - } -out: - return (ret); -} - -static int -get_key_material_file(libzfs_handle_t *hdl, const char *uri, - const char *fsname, zfs_keyformat_t keyformat, boolean_t newkey, - uint8_t **restrict buf, size_t *restrict len_out) -{ - (void) fsname, (void) newkey; - FILE *f = NULL; - int ret = 0; - - if (strlen(uri) < 7) - return (EINVAL); - - if ((f = fopen(uri + 7, "re")) == NULL) { - ret = errno; - errno = 0; - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Failed to open key material file: %s"), zfs_strerror(ret)); - return (ret); - } - - ret = get_key_material_raw(f, keyformat, buf, len_out); - - (void) fclose(f); - - return (ret); -} - -static int -get_key_material_https(libzfs_handle_t *hdl, const char *uri, - const char *fsname, zfs_keyformat_t keyformat, boolean_t newkey, - uint8_t **restrict buf, size_t *restrict len_out) -{ - (void) fsname, (void) newkey; - int ret = 0; - FILE *key = NULL; - boolean_t is_http = strncmp(uri, "http:", strlen("http:")) == 0; - - if (strlen(uri) < (is_http ? 7 : 8)) { - ret = EINVAL; - goto end; - } - -#if LIBFETCH_DYNAMIC -#define LOAD_FUNCTION(func) \ - __typeof__(func) *func = dlsym(hdl->libfetch, #func); - - if (hdl->libfetch == NULL) - hdl->libfetch = dlopen(LIBFETCH_SONAME, RTLD_LAZY); - - if (hdl->libfetch == NULL) { - hdl->libfetch = (void *)-1; - char *err = dlerror(); - if (err) - hdl->libfetch_load_error = strdup(err); - } - - if (hdl->libfetch == (void *)-1) { - ret = ENOSYS; - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Couldn't load %s: %s"), - LIBFETCH_SONAME, hdl->libfetch_load_error ?: "(?)"); - goto end; - } - - boolean_t ok; -#if LIBFETCH_IS_FETCH - LOAD_FUNCTION(fetchGetURL); - char *fetchLastErrString = dlsym(hdl->libfetch, "fetchLastErrString"); - - ok = fetchGetURL && fetchLastErrString; -#elif LIBFETCH_IS_LIBCURL - LOAD_FUNCTION(curl_easy_init); - LOAD_FUNCTION(curl_easy_setopt); - LOAD_FUNCTION(curl_easy_perform); - LOAD_FUNCTION(curl_easy_cleanup); - LOAD_FUNCTION(curl_easy_strerror); - LOAD_FUNCTION(curl_easy_getinfo); - - ok = curl_easy_init && curl_easy_setopt && curl_easy_perform && - curl_easy_cleanup && curl_easy_strerror && curl_easy_getinfo; -#endif - if (!ok) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "keylocation=%s back-end %s missing symbols."), - is_http ? "http://" : "https://", LIBFETCH_SONAME); - ret = ENOSYS; - goto end; - } -#endif - -#if LIBFETCH_IS_FETCH - key = fetchGetURL(uri, ""); - if (key == NULL) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Couldn't GET %s: %s"), - uri, fetchLastErrString); - ret = ENETDOWN; - } -#elif LIBFETCH_IS_LIBCURL - CURL *curl = curl_easy_init(); - if (curl == NULL) { - ret = ENOTSUP; - goto end; - } - - int kfd; -#ifdef O_TMPFILE - kfd = open(getenv("TMPDIR") ?: "/tmp", - O_RDWR | O_TMPFILE | O_EXCL | O_CLOEXEC, 0600); - if (kfd != -1) - goto kfdok; -#endif - - char *path; - if (asprintf(&path, - "%s/libzfs-XXXXXXXX.https", getenv("TMPDIR") ?: "/tmp") == -1) { - ret = ENOMEM; - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s"), - zfs_strerror(ret)); - goto end; - } - - kfd = mkostemps(path, strlen(".https"), O_CLOEXEC); - if (kfd == -1) { - ret = errno; - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Couldn't create temporary file %s: %s"), - path, zfs_strerror(ret)); - free(path); - goto end; - } - (void) unlink(path); - free(path); - -kfdok: - if ((key = fdopen(kfd, "r+")) == NULL) { - ret = errno; - (void) close(kfd); - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Couldn't reopen temporary file: %s"), zfs_strerror(ret)); - goto end; - } - - char errbuf[CURL_ERROR_SIZE] = ""; - char *cainfo = getenv("SSL_CA_CERT_FILE"); /* matches fetch(3) */ - char *capath = getenv("SSL_CA_CERT_PATH"); /* matches fetch(3) */ - char *clcert = getenv("SSL_CLIENT_CERT_FILE"); /* matches fetch(3) */ - char *clkey = getenv("SSL_CLIENT_KEY_FILE"); /* matches fetch(3) */ - (void) curl_easy_setopt(curl, CURLOPT_URL, uri); - (void) curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); - (void) curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 30000L); - (void) curl_easy_setopt(curl, CURLOPT_WRITEDATA, key); - (void) curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf); - if (cainfo != NULL) - (void) curl_easy_setopt(curl, CURLOPT_CAINFO, cainfo); - if (capath != NULL) - (void) curl_easy_setopt(curl, CURLOPT_CAPATH, capath); - if (clcert != NULL) - (void) curl_easy_setopt(curl, CURLOPT_SSLCERT, clcert); - if (clkey != NULL) - (void) curl_easy_setopt(curl, CURLOPT_SSLKEY, clkey); - - CURLcode res = curl_easy_perform(curl); - - if (res != CURLE_OK) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Failed to connect to %s: %s"), - uri, strlen(errbuf) ? errbuf : curl_easy_strerror(res)); - ret = ENETDOWN; - } else { - long resp = 200; - (void) curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &resp); - - if (resp < 200 || resp >= 300) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Couldn't GET %s: %ld"), - uri, resp); - ret = ENOENT; - } else - rewind(key); - } - - curl_easy_cleanup(curl); -#else - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "No keylocation=%s back-end."), is_http ? "http://" : "https://"); - ret = ENOSYS; -#endif - -end: - if (ret == 0) - ret = get_key_material_raw(key, keyformat, buf, len_out); - - if (key != NULL) - fclose(key); - - return (ret); -} - -/* - * Attempts to fetch key material, no matter where it might live. The key - * material is allocated and returned in km_out. *can_retry_out will be set - * to B_TRUE if the user is providing the key material interactively, allowing - * for re-entry attempts. - */ -static int -get_key_material(libzfs_handle_t *hdl, boolean_t do_verify, boolean_t newkey, - zfs_keyformat_t keyformat, const char *keylocation, const char *fsname, - uint8_t **km_out, size_t *kmlen_out, boolean_t *can_retry_out) -{ - int ret; - zfs_keylocation_t keyloc = ZFS_KEYLOCATION_NONE; - uint8_t *km = NULL; - size_t kmlen = 0; - char *uri_scheme = NULL; - zfs_uri_handler_t *handler = NULL; - boolean_t can_retry = B_FALSE; - - /* verify and parse the keylocation */ - ret = zfs_prop_parse_keylocation(hdl, keylocation, &keyloc, - &uri_scheme); - if (ret != 0) - goto error; - - /* open the appropriate file descriptor */ - switch (keyloc) { - case ZFS_KEYLOCATION_PROMPT: - if (isatty(fileno(stdin))) { - can_retry = keyformat != ZFS_KEYFORMAT_RAW; - ret = get_key_interactive(hdl, fsname, keyformat, - do_verify, newkey, &km, &kmlen); - } else { - /* fetch the key material into the buffer */ - ret = get_key_material_raw(stdin, keyformat, &km, - &kmlen); - } - - if (ret != 0) - goto error; - - break; - case ZFS_KEYLOCATION_URI: - ret = ENOTSUP; - - for (handler = uri_handlers; handler->zuh_scheme != NULL; - handler++) { - if (strcmp(handler->zuh_scheme, uri_scheme) != 0) - continue; - - if ((ret = handler->zuh_handler(hdl, keylocation, - fsname, keyformat, newkey, &km, &kmlen)) != 0) - goto error; - - break; - } - - if (ret == ENOTSUP) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "URI scheme is not supported")); - goto error; - } - - break; - default: - ret = EINVAL; - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Invalid keylocation.")); - goto error; - } - - if ((ret = validate_key(hdl, keyformat, (const char *)km, kmlen, - do_verify)) != 0) - goto error; - - *km_out = km; - *kmlen_out = kmlen; - if (can_retry_out != NULL) - *can_retry_out = can_retry; - - free(uri_scheme); - return (0); - -error: - free(km); - - *km_out = NULL; - *kmlen_out = 0; - - if (can_retry_out != NULL) - *can_retry_out = can_retry; - - free(uri_scheme); - return (ret); -} - -static int -derive_key(libzfs_handle_t *hdl, zfs_keyformat_t format, uint64_t iters, - uint8_t *key_material, uint64_t salt, - uint8_t **key_out) -{ - int ret; - uint8_t *key; - - *key_out = NULL; - - key = zfs_alloc(hdl, WRAPPING_KEY_LEN); - - switch (format) { - case ZFS_KEYFORMAT_RAW: - memcpy(key, key_material, WRAPPING_KEY_LEN); - break; - case ZFS_KEYFORMAT_HEX: - ret = hex_key_to_raw((char *)key_material, - WRAPPING_KEY_LEN * 2, key); - if (ret != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Invalid hex key provided.")); - goto error; - } - break; - case ZFS_KEYFORMAT_PASSPHRASE: - salt = LE_64(salt); - - ret = PKCS5_PBKDF2_HMAC_SHA1((char *)key_material, - strlen((char *)key_material), ((uint8_t *)&salt), - sizeof (uint64_t), iters, WRAPPING_KEY_LEN, key); - if (ret != 1) { - ret = EIO; - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Failed to generate key from passphrase.")); - goto error; - } - break; - default: - ret = EINVAL; - goto error; - } - - *key_out = key; - return (0); - -error: - free(key); - - *key_out = NULL; - return (ret); -} - -static boolean_t -encryption_feature_is_enabled(zpool_handle_t *zph) -{ - nvlist_t *features; - uint64_t feat_refcount; - - /* check that features can be enabled */ - if (zpool_get_prop_int(zph, ZPOOL_PROP_VERSION, NULL) - < SPA_VERSION_FEATURES) - return (B_FALSE); - - /* check for crypto feature */ - features = zpool_get_features(zph); - if (!features || nvlist_lookup_uint64(features, - spa_feature_table[SPA_FEATURE_ENCRYPTION].fi_guid, - &feat_refcount) != 0) - return (B_FALSE); - - return (B_TRUE); -} - -static int -populate_create_encryption_params_nvlists(libzfs_handle_t *hdl, - zfs_handle_t *zhp, boolean_t newkey, zfs_keyformat_t keyformat, - const char *keylocation, nvlist_t *props, uint8_t **wkeydata, - uint_t *wkeylen) -{ - int ret; - uint64_t iters = 0, salt = 0; - uint8_t *key_material = NULL; - size_t key_material_len = 0; - uint8_t *key_data = NULL; - const char *fsname = (zhp) ? zfs_get_name(zhp) : NULL; - - /* get key material from keyformat and keylocation */ - ret = get_key_material(hdl, B_TRUE, newkey, keyformat, keylocation, - fsname, &key_material, &key_material_len, NULL); - if (ret != 0) - goto error; - - /* passphrase formats require a salt and pbkdf2 iters property */ - if (keyformat == ZFS_KEYFORMAT_PASSPHRASE) { - /* always generate a new salt */ - ret = pkcs11_get_urandom((uint8_t *)&salt, sizeof (uint64_t)); - if (ret != sizeof (uint64_t)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Failed to generate salt.")); - goto error; - } - - ret = nvlist_add_uint64(props, - zfs_prop_to_name(ZFS_PROP_PBKDF2_SALT), salt); - if (ret != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Failed to add salt to properties.")); - goto error; - } - - /* - * If not otherwise specified, use the default number of - * pbkdf2 iterations. If specified, we have already checked - * that the given value is greater than MIN_PBKDF2_ITERATIONS - * during zfs_valid_proplist(). - */ - ret = nvlist_lookup_uint64(props, - zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS), &iters); - if (ret == ENOENT) { - iters = DEFAULT_PBKDF2_ITERATIONS; - ret = nvlist_add_uint64(props, - zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS), iters); - if (ret != 0) - goto error; - } else if (ret != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Failed to get pbkdf2 iterations.")); - goto error; - } - } else { - /* check that pbkdf2iters was not specified by the user */ - ret = nvlist_lookup_uint64(props, - zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS), &iters); - if (ret == 0) { - ret = EINVAL; - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Cannot specify pbkdf2iters with a non-passphrase " - "keyformat.")); - goto error; - } - } - - /* derive a key from the key material */ - ret = derive_key(hdl, keyformat, iters, key_material, salt, &key_data); - if (ret != 0) - goto error; - - free(key_material); - - *wkeydata = key_data; - *wkeylen = WRAPPING_KEY_LEN; - return (0); - -error: - if (key_material != NULL) - free(key_material); - if (key_data != NULL) - free(key_data); - - *wkeydata = NULL; - *wkeylen = 0; - return (ret); -} - -static boolean_t -proplist_has_encryption_props(nvlist_t *props) -{ - int ret; - uint64_t intval; - const char *strval; - - ret = nvlist_lookup_uint64(props, - zfs_prop_to_name(ZFS_PROP_ENCRYPTION), &intval); - if (ret == 0 && intval != ZIO_CRYPT_OFF) - return (B_TRUE); - - ret = nvlist_lookup_string(props, - zfs_prop_to_name(ZFS_PROP_KEYLOCATION), &strval); - if (ret == 0 && strcmp(strval, "none") != 0) - return (B_TRUE); - - ret = nvlist_lookup_uint64(props, - zfs_prop_to_name(ZFS_PROP_KEYFORMAT), &intval); - if (ret == 0) - return (B_TRUE); - - ret = nvlist_lookup_uint64(props, - zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS), &intval); - if (ret == 0) - return (B_TRUE); - - return (B_FALSE); -} - -int -zfs_crypto_get_encryption_root(zfs_handle_t *zhp, boolean_t *is_encroot, - char *buf) -{ - int ret; - char prop_encroot[MAXNAMELEN]; - - /* if the dataset isn't encrypted, just return */ - if (zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION) == ZIO_CRYPT_OFF) { - *is_encroot = B_FALSE; - if (buf != NULL) - buf[0] = '\0'; - return (0); - } - - ret = zfs_prop_get(zhp, ZFS_PROP_ENCRYPTION_ROOT, prop_encroot, - sizeof (prop_encroot), NULL, NULL, 0, B_TRUE); - if (ret != 0) { - *is_encroot = B_FALSE; - if (buf != NULL) - buf[0] = '\0'; - return (ret); - } - - *is_encroot = strcmp(prop_encroot, zfs_get_name(zhp)) == 0; - if (buf != NULL) - strcpy(buf, prop_encroot); - - return (0); -} - -int -zfs_crypto_create(libzfs_handle_t *hdl, char *parent_name, nvlist_t *props, - nvlist_t *pool_props, boolean_t stdin_available, uint8_t **wkeydata_out, - uint_t *wkeylen_out) -{ - int ret; - char errbuf[ERRBUFLEN]; - uint64_t crypt = ZIO_CRYPT_INHERIT, pcrypt = ZIO_CRYPT_INHERIT; - uint64_t keyformat = ZFS_KEYFORMAT_NONE; - const char *keylocation = NULL; - zfs_handle_t *pzhp = NULL; - uint8_t *wkeydata = NULL; - uint_t wkeylen = 0; - boolean_t local_crypt = B_TRUE; - - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "Encryption create error")); - - /* lookup crypt from props */ - ret = nvlist_lookup_uint64(props, - zfs_prop_to_name(ZFS_PROP_ENCRYPTION), &crypt); - if (ret != 0) - local_crypt = B_FALSE; - - /* lookup key location and format from props */ - (void) nvlist_lookup_uint64(props, - zfs_prop_to_name(ZFS_PROP_KEYFORMAT), &keyformat); - (void) nvlist_lookup_string(props, - zfs_prop_to_name(ZFS_PROP_KEYLOCATION), &keylocation); - - if (parent_name != NULL) { - /* get a reference to parent dataset */ - pzhp = make_dataset_handle(hdl, parent_name); - if (pzhp == NULL) { - ret = ENOENT; - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Failed to lookup parent.")); - goto out; - } - - /* Lookup parent's crypt */ - pcrypt = zfs_prop_get_int(pzhp, ZFS_PROP_ENCRYPTION); - - /* Params require the encryption feature */ - if (!encryption_feature_is_enabled(pzhp->zpool_hdl)) { - if (proplist_has_encryption_props(props)) { - ret = EINVAL; - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Encryption feature not enabled.")); - goto out; - } - - ret = 0; - goto out; - } - } else { - /* - * special case for root dataset where encryption feature - * feature won't be on disk yet - */ - if (!nvlist_exists(pool_props, "feature@encryption")) { - if (proplist_has_encryption_props(props)) { - ret = EINVAL; - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Encryption feature not enabled.")); - goto out; - } - - ret = 0; - goto out; - } - - pcrypt = ZIO_CRYPT_OFF; - } - - /* Get the inherited encryption property if we don't have it locally */ - if (!local_crypt) - crypt = pcrypt; - - /* - * At this point crypt should be the actual encryption value. If - * encryption is off just verify that no encryption properties have - * been specified and return. - */ - if (crypt == ZIO_CRYPT_OFF) { - if (proplist_has_encryption_props(props)) { - ret = EINVAL; - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Encryption must be turned on to set encryption " - "properties.")); - goto out; - } - - ret = 0; - goto out; - } - - /* - * If we have a parent crypt it is valid to specify encryption alone. - * This will result in a child that is encrypted with the chosen - * encryption suite that will also inherit the parent's key. If - * the parent is not encrypted we need an encryption suite provided. - */ - if (pcrypt == ZIO_CRYPT_OFF && keylocation == NULL && - keyformat == ZFS_KEYFORMAT_NONE) { - ret = EINVAL; - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Keyformat required for new encryption root.")); - goto out; - } - - /* - * Specifying a keylocation implies this will be a new encryption root. - * Check that a keyformat is also specified. - */ - if (keylocation != NULL && keyformat == ZFS_KEYFORMAT_NONE) { - ret = EINVAL; - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Keyformat required for new encryption root.")); - goto out; - } - - /* default to prompt if no keylocation is specified */ - if (keyformat != ZFS_KEYFORMAT_NONE && keylocation == NULL) { - keylocation = (char *)"prompt"; - ret = nvlist_add_string(props, - zfs_prop_to_name(ZFS_PROP_KEYLOCATION), keylocation); - if (ret != 0) - goto out; - } - - /* - * If a local key is provided, this dataset will be a new - * encryption root. Populate the encryption params. - */ - if (keylocation != NULL) { - /* - * 'zfs recv -o keylocation=prompt' won't work because stdin - * is being used by the send stream, so we disallow it. - */ - if (!stdin_available && strcmp(keylocation, "prompt") == 0) { - ret = EINVAL; - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "Cannot use " - "'prompt' keylocation because stdin is in use.")); - goto out; - } - - ret = populate_create_encryption_params_nvlists(hdl, NULL, - B_TRUE, keyformat, keylocation, props, &wkeydata, - &wkeylen); - if (ret != 0) - goto out; - } - - if (pzhp != NULL) - zfs_close(pzhp); - - *wkeydata_out = wkeydata; - *wkeylen_out = wkeylen; - return (0); - -out: - if (pzhp != NULL) - zfs_close(pzhp); - if (wkeydata != NULL) - free(wkeydata); - - *wkeydata_out = NULL; - *wkeylen_out = 0; - return (ret); -} - -int -zfs_crypto_clone_check(libzfs_handle_t *hdl, zfs_handle_t *origin_zhp, - char *parent_name, nvlist_t *props) -{ - (void) origin_zhp, (void) parent_name; - char errbuf[ERRBUFLEN]; - - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "Encryption clone error")); - - /* - * No encryption properties should be specified. They will all be - * inherited from the origin dataset. - */ - if (nvlist_exists(props, zfs_prop_to_name(ZFS_PROP_KEYFORMAT)) || - 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))) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Encryption properties must inherit from origin dataset.")); - return (EINVAL); - } - - return (0); -} - -typedef struct loadkeys_cbdata { - uint64_t cb_numfailed; - uint64_t cb_numattempted; -} loadkey_cbdata_t; - -static int -load_keys_cb(zfs_handle_t *zhp, void *arg) -{ - int ret; - boolean_t is_encroot; - loadkey_cbdata_t *cb = arg; - uint64_t keystatus = zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS); - - /* only attempt to load keys for encryption roots */ - ret = zfs_crypto_get_encryption_root(zhp, &is_encroot, NULL); - if (ret != 0 || !is_encroot) - goto out; - - /* don't attempt to load already loaded keys */ - if (keystatus == ZFS_KEYSTATUS_AVAILABLE) - goto out; - - /* Attempt to load the key. Record status in cb. */ - cb->cb_numattempted++; - - ret = zfs_crypto_load_key(zhp, B_FALSE, NULL); - if (ret) - cb->cb_numfailed++; - -out: - (void) zfs_iter_filesystems_v2(zhp, 0, load_keys_cb, cb); - zfs_close(zhp); - - /* always return 0, since this function is best effort */ - return (0); -} - -/* - * This function is best effort. It attempts to load all the keys for the given - * filesystem and all of its children. - */ -int -zfs_crypto_attempt_load_keys(libzfs_handle_t *hdl, const char *fsname) -{ - int ret; - zfs_handle_t *zhp = NULL; - loadkey_cbdata_t cb = { 0 }; - - zhp = zfs_open(hdl, fsname, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); - if (zhp == NULL) { - ret = ENOENT; - goto error; - } - - ret = load_keys_cb(zfs_handle_dup(zhp), &cb); - if (ret) - goto error; - - (void) printf(gettext("%llu / %llu keys successfully loaded\n"), - (u_longlong_t)(cb.cb_numattempted - cb.cb_numfailed), - (u_longlong_t)cb.cb_numattempted); - - if (cb.cb_numfailed != 0) { - ret = -1; - goto error; - } - - zfs_close(zhp); - return (0); - -error: - if (zhp != NULL) - zfs_close(zhp); - return (ret); -} - -int -zfs_crypto_load_key(zfs_handle_t *zhp, boolean_t noop, - const char *alt_keylocation) -{ - int ret, attempts = 0; - char errbuf[ERRBUFLEN]; - uint64_t keystatus, iters = 0, salt = 0; - uint64_t keyformat = ZFS_KEYFORMAT_NONE; - char prop_keylocation[MAXNAMELEN]; - char prop_encroot[MAXNAMELEN]; - const char *keylocation = NULL; - uint8_t *key_material = NULL, *key_data = NULL; - size_t key_material_len; - boolean_t is_encroot, can_retry = B_FALSE, correctible = B_FALSE; - - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "Key load error")); - - /* check that encryption is enabled for the pool */ - if (!encryption_feature_is_enabled(zhp->zpool_hdl)) { - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Encryption feature not enabled.")); - ret = EINVAL; - goto error; - } - - /* Fetch the keyformat. Check that the dataset is encrypted. */ - keyformat = zfs_prop_get_int(zhp, ZFS_PROP_KEYFORMAT); - if (keyformat == ZFS_KEYFORMAT_NONE) { - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "'%s' is not encrypted."), zfs_get_name(zhp)); - ret = EINVAL; - goto error; - } - - /* - * Fetch the key location. Check that we are working with an - * encryption root. - */ - ret = zfs_crypto_get_encryption_root(zhp, &is_encroot, prop_encroot); - if (ret != 0) { - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Failed to get encryption root for '%s'."), - zfs_get_name(zhp)); - goto error; - } else if (!is_encroot) { - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Keys must be loaded for encryption root of '%s' (%s)."), - zfs_get_name(zhp), prop_encroot); - ret = EINVAL; - goto error; - } - - /* - * if the caller has elected to override the keylocation property - * use that instead - */ - if (alt_keylocation != NULL) { - keylocation = alt_keylocation; - } else { - ret = zfs_prop_get(zhp, ZFS_PROP_KEYLOCATION, prop_keylocation, - sizeof (prop_keylocation), NULL, NULL, 0, B_TRUE); - if (ret != 0) { - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Failed to get keylocation for '%s'."), - zfs_get_name(zhp)); - goto error; - } - - keylocation = prop_keylocation; - } - - /* check that the key is unloaded unless this is a noop */ - if (!noop) { - keystatus = zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS); - if (keystatus == ZFS_KEYSTATUS_AVAILABLE) { - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Key already loaded for '%s'."), zfs_get_name(zhp)); - ret = EEXIST; - goto error; - } - } - - /* passphrase formats require a salt and pbkdf2_iters property */ - if (keyformat == ZFS_KEYFORMAT_PASSPHRASE) { - salt = zfs_prop_get_int(zhp, ZFS_PROP_PBKDF2_SALT); - iters = zfs_prop_get_int(zhp, ZFS_PROP_PBKDF2_ITERS); - } - -try_again: - /* fetching and deriving the key are correctable errors. set the flag */ - correctible = B_TRUE; - - /* get key material from key format and location */ - ret = get_key_material(zhp->zfs_hdl, B_FALSE, B_FALSE, keyformat, - keylocation, zfs_get_name(zhp), &key_material, &key_material_len, - &can_retry); - if (ret != 0) - goto error; - - /* derive a key from the key material */ - ret = derive_key(zhp->zfs_hdl, keyformat, iters, key_material, salt, - &key_data); - if (ret != 0) - goto error; - - correctible = B_FALSE; - - /* pass the wrapping key and noop flag to the ioctl */ - ret = lzc_load_key(zhp->zfs_name, noop, key_data, WRAPPING_KEY_LEN); - if (ret != 0) { - switch (ret) { - case EPERM: - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Permission denied.")); - break; - case EINVAL: - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Invalid parameters provided for dataset %s."), - zfs_get_name(zhp)); - break; - case EEXIST: - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Key already loaded for '%s'."), zfs_get_name(zhp)); - break; - case EBUSY: - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "'%s' is busy."), zfs_get_name(zhp)); - break; - case EACCES: - correctible = B_TRUE; - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Incorrect key provided for '%s'."), - zfs_get_name(zhp)); - break; - case ZFS_ERR_CRYPTO_NOTSUP: - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "'%s' uses an unsupported encryption suite."), - zfs_get_name(zhp)); - break; - } - goto error; - } - - free(key_material); - free(key_data); - - return (0); - -error: - zfs_error(zhp->zfs_hdl, EZFS_CRYPTOFAILED, errbuf); - if (key_material != NULL) { - free(key_material); - key_material = NULL; - } - if (key_data != NULL) { - free(key_data); - key_data = NULL; - } - - /* - * Here we decide if it is ok to allow the user to retry entering their - * key. The can_retry flag will be set if the user is entering their - * key from an interactive prompt. The correctable flag will only be - * set if an error that occurred could be corrected by retrying. Both - * flags are needed to allow the user to attempt key entry again - */ - attempts++; - if (can_retry && correctible && attempts < MAX_KEY_PROMPT_ATTEMPTS) - goto try_again; - - return (ret); -} - -int -zfs_crypto_unload_key(zfs_handle_t *zhp) -{ - int ret; - char errbuf[ERRBUFLEN]; - char prop_encroot[MAXNAMELEN]; - uint64_t keystatus, keyformat; - boolean_t is_encroot; - - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "Key unload error")); - - /* check that encryption is enabled for the pool */ - if (!encryption_feature_is_enabled(zhp->zpool_hdl)) { - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Encryption feature not enabled.")); - ret = EINVAL; - goto error; - } - - /* Fetch the keyformat. Check that the dataset is encrypted. */ - keyformat = zfs_prop_get_int(zhp, ZFS_PROP_KEYFORMAT); - if (keyformat == ZFS_KEYFORMAT_NONE) { - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "'%s' is not encrypted."), zfs_get_name(zhp)); - ret = EINVAL; - goto error; - } - - /* - * Fetch the key location. Check that we are working with an - * encryption root. - */ - ret = zfs_crypto_get_encryption_root(zhp, &is_encroot, prop_encroot); - if (ret != 0) { - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Failed to get encryption root for '%s'."), - zfs_get_name(zhp)); - goto error; - } else if (!is_encroot) { - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Keys must be unloaded for encryption root of '%s' (%s)."), - zfs_get_name(zhp), prop_encroot); - ret = EINVAL; - goto error; - } - - /* check that the key is loaded */ - keystatus = zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS); - if (keystatus == ZFS_KEYSTATUS_UNAVAILABLE) { - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Key already unloaded for '%s'."), zfs_get_name(zhp)); - ret = EACCES; - goto error; - } - - /* call the ioctl */ - ret = lzc_unload_key(zhp->zfs_name); - - if (ret != 0) { - switch (ret) { - case EPERM: - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Permission denied.")); - break; - case EACCES: - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Key already unloaded for '%s'."), - zfs_get_name(zhp)); - break; - case EBUSY: - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "'%s' is busy."), zfs_get_name(zhp)); - break; - } - zfs_error(zhp->zfs_hdl, EZFS_CRYPTOFAILED, errbuf); - } - - return (ret); - -error: - zfs_error(zhp->zfs_hdl, EZFS_CRYPTOFAILED, errbuf); - return (ret); -} - -static int -zfs_crypto_verify_rewrap_nvlist(zfs_handle_t *zhp, nvlist_t *props, - nvlist_t **props_out, char *errbuf) -{ - int ret; - nvpair_t *elem = NULL; - zfs_prop_t prop; - nvlist_t *new_props = NULL; - - new_props = fnvlist_alloc(); - - /* - * loop through all provided properties, we should only have - * keyformat, keylocation and pbkdf2iters. The actual validation of - * values is done by zfs_valid_proplist(). - */ - while ((elem = nvlist_next_nvpair(props, elem)) != NULL) { - const char *propname = nvpair_name(elem); - prop = zfs_name_to_prop(propname); - - switch (prop) { - case ZFS_PROP_PBKDF2_ITERS: - case ZFS_PROP_KEYFORMAT: - case ZFS_PROP_KEYLOCATION: - break; - default: - ret = EINVAL; - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Only keyformat, keylocation and pbkdf2iters may " - "be set with this command.")); - goto error; - } - } - - new_props = zfs_valid_proplist(zhp->zfs_hdl, zhp->zfs_type, props, - zfs_prop_get_int(zhp, ZFS_PROP_ZONED), NULL, zhp->zpool_hdl, - B_TRUE, errbuf); - if (new_props == NULL) { - ret = EINVAL; - goto error; - } - - *props_out = new_props; - return (0); - -error: - nvlist_free(new_props); - *props_out = NULL; - return (ret); -} - -int -zfs_crypto_rewrap(zfs_handle_t *zhp, nvlist_t *raw_props, boolean_t inheritkey) -{ - int ret; - char errbuf[ERRBUFLEN]; - boolean_t is_encroot; - nvlist_t *props = NULL; - uint8_t *wkeydata = NULL; - uint_t wkeylen = 0; - dcp_cmd_t cmd = (inheritkey) ? DCP_CMD_INHERIT : DCP_CMD_NEW_KEY; - uint64_t crypt, pcrypt, keystatus, pkeystatus; - uint64_t keyformat = ZFS_KEYFORMAT_NONE; - zfs_handle_t *pzhp = NULL; - const char *keylocation = NULL; - char origin_name[MAXNAMELEN]; - char prop_keylocation[MAXNAMELEN]; - char parent_name[ZFS_MAX_DATASET_NAME_LEN]; - - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "Key change error")); - - /* check that encryption is enabled for the pool */ - if (!encryption_feature_is_enabled(zhp->zpool_hdl)) { - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Encryption feature not enabled.")); - ret = EINVAL; - goto error; - } - - /* get crypt from dataset */ - crypt = zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION); - if (crypt == ZIO_CRYPT_OFF) { - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Dataset not encrypted.")); - ret = EINVAL; - goto error; - } - - /* get the encryption root of the dataset */ - ret = zfs_crypto_get_encryption_root(zhp, &is_encroot, NULL); - if (ret != 0) { - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Failed to get encryption root for '%s'."), - zfs_get_name(zhp)); - goto error; - } - - /* Clones use their origin's key and cannot rewrap it */ - ret = zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin_name, - sizeof (origin_name), NULL, NULL, 0, B_TRUE); - if (ret == 0 && strcmp(origin_name, "") != 0) { - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Keys cannot be changed on clones.")); - ret = EINVAL; - goto error; - } - - /* - * If the user wants to use the inheritkey variant of this function - * we don't need to collect any crypto arguments. - */ - if (!inheritkey) { - /* validate the provided properties */ - ret = zfs_crypto_verify_rewrap_nvlist(zhp, raw_props, &props, - errbuf); - if (ret != 0) - goto error; - - /* - * Load keyformat and keylocation from the nvlist. Fetch from - * the dataset properties if not specified. - */ - (void) nvlist_lookup_uint64(props, - zfs_prop_to_name(ZFS_PROP_KEYFORMAT), &keyformat); - (void) nvlist_lookup_string(props, - zfs_prop_to_name(ZFS_PROP_KEYLOCATION), &keylocation); - - if (is_encroot) { - /* - * If this is already an encryption root, just keep - * any properties not set by the user. - */ - if (keyformat == ZFS_KEYFORMAT_NONE) { - keyformat = zfs_prop_get_int(zhp, - ZFS_PROP_KEYFORMAT); - ret = nvlist_add_uint64(props, - zfs_prop_to_name(ZFS_PROP_KEYFORMAT), - keyformat); - if (ret != 0) { - zfs_error_aux(zhp->zfs_hdl, - dgettext(TEXT_DOMAIN, "Failed to " - "get existing keyformat " - "property.")); - goto error; - } - } - - if (keylocation == NULL) { - ret = zfs_prop_get(zhp, ZFS_PROP_KEYLOCATION, - prop_keylocation, sizeof (prop_keylocation), - NULL, NULL, 0, B_TRUE); - if (ret != 0) { - zfs_error_aux(zhp->zfs_hdl, - dgettext(TEXT_DOMAIN, "Failed to " - "get existing keylocation " - "property.")); - goto error; - } - - keylocation = prop_keylocation; - } - } else { - /* need a new key for non-encryption roots */ - if (keyformat == ZFS_KEYFORMAT_NONE) { - ret = EINVAL; - zfs_error_aux(zhp->zfs_hdl, - dgettext(TEXT_DOMAIN, "Keyformat required " - "for new encryption root.")); - goto error; - } - - /* default to prompt if no keylocation is specified */ - if (keylocation == NULL) { - keylocation = "prompt"; - ret = nvlist_add_string(props, - zfs_prop_to_name(ZFS_PROP_KEYLOCATION), - keylocation); - if (ret != 0) - goto error; - } - } - - /* fetch the new wrapping key and associated properties */ - ret = populate_create_encryption_params_nvlists(zhp->zfs_hdl, - zhp, B_TRUE, keyformat, keylocation, props, &wkeydata, - &wkeylen); - if (ret != 0) - goto error; - } else { - /* check that zhp is an encryption root */ - if (!is_encroot) { - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Key inheritting can only be performed on " - "encryption roots.")); - ret = EINVAL; - goto error; - } - - /* get the parent's name */ - ret = zfs_parent_name(zhp, parent_name, sizeof (parent_name)); - if (ret != 0) { - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Root dataset cannot inherit key.")); - ret = EINVAL; - goto error; - } - - /* get a handle to the parent */ - pzhp = make_dataset_handle(zhp->zfs_hdl, parent_name); - if (pzhp == NULL) { - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Failed to lookup parent.")); - ret = ENOENT; - goto error; - } - - /* parent must be encrypted */ - pcrypt = zfs_prop_get_int(pzhp, ZFS_PROP_ENCRYPTION); - if (pcrypt == ZIO_CRYPT_OFF) { - zfs_error_aux(pzhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Parent must be encrypted.")); - ret = EINVAL; - goto error; - } - - /* check that the parent's key is loaded */ - pkeystatus = zfs_prop_get_int(pzhp, ZFS_PROP_KEYSTATUS); - if (pkeystatus == ZFS_KEYSTATUS_UNAVAILABLE) { - zfs_error_aux(pzhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Parent key must be loaded.")); - ret = EACCES; - goto error; - } - } - - /* check that the key is loaded */ - keystatus = zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS); - if (keystatus == ZFS_KEYSTATUS_UNAVAILABLE) { - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Key must be loaded.")); - ret = EACCES; - goto error; - } - - /* call the ioctl */ - ret = lzc_change_key(zhp->zfs_name, cmd, props, wkeydata, wkeylen); - if (ret != 0) { - switch (ret) { - case EPERM: - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Permission denied.")); - break; - case EINVAL: - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Invalid properties for key change.")); - break; - case EACCES: - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Key is not currently loaded.")); - break; - } - zfs_error(zhp->zfs_hdl, EZFS_CRYPTOFAILED, errbuf); - } - - if (pzhp != NULL) - zfs_close(pzhp); - if (props != NULL) - nvlist_free(props); - if (wkeydata != NULL) - free(wkeydata); - - return (ret); - -error: - if (pzhp != NULL) - zfs_close(pzhp); - if (props != NULL) - nvlist_free(props); - if (wkeydata != NULL) - free(wkeydata); - - zfs_error(zhp->zfs_hdl, EZFS_CRYPTOFAILED, errbuf); - return (ret); -} - -boolean_t -zfs_is_encrypted(zfs_handle_t *zhp) -{ - uint8_t flags = zhp->zfs_dmustats.dds_flags; - - if (flags & DDS_FLAG_HAS_ENCRYPTED) - return ((flags & DDS_FLAG_ENCRYPTED) != 0); - - return (zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION) != ZIO_CRYPT_OFF); -} diff --git a/lib/libzfs/libzfs_dataset.c b/lib/libzfs/libzfs_dataset.c deleted file mode 100644 index e1b91fc47291..000000000000 --- a/lib/libzfs/libzfs_dataset.c +++ /dev/null @@ -1,5675 +0,0 @@ -// SPDX-License-Identifier: CDDL-1.0 -/* - * 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 - */ - -/* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2019 Joyent, Inc. - * Copyright (c) 2011, 2020 by Delphix. All rights reserved. - * Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved. - * Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>. - * Copyright (c) 2013 Martin Matuska. All rights reserved. - * Copyright (c) 2013 Steven Hartland. All rights reserved. - * Copyright 2017 Nexenta Systems, Inc. - * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com> - * Copyright 2017-2018 RackTop Systems. - * Copyright (c) 2019 Datto Inc. - * Copyright (c) 2019, loli10K <ezomori.nozomu@gmail.com> - * Copyright (c) 2021 Matt Fiddaman - */ - -#include <ctype.h> -#include <errno.h> -#include <libintl.h> -#include <stdio.h> -#include <stdlib.h> -#include <strings.h> -#include <unistd.h> -#include <stddef.h> -#include <zone.h> -#include <fcntl.h> -#include <sys/mntent.h> -#include <sys/mount.h> -#include <pwd.h> -#include <grp.h> -#ifdef HAVE_IDMAP -#include <idmap.h> -#include <aclutils.h> -#include <directory.h> -#endif /* HAVE_IDMAP */ - -#include <sys/dnode.h> -#include <sys/spa.h> -#include <sys/zap.h> -#include <sys/dsl_crypt.h> -#include <libzfs.h> -#include <libzutil.h> - -#include "zfs_namecheck.h" -#include "zfs_prop.h" -#include "libzfs_impl.h" -#include "zfs_deleg.h" - -static __thread struct passwd gpwd; -static __thread struct group ggrp; -static __thread char rpbuf[2048]; - -static int userquota_propname_decode(const char *propname, boolean_t zoned, - zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp); - -/* - * Given a single type (not a mask of types), return the type in a human - * readable form. - */ -const char * -zfs_type_to_name(zfs_type_t type) -{ - switch (type) { - case ZFS_TYPE_FILESYSTEM: - return (dgettext(TEXT_DOMAIN, "filesystem")); - case ZFS_TYPE_SNAPSHOT: - return (dgettext(TEXT_DOMAIN, "snapshot")); - case ZFS_TYPE_VOLUME: - return (dgettext(TEXT_DOMAIN, "volume")); - case ZFS_TYPE_POOL: - return (dgettext(TEXT_DOMAIN, "pool")); - case ZFS_TYPE_BOOKMARK: - return (dgettext(TEXT_DOMAIN, "bookmark")); - default: - assert(!"unhandled zfs_type_t"); - } - - return (NULL); -} - -/* - * Validate a ZFS path. This is used even before trying to open the dataset, to - * provide a more meaningful error message. We call zfs_error_aux() to - * explain exactly why the name was not valid. - */ -int -zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type, - boolean_t modifying) -{ - namecheck_err_t why; - char what; - - if (!(type & ZFS_TYPE_SNAPSHOT) && strchr(path, '@') != NULL) { - if (hdl != NULL) - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "snapshot delimiter '@' is not expected here")); - return (0); - } - - if (type == ZFS_TYPE_SNAPSHOT && strchr(path, '@') == NULL) { - if (hdl != NULL) - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "missing '@' delimiter in snapshot name")); - return (0); - } - - if (!(type & ZFS_TYPE_BOOKMARK) && strchr(path, '#') != NULL) { - if (hdl != NULL) - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "bookmark delimiter '#' is not expected here")); - return (0); - } - - if (type == ZFS_TYPE_BOOKMARK && strchr(path, '#') == NULL) { - if (hdl != NULL) - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "missing '#' delimiter in bookmark name")); - return (0); - } - - if (modifying && strchr(path, '%') != NULL) { - if (hdl != NULL) - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "invalid character %c in name"), '%'); - return (0); - } - - if (entity_namecheck(path, &why, &what) != 0) { - if (hdl != NULL) { - switch (why) { - case NAME_ERR_TOOLONG: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "name is too long")); - break; - - case NAME_ERR_LEADING_SLASH: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "leading slash in name")); - break; - - case NAME_ERR_EMPTY_COMPONENT: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "empty component or misplaced '@'" - " or '#' delimiter in name")); - break; - - case NAME_ERR_TRAILING_SLASH: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "trailing slash in name")); - break; - - case NAME_ERR_INVALCHAR: - zfs_error_aux(hdl, - dgettext(TEXT_DOMAIN, "invalid character " - "'%c' in name"), what); - break; - - case NAME_ERR_MULTIPLE_DELIMITERS: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "multiple '@' and/or '#' delimiters in " - "name")); - break; - - case NAME_ERR_NOLETTER: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "pool doesn't begin with a letter")); - break; - - case NAME_ERR_RESERVED: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "name is reserved")); - break; - - case NAME_ERR_DISKLIKE: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "reserved disk name")); - break; - - case NAME_ERR_SELF_REF: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "self reference, '.' is found in name")); - break; - - case NAME_ERR_PARENT_REF: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "parent reference, '..' is found in name")); - break; - - default: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "(%d) not defined"), why); - break; - } - } - - return (0); - } - - return (-1); -} - -int -zfs_name_valid(const char *name, zfs_type_t type) -{ - if (type == ZFS_TYPE_POOL) - return (zpool_name_valid(NULL, B_FALSE, name)); - return (zfs_validate_name(NULL, name, type, B_FALSE)); -} - -/* - * This function takes the raw DSL properties, and filters out the user-defined - * properties into a separate nvlist. - */ -static nvlist_t * -process_user_props(zfs_handle_t *zhp, nvlist_t *props) -{ - libzfs_handle_t *hdl = zhp->zfs_hdl; - nvpair_t *elem; - nvlist_t *nvl; - - if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) { - (void) no_memory(hdl); - return (NULL); - } - - elem = NULL; - while ((elem = nvlist_next_nvpair(props, elem)) != NULL) { - if (!zfs_prop_user(nvpair_name(elem))) - continue; - - nvlist_t *propval = fnvpair_value_nvlist(elem); - if (nvlist_add_nvlist(nvl, nvpair_name(elem), propval) != 0) { - nvlist_free(nvl); - (void) no_memory(hdl); - return (NULL); - } - } - - return (nvl); -} - -static zpool_handle_t * -zpool_add_handle(zfs_handle_t *zhp, const char *pool_name) -{ - libzfs_handle_t *hdl = zhp->zfs_hdl; - zpool_handle_t *zph; - - if ((zph = zpool_open_canfail(hdl, pool_name)) != NULL) { - if (hdl->libzfs_pool_handles != NULL) - zph->zpool_next = hdl->libzfs_pool_handles; - hdl->libzfs_pool_handles = zph; - } - return (zph); -} - -static zpool_handle_t * -zpool_find_handle(zfs_handle_t *zhp, const char *pool_name, int len) -{ - libzfs_handle_t *hdl = zhp->zfs_hdl; - zpool_handle_t *zph = hdl->libzfs_pool_handles; - - while ((zph != NULL) && - (strncmp(pool_name, zpool_get_name(zph), len) != 0)) - zph = zph->zpool_next; - return (zph); -} - -/* - * Returns a handle to the pool that contains the provided dataset. - * If a handle to that pool already exists then that handle is returned. - * Otherwise, a new handle is created and added to the list of handles. - */ -static zpool_handle_t * -zpool_handle(zfs_handle_t *zhp) -{ - char *pool_name; - int len; - zpool_handle_t *zph; - - len = strcspn(zhp->zfs_name, "/@#") + 1; - pool_name = zfs_alloc(zhp->zfs_hdl, len); - (void) strlcpy(pool_name, zhp->zfs_name, len); - - zph = zpool_find_handle(zhp, pool_name, len); - if (zph == NULL) - zph = zpool_add_handle(zhp, pool_name); - - free(pool_name); - return (zph); -} - -void -zpool_free_handles(libzfs_handle_t *hdl) -{ - zpool_handle_t *next, *zph = hdl->libzfs_pool_handles; - - while (zph != NULL) { - next = zph->zpool_next; - zpool_close(zph); - zph = next; - } - hdl->libzfs_pool_handles = NULL; -} - -/* - * Utility function to gather stats (objset and zpl) for the given object. - */ -static int -get_stats_ioctl(zfs_handle_t *zhp, zfs_cmd_t *zc) -{ - libzfs_handle_t *hdl = zhp->zfs_hdl; - - (void) strlcpy(zc->zc_name, zhp->zfs_name, sizeof (zc->zc_name)); - - while (zfs_ioctl(hdl, ZFS_IOC_OBJSET_STATS, zc) != 0) { - if (errno == ENOMEM) - zcmd_expand_dst_nvlist(hdl, zc); - else - return (-1); - } - return (0); -} - -/* - * Utility function to get the received properties of the given object. - */ -static int -get_recvd_props_ioctl(zfs_handle_t *zhp) -{ - libzfs_handle_t *hdl = zhp->zfs_hdl; - nvlist_t *recvdprops; - zfs_cmd_t zc = {"\0"}; - int err; - - zcmd_alloc_dst_nvlist(hdl, &zc, 0); - - (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); - - while (zfs_ioctl(hdl, ZFS_IOC_OBJSET_RECVD_PROPS, &zc) != 0) { - if (errno == ENOMEM) - zcmd_expand_dst_nvlist(hdl, &zc); - else { - zcmd_free_nvlists(&zc); - return (-1); - } - } - - err = zcmd_read_dst_nvlist(zhp->zfs_hdl, &zc, &recvdprops); - zcmd_free_nvlists(&zc); - if (err != 0) - return (-1); - - nvlist_free(zhp->zfs_recvd_props); - zhp->zfs_recvd_props = recvdprops; - - return (0); -} - -static int -put_stats_zhdl(zfs_handle_t *zhp, zfs_cmd_t *zc) -{ - nvlist_t *allprops, *userprops; - - zhp->zfs_dmustats = zc->zc_objset_stats; /* structure assignment */ - - if (zcmd_read_dst_nvlist(zhp->zfs_hdl, zc, &allprops) != 0) { - return (-1); - } - - /* - * XXX Why do we store the user props separately, in addition to - * storing them in zfs_props? - */ - if ((userprops = process_user_props(zhp, allprops)) == NULL) { - nvlist_free(allprops); - return (-1); - } - - nvlist_free(zhp->zfs_props); - nvlist_free(zhp->zfs_user_props); - - zhp->zfs_props = allprops; - zhp->zfs_user_props = userprops; - - return (0); -} - -static int -get_stats(zfs_handle_t *zhp) -{ - int rc = 0; - zfs_cmd_t zc = {"\0"}; - - zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0); - - if (get_stats_ioctl(zhp, &zc) != 0) - rc = -1; - else if (put_stats_zhdl(zhp, &zc) != 0) - rc = -1; - zcmd_free_nvlists(&zc); - return (rc); -} - -/* - * Refresh the properties currently stored in the handle. - */ -void -zfs_refresh_properties(zfs_handle_t *zhp) -{ - (void) get_stats(zhp); -} - -/* - * Makes a handle from the given dataset name. Used by zfs_open() and - * zfs_iter_* to create child handles on the fly. - */ -static int -make_dataset_handle_common(zfs_handle_t *zhp, zfs_cmd_t *zc) -{ - if (put_stats_zhdl(zhp, zc) != 0) - return (-1); - - /* - * We've managed to open the dataset and gather statistics. Determine - * the high-level type. - */ - if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) { - zhp->zfs_head_type = ZFS_TYPE_VOLUME; - } else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS) { - zhp->zfs_head_type = ZFS_TYPE_FILESYSTEM; - } else if (zhp->zfs_dmustats.dds_type == DMU_OST_OTHER) { - errno = EINVAL; - return (-1); - } else if (zhp->zfs_dmustats.dds_inconsistent) { - errno = EBUSY; - return (-1); - } else { - abort(); - } - - if (zhp->zfs_dmustats.dds_is_snapshot) - zhp->zfs_type = ZFS_TYPE_SNAPSHOT; - else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) - zhp->zfs_type = ZFS_TYPE_VOLUME; - else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS) - zhp->zfs_type = ZFS_TYPE_FILESYSTEM; - else - abort(); /* we should never see any other types */ - - if ((zhp->zpool_hdl = zpool_handle(zhp)) == NULL) - return (-1); - - return (0); -} - -zfs_handle_t * -make_dataset_handle(libzfs_handle_t *hdl, const char *path) -{ - zfs_cmd_t zc = {"\0"}; - - zfs_handle_t *zhp = calloc(1, sizeof (zfs_handle_t)); - - if (zhp == NULL) - return (NULL); - - zhp->zfs_hdl = hdl; - (void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name)); - zcmd_alloc_dst_nvlist(hdl, &zc, 0); - - if (get_stats_ioctl(zhp, &zc) == -1) { - zcmd_free_nvlists(&zc); - free(zhp); - return (NULL); - } - if (make_dataset_handle_common(zhp, &zc) == -1) { - free(zhp); - zhp = NULL; - } - zcmd_free_nvlists(&zc); - return (zhp); -} - -zfs_handle_t * -make_dataset_handle_zc(libzfs_handle_t *hdl, zfs_cmd_t *zc) -{ - zfs_handle_t *zhp = calloc(1, sizeof (zfs_handle_t)); - - if (zhp == NULL) - return (NULL); - - zhp->zfs_hdl = hdl; - (void) strlcpy(zhp->zfs_name, zc->zc_name, sizeof (zhp->zfs_name)); - if (make_dataset_handle_common(zhp, zc) == -1) { - free(zhp); - return (NULL); - } - return (zhp); -} - -zfs_handle_t * -make_dataset_simple_handle_zc(zfs_handle_t *pzhp, zfs_cmd_t *zc) -{ - zfs_handle_t *zhp = calloc(1, sizeof (zfs_handle_t)); - - if (zhp == NULL) - return (NULL); - - zhp->zfs_hdl = pzhp->zfs_hdl; - (void) strlcpy(zhp->zfs_name, zc->zc_name, sizeof (zhp->zfs_name)); - zhp->zfs_head_type = pzhp->zfs_type; - zhp->zfs_type = ZFS_TYPE_SNAPSHOT; - zhp->zpool_hdl = zpool_handle(zhp); - - if (zc->zc_objset_stats.dds_creation_txg != 0) { - /* structure assignment */ - zhp->zfs_dmustats = zc->zc_objset_stats; - } else { - if (get_stats_ioctl(zhp, zc) == -1) { - zcmd_free_nvlists(zc); - free(zhp); - return (NULL); - } - if (make_dataset_handle_common(zhp, zc) == -1) { - zcmd_free_nvlists(zc); - free(zhp); - return (NULL); - } - } - - if (zhp->zfs_dmustats.dds_is_snapshot || - strchr(zc->zc_name, '@') != NULL) - zhp->zfs_type = ZFS_TYPE_SNAPSHOT; - else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) - zhp->zfs_type = ZFS_TYPE_VOLUME; - else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS) - zhp->zfs_type = ZFS_TYPE_FILESYSTEM; - - return (zhp); -} - -zfs_handle_t * -zfs_handle_dup(zfs_handle_t *zhp_orig) -{ - zfs_handle_t *zhp = calloc(1, sizeof (zfs_handle_t)); - - if (zhp == NULL) - return (NULL); - - zhp->zfs_hdl = zhp_orig->zfs_hdl; - zhp->zpool_hdl = zhp_orig->zpool_hdl; - (void) strlcpy(zhp->zfs_name, zhp_orig->zfs_name, - sizeof (zhp->zfs_name)); - zhp->zfs_type = zhp_orig->zfs_type; - zhp->zfs_head_type = zhp_orig->zfs_head_type; - zhp->zfs_dmustats = zhp_orig->zfs_dmustats; - if (zhp_orig->zfs_props != NULL) { - if (nvlist_dup(zhp_orig->zfs_props, &zhp->zfs_props, 0) != 0) { - (void) no_memory(zhp->zfs_hdl); - zfs_close(zhp); - return (NULL); - } - } - if (zhp_orig->zfs_user_props != NULL) { - if (nvlist_dup(zhp_orig->zfs_user_props, - &zhp->zfs_user_props, 0) != 0) { - (void) no_memory(zhp->zfs_hdl); - zfs_close(zhp); - return (NULL); - } - } - if (zhp_orig->zfs_recvd_props != NULL) { - if (nvlist_dup(zhp_orig->zfs_recvd_props, - &zhp->zfs_recvd_props, 0)) { - (void) no_memory(zhp->zfs_hdl); - zfs_close(zhp); - return (NULL); - } - } - zhp->zfs_mntcheck = zhp_orig->zfs_mntcheck; - if (zhp_orig->zfs_mntopts != NULL) { - zhp->zfs_mntopts = zfs_strdup(zhp_orig->zfs_hdl, - zhp_orig->zfs_mntopts); - } - zhp->zfs_props_table = zhp_orig->zfs_props_table; - return (zhp); -} - -boolean_t -zfs_bookmark_exists(const char *path) -{ - nvlist_t *bmarks; - nvlist_t *props; - char fsname[ZFS_MAX_DATASET_NAME_LEN]; - char *bmark_name; - char *pound; - int err; - boolean_t rv; - - (void) strlcpy(fsname, path, sizeof (fsname)); - pound = strchr(fsname, '#'); - if (pound == NULL) - return (B_FALSE); - - *pound = '\0'; - bmark_name = pound + 1; - props = fnvlist_alloc(); - err = lzc_get_bookmarks(fsname, props, &bmarks); - nvlist_free(props); - if (err != 0) { - nvlist_free(bmarks); - return (B_FALSE); - } - - rv = nvlist_exists(bmarks, bmark_name); - nvlist_free(bmarks); - return (rv); -} - -zfs_handle_t * -make_bookmark_handle(zfs_handle_t *parent, const char *path, - nvlist_t *bmark_props) -{ - zfs_handle_t *zhp = calloc(1, sizeof (zfs_handle_t)); - - if (zhp == NULL) - return (NULL); - - /* Fill in the name. */ - zhp->zfs_hdl = parent->zfs_hdl; - (void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name)); - - /* Set the property lists. */ - if (nvlist_dup(bmark_props, &zhp->zfs_props, 0) != 0) { - free(zhp); - return (NULL); - } - - /* Set the types. */ - zhp->zfs_head_type = parent->zfs_head_type; - zhp->zfs_type = ZFS_TYPE_BOOKMARK; - - if ((zhp->zpool_hdl = zpool_handle(zhp)) == NULL) { - nvlist_free(zhp->zfs_props); - free(zhp); - return (NULL); - } - - return (zhp); -} - -struct zfs_open_bookmarks_cb_data { - const char *path; - zfs_handle_t *zhp; -}; - -static int -zfs_open_bookmarks_cb(zfs_handle_t *zhp, void *data) -{ - struct zfs_open_bookmarks_cb_data *dp = data; - - /* - * Is it the one we are looking for? - */ - if (strcmp(dp->path, zfs_get_name(zhp)) == 0) { - /* - * We found it. Save it and let the caller know we are done. - */ - dp->zhp = zhp; - return (EEXIST); - } - - /* - * Not found. Close the handle and ask for another one. - */ - zfs_close(zhp); - return (0); -} - -/* - * Opens the given snapshot, bookmark, filesystem, or volume. The 'types' - * argument is a mask of acceptable types. The function will print an - * appropriate error message and return NULL if it can't be opened. - */ -zfs_handle_t * -zfs_open(libzfs_handle_t *hdl, const char *path, int types) -{ - zfs_handle_t *zhp; - char errbuf[ERRBUFLEN]; - char *bookp; - - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot open '%s'"), path); - - /* - * Validate the name before we even try to open it. - */ - if (!zfs_validate_name(hdl, path, types, B_FALSE)) { - (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf); - errno = EINVAL; - return (NULL); - } - - /* - * Bookmarks needs to be handled separately. - */ - bookp = strchr(path, '#'); - if (bookp == NULL) { - /* - * Try to get stats for the dataset, which will tell us if it - * exists. - */ - errno = 0; - if ((zhp = make_dataset_handle(hdl, path)) == NULL) { - (void) zfs_standard_error(hdl, errno, errbuf); - return (NULL); - } - } else { - char dsname[ZFS_MAX_DATASET_NAME_LEN]; - zfs_handle_t *pzhp; - struct zfs_open_bookmarks_cb_data cb_data = {path, NULL}; - - /* - * We need to cut out '#' and everything after '#' - * to get the parent dataset name only. - */ - assert(bookp - path < sizeof (dsname)); - (void) strlcpy(dsname, path, - MIN(sizeof (dsname), bookp - path + 1)); - - /* - * Create handle for the parent dataset. - */ - errno = 0; - if ((pzhp = make_dataset_handle(hdl, dsname)) == NULL) { - (void) zfs_standard_error(hdl, errno, errbuf); - return (NULL); - } - - /* - * Iterate bookmarks to find the right one. - */ - errno = 0; - if ((zfs_iter_bookmarks_v2(pzhp, 0, zfs_open_bookmarks_cb, - &cb_data) == 0) && (cb_data.zhp == NULL)) { - (void) zfs_error(hdl, EZFS_NOENT, errbuf); - zfs_close(pzhp); - errno = ENOENT; - return (NULL); - } - if (cb_data.zhp == NULL) { - (void) zfs_standard_error(hdl, errno, errbuf); - zfs_close(pzhp); - return (NULL); - } - zhp = cb_data.zhp; - - /* - * Cleanup. - */ - zfs_close(pzhp); - } - - if (!(types & zhp->zfs_type)) { - (void) zfs_error(hdl, EZFS_BADTYPE, errbuf); - zfs_close(zhp); - errno = EINVAL; - return (NULL); - } - - return (zhp); -} - -/* - * Release a ZFS handle. Nothing to do but free the associated memory. - */ -void -zfs_close(zfs_handle_t *zhp) -{ - if (zhp->zfs_mntopts) - free(zhp->zfs_mntopts); - nvlist_free(zhp->zfs_props); - nvlist_free(zhp->zfs_user_props); - nvlist_free(zhp->zfs_recvd_props); - free(zhp); -} - -typedef struct mnttab_node { - struct mnttab mtn_mt; - avl_node_t mtn_node; -} mnttab_node_t; - -static int -libzfs_mnttab_cache_compare(const void *arg1, const void *arg2) -{ - const mnttab_node_t *mtn1 = (const mnttab_node_t *)arg1; - const mnttab_node_t *mtn2 = (const mnttab_node_t *)arg2; - int rv; - - rv = strcmp(mtn1->mtn_mt.mnt_special, mtn2->mtn_mt.mnt_special); - - return (TREE_ISIGN(rv)); -} - -void -libzfs_mnttab_init(libzfs_handle_t *hdl) -{ - pthread_mutex_init(&hdl->libzfs_mnttab_cache_lock, NULL); - assert(avl_numnodes(&hdl->libzfs_mnttab_cache) == 0); - avl_create(&hdl->libzfs_mnttab_cache, libzfs_mnttab_cache_compare, - sizeof (mnttab_node_t), offsetof(mnttab_node_t, mtn_node)); -} - -static int -libzfs_mnttab_update(libzfs_handle_t *hdl) -{ - FILE *mnttab; - struct mnttab entry; - - if ((mnttab = fopen(MNTTAB, "re")) == NULL) - return (ENOENT); - - while (getmntent(mnttab, &entry) == 0) { - mnttab_node_t *mtn; - avl_index_t where; - - if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) - continue; - - mtn = zfs_alloc(hdl, sizeof (mnttab_node_t)); - mtn->mtn_mt.mnt_special = zfs_strdup(hdl, entry.mnt_special); - mtn->mtn_mt.mnt_mountp = zfs_strdup(hdl, entry.mnt_mountp); - mtn->mtn_mt.mnt_fstype = zfs_strdup(hdl, entry.mnt_fstype); - mtn->mtn_mt.mnt_mntopts = zfs_strdup(hdl, entry.mnt_mntopts); - - /* Exclude duplicate mounts */ - if (avl_find(&hdl->libzfs_mnttab_cache, mtn, &where) != NULL) { - free(mtn->mtn_mt.mnt_special); - free(mtn->mtn_mt.mnt_mountp); - free(mtn->mtn_mt.mnt_fstype); - free(mtn->mtn_mt.mnt_mntopts); - free(mtn); - continue; - } - - avl_add(&hdl->libzfs_mnttab_cache, mtn); - } - - (void) fclose(mnttab); - return (0); -} - -void -libzfs_mnttab_fini(libzfs_handle_t *hdl) -{ - void *cookie = NULL; - mnttab_node_t *mtn; - - while ((mtn = avl_destroy_nodes(&hdl->libzfs_mnttab_cache, &cookie)) - != NULL) { - free(mtn->mtn_mt.mnt_special); - free(mtn->mtn_mt.mnt_mountp); - free(mtn->mtn_mt.mnt_fstype); - free(mtn->mtn_mt.mnt_mntopts); - free(mtn); - } - avl_destroy(&hdl->libzfs_mnttab_cache); - (void) pthread_mutex_destroy(&hdl->libzfs_mnttab_cache_lock); -} - -void -libzfs_mnttab_cache(libzfs_handle_t *hdl, boolean_t enable) -{ - hdl->libzfs_mnttab_enable = enable; -} - -int -libzfs_mnttab_find(libzfs_handle_t *hdl, const char *fsname, - struct mnttab *entry) -{ - FILE *mnttab; - mnttab_node_t find; - mnttab_node_t *mtn; - int ret = ENOENT; - - if (!hdl->libzfs_mnttab_enable) { - struct mnttab srch = { 0 }; - - if (avl_numnodes(&hdl->libzfs_mnttab_cache)) - libzfs_mnttab_fini(hdl); - - if ((mnttab = fopen(MNTTAB, "re")) == NULL) - return (ENOENT); - - srch.mnt_special = (char *)fsname; - srch.mnt_fstype = (char *)MNTTYPE_ZFS; - ret = getmntany(mnttab, entry, &srch) ? ENOENT : 0; - (void) fclose(mnttab); - return (ret); - } - - pthread_mutex_lock(&hdl->libzfs_mnttab_cache_lock); - if (avl_numnodes(&hdl->libzfs_mnttab_cache) == 0) { - int error; - - if ((error = libzfs_mnttab_update(hdl)) != 0) { - pthread_mutex_unlock(&hdl->libzfs_mnttab_cache_lock); - return (error); - } - } - - find.mtn_mt.mnt_special = (char *)fsname; - mtn = avl_find(&hdl->libzfs_mnttab_cache, &find, NULL); - if (mtn) { - *entry = mtn->mtn_mt; - ret = 0; - } - pthread_mutex_unlock(&hdl->libzfs_mnttab_cache_lock); - return (ret); -} - -void -libzfs_mnttab_add(libzfs_handle_t *hdl, const char *special, - const char *mountp, const char *mntopts) -{ - mnttab_node_t *mtn; - - pthread_mutex_lock(&hdl->libzfs_mnttab_cache_lock); - if (avl_numnodes(&hdl->libzfs_mnttab_cache) != 0) { - mtn = zfs_alloc(hdl, sizeof (mnttab_node_t)); - mtn->mtn_mt.mnt_special = zfs_strdup(hdl, special); - mtn->mtn_mt.mnt_mountp = zfs_strdup(hdl, mountp); - mtn->mtn_mt.mnt_fstype = zfs_strdup(hdl, MNTTYPE_ZFS); - mtn->mtn_mt.mnt_mntopts = zfs_strdup(hdl, mntopts); - /* - * Another thread may have already added this entry - * via libzfs_mnttab_update. If so we should skip it. - */ - if (avl_find(&hdl->libzfs_mnttab_cache, mtn, NULL) != NULL) { - free(mtn->mtn_mt.mnt_special); - free(mtn->mtn_mt.mnt_mountp); - free(mtn->mtn_mt.mnt_fstype); - free(mtn->mtn_mt.mnt_mntopts); - free(mtn); - } else { - avl_add(&hdl->libzfs_mnttab_cache, mtn); - } - } - pthread_mutex_unlock(&hdl->libzfs_mnttab_cache_lock); -} - -void -libzfs_mnttab_remove(libzfs_handle_t *hdl, const char *fsname) -{ - mnttab_node_t find; - mnttab_node_t *ret; - - pthread_mutex_lock(&hdl->libzfs_mnttab_cache_lock); - find.mtn_mt.mnt_special = (char *)fsname; - if ((ret = avl_find(&hdl->libzfs_mnttab_cache, (void *)&find, NULL)) - != NULL) { - avl_remove(&hdl->libzfs_mnttab_cache, ret); - free(ret->mtn_mt.mnt_special); - free(ret->mtn_mt.mnt_mountp); - free(ret->mtn_mt.mnt_fstype); - free(ret->mtn_mt.mnt_mntopts); - free(ret); - } - pthread_mutex_unlock(&hdl->libzfs_mnttab_cache_lock); -} - -int -zfs_spa_version(zfs_handle_t *zhp, int *spa_version) -{ - zpool_handle_t *zpool_handle = zhp->zpool_hdl; - - if (zpool_handle == NULL) - return (-1); - - *spa_version = zpool_get_prop_int(zpool_handle, - ZPOOL_PROP_VERSION, NULL); - return (0); -} - -/* - * The choice of reservation property depends on the SPA version. - */ -static int -zfs_which_resv_prop(zfs_handle_t *zhp, zfs_prop_t *resv_prop) -{ - int spa_version; - - if (zfs_spa_version(zhp, &spa_version) < 0) - return (-1); - - if (spa_version >= SPA_VERSION_REFRESERVATION) - *resv_prop = ZFS_PROP_REFRESERVATION; - else - *resv_prop = ZFS_PROP_RESERVATION; - - return (0); -} - -/* - * Given an nvlist of properties to set, validates that they are correct, and - * parses any numeric properties (index, boolean, etc) if they are specified as - * strings. - */ -nvlist_t * -zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl, - uint64_t zoned, zfs_handle_t *zhp, zpool_handle_t *zpool_hdl, - boolean_t key_params_ok, const char *errbuf) -{ - nvpair_t *elem; - uint64_t intval; - const char *strval; - zfs_prop_t prop; - nvlist_t *ret; - int chosen_normal = -1; - int chosen_utf = -1; - - if (nvlist_alloc(&ret, NV_UNIQUE_NAME, 0) != 0) { - (void) no_memory(hdl); - return (NULL); - } - - /* - * Make sure this property is valid and applies to this type. - */ - - elem = NULL; - while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { - const char *propname = nvpair_name(elem); - - prop = zfs_name_to_prop(propname); - if (prop == ZPROP_USERPROP && zfs_prop_user(propname)) { - /* - * This is a user property: make sure it's a - * string, and that it's less than ZAP_MAXNAMELEN. - */ - if (nvpair_type(elem) != DATA_TYPE_STRING) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "'%s' must be a string"), propname); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - - if (strlen(nvpair_name(elem)) >= ZAP_MAXNAMELEN) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "property name '%s' is too long"), - propname); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - - (void) nvpair_value_string(elem, &strval); - if (nvlist_add_string(ret, propname, strval) != 0) { - (void) no_memory(hdl); - goto error; - } - continue; - } - - /* - * Currently, only user properties can be modified on - * snapshots. - */ - if (type == ZFS_TYPE_SNAPSHOT) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "this property can not be modified for snapshots")); - (void) zfs_error(hdl, EZFS_PROPTYPE, errbuf); - goto error; - } - - if (prop == ZPROP_USERPROP && zfs_prop_userquota(propname)) { - zfs_userquota_prop_t uqtype; - char *newpropname = NULL; - char domain[128]; - uint64_t rid; - uint64_t valary[3]; - int rc; - - if (userquota_propname_decode(propname, zoned, - &uqtype, domain, sizeof (domain), &rid) != 0) { - zfs_error_aux(hdl, - dgettext(TEXT_DOMAIN, - "'%s' has an invalid user/group name"), - propname); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - - if (uqtype != ZFS_PROP_USERQUOTA && - uqtype != ZFS_PROP_GROUPQUOTA && - uqtype != ZFS_PROP_USEROBJQUOTA && - uqtype != ZFS_PROP_GROUPOBJQUOTA && - uqtype != ZFS_PROP_PROJECTQUOTA && - uqtype != ZFS_PROP_PROJECTOBJQUOTA) { - zfs_error_aux(hdl, - dgettext(TEXT_DOMAIN, "'%s' is readonly"), - propname); - (void) zfs_error(hdl, EZFS_PROPREADONLY, - errbuf); - goto error; - } - - if (nvpair_type(elem) == DATA_TYPE_STRING) { - (void) nvpair_value_string(elem, &strval); - if (strcmp(strval, "none") == 0) { - intval = 0; - } else if (zfs_nicestrtonum(hdl, - strval, &intval) != 0) { - (void) zfs_error(hdl, - EZFS_BADPROP, errbuf); - goto error; - } - } else if (nvpair_type(elem) == - DATA_TYPE_UINT64) { - (void) nvpair_value_uint64(elem, &intval); - if (intval == 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "use 'none' to disable " - "{user|group|project}quota")); - goto error; - } - } else { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "'%s' must be a number"), propname); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - - /* - * Encode the prop name as - * userquota@<hex-rid>-domain, to make it easy - * for the kernel to decode. - */ - rc = asprintf(&newpropname, "%s%llx-%s", - zfs_userquota_prop_prefixes[uqtype], - (longlong_t)rid, domain); - if (rc == -1 || newpropname == NULL) { - (void) no_memory(hdl); - goto error; - } - - valary[0] = uqtype; - valary[1] = rid; - valary[2] = intval; - if (nvlist_add_uint64_array(ret, newpropname, - valary, 3) != 0) { - free(newpropname); - (void) no_memory(hdl); - goto error; - } - free(newpropname); - continue; - } else if (prop == ZPROP_USERPROP && - zfs_prop_written(propname)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "'%s' is readonly"), - propname); - (void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf); - goto error; - } - - if (prop == ZPROP_INVAL) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "invalid property '%s'"), propname); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - - if (!zfs_prop_valid_for_type(prop, type, B_FALSE)) { - zfs_error_aux(hdl, - dgettext(TEXT_DOMAIN, "'%s' does not " - "apply to datasets of this type"), propname); - (void) zfs_error(hdl, EZFS_PROPTYPE, errbuf); - goto error; - } - - if (zfs_prop_readonly(prop) && - !(zfs_prop_setonce(prop) && zhp == NULL) && - !(zfs_prop_encryption_key_param(prop) && key_params_ok)) { - zfs_error_aux(hdl, - dgettext(TEXT_DOMAIN, "'%s' is readonly"), - propname); - (void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf); - goto error; - } - - if (zprop_parse_value(hdl, elem, prop, type, ret, - &strval, &intval, errbuf) != 0) - goto error; - - /* - * Perform some additional checks for specific properties. - */ - switch (prop) { - case ZFS_PROP_VERSION: - { - int version; - - if (zhp == NULL) - break; - version = zfs_prop_get_int(zhp, ZFS_PROP_VERSION); - if (intval < version) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Can not downgrade; already at version %u"), - version); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - break; - } - - case ZFS_PROP_VOLBLOCKSIZE: - case ZFS_PROP_RECORDSIZE: - { - int maxbs = SPA_MAXBLOCKSIZE; - char buf[64]; - - if (zpool_hdl != NULL) { - maxbs = zpool_get_prop_int(zpool_hdl, - ZPOOL_PROP_MAXBLOCKSIZE, NULL); - } - /* - * The value must be a power of two between - * SPA_MINBLOCKSIZE and maxbs. - */ - if (intval < SPA_MINBLOCKSIZE || - intval > maxbs || !ISP2(intval)) { - zfs_nicebytes(maxbs, buf, sizeof (buf)); - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "'%s' must be power of 2 from 512B " - "to %s"), propname, buf); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - break; - } - - case ZFS_PROP_SPECIAL_SMALL_BLOCKS: - { - int maxbs = SPA_MAXBLOCKSIZE; - char buf[64]; - - if (intval > SPA_MAXBLOCKSIZE) { - zfs_nicebytes(maxbs, buf, sizeof (buf)); - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "invalid '%s' property: must be between " - "zero and %s"), - propname, buf); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - break; - } - - case ZFS_PROP_MLSLABEL: - { -#ifdef HAVE_MLSLABEL - /* - * Verify the mlslabel string and convert to - * internal hex label string. - */ - - m_label_t *new_sl; - char *hex = NULL; /* internal label string */ - - /* Default value is already OK. */ - if (strcasecmp(strval, ZFS_MLSLABEL_DEFAULT) == 0) - break; - - /* Verify the label can be converted to binary form */ - if (((new_sl = m_label_alloc(MAC_LABEL)) == NULL) || - (str_to_label(strval, &new_sl, MAC_LABEL, - L_NO_CORRECTION, NULL) == -1)) { - goto badlabel; - } - - /* Now translate to hex internal label string */ - if (label_to_str(new_sl, &hex, M_INTERNAL, - DEF_NAMES) != 0) { - if (hex) - free(hex); - goto badlabel; - } - m_label_free(new_sl); - - /* If string is already in internal form, we're done. */ - if (strcmp(strval, hex) == 0) { - free(hex); - break; - } - - /* Replace the label string with the internal form. */ - (void) nvlist_remove(ret, zfs_prop_to_name(prop), - DATA_TYPE_STRING); - fnvlist_add_string(ret, zfs_prop_to_name(prop), hex); - free(hex); - - break; - -badlabel: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "invalid mlslabel '%s'"), strval); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - m_label_free(new_sl); /* OK if null */ - goto error; -#else - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "mlslabels are unsupported")); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; -#endif /* HAVE_MLSLABEL */ - } - - case ZFS_PROP_MOUNTPOINT: - { - namecheck_err_t why; - - if (strcmp(strval, ZFS_MOUNTPOINT_NONE) == 0 || - strcmp(strval, ZFS_MOUNTPOINT_LEGACY) == 0) - break; - - if (mountpoint_namecheck(strval, &why)) { - switch (why) { - case NAME_ERR_LEADING_SLASH: - zfs_error_aux(hdl, - dgettext(TEXT_DOMAIN, - "'%s' must be an absolute path, " - "'none', or 'legacy'"), propname); - break; - case NAME_ERR_TOOLONG: - zfs_error_aux(hdl, - dgettext(TEXT_DOMAIN, - "component of '%s' is too long"), - propname); - break; - - default: - zfs_error_aux(hdl, - dgettext(TEXT_DOMAIN, - "(%d) not defined"), - why); - break; - } - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - zfs_fallthrough; - } - - case ZFS_PROP_SHARESMB: - case ZFS_PROP_SHARENFS: - /* - * For the mountpoint and sharenfs or sharesmb - * properties, check if it can be set in a - * global/non-global zone based on - * the zoned property value: - * - * global zone non-global zone - * -------------------------------------------------- - * zoned=on mountpoint (no) mountpoint (yes) - * sharenfs (no) sharenfs (no) - * sharesmb (no) sharesmb (no) - * - * zoned=off mountpoint (yes) N/A - * sharenfs (yes) - * sharesmb (yes) - */ - if (zoned) { - if (getzoneid() == GLOBAL_ZONEID) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "'%s' cannot be set on " - "dataset in a non-global zone"), - propname); - (void) zfs_error(hdl, EZFS_ZONED, - errbuf); - goto error; - } else if (prop == ZFS_PROP_SHARENFS || - prop == ZFS_PROP_SHARESMB) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "'%s' cannot be set in " - "a non-global zone"), propname); - (void) zfs_error(hdl, EZFS_ZONED, - errbuf); - goto error; - } - } else if (getzoneid() != GLOBAL_ZONEID) { - /* - * If zoned property is 'off', this must be in - * a global zone. If not, something is wrong. - */ - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "'%s' cannot be set while dataset " - "'zoned' property is set"), propname); - (void) zfs_error(hdl, EZFS_ZONED, errbuf); - goto error; - } - - /* - * At this point, it is legitimate to set the - * property. Now we want to make sure that the - * property value is valid if it is sharenfs. - */ - if ((prop == ZFS_PROP_SHARENFS || - prop == ZFS_PROP_SHARESMB) && - strcmp(strval, "on") != 0 && - strcmp(strval, "off") != 0) { - enum sa_protocol proto; - - if (prop == ZFS_PROP_SHARESMB) - proto = SA_PROTOCOL_SMB; - else - proto = SA_PROTOCOL_NFS; - - if (sa_validate_shareopts(strval, proto) != - SA_OK) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "'%s' cannot be set to invalid " - "options"), propname); - (void) zfs_error(hdl, EZFS_BADPROP, - errbuf); - goto error; - } - } - - break; - - case ZFS_PROP_KEYLOCATION: - if (!zfs_prop_valid_keylocation(strval, B_FALSE)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "invalid keylocation")); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - - if (zhp != NULL) { - uint64_t crypt = - zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION); - - if (crypt == ZIO_CRYPT_OFF && - strcmp(strval, "none") != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "keylocation must be 'none' " - "for unencrypted datasets")); - (void) zfs_error(hdl, EZFS_BADPROP, - errbuf); - goto error; - } else if (crypt != ZIO_CRYPT_OFF && - strcmp(strval, "none") == 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "keylocation must not be 'none' " - "for encrypted datasets")); - (void) zfs_error(hdl, EZFS_BADPROP, - errbuf); - goto error; - } - } - break; - - case ZFS_PROP_PBKDF2_ITERS: - if (intval < MIN_PBKDF2_ITERATIONS) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "minimum pbkdf2 iterations is %u"), - MIN_PBKDF2_ITERATIONS); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - break; - - case ZFS_PROP_UTF8ONLY: - chosen_utf = (int)intval; - break; - - case ZFS_PROP_NORMALIZE: - chosen_normal = (int)intval; - break; - - default: - break; - } - - /* - * For changes to existing volumes, we have some additional - * checks to enforce. - */ - if (type == ZFS_TYPE_VOLUME && zhp != NULL) { - uint64_t blocksize = zfs_prop_get_int(zhp, - ZFS_PROP_VOLBLOCKSIZE); - char buf[64]; - - switch (prop) { - case ZFS_PROP_VOLSIZE: - if (intval % blocksize != 0) { - zfs_nicebytes(blocksize, buf, - sizeof (buf)); - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "'%s' must be a multiple of " - "volume block size (%s)"), - propname, buf); - (void) zfs_error(hdl, EZFS_BADPROP, - errbuf); - goto error; - } - - if (intval == 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "'%s' cannot be zero"), - propname); - (void) zfs_error(hdl, EZFS_BADPROP, - errbuf); - goto error; - } - break; - - default: - break; - } - } - - /* check encryption properties */ - if (zhp != NULL) { - int64_t crypt = zfs_prop_get_int(zhp, - ZFS_PROP_ENCRYPTION); - - switch (prop) { - case ZFS_PROP_COPIES: - if (crypt != ZIO_CRYPT_OFF && intval > 2) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "encrypted datasets cannot have " - "3 copies")); - (void) zfs_error(hdl, EZFS_BADPROP, - errbuf); - goto error; - } - break; - default: - break; - } - } - } - - /* - * If normalization was chosen, but no UTF8 choice was made, - * enforce rejection of non-UTF8 names. - * - * If normalization was chosen, but rejecting non-UTF8 names - * was explicitly not chosen, it is an error. - * - * If utf8only was turned off, but the parent has normalization, - * turn off normalization. - */ - if (chosen_normal > 0 && chosen_utf < 0) { - if (nvlist_add_uint64(ret, - zfs_prop_to_name(ZFS_PROP_UTF8ONLY), 1) != 0) { - (void) no_memory(hdl); - goto error; - } - } else if (chosen_normal > 0 && chosen_utf == 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "'%s' must be set 'on' if normalization chosen"), - zfs_prop_to_name(ZFS_PROP_UTF8ONLY)); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } else if (chosen_normal < 0 && chosen_utf == 0) { - if (nvlist_add_uint64(ret, - zfs_prop_to_name(ZFS_PROP_NORMALIZE), 0) != 0) { - (void) no_memory(hdl); - goto error; - } - } - return (ret); - -error: - nvlist_free(ret); - return (NULL); -} - -static int -zfs_add_synthetic_resv(zfs_handle_t *zhp, nvlist_t *nvl) -{ - uint64_t old_volsize; - uint64_t new_volsize; - uint64_t old_reservation; - uint64_t new_reservation; - zfs_prop_t resv_prop; - nvlist_t *props; - zpool_handle_t *zph = zpool_handle(zhp); - - /* - * If this is an existing volume, and someone is setting the volsize, - * make sure that it matches the reservation, or add it if necessary. - */ - old_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE); - if (zfs_which_resv_prop(zhp, &resv_prop) < 0) - return (-1); - old_reservation = zfs_prop_get_int(zhp, resv_prop); - - props = fnvlist_alloc(); - fnvlist_add_uint64(props, zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), - zfs_prop_get_int(zhp, ZFS_PROP_VOLBLOCKSIZE)); - - if ((zvol_volsize_to_reservation(zph, old_volsize, props) != - old_reservation) || nvlist_exists(nvl, - zfs_prop_to_name(resv_prop))) { - fnvlist_free(props); - return (0); - } - if (nvlist_lookup_uint64(nvl, zfs_prop_to_name(ZFS_PROP_VOLSIZE), - &new_volsize) != 0) { - fnvlist_free(props); - return (-1); - } - new_reservation = zvol_volsize_to_reservation(zph, new_volsize, props); - fnvlist_free(props); - - if (nvlist_add_uint64(nvl, zfs_prop_to_name(resv_prop), - new_reservation) != 0) { - (void) no_memory(zhp->zfs_hdl); - return (-1); - } - return (1); -} - -/* - * Helper for 'zfs {set|clone} refreservation=auto'. Must be called after - * zfs_valid_proplist(), as it is what sets the UINT64_MAX sentinel value. - * Return codes must match zfs_add_synthetic_resv(). - */ -static int -zfs_fix_auto_resv(zfs_handle_t *zhp, nvlist_t *nvl) -{ - uint64_t volsize; - uint64_t resvsize; - zfs_prop_t prop; - nvlist_t *props; - - if (!ZFS_IS_VOLUME(zhp)) { - return (0); - } - - if (zfs_which_resv_prop(zhp, &prop) != 0) { - return (-1); - } - - if (prop != ZFS_PROP_REFRESERVATION) { - return (0); - } - - if (nvlist_lookup_uint64(nvl, zfs_prop_to_name(prop), &resvsize) != 0) { - /* No value being set, so it can't be "auto" */ - return (0); - } - if (resvsize != UINT64_MAX) { - /* Being set to a value other than "auto" */ - return (0); - } - - props = fnvlist_alloc(); - - fnvlist_add_uint64(props, zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), - zfs_prop_get_int(zhp, ZFS_PROP_VOLBLOCKSIZE)); - - if (nvlist_lookup_uint64(nvl, zfs_prop_to_name(ZFS_PROP_VOLSIZE), - &volsize) != 0) { - volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE); - } - - resvsize = zvol_volsize_to_reservation(zpool_handle(zhp), volsize, - props); - fnvlist_free(props); - - (void) nvlist_remove_all(nvl, zfs_prop_to_name(prop)); - if (nvlist_add_uint64(nvl, zfs_prop_to_name(prop), resvsize) != 0) { - (void) no_memory(zhp->zfs_hdl); - return (-1); - } - return (1); -} - -static boolean_t -zfs_is_namespace_prop(zfs_prop_t prop) -{ - switch (prop) { - - case ZFS_PROP_ATIME: - case ZFS_PROP_RELATIME: - case ZFS_PROP_DEVICES: - case ZFS_PROP_EXEC: - case ZFS_PROP_SETUID: - case ZFS_PROP_READONLY: - case ZFS_PROP_XATTR: - case ZFS_PROP_NBMAND: - return (B_TRUE); - - default: - return (B_FALSE); - } -} - -/* - * Given a property name and value, set the property for the given dataset. - */ -int -zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval) -{ - int ret = -1; - char errbuf[ERRBUFLEN]; - libzfs_handle_t *hdl = zhp->zfs_hdl; - nvlist_t *nvl = NULL; - - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot set property for '%s'"), - zhp->zfs_name); - - if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0 || - nvlist_add_string(nvl, propname, propval) != 0) { - (void) no_memory(hdl); - goto error; - } - - ret = zfs_prop_set_list(zhp, nvl); - -error: - nvlist_free(nvl); - return (ret); -} - -/* - * Given an nvlist of property names and values, set the properties for the - * given dataset. - */ -int -zfs_prop_set_list(zfs_handle_t *zhp, nvlist_t *props) -{ - return (zfs_prop_set_list_flags(zhp, props, 0)); -} - -/* - * Given an nvlist of property names, values and flags, set the properties - * for the given dataset. If ZFS_SET_NOMOUNT is set, it allows to update - * mountpoint, sharenfs and sharesmb properties without (un/re)mounting - * and (un/re)sharing the dataset. - */ -int -zfs_prop_set_list_flags(zfs_handle_t *zhp, nvlist_t *props, int flags) -{ - zfs_cmd_t zc = {"\0"}; - int ret = -1; - prop_changelist_t **cls = NULL; - int cl_idx; - char errbuf[ERRBUFLEN]; - libzfs_handle_t *hdl = zhp->zfs_hdl; - nvlist_t *nvl; - int nvl_len = 0; - int added_resv = 0; - zfs_prop_t prop; - boolean_t nsprop = B_FALSE; - nvpair_t *elem; - - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot set property for '%s'"), - zhp->zfs_name); - - if ((nvl = zfs_valid_proplist(hdl, zhp->zfs_type, props, - zfs_prop_get_int(zhp, ZFS_PROP_ZONED), zhp, zhp->zpool_hdl, - B_FALSE, errbuf)) == NULL) - goto error; - - /* - * We have to check for any extra properties which need to be added - * before computing the length of the nvlist. - */ - for (elem = nvlist_next_nvpair(nvl, NULL); - elem != NULL; - elem = nvlist_next_nvpair(nvl, elem)) { - if (zfs_name_to_prop(nvpair_name(elem)) == ZFS_PROP_VOLSIZE && - (added_resv = zfs_add_synthetic_resv(zhp, nvl)) == -1) { - goto error; - } - } - - if (added_resv != 1 && - (added_resv = zfs_fix_auto_resv(zhp, nvl)) == -1) { - goto error; - } - - /* - * Check how many properties we're setting and allocate an array to - * store changelist pointers for postfix(). - */ - for (elem = nvlist_next_nvpair(nvl, NULL); - elem != NULL; - elem = nvlist_next_nvpair(nvl, elem)) - nvl_len++; - if ((cls = calloc(nvl_len, sizeof (prop_changelist_t *))) == NULL) - goto error; - - cl_idx = 0; - for (elem = nvlist_next_nvpair(nvl, NULL); - elem != NULL; - elem = nvlist_next_nvpair(nvl, elem)) { - - prop = zfs_name_to_prop(nvpair_name(elem)); - nsprop |= zfs_is_namespace_prop(prop); - - assert(cl_idx < nvl_len); - /* - * We don't want to unmount & remount the dataset when changing - * its canmount property to 'on' or 'noauto'. We only use - * the changelist logic to unmount when setting canmount=off. - */ - if (prop != ZFS_PROP_CANMOUNT || - (fnvpair_value_uint64(elem) == ZFS_CANMOUNT_OFF && - zfs_is_mounted(zhp, NULL))) { - cls[cl_idx] = changelist_gather(zhp, prop, - ((flags & ZFS_SET_NOMOUNT) ? - CL_GATHER_DONT_UNMOUNT : 0), 0); - if (cls[cl_idx] == NULL) - goto error; - } - - if (prop == ZFS_PROP_MOUNTPOINT && - changelist_haszonedchild(cls[cl_idx])) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "child dataset with inherited mountpoint is used " - "in a non-global zone")); - ret = zfs_error(hdl, EZFS_ZONED, errbuf); - goto error; - } - - if (cls[cl_idx] != NULL && - (ret = changelist_prefix(cls[cl_idx])) != 0) - goto error; - - cl_idx++; - } - assert(cl_idx == nvl_len); - - /* - * Execute the corresponding ioctl() to set this list of properties. - */ - (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); - - zcmd_write_src_nvlist(hdl, &zc, nvl); - zcmd_alloc_dst_nvlist(hdl, &zc, 0); - - ret = zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc); - - if (ret != 0) { - if (zc.zc_nvlist_dst_filled == B_FALSE) { - (void) zfs_standard_error(hdl, errno, errbuf); - goto error; - } - - /* Get the list of unset properties back and report them. */ - nvlist_t *errorprops = NULL; - if (zcmd_read_dst_nvlist(hdl, &zc, &errorprops) != 0) - goto error; - for (nvpair_t *elem = nvlist_next_nvpair(errorprops, NULL); - elem != NULL; - elem = nvlist_next_nvpair(errorprops, elem)) { - prop = zfs_name_to_prop(nvpair_name(elem)); - zfs_setprop_error(hdl, prop, errno, errbuf); - } - nvlist_free(errorprops); - - if (added_resv && errno == ENOSPC) { - /* clean up the volsize property we tried to set */ - uint64_t old_volsize = zfs_prop_get_int(zhp, - ZFS_PROP_VOLSIZE); - nvlist_free(nvl); - nvl = NULL; - zcmd_free_nvlists(&zc); - - if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) - goto error; - if (nvlist_add_uint64(nvl, - zfs_prop_to_name(ZFS_PROP_VOLSIZE), - old_volsize) != 0) - goto error; - zcmd_write_src_nvlist(hdl, &zc, nvl); - (void) zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc); - } - } else { - for (cl_idx = 0; cl_idx < nvl_len; cl_idx++) { - if (cls[cl_idx] != NULL) { - int clp_err = changelist_postfix(cls[cl_idx]); - if (clp_err != 0) - ret = clp_err; - } - } - - if (ret == 0) { - /* - * Refresh the statistics so the new property - * value is reflected. - */ - (void) get_stats(zhp); - - /* - * Remount the filesystem to propagate the change - * if one of the options handled by the generic - * Linux namespace layer has been modified. - */ - if (nsprop && zfs_is_mounted(zhp, NULL)) - ret = zfs_mount(zhp, MNTOPT_REMOUNT, 0); - } - } - -error: - nvlist_free(nvl); - zcmd_free_nvlists(&zc); - if (cls != NULL) { - for (cl_idx = 0; cl_idx < nvl_len; cl_idx++) { - if (cls[cl_idx] != NULL) - changelist_free(cls[cl_idx]); - } - free(cls); - } - return (ret); -} - -/* - * Given a property, inherit the value from the parent dataset, or if received - * is TRUE, revert to the received value, if any. - */ -int -zfs_prop_inherit(zfs_handle_t *zhp, const char *propname, boolean_t received) -{ - zfs_cmd_t zc = {"\0"}; - int ret; - prop_changelist_t *cl; - libzfs_handle_t *hdl = zhp->zfs_hdl; - char errbuf[ERRBUFLEN]; - zfs_prop_t prop; - - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot inherit %s for '%s'"), propname, zhp->zfs_name); - - zc.zc_cookie = received; - if ((prop = zfs_name_to_prop(propname)) == ZPROP_USERPROP) { - /* - * For user properties, the amount of work we have to do is very - * small, so just do it here. - */ - if (!zfs_prop_user(propname)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "invalid property")); - return (zfs_error(hdl, EZFS_BADPROP, errbuf)); - } - - (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); - (void) strlcpy(zc.zc_value, propname, sizeof (zc.zc_value)); - - if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_INHERIT_PROP, &zc) != 0) - return (zfs_standard_error(hdl, errno, errbuf)); - - (void) get_stats(zhp); - return (0); - } - - /* - * Verify that this property is inheritable. - */ - if (zfs_prop_readonly(prop)) - return (zfs_error(hdl, EZFS_PROPREADONLY, errbuf)); - - if (!zfs_prop_inheritable(prop) && !received) - return (zfs_error(hdl, EZFS_PROPNONINHERIT, errbuf)); - - /* - * Check to see if the value applies to this type - */ - if (!zfs_prop_valid_for_type(prop, zhp->zfs_type, B_FALSE)) - return (zfs_error(hdl, EZFS_PROPTYPE, errbuf)); - - /* - * Normalize the name, to get rid of shorthand abbreviations. - */ - propname = zfs_prop_to_name(prop); - (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); - (void) strlcpy(zc.zc_value, propname, sizeof (zc.zc_value)); - - if (prop == ZFS_PROP_MOUNTPOINT && getzoneid() == GLOBAL_ZONEID && - zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "dataset is used in a non-global zone")); - return (zfs_error(hdl, EZFS_ZONED, errbuf)); - } - - /* - * Determine datasets which will be affected by this change, if any. - */ - if ((cl = changelist_gather(zhp, prop, 0, 0)) == NULL) - return (-1); - - if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "child dataset with inherited mountpoint is used " - "in a non-global zone")); - ret = zfs_error(hdl, EZFS_ZONED, errbuf); - goto error; - } - - if ((ret = changelist_prefix(cl)) != 0) - goto error; - - if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_INHERIT_PROP, &zc) != 0) { - changelist_free(cl); - return (zfs_standard_error(hdl, errno, errbuf)); - } else { - - if ((ret = changelist_postfix(cl)) != 0) - goto error; - - /* - * Refresh the statistics so the new property is reflected. - */ - (void) get_stats(zhp); - - /* - * Remount the filesystem to propagate the change - * if one of the options handled by the generic - * Linux namespace layer has been modified. - */ - if (zfs_is_namespace_prop(prop) && - zfs_is_mounted(zhp, NULL)) - ret = zfs_mount(zhp, MNTOPT_REMOUNT, 0); - } - -error: - changelist_free(cl); - return (ret); -} - -/* - * True DSL properties are stored in an nvlist. The following two functions - * extract them appropriately. - */ -uint64_t -getprop_uint64(zfs_handle_t *zhp, zfs_prop_t prop, const char **source) -{ - nvlist_t *nv; - uint64_t value; - - *source = NULL; - if (nvlist_lookup_nvlist(zhp->zfs_props, - zfs_prop_to_name(prop), &nv) == 0) { - value = fnvlist_lookup_uint64(nv, ZPROP_VALUE); - (void) nvlist_lookup_string(nv, ZPROP_SOURCE, source); - } else { - verify(!zhp->zfs_props_table || - zhp->zfs_props_table[prop] == B_TRUE); - value = zfs_prop_default_numeric(prop); - *source = ""; - } - - return (value); -} - -static const char * -getprop_string(zfs_handle_t *zhp, zfs_prop_t prop, const char **source) -{ - nvlist_t *nv; - const char *value; - - *source = NULL; - if (nvlist_lookup_nvlist(zhp->zfs_props, - zfs_prop_to_name(prop), &nv) == 0) { - value = fnvlist_lookup_string(nv, ZPROP_VALUE); - (void) nvlist_lookup_string(nv, ZPROP_SOURCE, source); - } else { - verify(!zhp->zfs_props_table || - zhp->zfs_props_table[prop] == B_TRUE); - value = zfs_prop_default_string(prop); - *source = ""; - } - - return (value); -} - -static boolean_t -zfs_is_recvd_props_mode(zfs_handle_t *zhp) -{ - return (zhp->zfs_props != NULL && - zhp->zfs_props == zhp->zfs_recvd_props); -} - -static void -zfs_set_recvd_props_mode(zfs_handle_t *zhp, uintptr_t *cookie) -{ - *cookie = (uintptr_t)zhp->zfs_props; - zhp->zfs_props = zhp->zfs_recvd_props; -} - -static void -zfs_unset_recvd_props_mode(zfs_handle_t *zhp, uintptr_t *cookie) -{ - zhp->zfs_props = (nvlist_t *)*cookie; - *cookie = 0; -} - -/* - * Internal function for getting a numeric property. Both zfs_prop_get() and - * zfs_prop_get_int() are built using this interface. - * - * Certain properties can be overridden using 'mount -o'. In this case, scan - * the contents of the /proc/self/mounts entry, searching for the - * appropriate options. If they differ from the on-disk values, report the - * current values and mark the source "temporary". - */ -static int -get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src, - const char **source, uint64_t *val) -{ - zfs_cmd_t zc = {"\0"}; - nvlist_t *zplprops = NULL; - struct mnttab mnt; - const char *mntopt_on = NULL; - const char *mntopt_off = NULL; - boolean_t received = zfs_is_recvd_props_mode(zhp); - - *source = NULL; - - /* - * If the property is being fetched for a snapshot, check whether - * the property is valid for the snapshot's head dataset type. - */ - if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT && - !zfs_prop_valid_for_type(prop, zhp->zfs_head_type, B_TRUE)) { - *val = zfs_prop_default_numeric(prop); - return (-1); - } - - switch (prop) { - case ZFS_PROP_ATIME: - mntopt_on = MNTOPT_ATIME; - mntopt_off = MNTOPT_NOATIME; - break; - - case ZFS_PROP_RELATIME: - mntopt_on = MNTOPT_RELATIME; - mntopt_off = MNTOPT_NORELATIME; - break; - - case ZFS_PROP_DEVICES: - mntopt_on = MNTOPT_DEVICES; - mntopt_off = MNTOPT_NODEVICES; - break; - - case ZFS_PROP_EXEC: - mntopt_on = MNTOPT_EXEC; - mntopt_off = MNTOPT_NOEXEC; - break; - - case ZFS_PROP_READONLY: - mntopt_on = MNTOPT_RO; - mntopt_off = MNTOPT_RW; - break; - - case ZFS_PROP_SETUID: - mntopt_on = MNTOPT_SETUID; - mntopt_off = MNTOPT_NOSETUID; - break; - - case ZFS_PROP_XATTR: - mntopt_on = MNTOPT_XATTR; - mntopt_off = MNTOPT_NOXATTR; - break; - - case ZFS_PROP_NBMAND: - mntopt_on = MNTOPT_NBMAND; - mntopt_off = MNTOPT_NONBMAND; - break; - - default: - break; - } - - /* - * Because looking up the mount options is potentially expensive - * (iterating over all of /proc/self/mounts), we defer its - * calculation until we're looking up a property which requires - * its presence. - */ - if (!zhp->zfs_mntcheck && - (mntopt_on != NULL || prop == ZFS_PROP_MOUNTED)) { - libzfs_handle_t *hdl = zhp->zfs_hdl; - struct mnttab entry; - - if (libzfs_mnttab_find(hdl, zhp->zfs_name, &entry) == 0) - zhp->zfs_mntopts = zfs_strdup(hdl, - entry.mnt_mntopts); - - zhp->zfs_mntcheck = B_TRUE; - } - - if (zhp->zfs_mntopts == NULL) - mnt.mnt_mntopts = (char *)""; - else - mnt.mnt_mntopts = zhp->zfs_mntopts; - - switch (prop) { - case ZFS_PROP_ATIME: - case ZFS_PROP_RELATIME: - case ZFS_PROP_DEVICES: - case ZFS_PROP_EXEC: - case ZFS_PROP_READONLY: - case ZFS_PROP_SETUID: -#ifndef __FreeBSD__ - case ZFS_PROP_XATTR: -#endif - case ZFS_PROP_NBMAND: - *val = getprop_uint64(zhp, prop, source); - - if (received) - break; - - if (hasmntopt(&mnt, mntopt_on) && !*val) { - *val = B_TRUE; - if (src) - *src = ZPROP_SRC_TEMPORARY; - } else if (hasmntopt(&mnt, mntopt_off) && *val) { - *val = B_FALSE; - if (src) - *src = ZPROP_SRC_TEMPORARY; - } - break; - - case ZFS_PROP_CANMOUNT: - case ZFS_PROP_VOLSIZE: - case ZFS_PROP_QUOTA: - case ZFS_PROP_REFQUOTA: - case ZFS_PROP_RESERVATION: - case ZFS_PROP_REFRESERVATION: - case ZFS_PROP_FILESYSTEM_LIMIT: - case ZFS_PROP_SNAPSHOT_LIMIT: - case ZFS_PROP_FILESYSTEM_COUNT: - case ZFS_PROP_SNAPSHOT_COUNT: - *val = getprop_uint64(zhp, prop, source); - - if (*source == NULL) { - /* not default, must be local */ - *source = zhp->zfs_name; - } - break; - - case ZFS_PROP_MOUNTED: - *val = (zhp->zfs_mntopts != NULL); - break; - - case ZFS_PROP_NUMCLONES: - *val = zhp->zfs_dmustats.dds_num_clones; - break; - - case ZFS_PROP_VERSION: - case ZFS_PROP_NORMALIZE: - case ZFS_PROP_UTF8ONLY: - case ZFS_PROP_CASE: - case ZFS_PROP_DEFAULTUSERQUOTA: - case ZFS_PROP_DEFAULTGROUPQUOTA: - case ZFS_PROP_DEFAULTPROJECTQUOTA: - case ZFS_PROP_DEFAULTUSEROBJQUOTA: - case ZFS_PROP_DEFAULTGROUPOBJQUOTA: - case ZFS_PROP_DEFAULTPROJECTOBJQUOTA: - zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0); - - (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); - if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_OBJSET_ZPLPROPS, &zc)) { - zcmd_free_nvlists(&zc); - if (prop == ZFS_PROP_VERSION && - zhp->zfs_type == ZFS_TYPE_VOLUME) - *val = zfs_prop_default_numeric(prop); - return (-1); - } - if (zcmd_read_dst_nvlist(zhp->zfs_hdl, &zc, &zplprops) != 0 || - nvlist_lookup_uint64(zplprops, zfs_prop_to_name(prop), - val) != 0) { - zcmd_free_nvlists(&zc); - return (-1); - } - nvlist_free(zplprops); - zcmd_free_nvlists(&zc); - break; - - case ZFS_PROP_INCONSISTENT: - *val = zhp->zfs_dmustats.dds_inconsistent; - break; - - case ZFS_PROP_REDACTED: - *val = zhp->zfs_dmustats.dds_redacted; - break; - - case ZFS_PROP_GUID: - if (zhp->zfs_dmustats.dds_guid != 0) - *val = zhp->zfs_dmustats.dds_guid; - else - *val = getprop_uint64(zhp, prop, source); - break; - - case ZFS_PROP_CREATETXG: - /* - * We can directly read createtxg property from zfs - * handle for Filesystem, Snapshot and ZVOL types. - */ - if (((zhp->zfs_type == ZFS_TYPE_FILESYSTEM) || - (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) || - (zhp->zfs_type == ZFS_TYPE_VOLUME)) && - (zhp->zfs_dmustats.dds_creation_txg != 0)) { - *val = zhp->zfs_dmustats.dds_creation_txg; - break; - } else { - *val = getprop_uint64(zhp, prop, source); - } - zfs_fallthrough; - default: - switch (zfs_prop_get_type(prop)) { - case PROP_TYPE_NUMBER: - case PROP_TYPE_INDEX: - *val = getprop_uint64(zhp, prop, source); - /* - * If we tried to use a default value for a - * readonly property, it means that it was not - * present. Note this only applies to "truly" - * readonly properties, not set-once properties - * like volblocksize. - */ - if (zfs_prop_readonly(prop) && - !zfs_prop_setonce(prop) && - *source != NULL && (*source)[0] == '\0') { - *source = NULL; - return (-1); - } - break; - - case PROP_TYPE_STRING: - default: - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "cannot get non-numeric property")); - return (zfs_error(zhp->zfs_hdl, EZFS_BADPROP, - dgettext(TEXT_DOMAIN, "internal error"))); - } - } - - return (0); -} - -/* - * Calculate the source type, given the raw source string. - */ -static void -get_source(zfs_handle_t *zhp, zprop_source_t *srctype, const char *source, - char *statbuf, size_t statlen) -{ - if (statbuf == NULL || - srctype == NULL || *srctype == ZPROP_SRC_TEMPORARY) { - return; - } - - if (source == NULL) { - *srctype = ZPROP_SRC_NONE; - } else if (source[0] == '\0') { - *srctype = ZPROP_SRC_DEFAULT; - } else if (strstr(source, ZPROP_SOURCE_VAL_RECVD) != NULL) { - *srctype = ZPROP_SRC_RECEIVED; - } else { - if (strcmp(source, zhp->zfs_name) == 0) { - *srctype = ZPROP_SRC_LOCAL; - } else { - (void) strlcpy(statbuf, source, statlen); - *srctype = ZPROP_SRC_INHERITED; - } - } - -} - -int -zfs_prop_get_recvd(zfs_handle_t *zhp, const char *propname, char *propbuf, - size_t proplen, boolean_t literal) -{ - zfs_prop_t prop; - int err = 0; - - if (zhp->zfs_recvd_props == NULL) - if (get_recvd_props_ioctl(zhp) != 0) - return (-1); - - prop = zfs_name_to_prop(propname); - - if (prop != ZPROP_USERPROP) { - uintptr_t cookie; - if (!nvlist_exists(zhp->zfs_recvd_props, propname)) - return (-1); - zfs_set_recvd_props_mode(zhp, &cookie); - err = zfs_prop_get(zhp, prop, propbuf, proplen, - NULL, NULL, 0, literal); - zfs_unset_recvd_props_mode(zhp, &cookie); - } else { - nvlist_t *propval; - const char *recvdval; - if (nvlist_lookup_nvlist(zhp->zfs_recvd_props, - propname, &propval) != 0) - return (-1); - recvdval = fnvlist_lookup_string(propval, ZPROP_VALUE); - (void) strlcpy(propbuf, recvdval, proplen); - } - - return (err == 0 ? 0 : -1); -} - -static int -get_clones_string(zfs_handle_t *zhp, char *propbuf, size_t proplen) -{ - nvlist_t *value; - nvpair_t *pair; - - value = zfs_get_clones_nvl(zhp); - if (value == NULL || nvlist_empty(value)) - return (-1); - - propbuf[0] = '\0'; - for (pair = nvlist_next_nvpair(value, NULL); pair != NULL; - pair = nvlist_next_nvpair(value, pair)) { - if (propbuf[0] != '\0') - (void) strlcat(propbuf, ",", proplen); - (void) strlcat(propbuf, nvpair_name(pair), proplen); - } - - return (0); -} - -struct get_clones_arg { - uint64_t numclones; - nvlist_t *value; - const char *origin; - char buf[ZFS_MAX_DATASET_NAME_LEN]; -}; - -static int -get_clones_cb(zfs_handle_t *zhp, void *arg) -{ - struct get_clones_arg *gca = arg; - - if (gca->numclones == 0) { - zfs_close(zhp); - return (0); - } - - if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, gca->buf, sizeof (gca->buf), - NULL, NULL, 0, B_TRUE) != 0) - goto out; - if (strcmp(gca->buf, gca->origin) == 0) { - fnvlist_add_boolean(gca->value, zfs_get_name(zhp)); - gca->numclones--; - } - -out: - (void) zfs_iter_children_v2(zhp, 0, get_clones_cb, gca); - zfs_close(zhp); - return (0); -} - -nvlist_t * -zfs_get_clones_nvl(zfs_handle_t *zhp) -{ - nvlist_t *nv, *value; - - if (nvlist_lookup_nvlist(zhp->zfs_props, - zfs_prop_to_name(ZFS_PROP_CLONES), &nv) != 0) { - struct get_clones_arg gca; - - /* - * if this is a snapshot, then the kernel wasn't able - * to get the clones. Do it by slowly iterating. - */ - if (zhp->zfs_type != ZFS_TYPE_SNAPSHOT) - return (NULL); - if (nvlist_alloc(&nv, NV_UNIQUE_NAME, 0) != 0) - return (NULL); - if (nvlist_alloc(&value, NV_UNIQUE_NAME, 0) != 0) { - nvlist_free(nv); - return (NULL); - } - - gca.numclones = zfs_prop_get_int(zhp, ZFS_PROP_NUMCLONES); - gca.value = value; - gca.origin = zhp->zfs_name; - - if (gca.numclones != 0) { - zfs_handle_t *root; - char pool[ZFS_MAX_DATASET_NAME_LEN]; - char *cp = pool; - - /* get the pool name */ - (void) strlcpy(pool, zhp->zfs_name, sizeof (pool)); - (void) strsep(&cp, "/@"); - root = zfs_open(zhp->zfs_hdl, pool, - ZFS_TYPE_FILESYSTEM); - if (root == NULL) { - nvlist_free(nv); - nvlist_free(value); - return (NULL); - } - - (void) get_clones_cb(root, &gca); - } - - if (gca.numclones != 0 || - nvlist_add_nvlist(nv, ZPROP_VALUE, value) != 0 || - nvlist_add_nvlist(zhp->zfs_props, - zfs_prop_to_name(ZFS_PROP_CLONES), nv) != 0) { - nvlist_free(nv); - nvlist_free(value); - return (NULL); - } - nvlist_free(nv); - nvlist_free(value); - nv = fnvlist_lookup_nvlist(zhp->zfs_props, - zfs_prop_to_name(ZFS_PROP_CLONES)); - } - - return (fnvlist_lookup_nvlist(nv, ZPROP_VALUE)); -} - -static int -get_rsnaps_string(zfs_handle_t *zhp, char *propbuf, size_t proplen) -{ - nvlist_t *value; - uint64_t *snaps; - uint_t nsnaps; - - if (nvlist_lookup_nvlist(zhp->zfs_props, - zfs_prop_to_name(ZFS_PROP_REDACT_SNAPS), &value) != 0) - return (-1); - if (nvlist_lookup_uint64_array(value, ZPROP_VALUE, &snaps, - &nsnaps) != 0) - return (-1); - if (nsnaps == 0) { - /* There's no redaction snapshots; pass a special value back */ - (void) snprintf(propbuf, proplen, "none"); - return (0); - } - propbuf[0] = '\0'; - for (int i = 0; i < nsnaps; i++) { - char buf[128]; - if (propbuf[0] != '\0') - (void) strlcat(propbuf, ",", proplen); - (void) snprintf(buf, sizeof (buf), "%llu", - (u_longlong_t)snaps[i]); - (void) strlcat(propbuf, buf, proplen); - } - - return (0); -} - -/* - * Accepts a property and value and checks that the value - * matches the one found by the channel program. If they are - * not equal, print both of them. - */ -static void -zcp_check(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t intval, - const char *strval) -{ - if (!zhp->zfs_hdl->libzfs_prop_debug) - return; - int error; - char *poolname = zhp->zpool_hdl->zpool_name; - const char *prop_name = zfs_prop_to_name(prop); - const char *program = - "args = ...\n" - "ds = args['dataset']\n" - "prop = args['property']\n" - "value, setpoint = zfs.get_prop(ds, prop)\n" - "return {value=value, setpoint=setpoint}\n"; - nvlist_t *outnvl; - nvlist_t *retnvl; - nvlist_t *argnvl = fnvlist_alloc(); - - fnvlist_add_string(argnvl, "dataset", zhp->zfs_name); - fnvlist_add_string(argnvl, "property", zfs_prop_to_name(prop)); - - error = lzc_channel_program_nosync(poolname, program, - 10 * 1000 * 1000, 10 * 1024 * 1024, argnvl, &outnvl); - - if (error == 0) { - retnvl = fnvlist_lookup_nvlist(outnvl, "return"); - if (zfs_prop_get_type(prop) == PROP_TYPE_NUMBER) { - int64_t ans; - error = nvlist_lookup_int64(retnvl, "value", &ans); - if (error != 0) { - (void) fprintf(stderr, "%s: zcp check error: " - "%u\n", prop_name, error); - return; - } - if (ans != intval) { - (void) fprintf(stderr, "%s: zfs found %llu, " - "but zcp found %llu\n", prop_name, - (u_longlong_t)intval, (u_longlong_t)ans); - } - } else { - const char *str_ans; - error = nvlist_lookup_string(retnvl, "value", &str_ans); - if (error != 0) { - (void) fprintf(stderr, "%s: zcp check error: " - "%u\n", prop_name, error); - return; - } - if (strcmp(strval, str_ans) != 0) { - (void) fprintf(stderr, - "%s: zfs found '%s', but zcp found '%s'\n", - prop_name, strval, str_ans); - } - } - } else { - (void) fprintf(stderr, "%s: zcp check failed, channel program " - "error: %u\n", prop_name, error); - } - nvlist_free(argnvl); - nvlist_free(outnvl); -} - -/* - * Retrieve a property from the given object. If 'literal' is specified, then - * numbers are left as exact values. Otherwise, numbers are converted to a - * human-readable form. - * - * Returns 0 on success, or -1 on error. - */ -int -zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen, - zprop_source_t *src, char *statbuf, size_t statlen, boolean_t literal) -{ - const char *source = NULL; - uint64_t val; - const char *str; - const char *strval; - boolean_t received = zfs_is_recvd_props_mode(zhp); - - /* - * Check to see if this property applies to our object - */ - if (!zfs_prop_valid_for_type(prop, zhp->zfs_type, B_FALSE)) - return (-1); - - if (received && zfs_prop_readonly(prop)) - return (-1); - - if (src) - *src = ZPROP_SRC_NONE; - - switch (prop) { - case ZFS_PROP_CREATION: - /* - * 'creation' is a time_t stored in the statistics. We convert - * this into a string unless 'literal' is specified. - */ - { - val = getprop_uint64(zhp, prop, &source); - time_t time = (time_t)val; - struct tm t; - - if (literal || - localtime_r(&time, &t) == NULL || - strftime(propbuf, proplen, "%a %b %e %k:%M %Y", - &t) == 0) - (void) snprintf(propbuf, proplen, "%llu", - (u_longlong_t)val); - } - zcp_check(zhp, prop, val, NULL); - break; - - case ZFS_PROP_MOUNTPOINT: - /* - * Getting the precise mountpoint can be tricky. - * - * - for 'none' or 'legacy', return those values. - * - for inherited mountpoints, we want to take everything - * after our ancestor and append it to the inherited value. - * - * If the pool has an alternate root, we want to prepend that - * root to any values we return. - */ - - str = getprop_string(zhp, prop, &source); - - if (str[0] == '/') { - char buf[MAXPATHLEN]; - char *root = buf; - const char *relpath; - - /* - * If we inherit the mountpoint, even from a dataset - * with a received value, the source will be the path of - * the dataset we inherit from. If source is - * ZPROP_SOURCE_VAL_RECVD, the received value is not - * inherited. - */ - if (strcmp(source, ZPROP_SOURCE_VAL_RECVD) == 0) { - relpath = ""; - } else { - relpath = zhp->zfs_name + strlen(source); - if (relpath[0] == '/') - relpath++; - } - - if ((zpool_get_prop(zhp->zpool_hdl, - ZPOOL_PROP_ALTROOT, buf, MAXPATHLEN, NULL, - B_FALSE)) || (strcmp(root, "-") == 0)) - root[0] = '\0'; - /* - * Special case an alternate root of '/'. This will - * avoid having multiple leading slashes in the - * mountpoint path. - */ - if (strcmp(root, "/") == 0) - root++; - - /* - * If the mountpoint is '/' then skip over this - * if we are obtaining either an alternate root or - * an inherited mountpoint. - */ - if (str[1] == '\0' && (root[0] != '\0' || - relpath[0] != '\0')) - str++; - - if (relpath[0] == '\0') - (void) snprintf(propbuf, proplen, "%s%s", - root, str); - else - (void) snprintf(propbuf, proplen, "%s%s%s%s", - root, str, relpath[0] == '@' ? "" : "/", - relpath); - } else { - /* 'legacy' or 'none' */ - (void) strlcpy(propbuf, str, proplen); - } - zcp_check(zhp, prop, 0, propbuf); - break; - - case ZFS_PROP_ORIGIN: - if (*zhp->zfs_dmustats.dds_origin != '\0') { - str = (char *)&zhp->zfs_dmustats.dds_origin; - } else { - str = getprop_string(zhp, prop, &source); - } - if (str == NULL || *str == '\0') - str = zfs_prop_default_string(prop); - if (str == NULL) - return (-1); - (void) strlcpy(propbuf, str, proplen); - zcp_check(zhp, prop, 0, str); - break; - - case ZFS_PROP_REDACT_SNAPS: - if (get_rsnaps_string(zhp, propbuf, proplen) != 0) - return (-1); - break; - - case ZFS_PROP_CLONES: - if (get_clones_string(zhp, propbuf, proplen) != 0) - return (-1); - break; - - case ZFS_PROP_QUOTA: - case ZFS_PROP_REFQUOTA: - case ZFS_PROP_RESERVATION: - case ZFS_PROP_REFRESERVATION: - - if (get_numeric_property(zhp, prop, src, &source, &val) != 0) - return (-1); - /* - * If quota or reservation is 0, we translate this into 'none' - * (unless literal is set), and indicate that it's the default - * value. Otherwise, we print the number nicely and indicate - * that its set locally. - */ - if (val == 0) { - if (literal) - (void) strlcpy(propbuf, "0", proplen); - else - (void) strlcpy(propbuf, "none", proplen); - } else { - if (literal) - (void) snprintf(propbuf, proplen, "%llu", - (u_longlong_t)val); - else - zfs_nicebytes(val, propbuf, proplen); - } - zcp_check(zhp, prop, val, NULL); - break; - - case ZFS_PROP_FILESYSTEM_LIMIT: - case ZFS_PROP_SNAPSHOT_LIMIT: - case ZFS_PROP_FILESYSTEM_COUNT: - case ZFS_PROP_SNAPSHOT_COUNT: - - if (get_numeric_property(zhp, prop, src, &source, &val) != 0) - return (-1); - - /* - * If limit is UINT64_MAX, we translate this into 'none', and - * indicate that it's the default value. Otherwise, we print - * the number nicely and indicate that it's set locally. - */ - if (val == UINT64_MAX) { - (void) strlcpy(propbuf, "none", proplen); - } else if (literal) { - (void) snprintf(propbuf, proplen, "%llu", - (u_longlong_t)val); - } else { - zfs_nicenum(val, propbuf, proplen); - } - - zcp_check(zhp, prop, val, NULL); - break; - - case ZFS_PROP_REFRATIO: - case ZFS_PROP_COMPRESSRATIO: - if (get_numeric_property(zhp, prop, src, &source, &val) != 0) - return (-1); - if (literal) - (void) snprintf(propbuf, proplen, "%llu.%02llu", - (u_longlong_t)(val / 100), - (u_longlong_t)(val % 100)); - else - (void) snprintf(propbuf, proplen, "%llu.%02llux", - (u_longlong_t)(val / 100), - (u_longlong_t)(val % 100)); - zcp_check(zhp, prop, val, NULL); - break; - - case ZFS_PROP_TYPE: - switch (zhp->zfs_type) { - case ZFS_TYPE_FILESYSTEM: - str = "filesystem"; - break; - case ZFS_TYPE_VOLUME: - str = "volume"; - break; - case ZFS_TYPE_SNAPSHOT: - str = "snapshot"; - break; - case ZFS_TYPE_BOOKMARK: - str = "bookmark"; - break; - default: - abort(); - } - (void) snprintf(propbuf, proplen, "%s", str); - zcp_check(zhp, prop, 0, propbuf); - break; - - case ZFS_PROP_MOUNTED: - /* - * The 'mounted' property is a pseudo-property that described - * whether the filesystem is currently mounted. Even though - * it's a boolean value, the typical values of "on" and "off" - * don't make sense, so we translate to "yes" and "no". - */ - if (get_numeric_property(zhp, ZFS_PROP_MOUNTED, - src, &source, &val) != 0) - return (-1); - if (val) - (void) strlcpy(propbuf, "yes", proplen); - else - (void) strlcpy(propbuf, "no", proplen); - break; - - case ZFS_PROP_NAME: - /* - * The 'name' property is a pseudo-property derived from the - * dataset name. It is presented as a real property to simplify - * consumers. - */ - (void) strlcpy(propbuf, zhp->zfs_name, proplen); - zcp_check(zhp, prop, 0, propbuf); - break; - - case ZFS_PROP_MLSLABEL: - { -#ifdef HAVE_MLSLABEL - m_label_t *new_sl = NULL; - char *ascii = NULL; /* human readable label */ - - (void) strlcpy(propbuf, - getprop_string(zhp, prop, &source), proplen); - - if (literal || (strcasecmp(propbuf, - ZFS_MLSLABEL_DEFAULT) == 0)) - break; - - /* - * Try to translate the internal hex string to - * human-readable output. If there are any - * problems just use the hex string. - */ - - if (str_to_label(propbuf, &new_sl, MAC_LABEL, - L_NO_CORRECTION, NULL) == -1) { - m_label_free(new_sl); - break; - } - - if (label_to_str(new_sl, &ascii, M_LABEL, - DEF_NAMES) != 0) { - if (ascii) - free(ascii); - m_label_free(new_sl); - break; - } - m_label_free(new_sl); - - (void) strlcpy(propbuf, ascii, proplen); - free(ascii); -#else - (void) strlcpy(propbuf, - getprop_string(zhp, prop, &source), proplen); -#endif /* HAVE_MLSLABEL */ - } - break; - - case ZFS_PROP_GUID: - case ZFS_PROP_KEY_GUID: - case ZFS_PROP_IVSET_GUID: - case ZFS_PROP_CREATETXG: - case ZFS_PROP_OBJSETID: - case ZFS_PROP_PBKDF2_ITERS: - /* - * These properties are stored as numbers, but they are - * identifiers or counters. - * We don't want them to be pretty printed, because pretty - * printing truncates their values making them useless. - */ - if (get_numeric_property(zhp, prop, src, &source, &val) != 0) - return (-1); - (void) snprintf(propbuf, proplen, "%llu", (u_longlong_t)val); - zcp_check(zhp, prop, val, NULL); - break; - - case ZFS_PROP_REFERENCED: - case ZFS_PROP_AVAILABLE: - case ZFS_PROP_USED: - case ZFS_PROP_USEDSNAP: - case ZFS_PROP_USEDDS: - case ZFS_PROP_USEDREFRESERV: - case ZFS_PROP_USEDCHILD: - if (get_numeric_property(zhp, prop, src, &source, &val) != 0) - return (-1); - if (literal) { - (void) snprintf(propbuf, proplen, "%llu", - (u_longlong_t)val); - } else { - zfs_nicebytes(val, propbuf, proplen); - } - zcp_check(zhp, prop, val, NULL); - break; - - case ZFS_PROP_SNAPSHOTS_CHANGED: - { - if ((get_numeric_property(zhp, prop, src, &source, - &val) != 0) || val == 0) { - return (-1); - } - - time_t time = (time_t)val; - struct tm t; - - if (literal || - localtime_r(&time, &t) == NULL || - strftime(propbuf, proplen, "%a %b %e %k:%M:%S %Y", - &t) == 0) - (void) snprintf(propbuf, proplen, "%llu", - (u_longlong_t)val); - } - zcp_check(zhp, prop, val, NULL); - break; - - default: - switch (zfs_prop_get_type(prop)) { - case PROP_TYPE_NUMBER: - if (get_numeric_property(zhp, prop, src, - &source, &val) != 0) { - return (-1); - } - - if (literal) { - (void) snprintf(propbuf, proplen, "%llu", - (u_longlong_t)val); - } else { - zfs_nicenum(val, propbuf, proplen); - } - zcp_check(zhp, prop, val, NULL); - break; - - case PROP_TYPE_STRING: - str = getprop_string(zhp, prop, &source); - if (str == NULL) - return (-1); - - (void) strlcpy(propbuf, str, proplen); - zcp_check(zhp, prop, 0, str); - break; - - case PROP_TYPE_INDEX: - if (get_numeric_property(zhp, prop, src, - &source, &val) != 0) - return (-1); - if (zfs_prop_index_to_string(prop, val, &strval) != 0) - return (-1); - - (void) strlcpy(propbuf, strval, proplen); - zcp_check(zhp, prop, 0, strval); - break; - - default: - abort(); - } - } - - get_source(zhp, src, source, statbuf, statlen); - - return (0); -} - -/* - * Utility function to get the given numeric property. Does no validation that - * the given property is the appropriate type; should only be used with - * hard-coded property types. - */ -uint64_t -zfs_prop_get_int(zfs_handle_t *zhp, zfs_prop_t prop) -{ - const char *source; - uint64_t val = 0; - - (void) get_numeric_property(zhp, prop, NULL, &source, &val); - - return (val); -} - -static int -zfs_prop_set_int(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t val) -{ - char buf[64]; - - (void) snprintf(buf, sizeof (buf), "%llu", (longlong_t)val); - return (zfs_prop_set(zhp, zfs_prop_to_name(prop), buf)); -} - -/* - * Similar to zfs_prop_get(), but returns the value as an integer. - */ -int -zfs_prop_get_numeric(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t *value, - zprop_source_t *src, char *statbuf, size_t statlen) -{ - const char *source; - - /* - * Check to see if this property applies to our object - */ - if (!zfs_prop_valid_for_type(prop, zhp->zfs_type, B_FALSE)) { - return (zfs_error_fmt(zhp->zfs_hdl, EZFS_PROPTYPE, - dgettext(TEXT_DOMAIN, "cannot get property '%s'"), - zfs_prop_to_name(prop))); - } - - if (src) - *src = ZPROP_SRC_NONE; - - if (get_numeric_property(zhp, prop, src, &source, value) != 0) - return (-1); - - get_source(zhp, src, source, statbuf, statlen); - - return (0); -} - -#ifdef HAVE_IDMAP -static int -idmap_id_to_numeric_domain_rid(uid_t id, boolean_t isuser, - char **domainp, idmap_rid_t *ridp) -{ - idmap_get_handle_t *get_hdl = NULL; - idmap_stat status; - int err = EINVAL; - - if (idmap_get_create(&get_hdl) != IDMAP_SUCCESS) - goto out; - - if (isuser) { - err = idmap_get_sidbyuid(get_hdl, id, - IDMAP_REQ_FLG_USE_CACHE, domainp, ridp, &status); - } else { - err = idmap_get_sidbygid(get_hdl, id, - IDMAP_REQ_FLG_USE_CACHE, domainp, ridp, &status); - } - if (err == IDMAP_SUCCESS && - idmap_get_mappings(get_hdl) == IDMAP_SUCCESS && - status == IDMAP_SUCCESS) - err = 0; - else - err = EINVAL; -out: - if (get_hdl) - idmap_get_destroy(get_hdl); - return (err); -} -#endif /* HAVE_IDMAP */ - -/* - * convert the propname into parameters needed by kernel - * Eg: userquota@ahrens -> ZFS_PROP_USERQUOTA, "", 126829 - * Eg: userused@matt@domain -> ZFS_PROP_USERUSED, "S-1-123-456", 789 - * Eg: groupquota@staff -> ZFS_PROP_GROUPQUOTA, "", 1234 - * Eg: groupused@staff -> ZFS_PROP_GROUPUSED, "", 1234 - * Eg: projectquota@123 -> ZFS_PROP_PROJECTQUOTA, "", 123 - * Eg: projectused@789 -> ZFS_PROP_PROJECTUSED, "", 789 - */ -static int -userquota_propname_decode(const char *propname, boolean_t zoned, - zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp) -{ - zfs_userquota_prop_t type; - char *cp; - boolean_t isuser; - boolean_t isgroup; - boolean_t isproject; - struct passwd *pw; - struct group *gr; - - domain[0] = '\0'; - - /* Figure out the property type ({user|group|project}{quota|space}) */ - for (type = 0; type < ZFS_NUM_USERQUOTA_PROPS; type++) { - if (strncmp(propname, zfs_userquota_prop_prefixes[type], - strlen(zfs_userquota_prop_prefixes[type])) == 0) - break; - } - if (type == ZFS_NUM_USERQUOTA_PROPS) - return (EINVAL); - *typep = type; - - isuser = (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_USERUSED || - type == ZFS_PROP_USEROBJQUOTA || - type == ZFS_PROP_USEROBJUSED); - isgroup = (type == ZFS_PROP_GROUPQUOTA || type == ZFS_PROP_GROUPUSED || - type == ZFS_PROP_GROUPOBJQUOTA || - type == ZFS_PROP_GROUPOBJUSED); - isproject = (type == ZFS_PROP_PROJECTQUOTA || - type == ZFS_PROP_PROJECTUSED || type == ZFS_PROP_PROJECTOBJQUOTA || - type == ZFS_PROP_PROJECTOBJUSED); - - cp = strchr(propname, '@') + 1; - - if (isuser && - getpwnam_r(cp, &gpwd, rpbuf, sizeof (rpbuf), &pw) == 0 && - pw != NULL) { - if (zoned && getzoneid() == GLOBAL_ZONEID) - return (ENOENT); - *ridp = pw->pw_uid; - } else if (isgroup && - getgrnam_r(cp, &ggrp, rpbuf, sizeof (rpbuf), &gr) == 0 && - gr != NULL) { - if (zoned && getzoneid() == GLOBAL_ZONEID) - return (ENOENT); - *ridp = gr->gr_gid; - } else if (!isproject && strchr(cp, '@')) { -#ifdef HAVE_IDMAP - /* - * It's a SID name (eg "user@domain") that needs to be - * turned into S-1-domainID-RID. - */ - directory_error_t e; - char *numericsid = NULL; - char *end; - - if (zoned && getzoneid() == GLOBAL_ZONEID) - return (ENOENT); - if (isuser) { - e = directory_sid_from_user_name(NULL, - cp, &numericsid); - } else { - e = directory_sid_from_group_name(NULL, - cp, &numericsid); - } - if (e != NULL) { - directory_error_free(e); - return (ENOENT); - } - if (numericsid == NULL) - return (ENOENT); - cp = numericsid; - (void) strlcpy(domain, cp, domainlen); - cp = strrchr(domain, '-'); - *cp = '\0'; - cp++; - - errno = 0; - *ridp = strtoull(cp, &end, 10); - free(numericsid); - - if (errno != 0 || *end != '\0') - return (EINVAL); -#else - (void) domainlen; - return (ENOSYS); -#endif /* HAVE_IDMAP */ - } else { - /* It's a user/group/project ID (eg "12345"). */ - uid_t id; - char *end; - id = strtoul(cp, &end, 10); - if (*end != '\0') - return (EINVAL); - if (id > MAXUID && !isproject) { -#ifdef HAVE_IDMAP - /* It's an ephemeral ID. */ - idmap_rid_t rid; - char *mapdomain; - - if (idmap_id_to_numeric_domain_rid(id, isuser, - &mapdomain, &rid) != 0) - return (ENOENT); - (void) strlcpy(domain, mapdomain, domainlen); - *ridp = rid; -#else - return (ENOSYS); -#endif /* HAVE_IDMAP */ - } else { - *ridp = id; - } - } - - return (0); -} - -static int -zfs_prop_get_userquota_common(zfs_handle_t *zhp, const char *propname, - uint64_t *propvalue, zfs_userquota_prop_t *typep) -{ - int err; - zfs_cmd_t zc = {"\0"}; - - (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); - - err = userquota_propname_decode(propname, - zfs_prop_get_int(zhp, ZFS_PROP_ZONED), - typep, zc.zc_value, sizeof (zc.zc_value), &zc.zc_guid); - zc.zc_objset_type = *typep; - if (err) - return (err); - - err = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_USERSPACE_ONE, &zc); - if (err) - return (err); - - *propvalue = zc.zc_cookie; - return (0); -} - -int -zfs_prop_get_userquota_int(zfs_handle_t *zhp, const char *propname, - uint64_t *propvalue) -{ - zfs_userquota_prop_t type; - - return (zfs_prop_get_userquota_common(zhp, propname, propvalue, - &type)); -} - -int -zfs_prop_get_userquota(zfs_handle_t *zhp, const char *propname, - char *propbuf, int proplen, boolean_t literal) -{ - int err; - uint64_t propvalue; - zfs_userquota_prop_t type; - - err = zfs_prop_get_userquota_common(zhp, propname, &propvalue, - &type); - - if (err) - return (err); - - if (literal) { - (void) snprintf(propbuf, proplen, "%llu", - (u_longlong_t)propvalue); - } else if (propvalue == 0 && - (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_GROUPQUOTA || - type == ZFS_PROP_USEROBJQUOTA || type == ZFS_PROP_GROUPOBJQUOTA || - type == ZFS_PROP_PROJECTQUOTA || - type == ZFS_PROP_PROJECTOBJQUOTA)) { - (void) strlcpy(propbuf, "none", proplen); - } else if (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_GROUPQUOTA || - type == ZFS_PROP_USERUSED || type == ZFS_PROP_GROUPUSED || - type == ZFS_PROP_PROJECTUSED || type == ZFS_PROP_PROJECTQUOTA) { - zfs_nicebytes(propvalue, propbuf, proplen); - } else { - zfs_nicenum(propvalue, propbuf, proplen); - } - return (0); -} - -/* - * propname must start with "written@" or "written#". - */ -int -zfs_prop_get_written_int(zfs_handle_t *zhp, const char *propname, - uint64_t *propvalue) -{ - int err; - zfs_cmd_t zc = {"\0"}; - const char *snapname; - - (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); - - assert(zfs_prop_written(propname)); - snapname = propname + strlen("written@"); - if (strchr(snapname, '@') != NULL || strchr(snapname, '#') != NULL) { - /* full snapshot or bookmark name specified */ - (void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value)); - } else { - /* snapname is the short name, append it to zhp's fsname */ - char *cp; - - (void) strlcpy(zc.zc_value, zhp->zfs_name, - sizeof (zc.zc_value)); - cp = strchr(zc.zc_value, '@'); - if (cp != NULL) - *cp = '\0'; - (void) strlcat(zc.zc_value, snapname - 1, sizeof (zc.zc_value)); - } - - err = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_SPACE_WRITTEN, &zc); - if (err) - return (err); - - *propvalue = zc.zc_cookie; - return (0); -} - -int -zfs_prop_get_written(zfs_handle_t *zhp, const char *propname, - char *propbuf, int proplen, boolean_t literal) -{ - int err; - uint64_t propvalue; - - err = zfs_prop_get_written_int(zhp, propname, &propvalue); - - if (err) - return (err); - - if (literal) { - (void) snprintf(propbuf, proplen, "%llu", - (u_longlong_t)propvalue); - } else { - zfs_nicebytes(propvalue, propbuf, proplen); - } - - return (0); -} - -/* - * Returns the name of the given zfs handle. - */ -const char * -zfs_get_name(const zfs_handle_t *zhp) -{ - return (zhp->zfs_name); -} - -/* - * Returns the name of the parent pool for the given zfs handle. - */ -const char * -zfs_get_pool_name(const zfs_handle_t *zhp) -{ - return (zhp->zpool_hdl->zpool_name); -} - -/* - * Returns the type of the given zfs handle. - */ -zfs_type_t -zfs_get_type(const zfs_handle_t *zhp) -{ - return (zhp->zfs_type); -} - -/* - * Returns the type of the given zfs handle, - * or, if a snapshot, the type of the snapshotted dataset. - */ -zfs_type_t -zfs_get_underlying_type(const zfs_handle_t *zhp) -{ - return (zhp->zfs_head_type); -} - -/* - * Is one dataset name a child dataset of another? - * - * Needs to handle these cases: - * Dataset 1 "a/foo" "a/foo" "a/foo" "a/foo" - * Dataset 2 "a/fo" "a/foobar" "a/bar/baz" "a/foo/bar" - * Descendant? No. No. No. Yes. - */ -static boolean_t -is_descendant(const char *ds1, const char *ds2) -{ - size_t d1len = strlen(ds1); - - /* ds2 can't be a descendant if it's smaller */ - if (strlen(ds2) < d1len) - return (B_FALSE); - - /* otherwise, compare strings and verify that there's a '/' char */ - return (ds2[d1len] == '/' && (strncmp(ds1, ds2, d1len) == 0)); -} - -/* - * Given a complete name, return just the portion that refers to the parent. - * Will return -1 if there is no parent (path is just the name of the - * pool). - */ -static int -parent_name(const char *path, char *buf, size_t buflen) -{ - char *slashp; - - (void) strlcpy(buf, path, buflen); - - if ((slashp = strrchr(buf, '/')) == NULL) - return (-1); - *slashp = '\0'; - - return (0); -} - -int -zfs_parent_name(zfs_handle_t *zhp, char *buf, size_t buflen) -{ - return (parent_name(zfs_get_name(zhp), buf, buflen)); -} - -/* - * If accept_ancestor is false, then check to make sure that the given path has - * a parent, and that it exists. If accept_ancestor is true, then find the - * closest existing ancestor for the given path. In prefixlen return the - * length of already existing prefix of the given path. We also fetch the - * 'zoned' property, which is used to validate property settings when creating - * new datasets. - */ -static int -check_parents(libzfs_handle_t *hdl, const char *path, uint64_t *zoned, - boolean_t accept_ancestor, int *prefixlen) -{ - zfs_cmd_t zc = {"\0"}; - char parent[ZFS_MAX_DATASET_NAME_LEN]; - char *slash; - zfs_handle_t *zhp; - char errbuf[ERRBUFLEN]; - uint64_t is_zoned; - - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot create '%s'"), path); - - /* get parent, and check to see if this is just a pool */ - if (parent_name(path, parent, sizeof (parent)) != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "missing dataset name")); - return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); - } - - /* check to see if the pool exists */ - if ((slash = strchr(parent, '/')) == NULL) - slash = parent + strlen(parent); - (void) strlcpy(zc.zc_name, parent, - MIN(sizeof (zc.zc_name), slash - parent + 1)); - if (zfs_ioctl(hdl, ZFS_IOC_OBJSET_STATS, &zc) != 0 && - errno == ENOENT) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "no such pool '%s'"), zc.zc_name); - return (zfs_error(hdl, EZFS_NOENT, errbuf)); - } - - /* check to see if the parent dataset exists */ - while ((zhp = make_dataset_handle(hdl, parent)) == NULL) { - if (errno == ENOENT && accept_ancestor) { - /* - * Go deeper to find an ancestor, give up on top level. - */ - if (parent_name(parent, parent, sizeof (parent)) != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "no such pool '%s'"), zc.zc_name); - return (zfs_error(hdl, EZFS_NOENT, errbuf)); - } - } else if (errno == ENOENT) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "parent does not exist")); - return (zfs_error(hdl, EZFS_NOENT, errbuf)); - } else - return (zfs_standard_error(hdl, errno, errbuf)); - } - - is_zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED); - if (zoned != NULL) - *zoned = is_zoned; - - /* we are in a non-global zone, but parent is in the global zone */ - if (getzoneid() != GLOBAL_ZONEID && !is_zoned) { - (void) zfs_standard_error(hdl, EPERM, errbuf); - zfs_close(zhp); - return (-1); - } - - /* make sure parent is a filesystem */ - if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "parent is not a filesystem")); - (void) zfs_error(hdl, EZFS_BADTYPE, errbuf); - zfs_close(zhp); - return (-1); - } - - zfs_close(zhp); - if (prefixlen != NULL) - *prefixlen = strlen(parent); - return (0); -} - -/* - * Finds whether the dataset of the given type(s) exists. - */ -boolean_t -zfs_dataset_exists(libzfs_handle_t *hdl, const char *path, zfs_type_t types) -{ - zfs_handle_t *zhp; - - if (!zfs_validate_name(hdl, path, types, B_FALSE)) - return (B_FALSE); - - /* - * Try to get stats for the dataset, which will tell us if it exists. - */ - if ((zhp = make_dataset_handle(hdl, path)) != NULL) { - int ds_type = zhp->zfs_type; - - zfs_close(zhp); - if (types & ds_type) - return (B_TRUE); - } - return (B_FALSE); -} - -/* - * Given a path to 'target', create all the ancestors between - * the prefixlen portion of the path, and the target itself. - * Fail if the initial prefixlen-ancestor does not already exist. - */ -int -create_parents(libzfs_handle_t *hdl, char *target, int prefixlen) -{ - zfs_handle_t *h; - char *cp; - const char *opname; - - /* make sure prefix exists */ - cp = target + prefixlen; - if (*cp != '/') { - assert(strchr(cp, '/') == NULL); - h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM); - } else { - *cp = '\0'; - h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM); - *cp = '/'; - } - if (h == NULL) - return (-1); - zfs_close(h); - - /* - * Attempt to create, mount, and share any ancestor filesystems, - * up to the prefixlen-long one. - */ - for (cp = target + prefixlen + 1; - (cp = strchr(cp, '/')) != NULL; *cp = '/', cp++) { - - *cp = '\0'; - - h = make_dataset_handle(hdl, target); - if (h) { - /* it already exists, nothing to do here */ - zfs_close(h); - continue; - } - - if (zfs_create(hdl, target, ZFS_TYPE_FILESYSTEM, - NULL) != 0) { - opname = dgettext(TEXT_DOMAIN, "create"); - goto ancestorerr; - } - - h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM); - if (h == NULL) { - opname = dgettext(TEXT_DOMAIN, "open"); - goto ancestorerr; - } - - if (zfs_mount(h, NULL, 0) != 0) { - opname = dgettext(TEXT_DOMAIN, "mount"); - goto ancestorerr; - } - - if (zfs_share(h, NULL) != 0) { - opname = dgettext(TEXT_DOMAIN, "share"); - goto ancestorerr; - } - - zfs_close(h); - } - zfs_commit_shares(NULL); - - return (0); - -ancestorerr: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "failed to %s ancestor '%s'"), opname, target); - return (-1); -} - -/* - * Creates non-existing ancestors of the given path. - */ -int -zfs_create_ancestors(libzfs_handle_t *hdl, const char *path) -{ - int prefix; - char *path_copy; - char errbuf[ERRBUFLEN]; - int rc = 0; - - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot create '%s'"), path); - - /* - * Check that we are not passing the nesting limit - * before we start creating any ancestors. - */ - if (dataset_nestcheck(path) != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "maximum name nesting depth exceeded")); - return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); - } - - if (check_parents(hdl, path, NULL, B_TRUE, &prefix) != 0) - return (-1); - - if ((path_copy = strdup(path)) != NULL) { - rc = create_parents(hdl, path_copy, prefix); - free(path_copy); - } - if (path_copy == NULL || rc != 0) - return (-1); - - return (0); -} - -/* - * Create a new filesystem or volume. - */ -int -zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type, - nvlist_t *props) -{ - int ret; - uint64_t size = 0; - uint64_t blocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE); - uint64_t zoned; - enum lzc_dataset_type ost; - zpool_handle_t *zpool_handle; - uint8_t *wkeydata = NULL; - uint_t wkeylen = 0; - char errbuf[ERRBUFLEN]; - char parent[ZFS_MAX_DATASET_NAME_LEN]; - - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot create '%s'"), path); - - /* validate the path, taking care to note the extended error message */ - if (!zfs_validate_name(hdl, path, type, B_TRUE)) - return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); - - if (dataset_nestcheck(path) != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "maximum name nesting depth exceeded")); - return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); - } - - /* validate parents exist */ - if (check_parents(hdl, path, &zoned, B_FALSE, NULL) != 0) - return (-1); - - /* - * The failure modes when creating a dataset of a different type over - * one that already exists is a little strange. In particular, if you - * try to create a dataset on top of an existing dataset, the ioctl() - * will return ENOENT, not EEXIST. To prevent this from happening, we - * first try to see if the dataset exists. - */ - if (zfs_dataset_exists(hdl, path, ZFS_TYPE_DATASET)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "dataset already exists")); - return (zfs_error(hdl, EZFS_EXISTS, errbuf)); - } - - if (type == ZFS_TYPE_VOLUME) - ost = LZC_DATSET_TYPE_ZVOL; - else - ost = LZC_DATSET_TYPE_ZFS; - - /* open zpool handle for prop validation */ - char pool_path[ZFS_MAX_DATASET_NAME_LEN]; - (void) strlcpy(pool_path, path, sizeof (pool_path)); - - /* truncate pool_path at first slash */ - char *p = strchr(pool_path, '/'); - if (p != NULL) - *p = '\0'; - - if ((zpool_handle = zpool_open(hdl, pool_path)) == NULL) - return (-1); - - if (props && (props = zfs_valid_proplist(hdl, type, props, - zoned, NULL, zpool_handle, B_TRUE, errbuf)) == 0) { - zpool_close(zpool_handle); - return (-1); - } - zpool_close(zpool_handle); - - if (type == ZFS_TYPE_VOLUME) { - /* - * If we are creating a volume, the size and block size must - * satisfy a few restraints. First, the blocksize must be a - * valid block size between SPA_{MIN,MAX}BLOCKSIZE. Second, the - * volsize must be a multiple of the block size, and cannot be - * zero. - */ - if (props == NULL || nvlist_lookup_uint64(props, - zfs_prop_to_name(ZFS_PROP_VOLSIZE), &size) != 0) { - nvlist_free(props); - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "missing volume size")); - return (zfs_error(hdl, EZFS_BADPROP, errbuf)); - } - - if ((ret = nvlist_lookup_uint64(props, - zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), - &blocksize)) != 0) { - if (ret == ENOENT) { - blocksize = zfs_prop_default_numeric( - ZFS_PROP_VOLBLOCKSIZE); - } else { - nvlist_free(props); - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "missing volume block size")); - return (zfs_error(hdl, EZFS_BADPROP, errbuf)); - } - } - - if (size == 0) { - nvlist_free(props); - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "volume size cannot be zero")); - return (zfs_error(hdl, EZFS_BADPROP, errbuf)); - } - - if (size % blocksize != 0) { - nvlist_free(props); - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "volume size must be a multiple of volume block " - "size")); - return (zfs_error(hdl, EZFS_BADPROP, errbuf)); - } - } - - (void) parent_name(path, parent, sizeof (parent)); - if (zfs_crypto_create(hdl, parent, props, NULL, B_TRUE, - &wkeydata, &wkeylen) != 0) { - nvlist_free(props); - return (zfs_error(hdl, EZFS_CRYPTOFAILED, errbuf)); - } - - /* create the dataset */ - ret = lzc_create(path, ost, props, wkeydata, wkeylen); - nvlist_free(props); - if (wkeydata != NULL) - free(wkeydata); - - /* check for failure */ - if (ret != 0) { - switch (errno) { - case ENOENT: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "no such parent '%s'"), parent); - return (zfs_error(hdl, EZFS_NOENT, errbuf)); - - case ENOTSUP: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "pool must be upgraded to set this " - "property or value")); - return (zfs_error(hdl, EZFS_BADVERSION, errbuf)); - - case EACCES: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "encryption root's key is not loaded " - "or provided")); - return (zfs_error(hdl, EZFS_CRYPTOFAILED, errbuf)); - - case ERANGE: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "invalid property value(s) specified")); - return (zfs_error(hdl, EZFS_BADPROP, errbuf)); -#ifdef _ILP32 - case EOVERFLOW: - /* - * This platform can't address a volume this big. - */ - if (type == ZFS_TYPE_VOLUME) - return (zfs_error(hdl, EZFS_VOLTOOBIG, - errbuf)); - zfs_fallthrough; -#endif - default: - return (zfs_standard_error(hdl, errno, errbuf)); - } - } - - return (0); -} - -/* - * Destroys the given dataset. The caller must make sure that the filesystem - * isn't mounted, and that there are no active dependents. If the file system - * does not exist this function does nothing. - */ -int -zfs_destroy(zfs_handle_t *zhp, boolean_t defer) -{ - int error; - - if (zhp->zfs_type != ZFS_TYPE_SNAPSHOT && defer) - return (EINVAL); - - if (zhp->zfs_type == ZFS_TYPE_BOOKMARK) { - nvlist_t *nv = fnvlist_alloc(); - fnvlist_add_boolean(nv, zhp->zfs_name); - error = lzc_destroy_bookmarks(nv, NULL); - fnvlist_free(nv); - if (error != 0) { - return (zfs_standard_error_fmt(zhp->zfs_hdl, error, - dgettext(TEXT_DOMAIN, "cannot destroy '%s'"), - zhp->zfs_name)); - } - return (0); - } - - if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) { - nvlist_t *nv = fnvlist_alloc(); - fnvlist_add_boolean(nv, zhp->zfs_name); - error = lzc_destroy_snaps(nv, defer, NULL); - fnvlist_free(nv); - } else { - error = lzc_destroy(zhp->zfs_name); - } - - if (error != 0 && error != ENOENT) { - return (zfs_standard_error_fmt(zhp->zfs_hdl, errno, - dgettext(TEXT_DOMAIN, "cannot destroy '%s'"), - zhp->zfs_name)); - } - - remove_mountpoint(zhp); - - return (0); -} - -struct destroydata { - nvlist_t *nvl; - const char *snapname; -}; - -static int -zfs_check_snap_cb(zfs_handle_t *zhp, void *arg) -{ - struct destroydata *dd = arg; - char name[ZFS_MAX_DATASET_NAME_LEN]; - int rv = 0; - - if (snprintf(name, sizeof (name), "%s@%s", zhp->zfs_name, - dd->snapname) >= sizeof (name)) - return (EINVAL); - - if (lzc_exists(name)) - fnvlist_add_boolean(dd->nvl, name); - - rv = zfs_iter_filesystems_v2(zhp, 0, zfs_check_snap_cb, dd); - zfs_close(zhp); - return (rv); -} - -/* - * Destroys all snapshots with the given name in zhp & descendants. - */ -int -zfs_destroy_snaps(zfs_handle_t *zhp, char *snapname, boolean_t defer) -{ - int ret; - struct destroydata dd = { 0 }; - - dd.snapname = snapname; - dd.nvl = fnvlist_alloc(); - (void) zfs_check_snap_cb(zfs_handle_dup(zhp), &dd); - - if (nvlist_empty(dd.nvl)) { - ret = zfs_standard_error_fmt(zhp->zfs_hdl, ENOENT, - dgettext(TEXT_DOMAIN, "cannot destroy '%s@%s'"), - zhp->zfs_name, snapname); - } else { - ret = zfs_destroy_snaps_nvl(zhp->zfs_hdl, dd.nvl, defer); - } - fnvlist_free(dd.nvl); - return (ret); -} - -/* - * Destroys all the snapshots named in the nvlist. - */ -int -zfs_destroy_snaps_nvl(libzfs_handle_t *hdl, nvlist_t *snaps, boolean_t defer) -{ - nvlist_t *errlist = NULL; - nvpair_t *pair; - - int ret = zfs_destroy_snaps_nvl_os(hdl, snaps); - if (ret != 0) - return (ret); - - ret = lzc_destroy_snaps(snaps, defer, &errlist); - - if (ret == 0) { - nvlist_free(errlist); - return (0); - } - - if (nvlist_empty(errlist)) { - char errbuf[ERRBUFLEN]; - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot destroy snapshots")); - - ret = zfs_standard_error(hdl, ret, errbuf); - } - for (pair = nvlist_next_nvpair(errlist, NULL); - pair != NULL; pair = nvlist_next_nvpair(errlist, pair)) { - char errbuf[ERRBUFLEN]; - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot destroy snapshot %s"), - nvpair_name(pair)); - - switch (fnvpair_value_int32(pair)) { - case EEXIST: - zfs_error_aux(hdl, - dgettext(TEXT_DOMAIN, "snapshot is cloned")); - ret = zfs_error(hdl, EZFS_EXISTS, errbuf); - break; - case EBUSY: { - nvlist_t *existing_holds; - int err = lzc_get_holds(nvpair_name(pair), - &existing_holds); - - /* check the presence of holders */ - if (err == 0 && !nvlist_empty(existing_holds)) { - zfs_error_aux(hdl, - dgettext(TEXT_DOMAIN, "it's being held. " - "Run 'zfs holds -r %s' to see holders."), - nvpair_name(pair)); - ret = zfs_error(hdl, EBUSY, errbuf); - } else { - ret = zfs_standard_error(hdl, errno, errbuf); - } - - if (err == 0) - nvlist_free(existing_holds); - break; - } - default: - ret = zfs_standard_error(hdl, errno, errbuf); - break; - } - } - - nvlist_free(errlist); - return (ret); -} - -/* - * Clones the given dataset. The target must be of the same type as the source. - */ -int -zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props) -{ - char parent[ZFS_MAX_DATASET_NAME_LEN]; - int ret; - char errbuf[ERRBUFLEN]; - libzfs_handle_t *hdl = zhp->zfs_hdl; - uint64_t zoned; - - assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT); - - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot create '%s'"), target); - - /* validate the target/clone name */ - if (!zfs_validate_name(hdl, target, ZFS_TYPE_FILESYSTEM, B_TRUE)) - return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); - - /* validate parents exist */ - if (check_parents(hdl, target, &zoned, B_FALSE, NULL) != 0) - return (-1); - - (void) parent_name(target, parent, sizeof (parent)); - - /* do the clone */ - - if (props) { - zfs_type_t type = ZFS_TYPE_FILESYSTEM; - - if (ZFS_IS_VOLUME(zhp)) - type = ZFS_TYPE_VOLUME; - if ((props = zfs_valid_proplist(hdl, type, props, zoned, - zhp, zhp->zpool_hdl, B_TRUE, errbuf)) == NULL) - return (-1); - if (zfs_fix_auto_resv(zhp, props) == -1) { - nvlist_free(props); - return (-1); - } - } - - if (zfs_crypto_clone_check(hdl, zhp, parent, props) != 0) { - nvlist_free(props); - return (zfs_error(hdl, EZFS_CRYPTOFAILED, errbuf)); - } - - ret = lzc_clone(target, zhp->zfs_name, props); - nvlist_free(props); - - if (ret != 0) { - switch (errno) { - - case ENOENT: - /* - * The parent doesn't exist. We should have caught this - * above, but there may a race condition that has since - * destroyed the parent. - * - * At this point, we don't know whether it's the source - * that doesn't exist anymore, or whether the target - * dataset doesn't exist. - */ - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "no such parent '%s'"), parent); - return (zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf)); - - case EXDEV: - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "source and target pools differ")); - return (zfs_error(zhp->zfs_hdl, EZFS_CROSSTARGET, - errbuf)); - - default: - return (zfs_standard_error(zhp->zfs_hdl, errno, - errbuf)); - } - } - - return (ret); -} - -/* - * Promotes the given clone fs to be the clone parent. - */ -int -zfs_promote(zfs_handle_t *zhp) -{ - libzfs_handle_t *hdl = zhp->zfs_hdl; - char snapname[ZFS_MAX_DATASET_NAME_LEN]; - int ret; - char errbuf[ERRBUFLEN]; - - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot promote '%s'"), zhp->zfs_name); - - if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "snapshots can not be promoted")); - return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); - } - - if (zhp->zfs_dmustats.dds_origin[0] == '\0') { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "not a cloned filesystem")); - return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); - } - - if (!zfs_validate_name(hdl, zhp->zfs_name, zhp->zfs_type, B_TRUE)) - return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); - - ret = lzc_promote(zhp->zfs_name, snapname, sizeof (snapname)); - - if (ret != 0) { - switch (ret) { - case EACCES: - /* - * Promoting encrypted dataset outside its - * encryption root. - */ - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "cannot promote dataset outside its " - "encryption root")); - return (zfs_error(hdl, EZFS_EXISTS, errbuf)); - - case EEXIST: - /* There is a conflicting snapshot name. */ - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "conflicting snapshot '%s' from parent '%s'"), - snapname, zhp->zfs_dmustats.dds_origin); - return (zfs_error(hdl, EZFS_EXISTS, errbuf)); - - default: - return (zfs_standard_error(hdl, ret, errbuf)); - } - } - return (ret); -} - -typedef struct snapdata { - nvlist_t *sd_nvl; - const char *sd_snapname; -} snapdata_t; - -static int -zfs_snapshot_cb(zfs_handle_t *zhp, void *arg) -{ - snapdata_t *sd = arg; - char name[ZFS_MAX_DATASET_NAME_LEN]; - int rv = 0; - - if (zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT) == 0) { - if (snprintf(name, sizeof (name), "%s@%s", zfs_get_name(zhp), - sd->sd_snapname) >= sizeof (name)) - return (EINVAL); - - fnvlist_add_boolean(sd->sd_nvl, name); - - rv = zfs_iter_filesystems_v2(zhp, 0, zfs_snapshot_cb, sd); - } - zfs_close(zhp); - - return (rv); -} - -/* - * Creates snapshots. The keys in the snaps nvlist are the snapshots to be - * created. - */ -int -zfs_snapshot_nvl(libzfs_handle_t *hdl, nvlist_t *snaps, nvlist_t *props) -{ - int ret; - char errbuf[ERRBUFLEN]; - nvpair_t *elem; - nvlist_t *errors; - zpool_handle_t *zpool_hdl; - char pool[ZFS_MAX_DATASET_NAME_LEN]; - - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot create snapshots ")); - - elem = NULL; - while ((elem = nvlist_next_nvpair(snaps, elem)) != NULL) { - const char *snapname = nvpair_name(elem); - - /* validate the target name */ - if (!zfs_validate_name(hdl, snapname, ZFS_TYPE_SNAPSHOT, - B_TRUE)) { - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, - "cannot create snapshot '%s'"), snapname); - return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); - } - } - - /* - * get pool handle for prop validation. assumes all snaps are in the - * same pool, as does lzc_snapshot (below). - */ - elem = nvlist_next_nvpair(snaps, NULL); - if (elem == NULL) - return (-1); - (void) strlcpy(pool, nvpair_name(elem), sizeof (pool)); - pool[strcspn(pool, "/@")] = '\0'; - zpool_hdl = zpool_open(hdl, pool); - if (zpool_hdl == NULL) - return (-1); - - if (props != NULL && - (props = zfs_valid_proplist(hdl, ZFS_TYPE_SNAPSHOT, - props, B_FALSE, NULL, zpool_hdl, B_FALSE, errbuf)) == NULL) { - zpool_close(zpool_hdl); - return (-1); - } - zpool_close(zpool_hdl); - - ret = lzc_snapshot(snaps, props, &errors); - - if (ret != 0) { - boolean_t printed = B_FALSE; - for (elem = nvlist_next_nvpair(errors, NULL); - elem != NULL; - elem = nvlist_next_nvpair(errors, elem)) { - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, - "cannot create snapshot '%s'"), nvpair_name(elem)); - (void) zfs_standard_error(hdl, - fnvpair_value_int32(elem), errbuf); - printed = B_TRUE; - } - if (!printed) { - switch (ret) { - case EXDEV: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "multiple snapshots of same " - "fs not allowed")); - (void) zfs_error(hdl, EZFS_EXISTS, errbuf); - - break; - default: - (void) zfs_standard_error(hdl, ret, errbuf); - } - } - } - - nvlist_free(props); - nvlist_free(errors); - return (ret); -} - -int -zfs_snapshot(libzfs_handle_t *hdl, const char *path, boolean_t recursive, - nvlist_t *props) -{ - int ret; - snapdata_t sd = { 0 }; - char fsname[ZFS_MAX_DATASET_NAME_LEN]; - char *cp; - zfs_handle_t *zhp; - char errbuf[ERRBUFLEN]; - - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot snapshot %s"), path); - - if (!zfs_validate_name(hdl, path, ZFS_TYPE_SNAPSHOT, B_TRUE)) - return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); - - (void) strlcpy(fsname, path, sizeof (fsname)); - cp = strchr(fsname, '@'); - *cp = '\0'; - sd.sd_snapname = cp + 1; - - if ((zhp = zfs_open(hdl, fsname, ZFS_TYPE_FILESYSTEM | - ZFS_TYPE_VOLUME)) == NULL) { - return (-1); - } - - sd.sd_nvl = fnvlist_alloc(); - if (recursive) { - (void) zfs_snapshot_cb(zfs_handle_dup(zhp), &sd); - } else { - fnvlist_add_boolean(sd.sd_nvl, path); - } - - ret = zfs_snapshot_nvl(hdl, sd.sd_nvl, props); - fnvlist_free(sd.sd_nvl); - zfs_close(zhp); - return (ret); -} - -/* - * Destroy any more recent snapshots. We invoke this callback on any dependents - * of the snapshot first. If the 'cb_dependent' member is non-zero, then this - * is a dependent and we should just destroy it without checking the transaction - * group. - */ -typedef struct rollback_data { - const char *cb_target; /* the snapshot */ - uint64_t cb_create; /* creation time reference */ - boolean_t cb_error; - boolean_t cb_force; -} rollback_data_t; - -static int -rollback_destroy_dependent(zfs_handle_t *zhp, void *data) -{ - rollback_data_t *cbp = data; - prop_changelist_t *clp; - - /* We must destroy this clone; first unmount it */ - clp = changelist_gather(zhp, ZFS_PROP_NAME, 0, - cbp->cb_force ? MS_FORCE: 0); - if (clp == NULL || changelist_prefix(clp) != 0) { - cbp->cb_error = B_TRUE; - zfs_close(zhp); - return (0); - } - if (zfs_destroy(zhp, B_FALSE) != 0) - cbp->cb_error = B_TRUE; - else - changelist_remove(clp, zhp->zfs_name); - (void) changelist_postfix(clp); - changelist_free(clp); - - zfs_close(zhp); - return (0); -} - -static int -rollback_destroy(zfs_handle_t *zhp, void *data) -{ - rollback_data_t *cbp = data; - - if (zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > cbp->cb_create) { - cbp->cb_error |= zfs_iter_dependents_v2(zhp, 0, B_FALSE, - rollback_destroy_dependent, cbp); - - cbp->cb_error |= zfs_destroy(zhp, B_FALSE); - } - - zfs_close(zhp); - return (0); -} - -/* - * Given a dataset, rollback to a specific snapshot, discarding any - * data changes since then and making it the active dataset. - * - * Any snapshots and bookmarks more recent than the target are - * destroyed, along with their dependents (i.e. clones). - */ -int -zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, boolean_t force) -{ - rollback_data_t cb = { 0 }; - int err; - boolean_t restore_resv = 0; - uint64_t old_volsize = 0, new_volsize; - zfs_prop_t resv_prop = { 0 }; - uint64_t min_txg = 0; - - assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM || - zhp->zfs_type == ZFS_TYPE_VOLUME); - - /* - * Destroy all recent snapshots and their dependents. - */ - cb.cb_force = force; - cb.cb_target = snap->zfs_name; - cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG); - - if (cb.cb_create > 0) - min_txg = cb.cb_create; - - (void) zfs_iter_snapshots_v2(zhp, 0, rollback_destroy, &cb, - min_txg, 0); - - (void) zfs_iter_bookmarks_v2(zhp, 0, rollback_destroy, &cb); - - if (cb.cb_error) - return (-1); - - /* - * Now that we have verified that the snapshot is the latest, - * rollback to the given snapshot. - */ - - if (zhp->zfs_type == ZFS_TYPE_VOLUME) { - if (zfs_which_resv_prop(zhp, &resv_prop) < 0) - return (-1); - old_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE); - restore_resv = - (old_volsize == zfs_prop_get_int(zhp, resv_prop)); - } - - /* - * Pass both the filesystem and the wanted snapshot names, - * we would get an error back if the snapshot is destroyed or - * a new snapshot is created before this request is processed. - */ - err = lzc_rollback_to(zhp->zfs_name, snap->zfs_name); - if (err != 0) { - char errbuf[ERRBUFLEN]; - - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot rollback '%s'"), - zhp->zfs_name); - switch (err) { - case EEXIST: - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "there is a snapshot or bookmark more recent " - "than '%s'"), snap->zfs_name); - (void) zfs_error(zhp->zfs_hdl, EZFS_EXISTS, errbuf); - break; - case ESRCH: - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "'%s' is not found among snapshots of '%s'"), - snap->zfs_name, zhp->zfs_name); - (void) zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf); - break; - case EINVAL: - (void) zfs_error(zhp->zfs_hdl, EZFS_BADTYPE, errbuf); - break; - default: - (void) zfs_standard_error(zhp->zfs_hdl, err, errbuf); - } - return (err); - } - - /* - * For volumes, if the pre-rollback volsize matched the pre- - * rollback reservation and the volsize has changed then set - * the reservation property to the post-rollback volsize. - * Make a new handle since the rollback closed the dataset. - */ - if ((zhp->zfs_type == ZFS_TYPE_VOLUME) && - (zhp = make_dataset_handle(zhp->zfs_hdl, zhp->zfs_name))) { - if (restore_resv) { - new_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE); - if (old_volsize != new_volsize) - err = zfs_prop_set_int(zhp, resv_prop, - new_volsize); - } - zfs_close(zhp); - } - return (err); -} - -/* - * Renames the given dataset. - */ -int -zfs_rename(zfs_handle_t *zhp, const char *target, renameflags_t flags) -{ - int ret = 0; - zfs_cmd_t zc = {"\0"}; - char *delim; - prop_changelist_t *cl = NULL; - char parent[ZFS_MAX_DATASET_NAME_LEN]; - char property[ZFS_MAXPROPLEN]; - libzfs_handle_t *hdl = zhp->zfs_hdl; - char errbuf[ERRBUFLEN]; - - /* if we have the same exact name, just return success */ - if (strcmp(zhp->zfs_name, target) == 0) - return (0); - - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot rename to '%s'"), target); - - /* make sure source name is valid */ - if (!zfs_validate_name(hdl, zhp->zfs_name, zhp->zfs_type, B_TRUE)) - return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); - - /* - * Make sure the target name is valid - */ - if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) { - if ((strchr(target, '@') == NULL) || - *target == '@') { - /* - * Snapshot target name is abbreviated, - * reconstruct full dataset name - */ - (void) strlcpy(parent, zhp->zfs_name, - sizeof (parent)); - delim = strchr(parent, '@'); - if (strchr(target, '@') == NULL) - *(++delim) = '\0'; - else - *delim = '\0'; - (void) strlcat(parent, target, sizeof (parent)); - target = parent; - } else { - /* - * Make sure we're renaming within the same dataset. - */ - delim = strchr(target, '@'); - if (strncmp(zhp->zfs_name, target, delim - target) - != 0 || zhp->zfs_name[delim - target] != '@') { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "snapshots must be part of same " - "dataset")); - return (zfs_error(hdl, EZFS_CROSSTARGET, - errbuf)); - } - } - - if (!zfs_validate_name(hdl, target, zhp->zfs_type, B_TRUE)) - return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); - } else { - if (flags.recursive) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "recursive rename must be a snapshot")); - return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); - } - - if (!zfs_validate_name(hdl, target, zhp->zfs_type, B_TRUE)) - return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); - - /* validate parents */ - if (check_parents(hdl, target, NULL, B_FALSE, NULL) != 0) - return (-1); - - /* make sure we're in the same pool */ - verify((delim = strchr(target, '/')) != NULL); - if (strncmp(zhp->zfs_name, target, delim - target) != 0 || - zhp->zfs_name[delim - target] != '/') { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "datasets must be within same pool")); - return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf)); - } - - /* new name cannot be a child of the current dataset name */ - if (is_descendant(zhp->zfs_name, target)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "New dataset name cannot be a descendant of " - "current dataset name")); - return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); - } - } - - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot rename '%s'"), zhp->zfs_name); - - if (getzoneid() == GLOBAL_ZONEID && - zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "dataset is used in a non-global zone")); - return (zfs_error(hdl, EZFS_ZONED, errbuf)); - } - - /* - * Avoid unmounting file systems with mountpoint property set to - * 'legacy' or 'none' even if -u option is not given. - */ - if (zhp->zfs_type == ZFS_TYPE_FILESYSTEM && - !flags.recursive && !flags.nounmount && - zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, property, - sizeof (property), NULL, NULL, 0, B_FALSE) == 0 && - (strcmp(property, "legacy") == 0 || - strcmp(property, "none") == 0)) { - flags.nounmount = B_TRUE; - } - if (flags.recursive) { - char *parentname = zfs_strdup(zhp->zfs_hdl, zhp->zfs_name); - delim = strchr(parentname, '@'); - *delim = '\0'; - zfs_handle_t *zhrp = zfs_open(zhp->zfs_hdl, parentname, - ZFS_TYPE_DATASET); - free(parentname); - if (zhrp == NULL) { - ret = -1; - goto error; - } - zfs_close(zhrp); - } else if (zhp->zfs_type != ZFS_TYPE_SNAPSHOT) { - if ((cl = changelist_gather(zhp, ZFS_PROP_NAME, - flags.nounmount ? CL_GATHER_DONT_UNMOUNT : - CL_GATHER_ITER_MOUNTED, - flags.forceunmount ? MS_FORCE : 0)) == NULL) - return (-1); - - if (changelist_haszonedchild(cl)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "child dataset with inherited mountpoint is used " - "in a non-global zone")); - (void) zfs_error(hdl, EZFS_ZONED, errbuf); - ret = -1; - goto error; - } - - if ((ret = changelist_prefix(cl)) != 0) - goto error; - } - - if (ZFS_IS_VOLUME(zhp)) - zc.zc_objset_type = DMU_OST_ZVOL; - else - zc.zc_objset_type = DMU_OST_ZFS; - - (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); - (void) strlcpy(zc.zc_value, target, sizeof (zc.zc_value)); - - zc.zc_cookie = !!flags.recursive; - zc.zc_cookie |= (!!flags.nounmount) << 1; - - if ((ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_RENAME, &zc)) != 0) { - /* - * if it was recursive, the one that actually failed will - * be in zc.zc_name - */ - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot rename '%s'"), zc.zc_name); - - if (flags.recursive && errno == EEXIST) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "a child dataset already has a snapshot " - "with the new name")); - (void) zfs_error(hdl, EZFS_EXISTS, errbuf); - } else if (errno == EACCES) { - 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); - } - - /* - * On failure, we still want to remount any filesystems that - * were previously mounted, so we don't alter the system state. - */ - if (cl != NULL) - (void) changelist_postfix(cl); - } else { - if (cl != NULL) { - changelist_rename(cl, zfs_get_name(zhp), target); - ret = changelist_postfix(cl); - } - (void) strlcpy(zhp->zfs_name, target, sizeof (zhp->zfs_name)); - } - -error: - if (cl != NULL) { - changelist_free(cl); - } - return (ret); -} - -nvlist_t * -zfs_get_all_props(zfs_handle_t *zhp) -{ - return (zhp->zfs_props); -} - -nvlist_t * -zfs_get_recvd_props(zfs_handle_t *zhp) -{ - if (zhp->zfs_recvd_props == NULL) - if (get_recvd_props_ioctl(zhp) != 0) - return (NULL); - return (zhp->zfs_recvd_props); -} - -nvlist_t * -zfs_get_user_props(zfs_handle_t *zhp) -{ - return (zhp->zfs_user_props); -} - -/* - * This function is used by 'zfs list' to determine the exact set of columns to - * display, and their maximum widths. This does two main things: - * - * - If this is a list of all properties, then expand the list to include - * all native properties, and set a flag so that for each dataset we look - * for new unique user properties and add them to the list. - * - * - For non fixed-width properties, keep track of the maximum width seen - * so that we can size the column appropriately. If the user has - * requested received property values, we also need to compute the width - * of the RECEIVED column. - */ -int -zfs_expand_proplist(zfs_handle_t *zhp, zprop_list_t **plp, boolean_t received, - boolean_t literal) -{ - libzfs_handle_t *hdl = zhp->zfs_hdl; - zprop_list_t *entry; - zprop_list_t **last, **start; - nvlist_t *userprops, *propval; - nvpair_t *elem; - const char *strval; - char buf[ZFS_MAXPROPLEN]; - - if (zprop_expand_list(hdl, plp, ZFS_TYPE_DATASET) != 0) - return (-1); - - userprops = zfs_get_user_props(zhp); - - entry = *plp; - if (entry->pl_all && nvlist_next_nvpair(userprops, NULL) != NULL) { - /* - * Go through and add any user properties as necessary. We - * start by incrementing our list pointer to the first - * non-native property. - */ - start = plp; - while (*start != NULL) { - if ((*start)->pl_prop == ZPROP_USERPROP) - break; - start = &(*start)->pl_next; - } - - elem = NULL; - while ((elem = nvlist_next_nvpair(userprops, elem)) != NULL) { - /* - * See if we've already found this property in our list. - */ - for (last = start; *last != NULL; - last = &(*last)->pl_next) { - if (strcmp((*last)->pl_user_prop, - nvpair_name(elem)) == 0) - break; - } - - if (*last == NULL) { - entry = zfs_alloc(hdl, sizeof (zprop_list_t)); - entry->pl_user_prop = - zfs_strdup(hdl, nvpair_name(elem)); - entry->pl_prop = ZPROP_USERPROP; - entry->pl_width = strlen(nvpair_name(elem)); - entry->pl_all = B_TRUE; - *last = entry; - } - } - } - - /* - * Now go through and check the width of any non-fixed columns - */ - for (entry = *plp; entry != NULL; entry = entry->pl_next) { - if (entry->pl_fixed && !literal) - continue; - - if (entry->pl_prop != ZPROP_USERPROP) { - if (zfs_prop_get(zhp, entry->pl_prop, - buf, sizeof (buf), NULL, NULL, 0, literal) == 0) { - if (strlen(buf) > entry->pl_width) - entry->pl_width = strlen(buf); - } - if (received && zfs_prop_get_recvd(zhp, - zfs_prop_to_name(entry->pl_prop), - buf, sizeof (buf), literal) == 0) - if (strlen(buf) > entry->pl_recvd_width) - entry->pl_recvd_width = strlen(buf); - } else { - if (nvlist_lookup_nvlist(userprops, entry->pl_user_prop, - &propval) == 0) { - strval = fnvlist_lookup_string(propval, - ZPROP_VALUE); - if (strlen(strval) > entry->pl_width) - entry->pl_width = strlen(strval); - } - if (received && zfs_prop_get_recvd(zhp, - entry->pl_user_prop, - buf, sizeof (buf), literal) == 0) - if (strlen(buf) > entry->pl_recvd_width) - entry->pl_recvd_width = strlen(buf); - } - } - - return (0); -} - -void -zfs_prune_proplist(zfs_handle_t *zhp, uint8_t *props) -{ - nvpair_t *curr; - nvpair_t *next; - - /* - * Keep a reference to the props-table against which we prune the - * properties. - */ - zhp->zfs_props_table = props; - - curr = nvlist_next_nvpair(zhp->zfs_props, NULL); - - while (curr) { - zfs_prop_t zfs_prop = zfs_name_to_prop(nvpair_name(curr)); - next = nvlist_next_nvpair(zhp->zfs_props, curr); - - /* - * User properties will result in ZPROP_USERPROP (an alias - * for ZPROP_INVAL), and since we - * only know how to prune standard ZFS properties, we always - * leave these in the list. This can also happen if we - * encounter an unknown DSL property (when running older - * software, for example). - */ - if (zfs_prop != ZPROP_USERPROP && props[zfs_prop] == B_FALSE) - (void) nvlist_remove(zhp->zfs_props, - nvpair_name(curr), nvpair_type(curr)); - curr = next; - } -} - -static int -zfs_smb_acl_mgmt(libzfs_handle_t *hdl, char *dataset, char *path, - zfs_smb_acl_op_t cmd, char *resource1, char *resource2) -{ - zfs_cmd_t zc = {"\0"}; - nvlist_t *nvlist = NULL; - int error; - - (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); - (void) strlcpy(zc.zc_value, path, sizeof (zc.zc_value)); - zc.zc_cookie = (uint64_t)cmd; - - if (cmd == ZFS_SMB_ACL_RENAME) { - if (nvlist_alloc(&nvlist, NV_UNIQUE_NAME, 0) != 0) { - (void) no_memory(hdl); - return (0); - } - } - - switch (cmd) { - case ZFS_SMB_ACL_ADD: - case ZFS_SMB_ACL_REMOVE: - (void) strlcpy(zc.zc_string, resource1, sizeof (zc.zc_string)); - break; - case ZFS_SMB_ACL_RENAME: - if (nvlist_add_string(nvlist, ZFS_SMB_ACL_SRC, - resource1) != 0) { - (void) no_memory(hdl); - return (-1); - } - if (nvlist_add_string(nvlist, ZFS_SMB_ACL_TARGET, - resource2) != 0) { - (void) no_memory(hdl); - return (-1); - } - zcmd_write_src_nvlist(hdl, &zc, nvlist); - break; - case ZFS_SMB_ACL_PURGE: - break; - default: - return (-1); - } - error = lzc_ioctl_fd(hdl->libzfs_fd, ZFS_IOC_SMB_ACL, &zc); - nvlist_free(nvlist); - return (error); -} - -int -zfs_smb_acl_add(libzfs_handle_t *hdl, char *dataset, - char *path, char *resource) -{ - return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_ADD, - resource, NULL)); -} - -int -zfs_smb_acl_remove(libzfs_handle_t *hdl, char *dataset, - char *path, char *resource) -{ - return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_REMOVE, - resource, NULL)); -} - -int -zfs_smb_acl_purge(libzfs_handle_t *hdl, char *dataset, char *path) -{ - return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_PURGE, - NULL, NULL)); -} - -int -zfs_smb_acl_rename(libzfs_handle_t *hdl, char *dataset, char *path, - char *oldname, char *newname) -{ - return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_RENAME, - oldname, newname)); -} - -int -zfs_userspace(zfs_handle_t *zhp, zfs_userquota_prop_t type, - zfs_userspace_cb_t func, void *arg) -{ - zfs_cmd_t zc = {"\0"}; - zfs_useracct_t buf[100]; - libzfs_handle_t *hdl = zhp->zfs_hdl; - int ret; - - (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); - - zc.zc_objset_type = type; - zc.zc_nvlist_dst = (uintptr_t)buf; - - for (;;) { - zfs_useracct_t *zua = buf; - - zc.zc_nvlist_dst_size = sizeof (buf); - if (zfs_ioctl(hdl, ZFS_IOC_USERSPACE_MANY, &zc) != 0) { - if ((errno == ENOTSUP && - (type == ZFS_PROP_USEROBJUSED || - type == ZFS_PROP_GROUPOBJUSED || - type == ZFS_PROP_USEROBJQUOTA || - type == ZFS_PROP_GROUPOBJQUOTA || - type == ZFS_PROP_PROJECTOBJUSED || - type == ZFS_PROP_PROJECTOBJQUOTA || - type == ZFS_PROP_PROJECTUSED || - type == ZFS_PROP_PROJECTQUOTA))) - break; - - return (zfs_standard_error_fmt(hdl, errno, - dgettext(TEXT_DOMAIN, - "cannot get used/quota for %s"), zc.zc_name)); - } - if (zc.zc_nvlist_dst_size == 0) - break; - - while (zc.zc_nvlist_dst_size > 0) { - if ((ret = func(arg, zua->zu_domain, zua->zu_rid, - zua->zu_space, zc.zc_guid)) != 0) - return (ret); - zua++; - zc.zc_nvlist_dst_size -= sizeof (zfs_useracct_t); - } - } - - return (0); -} - -struct holdarg { - nvlist_t *nvl; - const char *snapname; - const char *tag; - boolean_t recursive; - int error; -}; - -static int -zfs_hold_one(zfs_handle_t *zhp, void *arg) -{ - struct holdarg *ha = arg; - char name[ZFS_MAX_DATASET_NAME_LEN]; - int rv = 0; - - if (snprintf(name, sizeof (name), "%s@%s", zhp->zfs_name, - ha->snapname) >= sizeof (name)) - return (EINVAL); - - if (lzc_exists(name)) - fnvlist_add_string(ha->nvl, name, ha->tag); - - if (ha->recursive) - rv = zfs_iter_filesystems_v2(zhp, 0, zfs_hold_one, ha); - zfs_close(zhp); - return (rv); -} - -int -zfs_hold(zfs_handle_t *zhp, const char *snapname, const char *tag, - boolean_t recursive, int cleanup_fd) -{ - int ret; - struct holdarg ha; - - ha.nvl = fnvlist_alloc(); - ha.snapname = snapname; - ha.tag = tag; - ha.recursive = recursive; - (void) zfs_hold_one(zfs_handle_dup(zhp), &ha); - - if (nvlist_empty(ha.nvl)) { - char errbuf[ERRBUFLEN]; - - fnvlist_free(ha.nvl); - ret = ENOENT; - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, - "cannot hold snapshot '%s@%s'"), - zhp->zfs_name, snapname); - (void) zfs_standard_error(zhp->zfs_hdl, ret, errbuf); - return (ret); - } - - ret = zfs_hold_nvl(zhp, cleanup_fd, ha.nvl); - fnvlist_free(ha.nvl); - - return (ret); -} - -int -zfs_hold_nvl(zfs_handle_t *zhp, int cleanup_fd, nvlist_t *holds) -{ - int ret; - nvlist_t *errors; - libzfs_handle_t *hdl = zhp->zfs_hdl; - char errbuf[ERRBUFLEN]; - nvpair_t *elem; - - errors = NULL; - ret = lzc_hold(holds, cleanup_fd, &errors); - - if (ret == 0) { - /* There may be errors even in the success case. */ - fnvlist_free(errors); - return (0); - } - - if (nvlist_empty(errors)) { - /* no hold-specific errors */ - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot hold")); - switch (ret) { - case ENOTSUP: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "pool must be upgraded")); - (void) zfs_error(hdl, EZFS_BADVERSION, errbuf); - break; - case EINVAL: - (void) zfs_error(hdl, EZFS_BADTYPE, errbuf); - break; - default: - (void) zfs_standard_error(hdl, ret, errbuf); - } - } - - for (elem = nvlist_next_nvpair(errors, NULL); - elem != NULL; - elem = nvlist_next_nvpair(errors, elem)) { - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, - "cannot hold snapshot '%s'"), nvpair_name(elem)); - switch (fnvpair_value_int32(elem)) { - case E2BIG: - /* - * Temporary tags wind up having the ds object id - * prepended. So even if we passed the length check - * above, it's still possible for the tag to wind - * up being slightly too long. - */ - (void) zfs_error(hdl, EZFS_TAGTOOLONG, errbuf); - break; - case EINVAL: - (void) zfs_error(hdl, EZFS_BADTYPE, errbuf); - break; - case EEXIST: - (void) zfs_error(hdl, EZFS_REFTAG_HOLD, errbuf); - break; - default: - (void) zfs_standard_error(hdl, - fnvpair_value_int32(elem), errbuf); - } - } - - fnvlist_free(errors); - return (ret); -} - -static int -zfs_release_one(zfs_handle_t *zhp, void *arg) -{ - struct holdarg *ha = arg; - char name[ZFS_MAX_DATASET_NAME_LEN]; - int rv = 0; - nvlist_t *existing_holds; - - if (snprintf(name, sizeof (name), "%s@%s", zhp->zfs_name, - ha->snapname) >= sizeof (name)) { - ha->error = EINVAL; - rv = EINVAL; - } - - if (lzc_get_holds(name, &existing_holds) != 0) { - ha->error = ENOENT; - } else if (!nvlist_exists(existing_holds, ha->tag)) { - ha->error = ESRCH; - } else { - nvlist_t *torelease = fnvlist_alloc(); - fnvlist_add_boolean(torelease, ha->tag); - fnvlist_add_nvlist(ha->nvl, name, torelease); - fnvlist_free(torelease); - } - - if (ha->recursive) - rv = zfs_iter_filesystems_v2(zhp, 0, zfs_release_one, ha); - zfs_close(zhp); - return (rv); -} - -int -zfs_release(zfs_handle_t *zhp, const char *snapname, const char *tag, - boolean_t recursive) -{ - int ret; - struct holdarg ha; - nvlist_t *errors = NULL; - nvpair_t *elem; - libzfs_handle_t *hdl = zhp->zfs_hdl; - char errbuf[ERRBUFLEN]; - - ha.nvl = fnvlist_alloc(); - ha.snapname = snapname; - ha.tag = tag; - ha.recursive = recursive; - ha.error = 0; - (void) zfs_release_one(zfs_handle_dup(zhp), &ha); - - if (nvlist_empty(ha.nvl)) { - fnvlist_free(ha.nvl); - ret = ha.error; - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, - "cannot release hold from snapshot '%s@%s'"), - zhp->zfs_name, snapname); - if (ret == ESRCH) { - (void) zfs_error(hdl, EZFS_REFTAG_RELE, errbuf); - } else { - (void) zfs_standard_error(hdl, ret, errbuf); - } - return (ret); - } - - ret = lzc_release(ha.nvl, &errors); - fnvlist_free(ha.nvl); - - if (ret == 0) { - /* There may be errors even in the success case. */ - fnvlist_free(errors); - return (0); - } - - if (nvlist_empty(errors)) { - /* no hold-specific errors */ - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot release")); - switch (errno) { - case ENOTSUP: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "pool must be upgraded")); - (void) zfs_error(hdl, EZFS_BADVERSION, errbuf); - break; - default: - (void) zfs_standard_error(hdl, errno, errbuf); - } - } - - for (elem = nvlist_next_nvpair(errors, NULL); - elem != NULL; - elem = nvlist_next_nvpair(errors, elem)) { - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, - "cannot release hold from snapshot '%s'"), - nvpair_name(elem)); - switch (fnvpair_value_int32(elem)) { - case ESRCH: - (void) zfs_error(hdl, EZFS_REFTAG_RELE, errbuf); - break; - case EINVAL: - (void) zfs_error(hdl, EZFS_BADTYPE, errbuf); - break; - default: - (void) zfs_standard_error(hdl, - fnvpair_value_int32(elem), errbuf); - } - } - - fnvlist_free(errors); - return (ret); -} - -int -zfs_get_fsacl(zfs_handle_t *zhp, nvlist_t **nvl) -{ - zfs_cmd_t zc = {"\0"}; - libzfs_handle_t *hdl = zhp->zfs_hdl; - int nvsz = 2048; - void *nvbuf; - int err = 0; - char errbuf[ERRBUFLEN]; - - assert(zhp->zfs_type == ZFS_TYPE_VOLUME || - zhp->zfs_type == ZFS_TYPE_FILESYSTEM); - -tryagain: - - nvbuf = malloc(nvsz); - if (nvbuf == NULL) { - err = (zfs_error(hdl, EZFS_NOMEM, zfs_strerror(errno))); - goto out; - } - - zc.zc_nvlist_dst_size = nvsz; - zc.zc_nvlist_dst = (uintptr_t)nvbuf; - - (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); - - if (zfs_ioctl(hdl, ZFS_IOC_GET_FSACL, &zc) != 0) { - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot get permissions on '%s'"), - zc.zc_name); - switch (errno) { - case ENOMEM: - free(nvbuf); - nvsz = zc.zc_nvlist_dst_size; - goto tryagain; - - case ENOTSUP: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "pool must be upgraded")); - err = zfs_error(hdl, EZFS_BADVERSION, errbuf); - break; - case EINVAL: - err = zfs_error(hdl, EZFS_BADTYPE, errbuf); - break; - case ENOENT: - err = zfs_error(hdl, EZFS_NOENT, errbuf); - break; - default: - err = zfs_standard_error(hdl, errno, errbuf); - break; - } - } else { - /* success */ - int rc = nvlist_unpack(nvbuf, zc.zc_nvlist_dst_size, nvl, 0); - if (rc) { - err = zfs_standard_error_fmt(hdl, rc, dgettext( - TEXT_DOMAIN, "cannot get permissions on '%s'"), - zc.zc_name); - } - } - - free(nvbuf); -out: - return (err); -} - -int -zfs_set_fsacl(zfs_handle_t *zhp, boolean_t un, nvlist_t *nvl) -{ - zfs_cmd_t zc = {"\0"}; - libzfs_handle_t *hdl = zhp->zfs_hdl; - char *nvbuf; - char errbuf[ERRBUFLEN]; - size_t nvsz; - int err; - - assert(zhp->zfs_type == ZFS_TYPE_VOLUME || - zhp->zfs_type == ZFS_TYPE_FILESYSTEM); - - err = nvlist_size(nvl, &nvsz, NV_ENCODE_NATIVE); - assert(err == 0); - - nvbuf = malloc(nvsz); - - err = nvlist_pack(nvl, &nvbuf, &nvsz, NV_ENCODE_NATIVE, 0); - assert(err == 0); - - zc.zc_nvlist_src_size = nvsz; - zc.zc_nvlist_src = (uintptr_t)nvbuf; - zc.zc_perm_action = un; - - (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); - - if (zfs_ioctl(hdl, ZFS_IOC_SET_FSACL, &zc) != 0) { - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot set permissions on '%s'"), - zc.zc_name); - switch (errno) { - case ENOTSUP: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "pool must be upgraded")); - err = zfs_error(hdl, EZFS_BADVERSION, errbuf); - break; - case EINVAL: - err = zfs_error(hdl, EZFS_BADTYPE, errbuf); - break; - case ENOENT: - err = zfs_error(hdl, EZFS_NOENT, errbuf); - break; - default: - err = zfs_standard_error(hdl, errno, errbuf); - break; - } - } - - free(nvbuf); - - return (err); -} - -int -zfs_get_holds(zfs_handle_t *zhp, nvlist_t **nvl) -{ - int err; - char errbuf[ERRBUFLEN]; - - err = lzc_get_holds(zhp->zfs_name, nvl); - - if (err != 0) { - libzfs_handle_t *hdl = zhp->zfs_hdl; - - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot get holds for '%s'"), - zhp->zfs_name); - switch (err) { - case ENOTSUP: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "pool must be upgraded")); - err = zfs_error(hdl, EZFS_BADVERSION, errbuf); - break; - case EINVAL: - err = zfs_error(hdl, EZFS_BADTYPE, errbuf); - break; - case ENOENT: - err = zfs_error(hdl, EZFS_NOENT, errbuf); - break; - default: - err = zfs_standard_error(hdl, errno, errbuf); - break; - } - } - - return (err); -} - -/* - * The theory of raidz space accounting - * - * The "referenced" property of RAIDZ vdevs is scaled such that a 128KB block - * will "reference" 128KB, even though it allocates more than that, to store the - * parity information (and perhaps skip sectors). This concept of the - * "referenced" (and other DMU space accounting) being lower than the allocated - * space by a constant factor is called "raidz deflation." - * - * As mentioned above, the constant factor for raidz deflation assumes a 128KB - * block size. However, zvols typically have a much smaller block size (default - * 8KB). These smaller blocks may require proportionally much more parity - * information (and perhaps skip sectors). In this case, the change to the - * "referenced" property may be much more than the logical block size. - * - * Suppose a raidz vdev has 5 disks with ashift=12. A 128k block may be written - * as follows. - * - * +-------+-------+-------+-------+-------+ - * | disk1 | disk2 | disk3 | disk4 | disk5 | - * +-------+-------+-------+-------+-------+ - * | P0 | D0 | D8 | D16 | D24 | - * | P1 | D1 | D9 | D17 | D25 | - * | P2 | D2 | D10 | D18 | D26 | - * | P3 | D3 | D11 | D19 | D27 | - * | P4 | D4 | D12 | D20 | D28 | - * | P5 | D5 | D13 | D21 | D29 | - * | P6 | D6 | D14 | D22 | D30 | - * | P7 | D7 | D15 | D23 | D31 | - * +-------+-------+-------+-------+-------+ - * - * Above, notice that 160k was allocated: 8 x 4k parity sectors + 32 x 4k data - * sectors. The dataset's referenced will increase by 128k and the pool's - * allocated and free properties will be adjusted by 160k. - * - * A 4k block written to the same raidz vdev will require two 4k sectors. The - * blank cells represent unallocated space. - * - * +-------+-------+-------+-------+-------+ - * | disk1 | disk2 | disk3 | disk4 | disk5 | - * +-------+-------+-------+-------+-------+ - * | P0 | D0 | | | | - * +-------+-------+-------+-------+-------+ - * - * Above, notice that the 4k block required one sector for parity and another - * for data. vdev_raidz_psize_to_asize() will return 8k and as such the pool's - * allocated and free properties will be adjusted by 8k. The dataset will not - * be charged 8k. Rather, it will be charged a value that is scaled according - * to the overhead of the 128k block on the same vdev. This 8k allocation will - * be charged 8k * 128k / 160k. 128k is from SPA_OLD_MAXBLOCKSIZE and 160k is - * as calculated in the 128k block example above. - * - * Every raidz allocation is sized to be a multiple of nparity+1 sectors. That - * is, every raidz1 allocation will be a multiple of 2 sectors, raidz2 - * allocations are a multiple of 3 sectors, and raidz3 allocations are a - * multiple of of 4 sectors. When a block does not fill the required number of - * sectors, skip blocks (sectors) are used. - * - * An 8k block being written to a raidz vdev may be written as follows: - * - * +-------+-------+-------+-------+-------+ - * | disk1 | disk2 | disk3 | disk4 | disk5 | - * +-------+-------+-------+-------+-------+ - * | P0 | D0 | D1 | S0 | | - * +-------+-------+-------+-------+-------+ - * - * In order to maintain the nparity+1 allocation size, a skip block (S0) was - * added. For this 8k block, the pool's allocated and free properties are - * adjusted by 16k and the dataset's referenced is increased by 16k * 128k / - * 160k. Again, 128k is from SPA_OLD_MAXBLOCKSIZE and 160k is as calculated in - * the 128k block example above. - * - * The situation is slightly different for dRAID since the minimum allocation - * size is the full group width. The same 8K block above would be written as - * follows in a dRAID group: - * - * +-------+-------+-------+-------+-------+ - * | disk1 | disk2 | disk3 | disk4 | disk5 | - * +-------+-------+-------+-------+-------+ - * | P0 | D0 | D1 | S0 | S1 | - * +-------+-------+-------+-------+-------+ - * - * Compression may lead to a variety of block sizes being written for the same - * volume or file. There is no clear way to reserve just the amount of space - * that will be required, so the worst case (no compression) is assumed. - * Note that metadata blocks will typically be compressed, so the reservation - * size returned by zvol_volsize_to_reservation() will generally be slightly - * larger than the maximum that the volume can reference. - */ - -/* - * Derived from function of same name in module/zfs/vdev_raidz.c. Returns the - * amount of space (in bytes) that will be allocated for the specified block - * size. Note that the "referenced" space accounted will be less than this, but - * not necessarily equal to "blksize", due to RAIDZ deflation. - */ -static uint64_t -vdev_raidz_psize_to_asize(uint64_t ndisks, uint64_t nparity, uint64_t ashift, - uint64_t blksize) -{ - uint64_t asize, ndata; - - ASSERT3U(ndisks, >, nparity); - ndata = ndisks - nparity; - asize = ((blksize - 1) >> ashift) + 1; - asize += nparity * ((asize + ndata - 1) / ndata); - asize = roundup(asize, nparity + 1) << ashift; - - return (asize); -} - -/* - * Derived from function of same name in module/zfs/vdev_draid.c. Returns the - * amount of space (in bytes) that will be allocated for the specified block - * size. - */ -static uint64_t -vdev_draid_psize_to_asize(uint64_t ndisks, uint64_t nparity, uint64_t ashift, - uint64_t blksize) -{ - ASSERT3U(ndisks, >, nparity); - uint64_t ndata = ndisks - nparity; - uint64_t rows = ((blksize - 1) / (ndata << ashift)) + 1; - uint64_t asize = (rows * ndisks) << ashift; - - return (asize); -} - -/* - * Determine how much space will be allocated if it lands on the most space- - * inefficient top-level vdev. Returns the size in bytes required to store one - * copy of the volume data. See theory comment above. - */ -static uint64_t -volsize_from_vdevs(zpool_handle_t *zhp, uint64_t nblocks, uint64_t blksize) -{ - nvlist_t *config, *tree, **vdevs; - uint_t nvdevs; - uint64_t ret = 0; - - config = zpool_get_config(zhp, NULL); - if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &tree) != 0 || - nvlist_lookup_nvlist_array(tree, ZPOOL_CONFIG_CHILDREN, - &vdevs, &nvdevs) != 0) { - return (nblocks * blksize); - } - - for (int v = 0; v < nvdevs; v++) { - const char *type; - uint64_t nparity, ashift, asize, tsize; - uint64_t volsize; - - if (nvlist_lookup_string(vdevs[v], ZPOOL_CONFIG_TYPE, - &type) != 0) - continue; - - if (strcmp(type, VDEV_TYPE_RAIDZ) != 0 && - strcmp(type, VDEV_TYPE_DRAID) != 0) - continue; - - if (nvlist_lookup_uint64(vdevs[v], - ZPOOL_CONFIG_NPARITY, &nparity) != 0) - continue; - - if (nvlist_lookup_uint64(vdevs[v], - ZPOOL_CONFIG_ASHIFT, &ashift) != 0) - continue; - - if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) { - nvlist_t **disks; - uint_t ndisks; - - if (nvlist_lookup_nvlist_array(vdevs[v], - ZPOOL_CONFIG_CHILDREN, &disks, &ndisks) != 0) - continue; - - /* allocation size for the "typical" 128k block */ - tsize = vdev_raidz_psize_to_asize(ndisks, nparity, - ashift, SPA_OLD_MAXBLOCKSIZE); - - /* allocation size for the blksize block */ - asize = vdev_raidz_psize_to_asize(ndisks, nparity, - ashift, blksize); - } else { - uint64_t ndata; - - if (nvlist_lookup_uint64(vdevs[v], - ZPOOL_CONFIG_DRAID_NDATA, &ndata) != 0) - continue; - - /* allocation size for the "typical" 128k block */ - tsize = vdev_draid_psize_to_asize(ndata + nparity, - nparity, ashift, SPA_OLD_MAXBLOCKSIZE); - - /* allocation size for the blksize block */ - asize = vdev_draid_psize_to_asize(ndata + nparity, - nparity, ashift, blksize); - } - - /* - * Scale this size down as a ratio of 128k / tsize. - * See theory statement above. - * - * Bitshift is to avoid the case of nblocks * asize < tsize - * producing a size of 0. - */ - volsize = (nblocks * asize) / (tsize >> SPA_MINBLOCKSHIFT); - /* - * If we would blow UINT64_MAX with this next multiplication, - * don't. - */ - if (volsize > - (UINT64_MAX / (SPA_OLD_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT))) - volsize = UINT64_MAX; - else - volsize *= (SPA_OLD_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT); - - if (volsize > ret) { - ret = volsize; - } - } - - if (ret == 0) { - ret = nblocks * blksize; - } - - return (ret); -} - -/* - * Convert the zvol's volume size to an appropriate reservation. See theory - * comment above. - * - * Note: If this routine is updated, it is necessary to update the ZFS test - * suite's shell version in reservation.shlib. - */ -uint64_t -zvol_volsize_to_reservation(zpool_handle_t *zph, uint64_t volsize, - nvlist_t *props) -{ - uint64_t numdb; - uint64_t nblocks, volblocksize; - int ncopies; - const char *strval; - - if (nvlist_lookup_string(props, - zfs_prop_to_name(ZFS_PROP_COPIES), &strval) == 0) - ncopies = atoi(strval); - else - ncopies = 1; - if (nvlist_lookup_uint64(props, - zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), - &volblocksize) != 0) - volblocksize = ZVOL_DEFAULT_BLOCKSIZE; - - nblocks = volsize / volblocksize; - /* - * Metadata defaults to using 128k blocks, not volblocksize blocks. For - * this reason, only the data blocks are scaled based on vdev config. - */ - volsize = volsize_from_vdevs(zph, nblocks, volblocksize); - - /* start with metadnode L0-L6 */ - numdb = 7; - /* calculate number of indirects */ - while (nblocks > 1) { - nblocks += DNODES_PER_LEVEL - 1; - nblocks /= DNODES_PER_LEVEL; - numdb += nblocks; - } - numdb *= MIN(SPA_DVAS_PER_BP, ncopies + 1); - volsize *= ncopies; - /* - * this is exactly DN_MAX_INDBLKSHIFT when metadata isn't - * compressed, but in practice they compress down to about - * 1100 bytes - */ - numdb *= 1ULL << DN_MAX_INDBLKSHIFT; - volsize += numdb; - return (volsize); -} - -/* - * Wait for the given activity and return the status of the wait (whether or not - * any waiting was done) in the 'waited' parameter. Non-existent fses are - * reported via the 'missing' parameter, rather than by printing an error - * message. This is convenient when this function is called in a loop over a - * long period of time (as it is, for example, by zfs's wait cmd). In that - * scenario, a fs being exported or destroyed should be considered a normal - * event, so we don't want to print an error when we find that the fs doesn't - * exist. - */ -int -zfs_wait_status(zfs_handle_t *zhp, zfs_wait_activity_t activity, - boolean_t *missing, boolean_t *waited) -{ - int error = lzc_wait_fs(zhp->zfs_name, activity, waited); - *missing = (error == ENOENT); - if (*missing) - return (0); - - if (error != 0) { - (void) zfs_standard_error_fmt(zhp->zfs_hdl, error, - dgettext(TEXT_DOMAIN, "error waiting in fs '%s'"), - zhp->zfs_name); - } - - return (error); -} diff --git a/lib/libzfs/libzfs_diff.c b/lib/libzfs/libzfs_diff.c deleted file mode 100644 index 5f50bce531f7..000000000000 --- a/lib/libzfs/libzfs_diff.c +++ /dev/null @@ -1,830 +0,0 @@ -// SPDX-License-Identifier: CDDL-1.0 -/* - * 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 - */ - -/* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2015 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2015, 2018 by Delphix. All rights reserved. - * Copyright 2016 Joyent, Inc. - * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com> - */ - -/* - * zfs diff support - */ -#include <ctype.h> -#include <errno.h> -#include <libintl.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <stddef.h> -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <pthread.h> -#include <sys/zfs_ioctl.h> -#include <libzfs.h> -#include <libzutil.h> -#include "libzfs_impl.h" - -#define ZDIFF_SNAPDIR "/.zfs/snapshot/" -#define ZDIFF_PREFIX "zfs-diff-%d" - -#define ZDIFF_ADDED '+' -#define ZDIFF_MODIFIED "M" -#define ZDIFF_REMOVED '-' -#define ZDIFF_RENAMED "R" - -#define ZDIFF_ADDED_COLOR ANSI_GREEN -#define ZDIFF_MODIFIED_COLOR ANSI_YELLOW -#define ZDIFF_REMOVED_COLOR ANSI_RED -#define ZDIFF_RENAMED_COLOR ANSI_BOLD_BLUE - -/* - * Given a {dsname, object id}, get the object path - */ -static int -get_stats_for_obj(differ_info_t *di, const char *dsname, uint64_t obj, - char *pn, int maxlen, zfs_stat_t *sb) -{ - zfs_cmd_t zc = {"\0"}; - int error; - - (void) strlcpy(zc.zc_name, dsname, sizeof (zc.zc_name)); - zc.zc_obj = obj; - - errno = 0; - error = zfs_ioctl(di->zhp->zfs_hdl, ZFS_IOC_OBJ_TO_STATS, &zc); - di->zerr = errno; - - /* we can get stats even if we failed to get a path */ - (void) memcpy(sb, &zc.zc_stat, sizeof (zfs_stat_t)); - if (error == 0) { - ASSERT0(di->zerr); - (void) strlcpy(pn, zc.zc_value, maxlen); - return (0); - } - - if (di->zerr == ESTALE) { - (void) snprintf(pn, maxlen, "(on_delete_queue)"); - return (0); - } else if (di->zerr == EPERM) { - (void) snprintf(di->errbuf, sizeof (di->errbuf), - dgettext(TEXT_DOMAIN, - "The sys_config privilege or diff delegated permission " - "is needed\nto discover path names")); - return (-1); - } else if (di->zerr == EACCES) { - (void) snprintf(di->errbuf, sizeof (di->errbuf), - dgettext(TEXT_DOMAIN, - "Key must be loaded to discover path names")); - return (-1); - } else { - (void) snprintf(di->errbuf, sizeof (di->errbuf), - dgettext(TEXT_DOMAIN, - "Unable to determine path or stats for " - "object %lld in %s"), (longlong_t)obj, dsname); - return (-1); - } -} - -/* - * stream_bytes - * - * Prints a file name out a character at a time. If the character is - * not in the range of what we consider "printable" ASCII, display it - * as an escaped 4-digit octal value. ASCII values less than a space - * are all control characters and we declare the upper end as the - * DELete character. This also is the last 7-bit ASCII character. - * We choose to treat all 8-bit ASCII as not printable for this - * application. - */ -static void -stream_bytes(FILE *fp, const char *string) -{ - char c; - - while ((c = *string++) != '\0') { - if (c > ' ' && c != '\\' && c < '\177') { - (void) fputc(c, fp); - } else { - (void) fprintf(fp, "\\%04hho", (uint8_t)c); - } - } -} - -/* - * Takes the type of change (like `print_file`), outputs the appropriate color - */ -static const char * -type_to_color(char type) -{ - if (type == '+') - return (ZDIFF_ADDED_COLOR); - else if (type == '-') - return (ZDIFF_REMOVED_COLOR); - else if (type == 'M') - return (ZDIFF_MODIFIED_COLOR); - else if (type == 'R') - return (ZDIFF_RENAMED_COLOR); - else - return (NULL); -} - - -static char -get_what(mode_t what) -{ - switch (what & S_IFMT) { - case S_IFBLK: - return ('B'); - case S_IFCHR: - return ('C'); - case S_IFDIR: - return ('/'); -#ifdef S_IFDOOR - case S_IFDOOR: - return ('>'); -#endif - case S_IFIFO: - return ('|'); - case S_IFLNK: - return ('@'); -#ifdef S_IFPORT - case S_IFPORT: - return ('P'); -#endif - case S_IFSOCK: - return ('='); - case S_IFREG: - return ('F'); - default: - return ('?'); - } -} - -static void -print_cmn(FILE *fp, differ_info_t *di, const char *file) -{ - if (!di->no_mangle) { - stream_bytes(fp, di->dsmnt); - stream_bytes(fp, file); - } else { - (void) fputs(di->dsmnt, fp); - (void) fputs(file, fp); - } -} - -static void -print_rename(FILE *fp, differ_info_t *di, const char *old, const char *new, - zfs_stat_t *isb) -{ - if (isatty(fileno(fp))) - color_start(ZDIFF_RENAMED_COLOR); - if (di->timestamped) - (void) fprintf(fp, "%10lld.%09lld\t", - (longlong_t)isb->zs_ctime[0], - (longlong_t)isb->zs_ctime[1]); - (void) fputs(ZDIFF_RENAMED "\t", fp); - if (di->classify) - (void) fprintf(fp, "%c\t", get_what(isb->zs_mode)); - print_cmn(fp, di, old); - (void) fputs(di->scripted ? "\t" : " -> ", fp); - print_cmn(fp, di, new); - (void) fputc('\n', fp); - - if (isatty(fileno(fp))) - color_end(); -} - -static void -print_link_change(FILE *fp, differ_info_t *di, int delta, const char *file, - zfs_stat_t *isb) -{ - if (isatty(fileno(fp))) - color_start(ZDIFF_MODIFIED_COLOR); - - if (di->timestamped) - (void) fprintf(fp, "%10lld.%09lld\t", - (longlong_t)isb->zs_ctime[0], - (longlong_t)isb->zs_ctime[1]); - (void) fputs(ZDIFF_MODIFIED "\t", fp); - if (di->classify) - (void) fprintf(fp, "%c\t", get_what(isb->zs_mode)); - print_cmn(fp, di, file); - (void) fprintf(fp, "\t(%+d)\n", delta); - if (isatty(fileno(fp))) - color_end(); -} - -static void -print_file(FILE *fp, differ_info_t *di, char type, const char *file, - zfs_stat_t *isb) -{ - if (isatty(fileno(fp))) - color_start(type_to_color(type)); - - if (di->timestamped) - (void) fprintf(fp, "%10lld.%09lld\t", - (longlong_t)isb->zs_ctime[0], - (longlong_t)isb->zs_ctime[1]); - (void) fprintf(fp, "%c\t", type); - if (di->classify) - (void) fprintf(fp, "%c\t", get_what(isb->zs_mode)); - print_cmn(fp, di, file); - (void) fputc('\n', fp); - - if (isatty(fileno(fp))) - color_end(); -} - -static int -write_inuse_diffs_one(FILE *fp, differ_info_t *di, uint64_t dobj) -{ - struct zfs_stat fsb, tsb; - mode_t fmode, tmode; - char fobjname[MAXPATHLEN], tobjname[MAXPATHLEN]; - boolean_t already_logged = B_FALSE; - int fobjerr, tobjerr; - int change; - - if (dobj == di->shares) - return (0); - - /* - * Check the from and to snapshots for info on the object. If - * we get ENOENT, then the object just didn't exist in that - * snapshot. If we get ENOTSUP, then we tried to get - * info on a non-ZPL object, which we don't care about anyway. - * For any other error we print a warning which includes the - * errno and continue. - */ - - fobjerr = get_stats_for_obj(di, di->fromsnap, dobj, fobjname, - MAXPATHLEN, &fsb); - if (fobjerr && di->zerr != ENOTSUP && di->zerr != ENOENT) { - zfs_error_aux(di->zhp->zfs_hdl, "%s", zfs_strerror(di->zerr)); - zfs_error(di->zhp->zfs_hdl, di->zerr, di->errbuf); - /* - * Let's not print an error for the same object more than - * once if it happens in both snapshots - */ - already_logged = B_TRUE; - } - - tobjerr = get_stats_for_obj(di, di->tosnap, dobj, tobjname, - MAXPATHLEN, &tsb); - - if (tobjerr && di->zerr != ENOTSUP && di->zerr != ENOENT) { - if (!already_logged) { - zfs_error_aux(di->zhp->zfs_hdl, - "%s", zfs_strerror(di->zerr)); - zfs_error(di->zhp->zfs_hdl, di->zerr, di->errbuf); - } - } - /* - * Unallocated object sharing the same meta dnode block - */ - if (fobjerr && tobjerr) { - di->zerr = 0; - return (0); - } - - di->zerr = 0; /* negate get_stats_for_obj() from side that failed */ - fmode = fsb.zs_mode & S_IFMT; - tmode = tsb.zs_mode & S_IFMT; - if (fmode == S_IFDIR || tmode == S_IFDIR || fsb.zs_links == 0 || - tsb.zs_links == 0) - change = 0; - else - change = tsb.zs_links - fsb.zs_links; - - if (fobjerr) { - if (change) { - print_link_change(fp, di, change, tobjname, &tsb); - return (0); - } - print_file(fp, di, ZDIFF_ADDED, tobjname, &tsb); - return (0); - } else if (tobjerr) { - if (change) { - print_link_change(fp, di, change, fobjname, &fsb); - return (0); - } - print_file(fp, di, ZDIFF_REMOVED, fobjname, &fsb); - return (0); - } - - if (fmode != tmode && fsb.zs_gen == tsb.zs_gen) - tsb.zs_gen++; /* Force a generational difference */ - - /* Simple modification or no change */ - if (fsb.zs_gen == tsb.zs_gen) { - /* No apparent changes. Could we assert !this? */ - if (fsb.zs_ctime[0] == tsb.zs_ctime[0] && - fsb.zs_ctime[1] == tsb.zs_ctime[1]) - return (0); - if (change) { - print_link_change(fp, di, change, - change > 0 ? fobjname : tobjname, &tsb); - } else if (strcmp(fobjname, tobjname) == 0) { - print_file(fp, di, *ZDIFF_MODIFIED, fobjname, &tsb); - } else { - print_rename(fp, di, fobjname, tobjname, &tsb); - } - return (0); - } else { - /* file re-created or object re-used */ - print_file(fp, di, ZDIFF_REMOVED, fobjname, &fsb); - print_file(fp, di, ZDIFF_ADDED, tobjname, &tsb); - return (0); - } -} - -static int -write_inuse_diffs(FILE *fp, differ_info_t *di, dmu_diff_record_t *dr) -{ - uint64_t o; - int err; - - for (o = dr->ddr_first; o <= dr->ddr_last; o++) { - if ((err = write_inuse_diffs_one(fp, di, o)) != 0) - return (err); - } - return (0); -} - -static int -describe_free(FILE *fp, differ_info_t *di, uint64_t object, char *namebuf, - int maxlen) -{ - struct zfs_stat sb; - - (void) get_stats_for_obj(di, di->fromsnap, object, namebuf, - maxlen, &sb); - - /* Don't print if in the delete queue on from side */ - if (di->zerr == ESTALE || di->zerr == ENOENT) { - di->zerr = 0; - return (0); - } - - print_file(fp, di, ZDIFF_REMOVED, namebuf, &sb); - return (0); -} - -static int -write_free_diffs(FILE *fp, differ_info_t *di, dmu_diff_record_t *dr) -{ - zfs_cmd_t zc = {"\0"}; - libzfs_handle_t *lhdl = di->zhp->zfs_hdl; - char fobjname[MAXPATHLEN]; - - (void) strlcpy(zc.zc_name, di->fromsnap, sizeof (zc.zc_name)); - zc.zc_obj = dr->ddr_first - 1; - - ASSERT0(di->zerr); - - while (zc.zc_obj < dr->ddr_last) { - int err; - - err = zfs_ioctl(lhdl, ZFS_IOC_NEXT_OBJ, &zc); - if (err == 0) { - if (zc.zc_obj == di->shares) { - zc.zc_obj++; - continue; - } - if (zc.zc_obj > dr->ddr_last) { - break; - } - (void) describe_free(fp, di, zc.zc_obj, fobjname, - MAXPATHLEN); - } else if (errno == ESRCH) { - break; - } else { - (void) snprintf(di->errbuf, sizeof (di->errbuf), - dgettext(TEXT_DOMAIN, - "next allocated object (> %lld) find failure"), - (longlong_t)zc.zc_obj); - di->zerr = errno; - break; - } - } - if (di->zerr) - return (-1); - return (0); -} - -static void * -differ(void *arg) -{ - differ_info_t *di = arg; - dmu_diff_record_t dr; - FILE *ofp; - int err = 0; - - if ((ofp = fdopen(di->outputfd, "w")) == NULL) { - di->zerr = errno; - strlcpy(di->errbuf, zfs_strerror(errno), sizeof (di->errbuf)); - (void) close(di->datafd); - return ((void *)-1); - } - - for (;;) { - char *cp = (char *)&dr; - int len = sizeof (dr); - int rv; - - do { - rv = read(di->datafd, cp, len); - cp += rv; - len -= rv; - } while (len > 0 && rv > 0); - - if (rv < 0 || (rv == 0 && len != sizeof (dr))) { - di->zerr = EPIPE; - break; - } else if (rv == 0) { - /* end of file at a natural breaking point */ - break; - } - - switch (dr.ddr_type) { - case DDR_FREE: - err = write_free_diffs(ofp, di, &dr); - break; - case DDR_INUSE: - err = write_inuse_diffs(ofp, di, &dr); - break; - default: - di->zerr = EPIPE; - break; - } - - if (err || di->zerr) - break; - } - - (void) fclose(ofp); - (void) close(di->datafd); - if (err) - return ((void *)-1); - if (di->zerr) { - ASSERT(di->zerr == EPIPE); - (void) snprintf(di->errbuf, sizeof (di->errbuf), - dgettext(TEXT_DOMAIN, - "Internal error: bad data from diff IOCTL")); - return ((void *)-1); - } - return ((void *)0); -} - -static int -make_temp_snapshot(differ_info_t *di) -{ - libzfs_handle_t *hdl = di->zhp->zfs_hdl; - zfs_cmd_t zc = {"\0"}; - - (void) snprintf(zc.zc_value, sizeof (zc.zc_value), - ZDIFF_PREFIX, getpid()); - (void) strlcpy(zc.zc_name, di->ds, sizeof (zc.zc_name)); - zc.zc_cleanup_fd = di->cleanupfd; - - if (zfs_ioctl(hdl, ZFS_IOC_TMP_SNAPSHOT, &zc) != 0) { - int err = errno; - if (err == EPERM) { - (void) snprintf(di->errbuf, sizeof (di->errbuf), - dgettext(TEXT_DOMAIN, "The diff delegated " - "permission is needed in order\nto create a " - "just-in-time snapshot for diffing\n")); - return (zfs_error(hdl, EZFS_DIFF, di->errbuf)); - } else { - (void) snprintf(di->errbuf, sizeof (di->errbuf), - dgettext(TEXT_DOMAIN, "Cannot create just-in-time " - "snapshot of '%s'"), zc.zc_name); - return (zfs_standard_error(hdl, err, di->errbuf)); - } - } - - di->tmpsnap = zfs_strdup(hdl, zc.zc_value); - di->tosnap = zfs_asprintf(hdl, "%s@%s", di->ds, di->tmpsnap); - return (0); -} - -static void -teardown_differ_info(differ_info_t *di) -{ - free(di->ds); - free(di->dsmnt); - free(di->fromsnap); - free(di->frommnt); - free(di->tosnap); - free(di->tmpsnap); - free(di->tomnt); - (void) close(di->cleanupfd); -} - -static int -get_snapshot_names(differ_info_t *di, const char *fromsnap, - const char *tosnap) -{ - libzfs_handle_t *hdl = di->zhp->zfs_hdl; - char *atptrf = NULL; - char *atptrt = NULL; - int fdslen, fsnlen; - int tdslen, tsnlen; - - /* - * Can accept - * fdslen fsnlen tdslen tsnlen - * dataset@snap1 - * 0. dataset@snap1 dataset@snap2 >0 >1 >0 >1 - * 1. dataset@snap1 @snap2 >0 >1 ==0 >1 - * 2. dataset@snap1 dataset >0 >1 >0 ==0 - * 3. @snap1 dataset@snap2 ==0 >1 >0 >1 - * 4. @snap1 dataset ==0 >1 >0 ==0 - */ - if (tosnap == NULL) { - /* only a from snapshot given, must be valid */ - (void) snprintf(di->errbuf, sizeof (di->errbuf), - dgettext(TEXT_DOMAIN, - "Badly formed snapshot name %s"), fromsnap); - - if (!zfs_validate_name(hdl, fromsnap, ZFS_TYPE_SNAPSHOT, - B_FALSE)) { - return (zfs_error(hdl, EZFS_INVALIDNAME, - di->errbuf)); - } - - atptrf = strchr(fromsnap, '@'); - ASSERT(atptrf != NULL); - fdslen = atptrf - fromsnap; - - di->fromsnap = zfs_strdup(hdl, fromsnap); - di->ds = zfs_strdup(hdl, fromsnap); - di->ds[fdslen] = '\0'; - - /* the to snap will be a just-in-time snap of the head */ - return (make_temp_snapshot(di)); - } - - (void) snprintf(di->errbuf, sizeof (di->errbuf), - dgettext(TEXT_DOMAIN, - "Unable to determine which snapshots to compare")); - - atptrf = strchr(fromsnap, '@'); - atptrt = strchr(tosnap, '@'); - fdslen = atptrf ? atptrf - fromsnap : strlen(fromsnap); - tdslen = atptrt ? atptrt - tosnap : strlen(tosnap); - fsnlen = strlen(fromsnap) - fdslen; /* includes @ sign */ - tsnlen = strlen(tosnap) - tdslen; /* includes @ sign */ - - if (fsnlen <= 1 || tsnlen == 1 || (fdslen == 0 && tdslen == 0)) { - return (zfs_error(hdl, EZFS_INVALIDNAME, di->errbuf)); - } else if ((fdslen > 0 && tdslen > 0) && - ((tdslen != fdslen || strncmp(fromsnap, tosnap, fdslen) != 0))) { - /* - * not the same dataset name, might be okay if - * tosnap is a clone of a fromsnap descendant. - */ - char origin[ZFS_MAX_DATASET_NAME_LEN]; - zprop_source_t src; - zfs_handle_t *zhp; - - di->ds = zfs_alloc(di->zhp->zfs_hdl, tdslen + 1); - (void) strlcpy(di->ds, tosnap, tdslen + 1); - - zhp = zfs_open(hdl, di->ds, ZFS_TYPE_FILESYSTEM); - while (zhp != NULL) { - if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin, - sizeof (origin), &src, NULL, 0, B_FALSE) != 0) { - (void) zfs_close(zhp); - zhp = NULL; - break; - } - if (strncmp(origin, fromsnap, fsnlen) == 0) - break; - - (void) zfs_close(zhp); - zhp = zfs_open(hdl, origin, ZFS_TYPE_FILESYSTEM); - } - - if (zhp == NULL) { - (void) snprintf(di->errbuf, sizeof (di->errbuf), - dgettext(TEXT_DOMAIN, - "Not an earlier snapshot from the same fs")); - return (zfs_error(hdl, EZFS_INVALIDNAME, di->errbuf)); - } else { - (void) zfs_close(zhp); - } - - di->isclone = B_TRUE; - di->fromsnap = zfs_strdup(hdl, fromsnap); - if (tsnlen) - di->tosnap = zfs_strdup(hdl, tosnap); - else - return (make_temp_snapshot(di)); - } else { - int dslen = fdslen ? fdslen : tdslen; - - di->ds = zfs_alloc(hdl, dslen + 1); - (void) strlcpy(di->ds, fdslen ? fromsnap : tosnap, dslen + 1); - - di->fromsnap = zfs_asprintf(hdl, "%s%s", di->ds, atptrf); - if (tsnlen) { - di->tosnap = zfs_asprintf(hdl, "%s%s", di->ds, atptrt); - } else { - return (make_temp_snapshot(di)); - } - } - return (0); -} - -static int -get_mountpoint(differ_info_t *di, char *dsnm, char **mntpt) -{ - boolean_t mounted; - - mounted = is_mounted(di->zhp->zfs_hdl, dsnm, mntpt); - if (mounted == B_FALSE) { - (void) snprintf(di->errbuf, sizeof (di->errbuf), - dgettext(TEXT_DOMAIN, - "Cannot diff an unmounted snapshot")); - return (zfs_error(di->zhp->zfs_hdl, EZFS_BADTYPE, di->errbuf)); - } - - /* Avoid a double slash at the beginning of root-mounted datasets */ - if (**mntpt == '/' && *(*mntpt + 1) == '\0') - **mntpt = '\0'; - return (0); -} - -static int -get_mountpoints(differ_info_t *di) -{ - char *strptr; - char *frommntpt; - - /* - * first get the mountpoint for the parent dataset - */ - if (get_mountpoint(di, di->ds, &di->dsmnt) != 0) - return (-1); - - strptr = strchr(di->tosnap, '@'); - ASSERT3P(strptr, !=, NULL); - di->tomnt = zfs_asprintf(di->zhp->zfs_hdl, "%s%s%s", di->dsmnt, - ZDIFF_SNAPDIR, ++strptr); - - strptr = strchr(di->fromsnap, '@'); - ASSERT3P(strptr, !=, NULL); - - frommntpt = di->dsmnt; - if (di->isclone) { - char *mntpt; - int err; - - *strptr = '\0'; - err = get_mountpoint(di, di->fromsnap, &mntpt); - *strptr = '@'; - if (err != 0) - return (-1); - frommntpt = mntpt; - } - - di->frommnt = zfs_asprintf(di->zhp->zfs_hdl, "%s%s%s", frommntpt, - ZDIFF_SNAPDIR, ++strptr); - - if (di->isclone) - free(frommntpt); - - return (0); -} - -static int -setup_differ_info(zfs_handle_t *zhp, const char *fromsnap, - const char *tosnap, differ_info_t *di) -{ - di->zhp = zhp; - - di->cleanupfd = open(ZFS_DEV, O_RDWR | O_CLOEXEC); - VERIFY(di->cleanupfd >= 0); - - if (get_snapshot_names(di, fromsnap, tosnap) != 0) - return (-1); - - if (get_mountpoints(di) != 0) - return (-1); - - if (find_shares_object(di) != 0) - return (-1); - - return (0); -} - -int -zfs_show_diffs(zfs_handle_t *zhp, int outfd, const char *fromsnap, - const char *tosnap, int flags) -{ - zfs_cmd_t zc = {"\0"}; - char errbuf[ERRBUFLEN]; - differ_info_t di = { 0 }; - pthread_t tid; - int pipefd[2]; - int iocerr; - - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "zfs diff failed")); - - if (setup_differ_info(zhp, fromsnap, tosnap, &di)) { - teardown_differ_info(&di); - return (-1); - } - - if (pipe2(pipefd, O_CLOEXEC)) { - zfs_error_aux(zhp->zfs_hdl, "%s", zfs_strerror(errno)); - teardown_differ_info(&di); - return (zfs_error(zhp->zfs_hdl, EZFS_PIPEFAILED, errbuf)); - } - - di.scripted = (flags & ZFS_DIFF_PARSEABLE); - di.classify = (flags & ZFS_DIFF_CLASSIFY); - di.timestamped = (flags & ZFS_DIFF_TIMESTAMP); - di.no_mangle = (flags & ZFS_DIFF_NO_MANGLE); - - di.outputfd = outfd; - di.datafd = pipefd[0]; - - if (pthread_create(&tid, NULL, differ, &di)) { - zfs_error_aux(zhp->zfs_hdl, "%s", zfs_strerror(errno)); - (void) close(pipefd[0]); - (void) close(pipefd[1]); - teardown_differ_info(&di); - return (zfs_error(zhp->zfs_hdl, - EZFS_THREADCREATEFAILED, errbuf)); - } - - /* do the ioctl() */ - (void) strlcpy(zc.zc_value, di.fromsnap, strlen(di.fromsnap) + 1); - (void) strlcpy(zc.zc_name, di.tosnap, strlen(di.tosnap) + 1); - zc.zc_cookie = pipefd[1]; - - iocerr = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_DIFF, &zc); - if (iocerr != 0) { - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "Unable to obtain diffs")); - if (errno == EPERM) { - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "\n The sys_mount privilege or diff delegated " - "permission is needed\n to execute the " - "diff ioctl")); - } else if (errno == EXDEV) { - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "\n Not an earlier snapshot from the same fs")); - } else if (errno != EPIPE || di.zerr == 0) { - zfs_error_aux(zhp->zfs_hdl, "%s", zfs_strerror(errno)); - } - (void) close(pipefd[1]); - (void) pthread_cancel(tid); - (void) pthread_join(tid, NULL); - teardown_differ_info(&di); - if (di.zerr != 0 && di.zerr != EPIPE) { - zfs_error_aux(zhp->zfs_hdl, "%s", - zfs_strerror(di.zerr)); - return (zfs_error(zhp->zfs_hdl, EZFS_DIFF, di.errbuf)); - } else { - return (zfs_error(zhp->zfs_hdl, EZFS_DIFFDATA, errbuf)); - } - } - - (void) close(pipefd[1]); - (void) pthread_join(tid, NULL); - - if (di.zerr != 0) { - zfs_error_aux(zhp->zfs_hdl, "%s", zfs_strerror(di.zerr)); - return (zfs_error(zhp->zfs_hdl, EZFS_DIFF, di.errbuf)); - } - teardown_differ_info(&di); - return (0); -} diff --git a/lib/libzfs/libzfs_impl.h b/lib/libzfs/libzfs_impl.h deleted file mode 100644 index 9053740ec2f0..000000000000 --- a/lib/libzfs/libzfs_impl.h +++ /dev/null @@ -1,242 +0,0 @@ -// SPDX-License-Identifier: CDDL-1.0 -/* - * 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 - */ - -/* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2020 by Delphix. All rights reserved. - * Copyright (c) 2018 Datto Inc. - * Copyright 2020 Joyent, Inc. - */ - -#ifndef _LIBZFS_IMPL_H -#define _LIBZFS_IMPL_H - -#include <sys/fs/zfs.h> -#include <sys/nvpair.h> -#include <sys/dmu.h> -#include <sys/zfs_ioctl.h> -#include <regex.h> - -#include <libuutil.h> -#include <libzfs.h> -#include <libshare.h> -#include <libzfs_core.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#define ERRBUFLEN 1024 - -struct libzfs_handle { - int libzfs_error; - int libzfs_fd; - zpool_handle_t *libzfs_pool_handles; - uu_avl_pool_t *libzfs_ns_avlpool; - uu_avl_t *libzfs_ns_avl; - uint64_t libzfs_ns_gen; - int libzfs_desc_active; - char libzfs_action[1024]; - char libzfs_desc[1024]; - int libzfs_printerr; - boolean_t libzfs_mnttab_enable; - /* - * We need a lock to handle the case where parallel mount - * threads are populating the mnttab cache simultaneously. The - * lock only protects the integrity of the avl tree, and does - * not protect the contents of the mnttab entries themselves. - */ - pthread_mutex_t libzfs_mnttab_cache_lock; - avl_tree_t libzfs_mnttab_cache; - int libzfs_pool_iter; - boolean_t libzfs_prop_debug; - regex_t libzfs_urire; - uint64_t libzfs_max_nvlist; - void *libfetch; - char *libfetch_load_error; -}; - -struct zfs_handle { - libzfs_handle_t *zfs_hdl; - zpool_handle_t *zpool_hdl; - char zfs_name[ZFS_MAX_DATASET_NAME_LEN]; - zfs_type_t zfs_type; /* type including snapshot */ - zfs_type_t zfs_head_type; /* type excluding snapshot */ - dmu_objset_stats_t zfs_dmustats; - nvlist_t *zfs_props; - nvlist_t *zfs_user_props; - nvlist_t *zfs_recvd_props; - boolean_t zfs_mntcheck; - char *zfs_mntopts; - uint8_t *zfs_props_table; -}; - -/* - * This is different from checking zfs_type, because it will also catch - * snapshots of volumes. - */ -#define ZFS_IS_VOLUME(zhp) ((zhp)->zfs_head_type == ZFS_TYPE_VOLUME) -#define ZHP_MAX_PROPNAMES 4 - -struct zpool_handle { - libzfs_handle_t *zpool_hdl; - zpool_handle_t *zpool_next; - char zpool_name[ZFS_MAX_DATASET_NAME_LEN]; - int zpool_state; - unsigned int zpool_n_propnames; - const char *zpool_propnames[ZHP_MAX_PROPNAMES]; - size_t zpool_config_size; - nvlist_t *zpool_config; - nvlist_t *zpool_old_config; - nvlist_t *zpool_props; - diskaddr_t zpool_start_block; -}; - -typedef int (*zfs_uri_handler_fn_t)(struct libzfs_handle *, const char *, - const char *, zfs_keyformat_t, boolean_t, uint8_t **, size_t *); - -typedef struct zfs_uri_handler { - const char *zuh_scheme; - zfs_uri_handler_fn_t zuh_handler; -} zfs_uri_handler_t; - -#define CONFIG_BUF_MINSIZE 262144 - -extern int zfs_error(libzfs_handle_t *, int, const char *); -extern int zfs_error_fmt(libzfs_handle_t *, int, const char *, ...) - __attribute__((format(printf, 3, 4))); -extern void zfs_error_aux(libzfs_handle_t *, const char *, ...) - __attribute__((format(printf, 2, 3))); -extern void *zfs_alloc(libzfs_handle_t *, size_t); -extern void *zfs_realloc(libzfs_handle_t *, void *, size_t, size_t); -extern char *zfs_asprintf(libzfs_handle_t *, const char *, ...) - __attribute__((format(printf, 2, 3))); -extern char *zfs_strdup(libzfs_handle_t *, const char *); -extern int no_memory(libzfs_handle_t *); - -extern int zfs_standard_error_fmt(libzfs_handle_t *, int, const char *, ...) - __attribute__((format(printf, 3, 4))); -extern void zfs_setprop_error(libzfs_handle_t *, zfs_prop_t, int, char *); -extern int zpool_standard_error(libzfs_handle_t *, int, const char *); -extern int zpool_standard_error_fmt(libzfs_handle_t *, int, const char *, ...) - __attribute__((format(printf, 3, 4))); - -extern zfs_handle_t *make_dataset_handle_zc(libzfs_handle_t *, zfs_cmd_t *); -extern zfs_handle_t *make_dataset_simple_handle_zc(zfs_handle_t *, zfs_cmd_t *); - -extern int zprop_parse_value(libzfs_handle_t *, nvpair_t *, int, zfs_type_t, - nvlist_t *, const char **, uint64_t *, const char *); -extern int zprop_expand_list(libzfs_handle_t *hdl, zprop_list_t **plp, - zfs_type_t type); - -/* - * Use this changelist_gather() flag to force attempting mounts - * on each change node regardless of whether or not it is currently - * mounted. - */ -#define CL_GATHER_MOUNT_ALWAYS 1 -/* - * changelist_gather() flag to force it to iterate on mounted datasets only - */ -#define CL_GATHER_ITER_MOUNTED 2 -/* - * Use this changelist_gather() flag to prevent unmounting of file systems. - */ -#define CL_GATHER_DONT_UNMOUNT 4 - -typedef struct prop_changelist prop_changelist_t; - -extern void zcmd_alloc_dst_nvlist(libzfs_handle_t *, zfs_cmd_t *, size_t); -extern void zcmd_write_src_nvlist(libzfs_handle_t *, zfs_cmd_t *, nvlist_t *); -extern void zcmd_write_conf_nvlist(libzfs_handle_t *, zfs_cmd_t *, nvlist_t *); -extern void zcmd_expand_dst_nvlist(libzfs_handle_t *, zfs_cmd_t *); -extern int zcmd_read_dst_nvlist(libzfs_handle_t *, zfs_cmd_t *, nvlist_t **); -extern void zcmd_free_nvlists(zfs_cmd_t *); - -extern int changelist_prefix(prop_changelist_t *); -extern int changelist_postfix(prop_changelist_t *); -extern void changelist_rename(prop_changelist_t *, const char *, const char *); -extern void changelist_remove(prop_changelist_t *, const char *); -extern void changelist_free(prop_changelist_t *); -extern prop_changelist_t *changelist_gather(zfs_handle_t *, zfs_prop_t, int, - int); -extern int changelist_unshare(prop_changelist_t *, const enum sa_protocol *); -extern int changelist_haszonedchild(prop_changelist_t *); - -extern void remove_mountpoint(zfs_handle_t *); -extern int create_parents(libzfs_handle_t *, char *, int); - -extern zfs_handle_t *make_dataset_handle(libzfs_handle_t *, const char *); -extern zfs_handle_t *make_bookmark_handle(zfs_handle_t *, const char *, - nvlist_t *props); - -extern int zpool_open_silent(libzfs_handle_t *, const char *, - zpool_handle_t **); - -extern boolean_t zpool_name_valid(libzfs_handle_t *, boolean_t, const char *); - -extern int zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type, - boolean_t modifying); - -extern void namespace_clear(libzfs_handle_t *); - -typedef struct { - zfs_prop_t p_prop; - int p_share_err; - int p_unshare_err; -} proto_table_t; - -typedef struct differ_info { - zfs_handle_t *zhp; - char *fromsnap; - char *frommnt; - char *tosnap; - char *tomnt; - char *ds; - char *dsmnt; - char *tmpsnap; - char errbuf[ERRBUFLEN]; - boolean_t isclone; - boolean_t scripted; - boolean_t classify; - boolean_t timestamped; - boolean_t no_mangle; - uint64_t shares; - int zerr; - int cleanupfd; - int outputfd; - int datafd; -} differ_info_t; - -extern int do_mount(zfs_handle_t *zhp, const char *mntpt, const char *opts, - int flags); -extern int do_unmount(zfs_handle_t *zhp, const char *mntpt, int flags); -extern int libzfs_load_module(void); -extern int zpool_relabel_disk(libzfs_handle_t *hdl, const char *path, - const char *msg); -extern int find_shares_object(differ_info_t *di); - -#ifdef __cplusplus -} -#endif - -#endif /* _LIBZFS_IMPL_H */ diff --git a/lib/libzfs/libzfs_import.c b/lib/libzfs/libzfs_import.c deleted file mode 100644 index 7f276e9592c9..000000000000 --- a/lib/libzfs/libzfs_import.c +++ /dev/null @@ -1,438 +0,0 @@ -// SPDX-License-Identifier: CDDL-1.0 -/* - * 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 - */ -/* - * Copyright 2015 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2018 by Delphix. All rights reserved. - * Copyright 2015 RackTop Systems. - * Copyright (c) 2016, Intel Corporation. - */ - -#include <errno.h> -#include <libintl.h> -#include <libgen.h> -#include <stddef.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include <unistd.h> -#include <sys/vdev_impl.h> -#include <libzfs.h> -#include "libzfs_impl.h" -#include <libzutil.h> -#include <sys/arc_impl.h> - -/* - * Returns true if the named pool matches the given GUID. - */ -static int -pool_active(libzfs_handle_t *hdl, const char *name, uint64_t guid, - boolean_t *isactive) -{ - zpool_handle_t *zhp; - - if (zpool_open_silent(hdl, name, &zhp) != 0) - return (-1); - - if (zhp == NULL) { - *isactive = B_FALSE; - return (0); - } - - uint64_t theguid = fnvlist_lookup_uint64(zhp->zpool_config, - ZPOOL_CONFIG_POOL_GUID); - - zpool_close(zhp); - - *isactive = (theguid == guid); - return (0); -} - -static nvlist_t * -refresh_config(libzfs_handle_t *hdl, nvlist_t *config) -{ - nvlist_t *nvl; - zfs_cmd_t zc = {"\0"}; - int err, dstbuf_size; - - zcmd_write_conf_nvlist(hdl, &zc, config); - - dstbuf_size = MAX(CONFIG_BUF_MINSIZE, zc.zc_nvlist_conf_size * 32); - - zcmd_alloc_dst_nvlist(hdl, &zc, dstbuf_size); - - while ((err = zfs_ioctl(hdl, ZFS_IOC_POOL_TRYIMPORT, - &zc)) != 0 && errno == ENOMEM) - zcmd_expand_dst_nvlist(hdl, &zc); - - if (err) { - zcmd_free_nvlists(&zc); - return (NULL); - } - - if (zcmd_read_dst_nvlist(hdl, &zc, &nvl) != 0) { - zcmd_free_nvlists(&zc); - return (NULL); - } - - zcmd_free_nvlists(&zc); - return (nvl); -} - -static nvlist_t * -refresh_config_libzfs(void *handle, nvlist_t *tryconfig) -{ - return (refresh_config((libzfs_handle_t *)handle, tryconfig)); -} - -static int -pool_active_libzfs(void *handle, const char *name, uint64_t guid, - boolean_t *isactive) -{ - return (pool_active((libzfs_handle_t *)handle, name, guid, isactive)); -} - -const pool_config_ops_t libzfs_config_ops = { - .pco_refresh_config = refresh_config_libzfs, - .pco_pool_active = pool_active_libzfs, -}; - -/* - * Return the offset of the given label. - */ -static uint64_t -label_offset(uint64_t size, int l) -{ - ASSERT0(P2PHASE_TYPED(size, sizeof (vdev_label_t), uint64_t)); - return (l * sizeof (vdev_label_t) + (l < VDEV_LABELS / 2 ? - 0 : size - VDEV_LABELS * sizeof (vdev_label_t))); -} - -/* - * Given a file descriptor, clear (zero) the label information. This function - * is used in the appliance stack as part of the ZFS sysevent module and - * to implement the "zpool labelclear" command. - */ -int -zpool_clear_label(int fd) -{ - struct stat64 statbuf; - int l; - vdev_label_t *label; - uint64_t size; - boolean_t labels_cleared = B_FALSE, clear_l2arc_header = B_FALSE, - header_cleared = B_FALSE; - - if (fstat64_blk(fd, &statbuf) == -1) - return (0); - - size = P2ALIGN_TYPED(statbuf.st_size, sizeof (vdev_label_t), uint64_t); - - if ((label = calloc(1, sizeof (vdev_label_t))) == NULL) - return (-1); - - for (l = 0; l < VDEV_LABELS; l++) { - uint64_t state, guid, l2cache; - nvlist_t *config; - - if (pread64(fd, label, sizeof (vdev_label_t), - label_offset(size, l)) != sizeof (vdev_label_t)) { - continue; - } - - if (nvlist_unpack(label->vl_vdev_phys.vp_nvlist, - sizeof (label->vl_vdev_phys.vp_nvlist), &config, 0) != 0) { - continue; - } - - /* Skip labels which do not have a valid guid. */ - if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_GUID, - &guid) != 0 || guid == 0) { - nvlist_free(config); - continue; - } - - /* Skip labels which are not in a known valid state. */ - if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, - &state) != 0 || state > POOL_STATE_L2CACHE) { - nvlist_free(config); - continue; - } - - /* If the device is a cache device clear the header. */ - if (!clear_l2arc_header) { - if (nvlist_lookup_uint64(config, - ZPOOL_CONFIG_POOL_STATE, &l2cache) == 0 && - l2cache == POOL_STATE_L2CACHE) { - clear_l2arc_header = B_TRUE; - } - } - - nvlist_free(config); - - /* - * A valid label was found, overwrite this label's nvlist - * and uberblocks with zeros on disk. This is done to prevent - * system utilities, like blkid, from incorrectly detecting a - * partial label. The leading pad space is left untouched. - */ - memset(label, 0, sizeof (vdev_label_t)); - size_t label_size = sizeof (vdev_label_t) - (2 * VDEV_PAD_SIZE); - - if (pwrite64(fd, label, label_size, label_offset(size, l) + - (2 * VDEV_PAD_SIZE)) == label_size) - labels_cleared = B_TRUE; - } - - if (clear_l2arc_header) { - _Static_assert(sizeof (*label) >= sizeof (l2arc_dev_hdr_phys_t), - "label < l2arc_dev_hdr_phys_t"); - memset(label, 0, sizeof (l2arc_dev_hdr_phys_t)); - if (pwrite64(fd, label, sizeof (l2arc_dev_hdr_phys_t), - VDEV_LABEL_START_SIZE) == sizeof (l2arc_dev_hdr_phys_t)) - header_cleared = B_TRUE; - } - - free(label); - - if (!labels_cleared || (clear_l2arc_header && !header_cleared)) - return (-1); - - return (0); -} - -static boolean_t -find_guid(nvlist_t *nv, uint64_t guid) -{ - nvlist_t **child; - uint_t c, children; - - if (fnvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID) == guid) - return (B_TRUE); - - if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, - &child, &children) == 0) { - for (c = 0; c < children; c++) - if (find_guid(child[c], guid)) - return (B_TRUE); - } - - return (B_FALSE); -} - -typedef struct aux_cbdata { - const char *cb_type; - uint64_t cb_guid; - zpool_handle_t *cb_zhp; -} aux_cbdata_t; - -static int -find_aux(zpool_handle_t *zhp, void *data) -{ - aux_cbdata_t *cbp = data; - nvlist_t **list; - uint_t count; - - nvlist_t *nvroot = fnvlist_lookup_nvlist(zhp->zpool_config, - ZPOOL_CONFIG_VDEV_TREE); - - if (nvlist_lookup_nvlist_array(nvroot, cbp->cb_type, - &list, &count) == 0) { - for (uint_t i = 0; i < count; i++) { - uint64_t guid = fnvlist_lookup_uint64(list[i], - ZPOOL_CONFIG_GUID); - if (guid == cbp->cb_guid) { - cbp->cb_zhp = zhp; - return (1); - } - } - } - - zpool_close(zhp); - return (0); -} - -/* - * Determines if the pool is in use. If so, it returns true and the state of - * the pool as well as the name of the pool. Name string is allocated and - * must be freed by the caller. - */ -int -zpool_in_use(libzfs_handle_t *hdl, int fd, pool_state_t *state, char **namestr, - boolean_t *inuse) -{ - nvlist_t *config; - const char *name = NULL; - boolean_t ret; - uint64_t guid = 0, vdev_guid; - zpool_handle_t *zhp; - nvlist_t *pool_config; - uint64_t stateval, isspare; - aux_cbdata_t cb = { 0 }; - boolean_t isactive; - - *inuse = B_FALSE; - - if (zpool_read_label(fd, &config, NULL) != 0) - return (-1); - - if (config == NULL) - return (0); - - stateval = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE); - vdev_guid = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_GUID); - - if (stateval != POOL_STATE_SPARE && stateval != POOL_STATE_L2CACHE) { - name = fnvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME); - guid = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID); - } - - switch (stateval) { - case POOL_STATE_EXPORTED: - /* - * A pool with an exported state may in fact be imported - * read-only, so check the in-core state to see if it's - * active and imported read-only. If it is, set - * its state to active. - */ - if (pool_active(hdl, name, guid, &isactive) == 0 && isactive && - (zhp = zpool_open_canfail(hdl, name)) != NULL) { - if (zpool_get_prop_int(zhp, ZPOOL_PROP_READONLY, NULL)) - stateval = POOL_STATE_ACTIVE; - - /* - * All we needed the zpool handle for is the - * readonly prop check. - */ - zpool_close(zhp); - } - - ret = B_TRUE; - break; - - case POOL_STATE_ACTIVE: - /* - * For an active pool, we have to determine if it's really part - * of a currently active pool (in which case the pool will exist - * and the guid will be the same), or whether it's part of an - * active pool that was disconnected without being explicitly - * exported. - */ - if (pool_active(hdl, name, guid, &isactive) != 0) { - nvlist_free(config); - return (-1); - } - - if (isactive) { - /* - * Because the device may have been removed while - * offlined, we only report it as active if the vdev is - * still present in the config. Otherwise, pretend like - * it's not in use. - */ - if ((zhp = zpool_open_canfail(hdl, name)) != NULL && - (pool_config = zpool_get_config(zhp, NULL)) - != NULL) { - nvlist_t *nvroot = fnvlist_lookup_nvlist( - pool_config, ZPOOL_CONFIG_VDEV_TREE); - ret = find_guid(nvroot, vdev_guid); - } else { - ret = B_FALSE; - } - - /* - * If this is an active spare within another pool, we - * treat it like an unused hot spare. This allows the - * user to create a pool with a hot spare that currently - * in use within another pool. Since we return B_TRUE, - * libdiskmgt will continue to prevent generic consumers - * from using the device. - */ - if (ret && nvlist_lookup_uint64(config, - ZPOOL_CONFIG_IS_SPARE, &isspare) == 0 && isspare) - stateval = POOL_STATE_SPARE; - - if (zhp != NULL) - zpool_close(zhp); - } else { - stateval = POOL_STATE_POTENTIALLY_ACTIVE; - ret = B_TRUE; - } - break; - - case POOL_STATE_SPARE: - /* - * For a hot spare, it can be either definitively in use, or - * potentially active. To determine if it's in use, we iterate - * over all pools in the system and search for one with a spare - * with a matching guid. - * - * Due to the shared nature of spares, we don't actually report - * the potentially active case as in use. This means the user - * can freely create pools on the hot spares of exported pools, - * but to do otherwise makes the resulting code complicated, and - * we end up having to deal with this case anyway. - */ - cb.cb_zhp = NULL; - cb.cb_guid = vdev_guid; - cb.cb_type = ZPOOL_CONFIG_SPARES; - if (zpool_iter(hdl, find_aux, &cb) == 1) { - name = (char *)zpool_get_name(cb.cb_zhp); - ret = B_TRUE; - } else { - ret = B_FALSE; - } - break; - - case POOL_STATE_L2CACHE: - - /* - * Check if any pool is currently using this l2cache device. - */ - cb.cb_zhp = NULL; - cb.cb_guid = vdev_guid; - cb.cb_type = ZPOOL_CONFIG_L2CACHE; - if (zpool_iter(hdl, find_aux, &cb) == 1) { - name = (char *)zpool_get_name(cb.cb_zhp); - ret = B_TRUE; - } else { - ret = B_FALSE; - } - break; - - default: - ret = B_FALSE; - } - - - if (ret) { - *namestr = zfs_strdup(hdl, name); - *state = (pool_state_t)stateval; - } - - if (cb.cb_zhp) - zpool_close(cb.cb_zhp); - - nvlist_free(config); - *inuse = ret; - return (0); -} diff --git a/lib/libzfs/libzfs_iter.c b/lib/libzfs/libzfs_iter.c deleted file mode 100644 index 1844ce1624b3..000000000000 --- a/lib/libzfs/libzfs_iter.c +++ /dev/null @@ -1,655 +0,0 @@ -// SPDX-License-Identifier: CDDL-1.0 -/* - * 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 - */ - -/* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2013, 2019 by Delphix. All rights reserved. - * Copyright 2014 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2019 Datto Inc. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <stddef.h> -#include <libintl.h> -#include <libzfs.h> -#include <libzutil.h> -#include <sys/mntent.h> - -#include "libzfs_impl.h" - -static int -zfs_iter_clones(zfs_handle_t *zhp, int flags __maybe_unused, zfs_iter_f func, - void *data) -{ - nvlist_t *nvl = zfs_get_clones_nvl(zhp); - nvpair_t *pair; - - if (nvl == NULL) - return (0); - - for (pair = nvlist_next_nvpair(nvl, NULL); pair != NULL; - pair = nvlist_next_nvpair(nvl, pair)) { - zfs_handle_t *clone = zfs_open(zhp->zfs_hdl, nvpair_name(pair), - ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); - if (clone != NULL) { - int err = func(clone, data); - if (err != 0) - return (err); - } - } - return (0); -} - -static int -zfs_do_list_ioctl(zfs_handle_t *zhp, int arg, zfs_cmd_t *zc) -{ - int rc; - uint64_t orig_cookie; - - orig_cookie = zc->zc_cookie; -top: - (void) strlcpy(zc->zc_name, zhp->zfs_name, sizeof (zc->zc_name)); - zc->zc_objset_stats.dds_creation_txg = 0; - rc = zfs_ioctl(zhp->zfs_hdl, arg, zc); - - if (rc == -1) { - switch (errno) { - case ENOMEM: - /* expand nvlist memory and try again */ - zcmd_expand_dst_nvlist(zhp->zfs_hdl, zc); - zc->zc_cookie = orig_cookie; - goto top; - /* - * An errno value of ESRCH indicates normal completion. - * If ENOENT is returned, then the underlying dataset - * has been removed since we obtained the handle. - */ - case ESRCH: - case ENOENT: - rc = 1; - break; - default: - rc = zfs_standard_error(zhp->zfs_hdl, errno, - dgettext(TEXT_DOMAIN, - "cannot iterate filesystems")); - break; - } - } - return (rc); -} - -/* - * Iterate over all child filesystems - */ -int -zfs_iter_filesystems(zfs_handle_t *zhp, zfs_iter_f func, void *data) -{ - return (zfs_iter_filesystems_v2(zhp, 0, func, data)); -} - -int -zfs_iter_filesystems_v2(zfs_handle_t *zhp, int flags, zfs_iter_f func, - void *data) -{ - zfs_cmd_t zc = {"\0"}; - zfs_handle_t *nzhp; - int ret; - - if (zhp->zfs_type != ZFS_TYPE_FILESYSTEM) - return (0); - - zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0); - - if ((flags & ZFS_ITER_SIMPLE) == ZFS_ITER_SIMPLE) - zc.zc_simple = B_TRUE; - - while ((ret = zfs_do_list_ioctl(zhp, ZFS_IOC_DATASET_LIST_NEXT, - &zc)) == 0) { - if (zc.zc_simple) - nzhp = make_dataset_simple_handle_zc(zhp, &zc); - else - nzhp = make_dataset_handle_zc(zhp->zfs_hdl, &zc); - /* - * Silently ignore errors, as the only plausible explanation is - * that the pool has since been removed. - */ - if (nzhp == NULL) - continue; - - if ((ret = func(nzhp, data)) != 0) { - zcmd_free_nvlists(&zc); - return (ret); - } - } - zcmd_free_nvlists(&zc); - return ((ret < 0) ? ret : 0); -} - -/* - * Iterate over all snapshots - */ -int -zfs_iter_snapshots(zfs_handle_t *zhp, boolean_t simple, zfs_iter_f func, - void *data, uint64_t min_txg, uint64_t max_txg) -{ - return (zfs_iter_snapshots_v2(zhp, simple ? ZFS_ITER_SIMPLE : 0, func, - data, min_txg, max_txg)); -} - -int -zfs_iter_snapshots_v2(zfs_handle_t *zhp, int flags, zfs_iter_f func, - void *data, uint64_t min_txg, uint64_t max_txg) -{ - zfs_cmd_t zc = {"\0"}; - zfs_handle_t *nzhp; - int ret; - nvlist_t *range_nvl = NULL; - - if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT || - zhp->zfs_type == ZFS_TYPE_BOOKMARK) - return (0); - - zc.zc_simple = (flags & ZFS_ITER_SIMPLE) != 0; - - zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0); - - if (min_txg != 0) { - range_nvl = fnvlist_alloc(); - fnvlist_add_uint64(range_nvl, SNAP_ITER_MIN_TXG, min_txg); - } - if (max_txg != 0) { - if (range_nvl == NULL) - range_nvl = fnvlist_alloc(); - fnvlist_add_uint64(range_nvl, SNAP_ITER_MAX_TXG, max_txg); - } - - if (range_nvl != NULL) - zcmd_write_src_nvlist(zhp->zfs_hdl, &zc, range_nvl); - - while ((ret = zfs_do_list_ioctl(zhp, ZFS_IOC_SNAPSHOT_LIST_NEXT, - &zc)) == 0) { - - if (zc.zc_simple) - nzhp = make_dataset_simple_handle_zc(zhp, &zc); - else - nzhp = make_dataset_handle_zc(zhp->zfs_hdl, &zc); - if (nzhp == NULL) - continue; - - if ((ret = func(nzhp, data)) != 0) { - zcmd_free_nvlists(&zc); - fnvlist_free(range_nvl); - return (ret); - } - } - zcmd_free_nvlists(&zc); - fnvlist_free(range_nvl); - return ((ret < 0) ? ret : 0); -} - -/* - * Iterate over all bookmarks - */ -int -zfs_iter_bookmarks(zfs_handle_t *zhp, zfs_iter_f func, void *data) -{ - return (zfs_iter_bookmarks_v2(zhp, 0, func, data)); -} - -int -zfs_iter_bookmarks_v2(zfs_handle_t *zhp, int flags __maybe_unused, - zfs_iter_f func, void *data) -{ - zfs_handle_t *nzhp; - nvlist_t *props = NULL; - nvlist_t *bmarks = NULL; - int err; - nvpair_t *pair; - - if ((zfs_get_type(zhp) & (ZFS_TYPE_SNAPSHOT | ZFS_TYPE_BOOKMARK)) != 0) - return (0); - - /* Setup the requested properties nvlist. */ - props = fnvlist_alloc(); - for (zfs_prop_t p = 0; p < ZFS_NUM_PROPS; p++) { - if (zfs_prop_valid_for_type(p, ZFS_TYPE_BOOKMARK, B_FALSE)) { - fnvlist_add_boolean(props, zfs_prop_to_name(p)); - } - } - fnvlist_add_boolean(props, "redact_complete"); - - if ((err = lzc_get_bookmarks(zhp->zfs_name, props, &bmarks)) != 0) - goto out; - - for (pair = nvlist_next_nvpair(bmarks, NULL); - pair != NULL; pair = nvlist_next_nvpair(bmarks, pair)) { - char name[ZFS_MAX_DATASET_NAME_LEN]; - const char *bmark_name; - nvlist_t *bmark_props; - - bmark_name = nvpair_name(pair); - bmark_props = fnvpair_value_nvlist(pair); - - if (snprintf(name, sizeof (name), "%s#%s", zhp->zfs_name, - bmark_name) >= sizeof (name)) { - err = EINVAL; - goto out; - } - - nzhp = make_bookmark_handle(zhp, name, bmark_props); - if (nzhp == NULL) - continue; - - if ((err = func(nzhp, data)) != 0) - goto out; - } - -out: - fnvlist_free(props); - fnvlist_free(bmarks); - - return (err); -} - -/* - * Routines for dealing with the sorted snapshot functionality - */ -typedef struct zfs_node { - zfs_handle_t *zn_handle; - avl_node_t zn_avlnode; -} zfs_node_t; - -static int -zfs_sort_snaps(zfs_handle_t *zhp, void *data) -{ - avl_tree_t *avl = data; - zfs_node_t *node; - zfs_node_t search; - - search.zn_handle = zhp; - node = avl_find(avl, &search, NULL); - if (node) { - /* - * If this snapshot was renamed while we were creating the - * AVL tree, it's possible that we already inserted it under - * its old name. Remove the old handle before adding the new - * one. - */ - zfs_close(node->zn_handle); - avl_remove(avl, node); - free(node); - } - - node = zfs_alloc(zhp->zfs_hdl, sizeof (zfs_node_t)); - node->zn_handle = zhp; - avl_add(avl, node); - - return (0); -} - -static int -zfs_snapshot_compare(const void *larg, const void *rarg) -{ - zfs_handle_t *l = ((zfs_node_t *)larg)->zn_handle; - zfs_handle_t *r = ((zfs_node_t *)rarg)->zn_handle; - uint64_t lcreate, rcreate; - - /* - * Sort them according to creation time. We use the hidden - * CREATETXG property to get an absolute ordering of snapshots. - */ - lcreate = zfs_prop_get_int(l, ZFS_PROP_CREATETXG); - rcreate = zfs_prop_get_int(r, ZFS_PROP_CREATETXG); - - return (TREE_CMP(lcreate, rcreate)); -} - -int -zfs_iter_snapshots_sorted(zfs_handle_t *zhp, zfs_iter_f callback, - void *data, uint64_t min_txg, uint64_t max_txg) -{ - return (zfs_iter_snapshots_sorted_v2(zhp, 0, callback, data, - min_txg, max_txg)); -} - -int -zfs_iter_snapshots_sorted_v2(zfs_handle_t *zhp, int flags, zfs_iter_f callback, - void *data, uint64_t min_txg, uint64_t max_txg) -{ - int ret = 0; - zfs_node_t *node; - avl_tree_t avl; - void *cookie = NULL; - - avl_create(&avl, zfs_snapshot_compare, - sizeof (zfs_node_t), offsetof(zfs_node_t, zn_avlnode)); - - ret = zfs_iter_snapshots_v2(zhp, flags, zfs_sort_snaps, &avl, min_txg, - max_txg); - - for (node = avl_first(&avl); node != NULL; node = AVL_NEXT(&avl, node)) - ret |= callback(node->zn_handle, data); - - while ((node = avl_destroy_nodes(&avl, &cookie)) != NULL) - free(node); - - avl_destroy(&avl); - - return (ret); -} - -typedef struct { - char *ssa_first; - char *ssa_last; - boolean_t ssa_seenfirst; - boolean_t ssa_seenlast; - zfs_iter_f ssa_func; - void *ssa_arg; -} snapspec_arg_t; - -static int -snapspec_cb(zfs_handle_t *zhp, void *arg) -{ - snapspec_arg_t *ssa = arg; - const char *shortsnapname; - int err = 0; - - if (ssa->ssa_seenlast) - return (0); - - shortsnapname = strchr(zfs_get_name(zhp), '@') + 1; - if (!ssa->ssa_seenfirst && strcmp(shortsnapname, ssa->ssa_first) == 0) - ssa->ssa_seenfirst = B_TRUE; - if (strcmp(shortsnapname, ssa->ssa_last) == 0) - ssa->ssa_seenlast = B_TRUE; - - if (ssa->ssa_seenfirst) { - err = ssa->ssa_func(zhp, ssa->ssa_arg); - } else { - zfs_close(zhp); - } - - return (err); -} - -/* - * spec is a string like "A,B%C,D" - * - * <snaps>, where <snaps> can be: - * <snap> (single snapshot) - * <snap>%<snap> (range of snapshots, inclusive) - * %<snap> (range of snapshots, starting with earliest) - * <snap>% (range of snapshots, ending with last) - * % (all snapshots) - * <snaps>[,...] (comma separated list of the above) - * - * If a snapshot can not be opened, continue trying to open the others, but - * return ENOENT at the end. - */ -int -zfs_iter_snapspec(zfs_handle_t *fs_zhp, const char *spec_orig, - zfs_iter_f func, void *arg) -{ - return (zfs_iter_snapspec_v2(fs_zhp, 0, spec_orig, func, arg)); -} - -int -zfs_iter_snapspec_v2(zfs_handle_t *fs_zhp, int flags, const char *spec_orig, - zfs_iter_f func, void *arg) -{ - char *buf, *comma_separated, *cp; - int err = 0; - int ret = 0; - - buf = zfs_strdup(fs_zhp->zfs_hdl, spec_orig); - cp = buf; - - while ((comma_separated = strsep(&cp, ",")) != NULL) { - char *pct = strchr(comma_separated, '%'); - if (pct != NULL) { - snapspec_arg_t ssa = { 0 }; - ssa.ssa_func = func; - ssa.ssa_arg = arg; - - if (pct == comma_separated) - ssa.ssa_seenfirst = B_TRUE; - else - ssa.ssa_first = comma_separated; - *pct = '\0'; - ssa.ssa_last = pct + 1; - - /* - * If there is a lastname specified, make sure it - * exists. - */ - if (ssa.ssa_last[0] != '\0') { - char snapname[ZFS_MAX_DATASET_NAME_LEN]; - (void) snprintf(snapname, sizeof (snapname), - "%s@%s", zfs_get_name(fs_zhp), - ssa.ssa_last); - if (!zfs_dataset_exists(fs_zhp->zfs_hdl, - snapname, ZFS_TYPE_SNAPSHOT)) { - ret = ENOENT; - continue; - } - } - - err = zfs_iter_snapshots_sorted_v2(fs_zhp, flags, - snapspec_cb, &ssa, 0, 0); - if (ret == 0) - ret = err; - if (ret == 0 && (!ssa.ssa_seenfirst || - (ssa.ssa_last[0] != '\0' && !ssa.ssa_seenlast))) { - ret = ENOENT; - } - } else { - char snapname[ZFS_MAX_DATASET_NAME_LEN]; - zfs_handle_t *snap_zhp; - (void) snprintf(snapname, sizeof (snapname), "%s@%s", - zfs_get_name(fs_zhp), comma_separated); - snap_zhp = make_dataset_handle(fs_zhp->zfs_hdl, - snapname); - if (snap_zhp == NULL) { - ret = ENOENT; - continue; - } - err = func(snap_zhp, arg); - if (ret == 0) - ret = err; - } - } - - free(buf); - return (ret); -} - -/* - * Iterate over all children, snapshots and filesystems - * Process snapshots before filesystems because they are nearer the input - * handle: this is extremely important when used with zfs_iter_f functions - * looking for data, following the logic that we would like to find it as soon - * and as close as possible. - */ -int -zfs_iter_children(zfs_handle_t *zhp, zfs_iter_f func, void *data) -{ - return (zfs_iter_children_v2(zhp, 0, func, data)); -} - -int -zfs_iter_children_v2(zfs_handle_t *zhp, int flags, zfs_iter_f func, void *data) -{ - int ret; - - if ((ret = zfs_iter_snapshots_v2(zhp, flags, func, data, 0, 0)) != 0) - return (ret); - - return (zfs_iter_filesystems_v2(zhp, flags, func, data)); -} - - -typedef struct iter_stack_frame { - struct iter_stack_frame *next; - zfs_handle_t *zhp; -} iter_stack_frame_t; - -typedef struct iter_dependents_arg { - boolean_t first; - int flags; - boolean_t allowrecursion; - iter_stack_frame_t *stack; - zfs_iter_f func; - void *data; -} iter_dependents_arg_t; - -static int -iter_dependents_cb(zfs_handle_t *zhp, void *arg) -{ - iter_dependents_arg_t *ida = arg; - int err = 0; - boolean_t first = ida->first; - ida->first = B_FALSE; - - if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) { - err = zfs_iter_clones(zhp, ida->flags, iter_dependents_cb, ida); - } else if (zhp->zfs_type != ZFS_TYPE_BOOKMARK) { - iter_stack_frame_t isf; - iter_stack_frame_t *f; - - /* - * check if there is a cycle by seeing if this fs is already - * on the stack. - */ - for (f = ida->stack; f != NULL; f = f->next) { - if (f->zhp->zfs_dmustats.dds_guid == - zhp->zfs_dmustats.dds_guid) { - if (ida->allowrecursion) { - zfs_close(zhp); - return (0); - } else { - zfs_error_aux(zhp->zfs_hdl, - dgettext(TEXT_DOMAIN, - "recursive dependency at '%s'"), - zfs_get_name(zhp)); - err = zfs_error(zhp->zfs_hdl, - EZFS_RECURSIVE, - dgettext(TEXT_DOMAIN, - "cannot determine dependent " - "datasets")); - zfs_close(zhp); - return (err); - } - } - } - - isf.zhp = zhp; - isf.next = ida->stack; - ida->stack = &isf; - err = zfs_iter_filesystems_v2(zhp, ida->flags, - iter_dependents_cb, ida); - if (err == 0) - err = zfs_iter_snapshots_sorted_v2(zhp, ida->flags, - iter_dependents_cb, ida, 0, 0); - ida->stack = isf.next; - } - - if (!first && err == 0) - err = ida->func(zhp, ida->data); - else - zfs_close(zhp); - - return (err); -} - -int -zfs_iter_dependents(zfs_handle_t *zhp, boolean_t allowrecursion, - zfs_iter_f func, void *data) -{ - return (zfs_iter_dependents_v2(zhp, 0, allowrecursion, func, data)); -} - -int -zfs_iter_dependents_v2(zfs_handle_t *zhp, int flags, boolean_t allowrecursion, - zfs_iter_f func, void *data) -{ - iter_dependents_arg_t ida; - ida.flags = flags; - ida.allowrecursion = allowrecursion; - ida.stack = NULL; - ida.func = func; - ida.data = data; - ida.first = B_TRUE; - return (iter_dependents_cb(zfs_handle_dup(zhp), &ida)); -} - -/* - * Iterate over mounted children of the specified dataset - */ -int -zfs_iter_mounted(zfs_handle_t *zhp, zfs_iter_f func, void *data) -{ - char mnt_prop[ZFS_MAXPROPLEN]; - struct mnttab entry; - zfs_handle_t *mtab_zhp; - size_t namelen = strlen(zhp->zfs_name); - FILE *mnttab; - int err = 0; - - if ((mnttab = fopen(MNTTAB, "re")) == NULL) - return (ENOENT); - - while (err == 0 && getmntent(mnttab, &entry) == 0) { - /* Ignore non-ZFS entries */ - if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) - continue; - - /* Ignore datasets not within the provided dataset */ - if (strncmp(entry.mnt_special, zhp->zfs_name, namelen) != 0 || - entry.mnt_special[namelen] != '/') - continue; - - /* Skip snapshot of any child dataset */ - if (strchr(entry.mnt_special, '@') != NULL) - continue; - - if ((mtab_zhp = zfs_open(zhp->zfs_hdl, entry.mnt_special, - ZFS_TYPE_FILESYSTEM)) == NULL) - continue; - - /* Ignore legacy mounts as they are user managed */ - verify(zfs_prop_get(mtab_zhp, ZFS_PROP_MOUNTPOINT, mnt_prop, - sizeof (mnt_prop), NULL, NULL, 0, B_FALSE) == 0); - if (strcmp(mnt_prop, "legacy") == 0) { - zfs_close(mtab_zhp); - continue; - } - - err = func(mtab_zhp, data); - } - - fclose(mnttab); - - return (err); -} diff --git a/lib/libzfs/libzfs_mount.c b/lib/libzfs/libzfs_mount.c deleted file mode 100644 index 5c9e2199eed4..000000000000 --- a/lib/libzfs/libzfs_mount.c +++ /dev/null @@ -1,1468 +0,0 @@ -// SPDX-License-Identifier: CDDL-1.0 -/* - * 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 - */ - -/* - * Copyright 2015 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2014, 2022 by Delphix. All rights reserved. - * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com> - * Copyright 2017 RackTop Systems. - * Copyright (c) 2018 Datto Inc. - * Copyright 2018 OmniOS Community Edition (OmniOSce) Association. - */ - -/* - * Routines to manage ZFS mounts. We separate all the nasty routines that have - * to deal with the OS. The following functions are the main entry points -- - * they are used by mount and unmount and when changing a filesystem's - * mountpoint. - * - * zfs_is_mounted() - * zfs_mount() - * zfs_mount_at() - * zfs_unmount() - * zfs_unmountall() - * - * This file also contains the functions used to manage sharing filesystems: - * - * zfs_is_shared() - * zfs_share() - * zfs_unshare() - * zfs_unshareall() - * zfs_commit_shares() - * - * The following functions are available for pool consumers, and will - * mount/unmount and share/unshare all datasets within pool: - * - * zpool_enable_datasets() - * zpool_disable_datasets() - */ - -#include <dirent.h> -#include <dlfcn.h> -#include <errno.h> -#include <fcntl.h> -#include <libgen.h> -#include <libintl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <zone.h> -#include <sys/mntent.h> -#include <sys/mount.h> -#include <sys/stat.h> -#include <sys/vfs.h> -#include <sys/dsl_crypt.h> - -#include <libzfs.h> -#include <libzutil.h> - -#include "libzfs_impl.h" -#include <thread_pool.h> - -#include <libshare.h> -#include <sys/systeminfo.h> -#define MAXISALEN 257 /* based on sysinfo(2) man page */ - -static void zfs_mount_task(void *); - -static const proto_table_t proto_table[SA_PROTOCOL_COUNT] = { - [SA_PROTOCOL_NFS] = - {ZFS_PROP_SHARENFS, EZFS_SHARENFSFAILED, EZFS_UNSHARENFSFAILED}, - [SA_PROTOCOL_SMB] = - {ZFS_PROP_SHARESMB, EZFS_SHARESMBFAILED, EZFS_UNSHARESMBFAILED}, -}; - -static const enum sa_protocol share_all_proto[SA_PROTOCOL_COUNT + 1] = { - SA_PROTOCOL_NFS, - SA_PROTOCOL_SMB, - SA_NO_PROTOCOL -}; - - - -static boolean_t -dir_is_empty_stat(const char *dirname) -{ - struct stat st; - - /* - * We only want to return false if the given path is a non empty - * directory, all other errors are handled elsewhere. - */ - if (stat(dirname, &st) < 0 || !S_ISDIR(st.st_mode)) { - return (B_TRUE); - } - - /* - * An empty directory will still have two entries in it, one - * entry for each of "." and "..". - */ - if (st.st_size > 2) { - return (B_FALSE); - } - - return (B_TRUE); -} - -static boolean_t -dir_is_empty_readdir(const char *dirname) -{ - DIR *dirp; - struct dirent64 *dp; - int dirfd; - - if ((dirfd = openat(AT_FDCWD, dirname, - O_RDONLY | O_NDELAY | O_LARGEFILE | O_CLOEXEC, 0)) < 0) { - return (B_TRUE); - } - - if ((dirp = fdopendir(dirfd)) == NULL) { - (void) close(dirfd); - return (B_TRUE); - } - - while ((dp = readdir64(dirp)) != NULL) { - - if (strcmp(dp->d_name, ".") == 0 || - strcmp(dp->d_name, "..") == 0) - continue; - - (void) closedir(dirp); - return (B_FALSE); - } - - (void) closedir(dirp); - return (B_TRUE); -} - -/* - * Returns true if the specified directory is empty. If we can't open the - * directory at all, return true so that the mount can fail with a more - * informative error message. - */ -static boolean_t -dir_is_empty(const char *dirname) -{ - struct statfs64 st; - - /* - * If the statvfs call fails or the filesystem is not a ZFS - * filesystem, fall back to the slow path which uses readdir. - */ - if ((statfs64(dirname, &st) != 0) || - (st.f_type != ZFS_SUPER_MAGIC)) { - return (dir_is_empty_readdir(dirname)); - } - - /* - * At this point, we know the provided path is on a ZFS - * filesystem, so we can use stat instead of readdir to - * determine if the directory is empty or not. We try to avoid - * using readdir because that requires opening "dirname"; this - * open file descriptor can potentially end up in a child - * process if there's a concurrent fork, thus preventing the - * zfs_mount() from otherwise succeeding (the open file - * descriptor inherited by the child process will cause the - * parent's mount to fail with EBUSY). The performance - * implications of replacing the open, read, and close with a - * single stat is nice; but is not the main motivation for the - * added complexity. - */ - return (dir_is_empty_stat(dirname)); -} - -/* - * Checks to see if the mount is active. If the filesystem is mounted, we fill - * in 'where' with the current mountpoint, and return 1. Otherwise, we return - * 0. - */ -boolean_t -is_mounted(libzfs_handle_t *zfs_hdl, const char *special, char **where) -{ - struct mnttab entry; - - if (libzfs_mnttab_find(zfs_hdl, special, &entry) != 0) - return (B_FALSE); - - if (where != NULL) - *where = zfs_strdup(zfs_hdl, entry.mnt_mountp); - - return (B_TRUE); -} - -boolean_t -zfs_is_mounted(zfs_handle_t *zhp, char **where) -{ - return (is_mounted(zhp->zfs_hdl, zfs_get_name(zhp), where)); -} - -/* - * Checks any higher order concerns about whether the given dataset is - * mountable, false otherwise. zfs_is_mountable_internal specifically assumes - * that the caller has verified the sanity of mounting the dataset at - * its mountpoint to the extent the caller wants. - */ -static boolean_t -zfs_is_mountable_internal(zfs_handle_t *zhp) -{ - if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED) && - getzoneid() == GLOBAL_ZONEID) - return (B_FALSE); - - return (B_TRUE); -} - -/* - * Returns true if the given dataset is mountable, false otherwise. Returns the - * mountpoint in 'buf'. - */ -static boolean_t -zfs_is_mountable(zfs_handle_t *zhp, char *buf, size_t buflen, - zprop_source_t *source, int flags) -{ - char sourceloc[MAXNAMELEN]; - zprop_source_t sourcetype; - - if (!zfs_prop_valid_for_type(ZFS_PROP_MOUNTPOINT, zhp->zfs_type, - B_FALSE)) - return (B_FALSE); - - verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, buf, buflen, - &sourcetype, sourceloc, sizeof (sourceloc), B_FALSE) == 0); - - if (strcmp(buf, ZFS_MOUNTPOINT_NONE) == 0 || - strcmp(buf, ZFS_MOUNTPOINT_LEGACY) == 0) - return (B_FALSE); - - if (zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT) == ZFS_CANMOUNT_OFF) - return (B_FALSE); - - if (!zfs_is_mountable_internal(zhp)) - return (B_FALSE); - - if (zfs_prop_get_int(zhp, ZFS_PROP_REDACTED) && !(flags & MS_FORCE)) - return (B_FALSE); - - if (source) - *source = sourcetype; - - return (B_TRUE); -} - -/* - * The filesystem is mounted by invoking the system mount utility rather - * than by the system call mount(2). This ensures that the /etc/mtab - * file is correctly locked for the update. Performing our own locking - * and /etc/mtab update requires making an unsafe assumption about how - * the mount utility performs its locking. Unfortunately, this also means - * in the case of a mount failure we do not have the exact errno. We must - * make due with return value from the mount process. - * - * In the long term a shared library called libmount is under development - * which provides a common API to address the locking and errno issues. - * Once the standard mount utility has been updated to use this library - * we can add an autoconf check to conditionally use it. - * - * http://www.kernel.org/pub/linux/utils/util-linux/libmount-docs/index.html - */ - -static int -zfs_add_option(zfs_handle_t *zhp, char *options, int len, - zfs_prop_t prop, const char *on, const char *off) -{ - const char *source; - uint64_t value; - - /* Skip adding duplicate default options */ - if ((strstr(options, on) != NULL) || (strstr(options, off) != NULL)) - return (0); - - /* - * zfs_prop_get_int() is not used to ensure our mount options - * are not influenced by the current /proc/self/mounts contents. - */ - value = getprop_uint64(zhp, prop, &source); - - (void) strlcat(options, ",", len); - (void) strlcat(options, value ? on : off, len); - - return (0); -} - -static int -zfs_add_options(zfs_handle_t *zhp, char *options, int len) -{ - int error = 0; - - error = zfs_add_option(zhp, options, len, - ZFS_PROP_ATIME, MNTOPT_ATIME, MNTOPT_NOATIME); - /* - * don't add relatime/strictatime when atime=off, otherwise strictatime - * will force atime=on - */ - if (strstr(options, MNTOPT_NOATIME) == NULL) { - error = zfs_add_option(zhp, options, len, - ZFS_PROP_RELATIME, MNTOPT_RELATIME, MNTOPT_STRICTATIME); - } - error = error ? error : zfs_add_option(zhp, options, len, - ZFS_PROP_DEVICES, MNTOPT_DEVICES, MNTOPT_NODEVICES); - error = error ? error : zfs_add_option(zhp, options, len, - ZFS_PROP_EXEC, MNTOPT_EXEC, MNTOPT_NOEXEC); - error = error ? error : zfs_add_option(zhp, options, len, - ZFS_PROP_READONLY, MNTOPT_RO, MNTOPT_RW); - error = error ? error : zfs_add_option(zhp, options, len, - ZFS_PROP_SETUID, MNTOPT_SETUID, MNTOPT_NOSETUID); - error = error ? error : zfs_add_option(zhp, options, len, - ZFS_PROP_NBMAND, MNTOPT_NBMAND, MNTOPT_NONBMAND); - - return (error); -} - -int -zfs_mount(zfs_handle_t *zhp, const char *options, int flags) -{ - char mountpoint[ZFS_MAXPROPLEN]; - - if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL, - flags)) - return (0); - - return (zfs_mount_at(zhp, options, flags, mountpoint)); -} - -/* - * Mount the given filesystem. - */ -int -zfs_mount_at(zfs_handle_t *zhp, const char *options, int flags, - const char *mountpoint) -{ - struct stat buf; - char mntopts[MNT_LINE_MAX]; - char overlay[ZFS_MAXPROPLEN]; - char prop_encroot[MAXNAMELEN]; - boolean_t is_encroot; - zfs_handle_t *encroot_hp = zhp; - libzfs_handle_t *hdl = zhp->zfs_hdl; - uint64_t keystatus; - int remount = 0, rc; - - if (options == NULL) { - (void) strlcpy(mntopts, MNTOPT_DEFAULTS, sizeof (mntopts)); - } else { - (void) strlcpy(mntopts, options, sizeof (mntopts)); - } - - if (strstr(mntopts, MNTOPT_REMOUNT) != NULL) - remount = 1; - - /* Potentially duplicates some checks if invoked by zfs_mount(). */ - if (!zfs_is_mountable_internal(zhp)) - return (0); - - /* - * If the pool is imported read-only then all mounts must be read-only - */ - if (zpool_get_prop_int(zhp->zpool_hdl, ZPOOL_PROP_READONLY, NULL)) - (void) strlcat(mntopts, "," MNTOPT_RO, sizeof (mntopts)); - - /* - * Append default mount options which apply to the mount point. - * This is done because under Linux (unlike Solaris) multiple mount - * points may reference a single super block. This means that just - * given a super block there is no back reference to update the per - * mount point options. - */ - rc = zfs_add_options(zhp, mntopts, sizeof (mntopts)); - if (rc) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "default options unavailable")); - return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED, - dgettext(TEXT_DOMAIN, "cannot mount '%s'"), - mountpoint)); - } - - /* - * If the filesystem is encrypted the key must be loaded in order to - * mount. If the key isn't loaded, the MS_CRYPT flag decides whether - * or not we attempt to load the keys. Note: we must call - * zfs_refresh_properties() here since some callers of this function - * (most notably zpool_enable_datasets()) may implicitly load our key - * by loading the parent's key first. - */ - if (zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION) != ZIO_CRYPT_OFF) { - zfs_refresh_properties(zhp); - keystatus = zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS); - - /* - * If the key is unavailable and MS_CRYPT is set give the - * user a chance to enter the key. Otherwise just fail - * immediately. - */ - if (keystatus == ZFS_KEYSTATUS_UNAVAILABLE) { - if (flags & MS_CRYPT) { - rc = zfs_crypto_get_encryption_root(zhp, - &is_encroot, prop_encroot); - if (rc) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Failed to get encryption root for " - "'%s'."), zfs_get_name(zhp)); - return (rc); - } - - if (!is_encroot) { - encroot_hp = zfs_open(hdl, prop_encroot, - ZFS_TYPE_DATASET); - if (encroot_hp == NULL) - return (hdl->libzfs_error); - } - - rc = zfs_crypto_load_key(encroot_hp, - B_FALSE, NULL); - - if (!is_encroot) - zfs_close(encroot_hp); - if (rc) - return (rc); - } else { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "encryption key not loaded")); - return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED, - dgettext(TEXT_DOMAIN, "cannot mount '%s'"), - mountpoint)); - } - } - - } - - /* - * Append zfsutil option so the mount helper allow the mount - */ - strlcat(mntopts, "," MNTOPT_ZFSUTIL, sizeof (mntopts)); - - /* Create the directory if it doesn't already exist */ - if (lstat(mountpoint, &buf) != 0) { - if (mkdirp(mountpoint, 0755) != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "failed to create mountpoint: %s"), - zfs_strerror(errno)); - return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED, - dgettext(TEXT_DOMAIN, "cannot mount '%s'"), - mountpoint)); - } - } - - /* - * Overlay mounts are enabled by default but may be disabled - * via the 'overlay' property. The -O flag remains for compatibility. - */ - if (!(flags & MS_OVERLAY)) { - if (zfs_prop_get(zhp, ZFS_PROP_OVERLAY, overlay, - sizeof (overlay), NULL, NULL, 0, B_FALSE) == 0) { - if (strcmp(overlay, "on") == 0) { - flags |= MS_OVERLAY; - } - } - } - - /* - * Determine if the mountpoint is empty. If so, refuse to perform the - * mount. We don't perform this check if 'remount' is - * specified or if overlay option (-O) is given - */ - if ((flags & MS_OVERLAY) == 0 && !remount && - !dir_is_empty(mountpoint)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "directory is not empty")); - return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED, - dgettext(TEXT_DOMAIN, "cannot mount '%s'"), mountpoint)); - } - - /* perform the mount */ - rc = do_mount(zhp, mountpoint, mntopts, flags); - if (rc) { - /* - * Generic errors are nasty, but there are just way too many - * from mount(), and they're well-understood. We pick a few - * common ones to improve upon. - */ - if (rc == EBUSY) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "mountpoint or dataset is busy")); - } else if (rc == EPERM) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Insufficient privileges")); - } else if (rc == ENOTSUP) { - int spa_version; - - VERIFY0(zfs_spa_version(zhp, &spa_version)); - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Can't mount a version %llu " - "file system on a version %d pool. Pool must be" - " upgraded to mount this file system."), - (u_longlong_t)zfs_prop_get_int(zhp, - ZFS_PROP_VERSION), spa_version); - } else { - zfs_error_aux(hdl, "%s", zfs_strerror(rc)); - } - return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED, - dgettext(TEXT_DOMAIN, "cannot mount '%s'"), - zhp->zfs_name)); - } - - /* remove the mounted entry before re-adding on remount */ - if (remount) - libzfs_mnttab_remove(hdl, zhp->zfs_name); - - /* add the mounted entry into our cache */ - libzfs_mnttab_add(hdl, zfs_get_name(zhp), mountpoint, mntopts); - return (0); -} - -/* - * Unmount a single filesystem. - */ -static int -unmount_one(zfs_handle_t *zhp, const char *mountpoint, int flags) -{ - int error; - - error = do_unmount(zhp, mountpoint, flags); - if (error != 0) { - int libzfs_err; - - switch (error) { - case EBUSY: - libzfs_err = EZFS_BUSY; - break; - case EIO: - libzfs_err = EZFS_IO; - break; - case ENOENT: - libzfs_err = EZFS_NOENT; - break; - case ENOMEM: - libzfs_err = EZFS_NOMEM; - break; - case EPERM: - libzfs_err = EZFS_PERM; - break; - default: - libzfs_err = EZFS_UMOUNTFAILED; - } - if (zhp) { - return (zfs_error_fmt(zhp->zfs_hdl, libzfs_err, - dgettext(TEXT_DOMAIN, "cannot unmount '%s'"), - mountpoint)); - } else { - return (-1); - } - } - - return (0); -} - -/* - * Unmount the given filesystem. - */ -int -zfs_unmount(zfs_handle_t *zhp, const char *mountpoint, int flags) -{ - libzfs_handle_t *hdl = zhp->zfs_hdl; - struct mnttab entry; - char *mntpt = NULL; - boolean_t encroot, unmounted = B_FALSE; - - /* check to see if we need to unmount the filesystem */ - if (mountpoint != NULL || ((zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) && - libzfs_mnttab_find(hdl, zhp->zfs_name, &entry) == 0)) { - /* - * mountpoint may have come from a call to - * getmnt/getmntany if it isn't NULL. If it is NULL, - * we know it comes from libzfs_mnttab_find which can - * then get freed later. We strdup it to play it safe. - */ - if (mountpoint == NULL) - mntpt = zfs_strdup(hdl, entry.mnt_mountp); - else - mntpt = zfs_strdup(hdl, mountpoint); - - /* - * Unshare and unmount the filesystem - */ - if (zfs_unshare(zhp, mntpt, share_all_proto) != 0) { - free(mntpt); - return (-1); - } - zfs_commit_shares(NULL); - - if (unmount_one(zhp, mntpt, flags) != 0) { - free(mntpt); - (void) zfs_share(zhp, NULL); - zfs_commit_shares(NULL); - return (-1); - } - - libzfs_mnttab_remove(hdl, zhp->zfs_name); - free(mntpt); - unmounted = B_TRUE; - } - - /* - * If the MS_CRYPT flag is provided we must ensure we attempt to - * unload the dataset's key regardless of whether we did any work - * to unmount it. We only do this for encryption roots. - */ - if ((flags & MS_CRYPT) != 0 && - zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION) != ZIO_CRYPT_OFF) { - zfs_refresh_properties(zhp); - - if (zfs_crypto_get_encryption_root(zhp, &encroot, NULL) != 0 && - unmounted) { - (void) zfs_mount(zhp, NULL, 0); - return (-1); - } - - if (encroot && zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS) == - ZFS_KEYSTATUS_AVAILABLE && - zfs_crypto_unload_key(zhp) != 0) { - (void) zfs_mount(zhp, NULL, 0); - return (-1); - } - } - - zpool_disable_volume_os(zhp->zfs_name); - - return (0); -} - -/* - * Unmount this filesystem and any children inheriting the mountpoint property. - * To do this, just act like we're changing the mountpoint property, but don't - * remount the filesystems afterwards. - */ -int -zfs_unmountall(zfs_handle_t *zhp, int flags) -{ - prop_changelist_t *clp; - int ret; - - clp = changelist_gather(zhp, ZFS_PROP_MOUNTPOINT, - CL_GATHER_ITER_MOUNTED, flags); - if (clp == NULL) - return (-1); - - ret = changelist_prefix(clp); - changelist_free(clp); - - return (ret); -} - -/* - * Unshare a filesystem by mountpoint. - */ -static int -unshare_one(libzfs_handle_t *hdl, const char *name, const char *mountpoint, - enum sa_protocol proto) -{ - int err = sa_disable_share(mountpoint, proto); - if (err != SA_OK) - return (zfs_error_fmt(hdl, proto_table[proto].p_unshare_err, - dgettext(TEXT_DOMAIN, "cannot unshare '%s': %s"), - name, sa_errorstr(err))); - - return (0); -} - -/* - * Share the given filesystem according to the options in the specified - * protocol specific properties (sharenfs, sharesmb). We rely - * on "libshare" to do the dirty work for us. - */ -int -zfs_share(zfs_handle_t *zhp, const enum sa_protocol *proto) -{ - char mountpoint[ZFS_MAXPROPLEN]; - char shareopts[ZFS_MAXPROPLEN]; - char sourcestr[ZFS_MAXPROPLEN]; - const enum sa_protocol *curr_proto; - zprop_source_t sourcetype; - int err = 0; - - if (proto == NULL) - proto = share_all_proto; - - if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL, 0)) - return (0); - - for (curr_proto = proto; *curr_proto != SA_NO_PROTOCOL; curr_proto++) { - /* - * Return success if there are no share options. - */ - if (zfs_prop_get(zhp, proto_table[*curr_proto].p_prop, - shareopts, sizeof (shareopts), &sourcetype, sourcestr, - ZFS_MAXPROPLEN, B_FALSE) != 0 || - strcmp(shareopts, "off") == 0) - continue; - - /* - * If the 'zoned' property is set, then zfs_is_mountable() - * will have already bailed out if we are in the global zone. - * But local zones cannot be NFS servers, so we ignore it for - * local zones as well. - */ - if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) - continue; - - err = sa_enable_share(zfs_get_name(zhp), mountpoint, shareopts, - *curr_proto); - if (err != SA_OK) { - return (zfs_error_fmt(zhp->zfs_hdl, - proto_table[*curr_proto].p_share_err, - dgettext(TEXT_DOMAIN, "cannot share '%s: %s'"), - zfs_get_name(zhp), sa_errorstr(err))); - } - - } - return (0); -} - -/* - * Check to see if the filesystem is currently shared. - */ -boolean_t -zfs_is_shared(zfs_handle_t *zhp, char **where, - const enum sa_protocol *proto) -{ - char *mountpoint; - if (proto == NULL) - proto = share_all_proto; - - if (ZFS_IS_VOLUME(zhp)) - return (B_FALSE); - - if (!zfs_is_mounted(zhp, &mountpoint)) - return (B_FALSE); - - for (const enum sa_protocol *p = proto; *p != SA_NO_PROTOCOL; ++p) - if (sa_is_shared(mountpoint, *p)) { - if (where != NULL) - *where = mountpoint; - else - free(mountpoint); - return (B_TRUE); - } - - free(mountpoint); - return (B_FALSE); -} - -void -zfs_commit_shares(const enum sa_protocol *proto) -{ - if (proto == NULL) - proto = share_all_proto; - - for (const enum sa_protocol *p = proto; *p != SA_NO_PROTOCOL; ++p) - sa_commit_shares(*p); -} - -void -zfs_truncate_shares(const enum sa_protocol *proto) -{ - if (proto == NULL) - proto = share_all_proto; - - for (const enum sa_protocol *p = proto; *p != SA_NO_PROTOCOL; ++p) - sa_truncate_shares(*p); -} - -/* - * Unshare the given filesystem. - */ -int -zfs_unshare(zfs_handle_t *zhp, const char *mountpoint, - const enum sa_protocol *proto) -{ - libzfs_handle_t *hdl = zhp->zfs_hdl; - struct mnttab entry; - - if (proto == NULL) - proto = share_all_proto; - - if (mountpoint != NULL || ((zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) && - libzfs_mnttab_find(hdl, zfs_get_name(zhp), &entry) == 0)) { - - /* check to see if need to unmount the filesystem */ - const char *mntpt = mountpoint ?: entry.mnt_mountp; - - for (const enum sa_protocol *curr_proto = proto; - *curr_proto != SA_NO_PROTOCOL; curr_proto++) - if (sa_is_shared(mntpt, *curr_proto) && - unshare_one(hdl, zhp->zfs_name, - mntpt, *curr_proto) != 0) - return (-1); - } - - return (0); -} - -/* - * Same as zfs_unmountall(), but for NFS and SMB unshares. - */ -int -zfs_unshareall(zfs_handle_t *zhp, const enum sa_protocol *proto) -{ - prop_changelist_t *clp; - int ret; - - if (proto == NULL) - proto = share_all_proto; - - clp = changelist_gather(zhp, ZFS_PROP_SHARENFS, 0, 0); - if (clp == NULL) - return (-1); - - ret = changelist_unshare(clp, proto); - changelist_free(clp); - - return (ret); -} - -/* - * Remove the mountpoint associated with the current dataset, if necessary. - * We only remove the underlying directory if: - * - * - The mountpoint is not 'none' or 'legacy' - * - The mountpoint is non-empty - * - The mountpoint is the default or inherited - * - The 'zoned' property is set, or we're in a local zone - * - * Any other directories we leave alone. - */ -void -remove_mountpoint(zfs_handle_t *zhp) -{ - char mountpoint[ZFS_MAXPROPLEN]; - zprop_source_t source; - - if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), - &source, 0)) - return; - - if (source == ZPROP_SRC_DEFAULT || - source == ZPROP_SRC_INHERITED) { - /* - * Try to remove the directory, silently ignoring any errors. - * The filesystem may have since been removed or moved around, - * and this error isn't really useful to the administrator in - * any way. - */ - (void) rmdir(mountpoint); - } -} - -/* - * Add the given zfs handle to the cb_handles array, dynamically reallocating - * the array if it is out of space. - */ -void -libzfs_add_handle(get_all_cb_t *cbp, zfs_handle_t *zhp) -{ - if (cbp->cb_alloc == cbp->cb_used) { - size_t newsz; - zfs_handle_t **newhandles; - - newsz = cbp->cb_alloc != 0 ? cbp->cb_alloc * 2 : 64; - newhandles = zfs_realloc(zhp->zfs_hdl, - cbp->cb_handles, cbp->cb_alloc * sizeof (zfs_handle_t *), - newsz * sizeof (zfs_handle_t *)); - cbp->cb_handles = newhandles; - cbp->cb_alloc = newsz; - } - cbp->cb_handles[cbp->cb_used++] = zhp; -} - -/* - * Recursive helper function used during file system enumeration - */ -static int -zfs_iter_cb(zfs_handle_t *zhp, void *data) -{ - get_all_cb_t *cbp = data; - - if (!(zfs_get_type(zhp) & ZFS_TYPE_FILESYSTEM)) { - zfs_close(zhp); - return (0); - } - - if (zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT) == ZFS_CANMOUNT_NOAUTO) { - zfs_close(zhp); - return (0); - } - - if (zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS) == - ZFS_KEYSTATUS_UNAVAILABLE) { - zfs_close(zhp); - return (0); - } - - /* - * If this filesystem is inconsistent and has a receive resume - * token, we can not mount it. - */ - if (zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT) && - zfs_prop_get(zhp, ZFS_PROP_RECEIVE_RESUME_TOKEN, - NULL, 0, NULL, NULL, 0, B_TRUE) == 0) { - zfs_close(zhp); - return (0); - } - - libzfs_add_handle(cbp, zhp); - if (zfs_iter_filesystems_v2(zhp, 0, zfs_iter_cb, cbp) != 0) { - zfs_close(zhp); - return (-1); - } - return (0); -} - -/* - * Sort comparator that compares two mountpoint paths. We sort these paths so - * that subdirectories immediately follow their parents. This means that we - * effectively treat the '/' character as the lowest value non-nul char. - * Since filesystems from non-global zones can have the same mountpoint - * as other filesystems, the comparator sorts global zone filesystems to - * the top of the list. This means that the global zone will traverse the - * filesystem list in the correct order and can stop when it sees the - * first zoned filesystem. In a non-global zone, only the delegated - * filesystems are seen. - * - * An example sorted list using this comparator would look like: - * - * /foo - * /foo/bar - * /foo/bar/baz - * /foo/baz - * /foo.bar - * /foo (NGZ1) - * /foo (NGZ2) - * - * The mounting code depends on this ordering to deterministically iterate - * over filesystems in order to spawn parallel mount tasks. - */ -static int -mountpoint_cmp(const void *arga, const void *argb) -{ - zfs_handle_t *const *zap = arga; - zfs_handle_t *za = *zap; - zfs_handle_t *const *zbp = argb; - zfs_handle_t *zb = *zbp; - char mounta[MAXPATHLEN]; - char mountb[MAXPATHLEN]; - const char *a = mounta; - const char *b = mountb; - boolean_t gota, gotb; - uint64_t zoneda, zonedb; - - zoneda = zfs_prop_get_int(za, ZFS_PROP_ZONED); - zonedb = zfs_prop_get_int(zb, ZFS_PROP_ZONED); - if (zoneda && !zonedb) - return (1); - if (!zoneda && zonedb) - return (-1); - - gota = (zfs_get_type(za) == ZFS_TYPE_FILESYSTEM); - if (gota) { - verify(zfs_prop_get(za, ZFS_PROP_MOUNTPOINT, mounta, - sizeof (mounta), NULL, NULL, 0, B_FALSE) == 0); - } - gotb = (zfs_get_type(zb) == ZFS_TYPE_FILESYSTEM); - if (gotb) { - verify(zfs_prop_get(zb, ZFS_PROP_MOUNTPOINT, mountb, - sizeof (mountb), NULL, NULL, 0, B_FALSE) == 0); - } - - if (gota && gotb) { - while (*a != '\0' && (*a == *b)) { - a++; - b++; - } - if (*a == *b) - return (0); - if (*a == '\0') - return (-1); - if (*b == '\0') - return (1); - if (*a == '/') - return (-1); - if (*b == '/') - return (1); - return (*a < *b ? -1 : *a > *b); - } - - if (gota) - return (-1); - if (gotb) - return (1); - - /* - * If neither filesystem has a mountpoint, revert to sorting by - * dataset name. - */ - return (strcmp(zfs_get_name(za), zfs_get_name(zb))); -} - -/* - * Return true if path2 is a child of path1 or path2 equals path1 or - * path1 is "/" (path2 is always a child of "/"). - */ -static boolean_t -libzfs_path_contains(const char *path1, const char *path2) -{ - return (strcmp(path1, path2) == 0 || strcmp(path1, "/") == 0 || - (strstr(path2, path1) == path2 && path2[strlen(path1)] == '/')); -} - -/* - * Given a mountpoint specified by idx in the handles array, find the first - * non-descendent of that mountpoint and return its index. Descendant paths - * start with the parent's path. This function relies on the ordering - * enforced by mountpoint_cmp(). - */ -static int -non_descendant_idx(zfs_handle_t **handles, size_t num_handles, int idx) -{ - char parent[ZFS_MAXPROPLEN]; - char child[ZFS_MAXPROPLEN]; - int i; - - verify(zfs_prop_get(handles[idx], ZFS_PROP_MOUNTPOINT, parent, - sizeof (parent), NULL, NULL, 0, B_FALSE) == 0); - - for (i = idx + 1; i < num_handles; i++) { - verify(zfs_prop_get(handles[i], ZFS_PROP_MOUNTPOINT, child, - sizeof (child), NULL, NULL, 0, B_FALSE) == 0); - if (!libzfs_path_contains(parent, child)) - break; - } - return (i); -} - -typedef struct mnt_param { - libzfs_handle_t *mnt_hdl; - tpool_t *mnt_tp; - zfs_handle_t **mnt_zhps; /* filesystems to mount */ - size_t mnt_num_handles; - int mnt_idx; /* Index of selected entry to mount */ - zfs_iter_f mnt_func; - void *mnt_data; -} mnt_param_t; - -/* - * Allocate and populate the parameter struct for mount function, and - * schedule mounting of the entry selected by idx. - */ -static void -zfs_dispatch_mount(libzfs_handle_t *hdl, zfs_handle_t **handles, - size_t num_handles, int idx, zfs_iter_f func, void *data, tpool_t *tp) -{ - mnt_param_t *mnt_param = zfs_alloc(hdl, sizeof (mnt_param_t)); - - mnt_param->mnt_hdl = hdl; - mnt_param->mnt_tp = tp; - mnt_param->mnt_zhps = handles; - mnt_param->mnt_num_handles = num_handles; - mnt_param->mnt_idx = idx; - mnt_param->mnt_func = func; - mnt_param->mnt_data = data; - - if (tpool_dispatch(tp, zfs_mount_task, (void*)mnt_param)) { - /* Could not dispatch to thread pool; execute directly */ - zfs_mount_task((void*)mnt_param); - } -} - -/* - * This is the structure used to keep state of mounting or sharing operations - * during a call to zpool_enable_datasets(). - */ -typedef struct mount_state { - /* - * ms_mntstatus is set to -1 if any mount fails. While multiple threads - * could update this variable concurrently, no synchronization is - * needed as it's only ever set to -1. - */ - int ms_mntstatus; - int ms_mntflags; - const char *ms_mntopts; -} mount_state_t; - -static int -zfs_mount_one(zfs_handle_t *zhp, void *arg) -{ - mount_state_t *ms = arg; - int ret = 0; - - /* - * don't attempt to mount encrypted datasets with - * unloaded keys - */ - if (zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS) == - ZFS_KEYSTATUS_UNAVAILABLE) - return (0); - - if (zfs_mount(zhp, ms->ms_mntopts, ms->ms_mntflags) != 0) - ret = ms->ms_mntstatus = -1; - return (ret); -} - -static int -zfs_share_one(zfs_handle_t *zhp, void *arg) -{ - mount_state_t *ms = arg; - int ret = 0; - - if (zfs_share(zhp, NULL) != 0) - ret = ms->ms_mntstatus = -1; - return (ret); -} - -/* - * Thread pool function to mount one file system. On completion, it finds and - * schedules its children to be mounted. This depends on the sorting done in - * zfs_foreach_mountpoint(). Note that the degenerate case (chain of entries - * each descending from the previous) will have no parallelism since we always - * have to wait for the parent to finish mounting before we can schedule - * its children. - */ -static void -zfs_mount_task(void *arg) -{ - mnt_param_t *mp = arg; - int idx = mp->mnt_idx; - zfs_handle_t **handles = mp->mnt_zhps; - size_t num_handles = mp->mnt_num_handles; - char mountpoint[ZFS_MAXPROPLEN]; - - verify(zfs_prop_get(handles[idx], ZFS_PROP_MOUNTPOINT, mountpoint, - sizeof (mountpoint), NULL, NULL, 0, B_FALSE) == 0); - - if (mp->mnt_func(handles[idx], mp->mnt_data) != 0) - goto out; - - /* - * We dispatch tasks to mount filesystems with mountpoints underneath - * this one. We do this by dispatching the next filesystem with a - * descendant mountpoint of the one we just mounted, then skip all of - * its descendants, dispatch the next descendant mountpoint, and so on. - * The non_descendant_idx() function skips over filesystems that are - * descendants of the filesystem we just dispatched. - */ - for (int i = idx + 1; i < num_handles; - i = non_descendant_idx(handles, num_handles, i)) { - char child[ZFS_MAXPROPLEN]; - verify(zfs_prop_get(handles[i], ZFS_PROP_MOUNTPOINT, - child, sizeof (child), NULL, NULL, 0, B_FALSE) == 0); - - if (!libzfs_path_contains(mountpoint, child)) - break; /* not a descendant, return */ - zfs_dispatch_mount(mp->mnt_hdl, handles, num_handles, i, - mp->mnt_func, mp->mnt_data, mp->mnt_tp); - } - -out: - free(mp); -} - -/* - * Issue the func callback for each ZFS handle contained in the handles - * array. This function is used to mount all datasets, and so this function - * guarantees that filesystems for parent mountpoints are called before their - * children. As such, before issuing any callbacks, we first sort the array - * of handles by mountpoint. - * - * Callbacks are issued in one of two ways: - * - * 1. Sequentially: If the nthr argument is <= 1 or the ZFS_SERIAL_MOUNT - * environment variable is set, then we issue callbacks sequentially. - * - * 2. In parallel: If the nthr argument is > 1 and the ZFS_SERIAL_MOUNT - * environment variable is not set, then we use a tpool to dispatch threads - * to mount filesystems in parallel. This function dispatches tasks to mount - * the filesystems at the top-level mountpoints, and these tasks in turn - * are responsible for recursively mounting filesystems in their children - * mountpoints. The value of the nthr argument will be the number of worker - * threads for the thread pool. - */ -void -zfs_foreach_mountpoint(libzfs_handle_t *hdl, zfs_handle_t **handles, - size_t num_handles, zfs_iter_f func, void *data, uint_t nthr) -{ - zoneid_t zoneid = getzoneid(); - - /* - * The ZFS_SERIAL_MOUNT environment variable is an undocumented - * variable that can be used as a convenience to do a/b comparison - * of serial vs. parallel mounting. - */ - boolean_t serial_mount = nthr <= 1 || - (getenv("ZFS_SERIAL_MOUNT") != NULL); - - /* - * Sort the datasets by mountpoint. See mountpoint_cmp for details - * of how these are sorted. - */ - qsort(handles, num_handles, sizeof (zfs_handle_t *), mountpoint_cmp); - - if (serial_mount) { - for (int i = 0; i < num_handles; i++) { - func(handles[i], data); - } - return; - } - - /* - * Issue the callback function for each dataset using a parallel - * algorithm that uses a thread pool to manage threads. - */ - tpool_t *tp = tpool_create(1, nthr, 0, NULL); - - /* - * There may be multiple "top level" mountpoints outside of the pool's - * root mountpoint, e.g.: /foo /bar. Dispatch a mount task for each of - * these. - */ - for (int i = 0; i < num_handles; - i = non_descendant_idx(handles, num_handles, i)) { - /* - * Since the mountpoints have been sorted so that the zoned - * filesystems are at the end, a zoned filesystem seen from - * the global zone means that we're done. - */ - if (zoneid == GLOBAL_ZONEID && - zfs_prop_get_int(handles[i], ZFS_PROP_ZONED)) - break; - zfs_dispatch_mount(hdl, handles, num_handles, i, func, data, - tp); - } - - tpool_wait(tp); /* wait for all scheduled mounts to complete */ - tpool_destroy(tp); -} - -/* - * Mount and share all datasets within the given pool. This assumes that no - * datasets within the pool are currently mounted. nthr will be number of - * worker threads to use while mounting datasets. - */ -int -zpool_enable_datasets(zpool_handle_t *zhp, const char *mntopts, int flags, - uint_t nthr) -{ - get_all_cb_t cb = { 0 }; - mount_state_t ms = { 0 }; - zfs_handle_t *zfsp; - int ret = 0; - - if ((zfsp = zfs_open(zhp->zpool_hdl, zhp->zpool_name, - ZFS_TYPE_DATASET)) == NULL) - goto out; - - /* - * Gather all non-snapshot datasets within the pool. Start by adding - * the root filesystem for this pool to the list, and then iterate - * over all child filesystems. - */ - libzfs_add_handle(&cb, zfsp); - if (zfs_iter_filesystems_v2(zfsp, 0, zfs_iter_cb, &cb) != 0) - goto out; - - /* - * Mount all filesystems - */ - ms.ms_mntopts = mntopts; - ms.ms_mntflags = flags; - zfs_foreach_mountpoint(zhp->zpool_hdl, cb.cb_handles, cb.cb_used, - zfs_mount_one, &ms, nthr); - if (ms.ms_mntstatus != 0) - ret = EZFS_MOUNTFAILED; - - /* - * Share all filesystems that need to be shared. This needs to be - * a separate pass because libshare is not mt-safe, and so we need - * to share serially. - */ - ms.ms_mntstatus = 0; - zfs_foreach_mountpoint(zhp->zpool_hdl, cb.cb_handles, cb.cb_used, - zfs_share_one, &ms, 1); - if (ms.ms_mntstatus != 0) - ret = EZFS_SHAREFAILED; - else - zfs_commit_shares(NULL); - -out: - for (int i = 0; i < cb.cb_used; i++) - zfs_close(cb.cb_handles[i]); - free(cb.cb_handles); - - return (ret); -} - -struct sets_s { - char *mountpoint; - zfs_handle_t *dataset; -}; - -static int -mountpoint_compare(const void *a, const void *b) -{ - const struct sets_s *mounta = (struct sets_s *)a; - const struct sets_s *mountb = (struct sets_s *)b; - - return (strcmp(mountb->mountpoint, mounta->mountpoint)); -} - -/* - * Unshare and unmount all datasets within the given pool. We don't want to - * rely on traversing the DSL to discover the filesystems within the pool, - * because this may be expensive (if not all of them are mounted), and can fail - * arbitrarily (on I/O error, for example). Instead, we walk /proc/self/mounts - * and gather all the filesystems that are currently mounted. - */ -int -zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force) -{ - int used, alloc; - FILE *mnttab; - struct mnttab entry; - size_t namelen; - struct sets_s *sets = NULL; - libzfs_handle_t *hdl = zhp->zpool_hdl; - int i; - int ret = -1; - int flags = (force ? MS_FORCE : 0); - - namelen = strlen(zhp->zpool_name); - - if ((mnttab = fopen(MNTTAB, "re")) == NULL) - return (ENOENT); - - used = alloc = 0; - while (getmntent(mnttab, &entry) == 0) { - /* - * Ignore non-ZFS entries. - */ - if (entry.mnt_fstype == NULL || - strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) - continue; - - /* - * Ignore filesystems not within this pool. - */ - if (entry.mnt_mountp == NULL || - strncmp(entry.mnt_special, zhp->zpool_name, namelen) != 0 || - (entry.mnt_special[namelen] != '/' && - entry.mnt_special[namelen] != '\0')) - continue; - - /* - * At this point we've found a filesystem within our pool. Add - * it to our growing list. - */ - if (used == alloc) { - if (alloc == 0) { - sets = zfs_alloc(hdl, - 8 * sizeof (struct sets_s)); - alloc = 8; - } else { - sets = zfs_realloc(hdl, sets, - alloc * sizeof (struct sets_s), - alloc * 2 * sizeof (struct sets_s)); - - alloc *= 2; - } - } - - sets[used].mountpoint = zfs_strdup(hdl, entry.mnt_mountp); - - /* - * This is allowed to fail, in case there is some I/O error. It - * is only used to determine if we need to remove the underlying - * mountpoint, so failure is not fatal. - */ - sets[used].dataset = make_dataset_handle(hdl, - entry.mnt_special); - - used++; - } - - /* - * At this point, we have the entire list of filesystems, so sort it by - * mountpoint. - */ - if (used != 0) - qsort(sets, used, sizeof (struct sets_s), mountpoint_compare); - - /* - * Walk through and first unshare everything. - */ - for (i = 0; i < used; i++) { - for (enum sa_protocol p = 0; p < SA_PROTOCOL_COUNT; ++p) { - if (sa_is_shared(sets[i].mountpoint, p) && - unshare_one(hdl, sets[i].mountpoint, - sets[i].mountpoint, p) != 0) - goto out; - } - } - zfs_commit_shares(NULL); - - /* - * Now unmount everything, removing the underlying directories as - * appropriate. - */ - for (i = 0; i < used; i++) { - if (unmount_one(sets[i].dataset, sets[i].mountpoint, - flags) != 0) - goto out; - } - - for (i = 0; i < used; i++) { - if (sets[i].dataset) - remove_mountpoint(sets[i].dataset); - } - - zpool_disable_datasets_os(zhp, force); - - ret = 0; -out: - (void) fclose(mnttab); - for (i = 0; i < used; i++) { - if (sets[i].dataset) - zfs_close(sets[i].dataset); - free(sets[i].mountpoint); - } - free(sets); - - return (ret); -} diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c deleted file mode 100644 index ce154ae1a4cd..000000000000 --- a/lib/libzfs/libzfs_pool.c +++ /dev/null @@ -1,5763 +0,0 @@ -// SPDX-License-Identifier: CDDL-1.0 -/* - * 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 - */ - -/* - * Copyright 2015 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2024 by Delphix. All rights reserved. - * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com> - * Copyright (c) 2018 Datto Inc. - * Copyright (c) 2017 Open-E, Inc. All Rights Reserved. - * Copyright (c) 2017, Intel Corporation. - * Copyright (c) 2018, loli10K <ezomori.nozomu@gmail.com> - * Copyright (c) 2021, Colm Buckley <colm@tuatha.org> - * Copyright (c) 2021, 2023, Klara Inc. - * Copyright (c) 2025 Hewlett Packard Enterprise Development LP. - */ - -#include <errno.h> -#include <libintl.h> -#include <stdio.h> -#include <stdlib.h> -#include <strings.h> -#include <unistd.h> -#include <libgen.h> -#include <zone.h> -#include <sys/stat.h> -#include <sys/efi_partition.h> -#include <sys/systeminfo.h> -#include <sys/zfs_ioctl.h> -#include <sys/zfs_sysfs.h> -#include <sys/vdev_disk.h> -#include <sys/types.h> -#include <dlfcn.h> -#include <libzutil.h> -#include <fcntl.h> - -#include "zfs_namecheck.h" -#include "zfs_prop.h" -#include "libzfs_impl.h" -#include "zfs_comutil.h" -#include "zfeature_common.h" - -static boolean_t zpool_vdev_is_interior(const char *name); - -typedef struct prop_flags { - unsigned int create:1; /* Validate property on creation */ - unsigned int import:1; /* Validate property on import */ - unsigned int vdevprop:1; /* Validate property as a VDEV property */ -} prop_flags_t; - -/* - * ==================================================================== - * zpool property functions - * ==================================================================== - */ - -static int -zpool_get_all_props(zpool_handle_t *zhp) -{ - zfs_cmd_t zc = {"\0"}; - libzfs_handle_t *hdl = zhp->zpool_hdl; - - (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); - - if (zhp->zpool_n_propnames > 0) { - nvlist_t *innvl = fnvlist_alloc(); - fnvlist_add_string_array(innvl, ZPOOL_GET_PROPS_NAMES, - zhp->zpool_propnames, zhp->zpool_n_propnames); - zcmd_write_src_nvlist(hdl, &zc, innvl); - fnvlist_free(innvl); - } - - zcmd_alloc_dst_nvlist(hdl, &zc, 0); - - while (zfs_ioctl(hdl, ZFS_IOC_POOL_GET_PROPS, &zc) != 0) { - if (errno == ENOMEM) - zcmd_expand_dst_nvlist(hdl, &zc); - else { - zcmd_free_nvlists(&zc); - return (-1); - } - } - - if (zcmd_read_dst_nvlist(hdl, &zc, &zhp->zpool_props) != 0) { - zcmd_free_nvlists(&zc); - return (-1); - } - - zcmd_free_nvlists(&zc); - - return (0); -} - -int -zpool_props_refresh(zpool_handle_t *zhp) -{ - nvlist_t *old_props; - - old_props = zhp->zpool_props; - - if (zpool_get_all_props(zhp) != 0) - return (-1); - - nvlist_free(old_props); - return (0); -} - -static const char * -zpool_get_prop_string(zpool_handle_t *zhp, zpool_prop_t prop, - zprop_source_t *src) -{ - nvlist_t *nv, *nvl; - const char *value; - zprop_source_t source; - - nvl = zhp->zpool_props; - if (nvlist_lookup_nvlist(nvl, zpool_prop_to_name(prop), &nv) == 0) { - source = fnvlist_lookup_uint64(nv, ZPROP_SOURCE); - value = fnvlist_lookup_string(nv, ZPROP_VALUE); - } else { - source = ZPROP_SRC_DEFAULT; - if ((value = zpool_prop_default_string(prop)) == NULL) - value = "-"; - } - - if (src) - *src = source; - - return (value); -} - -uint64_t -zpool_get_prop_int(zpool_handle_t *zhp, zpool_prop_t prop, zprop_source_t *src) -{ - nvlist_t *nv, *nvl; - uint64_t value; - zprop_source_t source; - - if (zhp->zpool_props == NULL && zpool_get_all_props(zhp)) { - /* - * zpool_get_all_props() has most likely failed because - * the pool is faulted, but if all we need is the top level - * vdev's guid then get it from the zhp config nvlist. - */ - if ((prop == ZPOOL_PROP_GUID) && - (nvlist_lookup_nvlist(zhp->zpool_config, - ZPOOL_CONFIG_VDEV_TREE, &nv) == 0) && - (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &value) - == 0)) { - return (value); - } - return (zpool_prop_default_numeric(prop)); - } - - nvl = zhp->zpool_props; - if (nvlist_lookup_nvlist(nvl, zpool_prop_to_name(prop), &nv) == 0) { - source = fnvlist_lookup_uint64(nv, ZPROP_SOURCE); - value = fnvlist_lookup_uint64(nv, ZPROP_VALUE); - } else { - source = ZPROP_SRC_DEFAULT; - value = zpool_prop_default_numeric(prop); - } - - if (src) - *src = source; - - return (value); -} - -/* - * Map VDEV STATE to printed strings. - */ -const char * -zpool_state_to_name(vdev_state_t state, vdev_aux_t aux) -{ - switch (state) { - case VDEV_STATE_CLOSED: - case VDEV_STATE_OFFLINE: - return (gettext("OFFLINE")); - case VDEV_STATE_REMOVED: - return (gettext("REMOVED")); - case VDEV_STATE_CANT_OPEN: - if (aux == VDEV_AUX_CORRUPT_DATA || aux == VDEV_AUX_BAD_LOG) - return (gettext("FAULTED")); - else if (aux == VDEV_AUX_SPLIT_POOL) - return (gettext("SPLIT")); - else - return (gettext("UNAVAIL")); - case VDEV_STATE_FAULTED: - return (gettext("FAULTED")); - case VDEV_STATE_DEGRADED: - return (gettext("DEGRADED")); - case VDEV_STATE_HEALTHY: - return (gettext("ONLINE")); - - default: - break; - } - - return (gettext("UNKNOWN")); -} - -/* - * Map POOL STATE to printed strings. - */ -const char * -zpool_pool_state_to_name(pool_state_t state) -{ - switch (state) { - default: - break; - case POOL_STATE_ACTIVE: - return (gettext("ACTIVE")); - case POOL_STATE_EXPORTED: - return (gettext("EXPORTED")); - case POOL_STATE_DESTROYED: - return (gettext("DESTROYED")); - case POOL_STATE_SPARE: - return (gettext("SPARE")); - case POOL_STATE_L2CACHE: - return (gettext("L2CACHE")); - case POOL_STATE_UNINITIALIZED: - return (gettext("UNINITIALIZED")); - case POOL_STATE_UNAVAIL: - return (gettext("UNAVAIL")); - case POOL_STATE_POTENTIALLY_ACTIVE: - return (gettext("POTENTIALLY_ACTIVE")); - } - - return (gettext("UNKNOWN")); -} - -/* - * Given a pool handle, return the pool health string ("ONLINE", "DEGRADED", - * "SUSPENDED", etc). - */ -const char * -zpool_get_state_str(zpool_handle_t *zhp) -{ - zpool_errata_t errata; - zpool_status_t status; - const char *str; - - status = zpool_get_status(zhp, NULL, &errata); - - if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { - str = gettext("FAULTED"); - } else if (status == ZPOOL_STATUS_IO_FAILURE_WAIT || - status == ZPOOL_STATUS_IO_FAILURE_CONTINUE || - status == ZPOOL_STATUS_IO_FAILURE_MMP) { - str = gettext("SUSPENDED"); - } else { - nvlist_t *nvroot = fnvlist_lookup_nvlist( - zpool_get_config(zhp, NULL), ZPOOL_CONFIG_VDEV_TREE); - uint_t vsc; - vdev_stat_t *vs = (vdev_stat_t *)fnvlist_lookup_uint64_array( - nvroot, ZPOOL_CONFIG_VDEV_STATS, &vsc); - str = zpool_state_to_name(vs->vs_state, vs->vs_aux); - } - return (str); -} - -/* - * Get a zpool property value for 'prop' and return the value in - * a pre-allocated buffer. - */ -int -zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, - size_t len, zprop_source_t *srctype, boolean_t literal) -{ - uint64_t intval; - const char *strval; - zprop_source_t src = ZPROP_SRC_NONE; - - if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { - switch (prop) { - case ZPOOL_PROP_NAME: - (void) strlcpy(buf, zpool_get_name(zhp), len); - break; - - case ZPOOL_PROP_HEALTH: - (void) strlcpy(buf, zpool_get_state_str(zhp), len); - break; - - case ZPOOL_PROP_GUID: - intval = zpool_get_prop_int(zhp, prop, &src); - (void) snprintf(buf, len, "%llu", (u_longlong_t)intval); - break; - - case ZPOOL_PROP_ALTROOT: - case ZPOOL_PROP_CACHEFILE: - case ZPOOL_PROP_COMMENT: - case ZPOOL_PROP_COMPATIBILITY: - if (zhp->zpool_props != NULL || - zpool_get_all_props(zhp) == 0) { - (void) strlcpy(buf, - zpool_get_prop_string(zhp, prop, &src), - len); - break; - } - zfs_fallthrough; - default: - (void) strlcpy(buf, "-", len); - break; - } - - if (srctype != NULL) - *srctype = src; - return (0); - } - - /* - * ZPOOL_PROP_DEDUPCACHED can be fetched by name only using - * the ZPOOL_GET_PROPS_NAMES mechanism - */ - if (prop == ZPOOL_PROP_DEDUPCACHED) { - zpool_add_propname(zhp, ZPOOL_DEDUPCACHED_PROP_NAME); - (void) zpool_props_refresh(zhp); - } - - if (zhp->zpool_props == NULL && zpool_get_all_props(zhp) && - prop != ZPOOL_PROP_NAME) - return (-1); - - switch (zpool_prop_get_type(prop)) { - case PROP_TYPE_STRING: - (void) strlcpy(buf, zpool_get_prop_string(zhp, prop, &src), - len); - break; - - case PROP_TYPE_NUMBER: - intval = zpool_get_prop_int(zhp, prop, &src); - - switch (prop) { - case ZPOOL_PROP_DEDUP_TABLE_QUOTA: - /* - * If dedup quota is 0, we translate this into 'none' - * (unless literal is set). And if it is UINT64_MAX - * we translate that as 'automatic' (limit to size of - * the dedicated dedup VDEV. Otherwise, fall throught - * into the regular number formating. - */ - if (intval == 0) { - (void) strlcpy(buf, literal ? "0" : "none", - len); - break; - } else if (intval == UINT64_MAX) { - (void) strlcpy(buf, "auto", len); - break; - } - zfs_fallthrough; - - case ZPOOL_PROP_SIZE: - case ZPOOL_PROP_ALLOCATED: - case ZPOOL_PROP_FREE: - case ZPOOL_PROP_FREEING: - case ZPOOL_PROP_LEAKED: - case ZPOOL_PROP_ASHIFT: - case ZPOOL_PROP_MAXBLOCKSIZE: - case ZPOOL_PROP_MAXDNODESIZE: - case ZPOOL_PROP_BCLONESAVED: - case ZPOOL_PROP_BCLONEUSED: - case ZPOOL_PROP_DEDUP_TABLE_SIZE: - case ZPOOL_PROP_DEDUPCACHED: - if (literal) - (void) snprintf(buf, len, "%llu", - (u_longlong_t)intval); - else - (void) zfs_nicenum(intval, buf, len); - break; - - case ZPOOL_PROP_EXPANDSZ: - case ZPOOL_PROP_CHECKPOINT: - if (intval == 0) { - (void) strlcpy(buf, "-", len); - } else if (literal) { - (void) snprintf(buf, len, "%llu", - (u_longlong_t)intval); - } else { - (void) zfs_nicebytes(intval, buf, len); - } - break; - - case ZPOOL_PROP_CAPACITY: - if (literal) { - (void) snprintf(buf, len, "%llu", - (u_longlong_t)intval); - } else { - (void) snprintf(buf, len, "%llu%%", - (u_longlong_t)intval); - } - break; - - case ZPOOL_PROP_FRAGMENTATION: - if (intval == UINT64_MAX) { - (void) strlcpy(buf, "-", len); - } else if (literal) { - (void) snprintf(buf, len, "%llu", - (u_longlong_t)intval); - } else { - (void) snprintf(buf, len, "%llu%%", - (u_longlong_t)intval); - } - break; - - case ZPOOL_PROP_BCLONERATIO: - case ZPOOL_PROP_DEDUPRATIO: - if (literal) - (void) snprintf(buf, len, "%llu.%02llu", - (u_longlong_t)(intval / 100), - (u_longlong_t)(intval % 100)); - else - (void) snprintf(buf, len, "%llu.%02llux", - (u_longlong_t)(intval / 100), - (u_longlong_t)(intval % 100)); - break; - - case ZPOOL_PROP_HEALTH: - (void) strlcpy(buf, zpool_get_state_str(zhp), len); - break; - case ZPOOL_PROP_VERSION: - if (intval >= SPA_VERSION_FEATURES) { - (void) snprintf(buf, len, "-"); - break; - } - zfs_fallthrough; - default: - (void) snprintf(buf, len, "%llu", (u_longlong_t)intval); - } - break; - - case PROP_TYPE_INDEX: - intval = zpool_get_prop_int(zhp, prop, &src); - if (zpool_prop_index_to_string(prop, intval, &strval) - != 0) - return (-1); - (void) strlcpy(buf, strval, len); - break; - - default: - abort(); - } - - if (srctype) - *srctype = src; - - return (0); -} - -/* - * Get a zpool property value for 'propname' and return the value in - * a pre-allocated buffer. - */ -int -zpool_get_userprop(zpool_handle_t *zhp, const char *propname, char *buf, - size_t len, zprop_source_t *srctype) -{ - nvlist_t *nv; - uint64_t ival; - const char *value; - zprop_source_t source = ZPROP_SRC_LOCAL; - - if (zhp->zpool_props == NULL) - zpool_get_all_props(zhp); - - if (nvlist_lookup_nvlist(zhp->zpool_props, propname, &nv) == 0) { - if (nvlist_lookup_uint64(nv, ZPROP_SOURCE, &ival) == 0) - source = ival; - verify(nvlist_lookup_string(nv, ZPROP_VALUE, &value) == 0); - } else { - source = ZPROP_SRC_DEFAULT; - value = "-"; - } - - if (srctype) - *srctype = source; - - (void) strlcpy(buf, value, len); - - return (0); -} - -/* - * Check if the bootfs name has the same pool name as it is set to. - * Assuming bootfs is a valid dataset name. - */ -static boolean_t -bootfs_name_valid(const char *pool, const char *bootfs) -{ - int len = strlen(pool); - if (bootfs[0] == '\0') - return (B_TRUE); - - if (!zfs_name_valid(bootfs, ZFS_TYPE_FILESYSTEM|ZFS_TYPE_SNAPSHOT)) - return (B_FALSE); - - if (strncmp(pool, bootfs, len) == 0 && - (bootfs[len] == '/' || bootfs[len] == '\0')) - return (B_TRUE); - - return (B_FALSE); -} - -/* - * Given an nvlist of zpool properties to be set, validate that they are - * correct, and parse any numeric properties (index, boolean, etc) if they are - * specified as strings. - */ -static nvlist_t * -zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname, - nvlist_t *props, uint64_t version, prop_flags_t flags, char *errbuf) -{ - nvpair_t *elem; - nvlist_t *retprops; - zpool_prop_t prop; - const char *strval; - uint64_t intval; - const char *check; - struct stat64 statbuf; - zpool_handle_t *zhp; - char *parent, *slash; - char report[1024]; - - if (nvlist_alloc(&retprops, NV_UNIQUE_NAME, 0) != 0) { - (void) no_memory(hdl); - return (NULL); - } - - elem = NULL; - while ((elem = nvlist_next_nvpair(props, elem)) != NULL) { - const char *propname = nvpair_name(elem); - - if (flags.vdevprop && zpool_prop_vdev(propname)) { - vdev_prop_t vprop = vdev_name_to_prop(propname); - - if (vdev_prop_readonly(vprop)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' " - "is readonly"), propname); - (void) zfs_error(hdl, EZFS_PROPREADONLY, - errbuf); - goto error; - } - - if (zprop_parse_value(hdl, elem, vprop, ZFS_TYPE_VDEV, - retprops, &strval, &intval, errbuf) != 0) - goto error; - - continue; - } else if (flags.vdevprop && vdev_prop_user(propname)) { - if (nvlist_add_nvpair(retprops, elem) != 0) { - (void) no_memory(hdl); - goto error; - } - continue; - } else if (flags.vdevprop) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "invalid property: '%s'"), propname); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - - prop = zpool_name_to_prop(propname); - if (prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname)) { - int err; - char *fname = strchr(propname, '@') + 1; - - err = zfeature_lookup_name(fname, NULL); - if (err != 0) { - ASSERT3U(err, ==, ENOENT); - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "feature '%s' unsupported by kernel"), - fname); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - - if (nvpair_type(elem) != DATA_TYPE_STRING) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "'%s' must be a string"), propname); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - - (void) nvpair_value_string(elem, &strval); - if (strcmp(strval, ZFS_FEATURE_ENABLED) != 0 && - strcmp(strval, ZFS_FEATURE_DISABLED) != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "property '%s' can only be set to " - "'enabled' or 'disabled'"), propname); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - - if (!flags.create && - strcmp(strval, ZFS_FEATURE_DISABLED) == 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "property '%s' can only be set to " - "'disabled' at creation time"), propname); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - - if (nvlist_add_uint64(retprops, propname, 0) != 0) { - (void) no_memory(hdl); - goto error; - } - continue; - } else if (prop == ZPOOL_PROP_INVAL && - zfs_prop_user(propname)) { - /* - * This is a user property: make sure it's a - * string, and that it's less than ZAP_MAXNAMELEN. - */ - if (nvpair_type(elem) != DATA_TYPE_STRING) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "'%s' must be a string"), propname); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - - if (strlen(nvpair_name(elem)) >= ZAP_MAXNAMELEN) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "property name '%s' is too long"), - propname); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - - (void) nvpair_value_string(elem, &strval); - - if (strlen(strval) >= ZFS_MAXPROPLEN) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "property value '%s' is too long"), - strval); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - - if (nvlist_add_string(retprops, propname, - strval) != 0) { - (void) no_memory(hdl); - goto error; - } - - continue; - } - - /* - * Make sure this property is valid and applies to this type. - */ - if (prop == ZPOOL_PROP_INVAL) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "invalid property '%s'"), propname); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - - if (zpool_prop_readonly(prop)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' " - "is readonly"), propname); - (void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf); - goto error; - } - - if (!flags.create && zpool_prop_setonce(prop)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "property '%s' can only be set at " - "creation time"), propname); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - - if (zprop_parse_value(hdl, elem, prop, ZFS_TYPE_POOL, retprops, - &strval, &intval, errbuf) != 0) - goto error; - - /* - * Perform additional checking for specific properties. - */ - switch (prop) { - case ZPOOL_PROP_VERSION: - if (intval < version || - !SPA_VERSION_IS_SUPPORTED(intval)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "property '%s' number %llu is invalid."), - propname, (unsigned long long)intval); - (void) zfs_error(hdl, EZFS_BADVERSION, errbuf); - goto error; - } - break; - - case ZPOOL_PROP_ASHIFT: - if (intval != 0 && - (intval < ASHIFT_MIN || intval > ASHIFT_MAX)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "property '%s' number %llu is invalid, " - "only values between %" PRId32 " and %" - PRId32 " are allowed."), - propname, (unsigned long long)intval, - ASHIFT_MIN, ASHIFT_MAX); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - break; - - case ZPOOL_PROP_BOOTFS: - if (flags.create || flags.import) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "property '%s' cannot be set at creation " - "or import time"), propname); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - - if (version < SPA_VERSION_BOOTFS) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "pool must be upgraded to support " - "'%s' property"), propname); - (void) zfs_error(hdl, EZFS_BADVERSION, errbuf); - goto error; - } - - /* - * bootfs property value has to be a dataset name and - * the dataset has to be in the same pool as it sets to. - */ - if (!bootfs_name_valid(poolname, strval)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' " - "is an invalid name"), strval); - (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf); - goto error; - } - - if ((zhp = zpool_open_canfail(hdl, poolname)) == NULL) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "could not open pool '%s'"), poolname); - (void) zfs_error(hdl, EZFS_OPENFAILED, errbuf); - goto error; - } - zpool_close(zhp); - break; - - case ZPOOL_PROP_ALTROOT: - if (!flags.create && !flags.import) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "property '%s' can only be set during pool " - "creation or import"), propname); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - - if (strval[0] != '/') { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "bad alternate root '%s'"), strval); - (void) zfs_error(hdl, EZFS_BADPATH, errbuf); - goto error; - } - break; - - case ZPOOL_PROP_CACHEFILE: - if (strval[0] == '\0') - break; - - if (strcmp(strval, "none") == 0) - break; - - if (strval[0] != '/') { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "property '%s' must be empty, an " - "absolute path, or 'none'"), propname); - (void) zfs_error(hdl, EZFS_BADPATH, errbuf); - goto error; - } - - parent = strdup(strval); - if (parent == NULL) { - (void) zfs_error(hdl, EZFS_NOMEM, errbuf); - goto error; - } - slash = strrchr(parent, '/'); - - if (slash[1] == '\0' || strcmp(slash, "/.") == 0 || - strcmp(slash, "/..") == 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "'%s' is not a valid file"), parent); - (void) zfs_error(hdl, EZFS_BADPATH, errbuf); - free(parent); - goto error; - } - - *slash = '\0'; - - if (parent[0] != '\0' && - (stat64(parent, &statbuf) != 0 || - !S_ISDIR(statbuf.st_mode))) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "'%s' is not a valid directory"), - parent); - (void) zfs_error(hdl, EZFS_BADPATH, errbuf); - free(parent); - goto error; - } - free(parent); - - break; - - case ZPOOL_PROP_COMPATIBILITY: - switch (zpool_load_compat(strval, NULL, report, 1024)) { - case ZPOOL_COMPATIBILITY_OK: - case ZPOOL_COMPATIBILITY_WARNTOKEN: - break; - case ZPOOL_COMPATIBILITY_BADFILE: - case ZPOOL_COMPATIBILITY_BADTOKEN: - case ZPOOL_COMPATIBILITY_NOFILES: - zfs_error_aux(hdl, "%s", report); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - break; - - case ZPOOL_PROP_COMMENT: - for (check = strval; *check != '\0'; check++) { - if (!isprint(*check)) { - zfs_error_aux(hdl, - dgettext(TEXT_DOMAIN, - "comment may only have printable " - "characters")); - (void) zfs_error(hdl, EZFS_BADPROP, - errbuf); - goto error; - } - } - if (strlen(strval) > ZPROP_MAX_COMMENT) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "comment must not exceed %d characters"), - ZPROP_MAX_COMMENT); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - break; - case ZPOOL_PROP_READONLY: - if (!flags.import) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "property '%s' can only be set at " - "import time"), propname); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - break; - case ZPOOL_PROP_MULTIHOST: - if (get_system_hostid() == 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "requires a non-zero system hostid")); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - break; - case ZPOOL_PROP_DEDUPDITTO: - printf("Note: property '%s' no longer has " - "any effect\n", propname); - break; - - default: - break; - } - } - - return (retprops); -error: - nvlist_free(retprops); - return (NULL); -} - -/* - * Set zpool property : propname=propval. - */ -int -zpool_set_prop(zpool_handle_t *zhp, const char *propname, const char *propval) -{ - zfs_cmd_t zc = {"\0"}; - int ret; - char errbuf[ERRBUFLEN]; - nvlist_t *nvl = NULL; - nvlist_t *realprops; - uint64_t version; - prop_flags_t flags = { 0 }; - - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot set property for '%s'"), - zhp->zpool_name); - - if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) - return (no_memory(zhp->zpool_hdl)); - - if (nvlist_add_string(nvl, propname, propval) != 0) { - nvlist_free(nvl); - return (no_memory(zhp->zpool_hdl)); - } - - version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL); - if ((realprops = zpool_valid_proplist(zhp->zpool_hdl, - zhp->zpool_name, nvl, version, flags, errbuf)) == NULL) { - nvlist_free(nvl); - return (-1); - } - - nvlist_free(nvl); - nvl = realprops; - - /* - * Execute the corresponding ioctl() to set this property. - */ - (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); - - zcmd_write_src_nvlist(zhp->zpool_hdl, &zc, nvl); - - ret = zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_SET_PROPS, &zc); - - zcmd_free_nvlists(&zc); - nvlist_free(nvl); - - if (ret) - (void) zpool_standard_error(zhp->zpool_hdl, errno, errbuf); - else - (void) zpool_props_refresh(zhp); - - return (ret); -} - -int -zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp, - zfs_type_t type, boolean_t literal) -{ - libzfs_handle_t *hdl = zhp->zpool_hdl; - zprop_list_t *entry; - char buf[ZFS_MAXPROPLEN]; - nvlist_t *features = NULL; - nvpair_t *nvp; - zprop_list_t **last; - boolean_t firstexpand = (NULL == *plp); - int i; - - if (zprop_expand_list(hdl, plp, type) != 0) - return (-1); - - if (type == ZFS_TYPE_VDEV) - return (0); - - last = plp; - while (*last != NULL) - last = &(*last)->pl_next; - - if ((*plp)->pl_all) - features = zpool_get_features(zhp); - - if ((*plp)->pl_all && firstexpand) { - /* Handle userprops in the all properties case */ - if (zhp->zpool_props == NULL && zpool_props_refresh(zhp)) - return (-1); - - nvp = NULL; - while ((nvp = nvlist_next_nvpair(zhp->zpool_props, nvp)) != - NULL) { - const char *propname = nvpair_name(nvp); - - if (!zfs_prop_user(propname)) - continue; - - entry = zfs_alloc(hdl, sizeof (zprop_list_t)); - entry->pl_prop = ZPROP_USERPROP; - entry->pl_user_prop = zfs_strdup(hdl, propname); - entry->pl_width = strlen(entry->pl_user_prop); - entry->pl_all = B_TRUE; - - *last = entry; - last = &entry->pl_next; - } - - for (i = 0; i < SPA_FEATURES; i++) { - entry = zfs_alloc(hdl, sizeof (zprop_list_t)); - entry->pl_prop = ZPROP_USERPROP; - entry->pl_user_prop = zfs_asprintf(hdl, "feature@%s", - spa_feature_table[i].fi_uname); - entry->pl_width = strlen(entry->pl_user_prop); - entry->pl_all = B_TRUE; - - *last = entry; - last = &entry->pl_next; - } - } - - /* add any unsupported features */ - for (nvp = nvlist_next_nvpair(features, NULL); - nvp != NULL; nvp = nvlist_next_nvpair(features, nvp)) { - char *propname; - boolean_t found; - - if (zfeature_is_supported(nvpair_name(nvp))) - continue; - - propname = zfs_asprintf(hdl, "unsupported@%s", - nvpair_name(nvp)); - - /* - * Before adding the property to the list make sure that no - * other pool already added the same property. - */ - found = B_FALSE; - entry = *plp; - while (entry != NULL) { - if (entry->pl_user_prop != NULL && - strcmp(propname, entry->pl_user_prop) == 0) { - found = B_TRUE; - break; - } - entry = entry->pl_next; - } - if (found) { - free(propname); - continue; - } - - entry = zfs_alloc(hdl, sizeof (zprop_list_t)); - entry->pl_prop = ZPROP_USERPROP; - entry->pl_user_prop = propname; - entry->pl_width = strlen(entry->pl_user_prop); - entry->pl_all = B_TRUE; - - *last = entry; - last = &entry->pl_next; - } - - for (entry = *plp; entry != NULL; entry = entry->pl_next) { - if (entry->pl_fixed && !literal) - continue; - - if (entry->pl_prop != ZPROP_USERPROP && - zpool_get_prop(zhp, entry->pl_prop, buf, sizeof (buf), - NULL, literal) == 0) { - if (strlen(buf) > entry->pl_width) - entry->pl_width = strlen(buf); - } else if (entry->pl_prop == ZPROP_INVAL && - zfs_prop_user(entry->pl_user_prop) && - zpool_get_userprop(zhp, entry->pl_user_prop, buf, - sizeof (buf), NULL) == 0) { - if (strlen(buf) > entry->pl_width) - entry->pl_width = strlen(buf); - } - } - - return (0); -} - -int -vdev_expand_proplist(zpool_handle_t *zhp, const char *vdevname, - zprop_list_t **plp) -{ - zprop_list_t *entry; - char buf[ZFS_MAXPROPLEN]; - const char *strval = NULL; - int err = 0; - nvpair_t *elem = NULL; - nvlist_t *vprops = NULL; - nvlist_t *propval = NULL; - const char *propname; - vdev_prop_t prop; - zprop_list_t **last; - - for (entry = *plp; entry != NULL; entry = entry->pl_next) { - if (entry->pl_fixed) - continue; - - if (zpool_get_vdev_prop(zhp, vdevname, entry->pl_prop, - entry->pl_user_prop, buf, sizeof (buf), NULL, - B_FALSE) == 0) { - if (strlen(buf) > entry->pl_width) - entry->pl_width = strlen(buf); - } - if (entry->pl_prop == VDEV_PROP_NAME && - strlen(vdevname) > entry->pl_width) - entry->pl_width = strlen(vdevname); - } - - /* Handle the all properties case */ - last = plp; - if (*last != NULL && (*last)->pl_all == B_TRUE) { - while (*last != NULL) - last = &(*last)->pl_next; - - err = zpool_get_all_vdev_props(zhp, vdevname, &vprops); - if (err != 0) - return (err); - - while ((elem = nvlist_next_nvpair(vprops, elem)) != NULL) { - propname = nvpair_name(elem); - - /* Skip properties that are not user defined */ - if ((prop = vdev_name_to_prop(propname)) != - VDEV_PROP_USERPROP) - continue; - - if (nvpair_value_nvlist(elem, &propval) != 0) - continue; - - strval = fnvlist_lookup_string(propval, ZPROP_VALUE); - - entry = zfs_alloc(zhp->zpool_hdl, - sizeof (zprop_list_t)); - entry->pl_prop = prop; - entry->pl_user_prop = zfs_strdup(zhp->zpool_hdl, - propname); - entry->pl_width = strlen(strval); - entry->pl_all = B_TRUE; - *last = entry; - last = &entry->pl_next; - } - } - - return (0); -} - -/* - * Get the state for the given feature on the given ZFS pool. - */ -int -zpool_prop_get_feature(zpool_handle_t *zhp, const char *propname, char *buf, - size_t len) -{ - uint64_t refcount; - boolean_t found = B_FALSE; - nvlist_t *features = zpool_get_features(zhp); - boolean_t supported; - const char *feature = strchr(propname, '@') + 1; - - supported = zpool_prop_feature(propname); - ASSERT(supported || zpool_prop_unsupported(propname)); - - /* - * Convert from feature name to feature guid. This conversion is - * unnecessary for unsupported@... properties because they already - * use guids. - */ - if (supported) { - int ret; - spa_feature_t fid; - - ret = zfeature_lookup_name(feature, &fid); - if (ret != 0) { - (void) strlcpy(buf, "-", len); - return (ENOTSUP); - } - feature = spa_feature_table[fid].fi_guid; - } - - if (nvlist_lookup_uint64(features, feature, &refcount) == 0) - found = B_TRUE; - - if (supported) { - if (!found) { - (void) strlcpy(buf, ZFS_FEATURE_DISABLED, len); - } else { - if (refcount == 0) - (void) strlcpy(buf, ZFS_FEATURE_ENABLED, len); - else - (void) strlcpy(buf, ZFS_FEATURE_ACTIVE, len); - } - } else { - if (found) { - if (refcount == 0) { - (void) strcpy(buf, ZFS_UNSUPPORTED_INACTIVE); - } else { - (void) strcpy(buf, ZFS_UNSUPPORTED_READONLY); - } - } else { - (void) strlcpy(buf, "-", len); - return (ENOTSUP); - } - } - - return (0); -} - -/* - * Validate the given pool name, optionally putting an extended error message in - * 'buf'. - */ -boolean_t -zpool_name_valid(libzfs_handle_t *hdl, boolean_t isopen, const char *pool) -{ - namecheck_err_t why; - char what; - int ret; - - ret = pool_namecheck(pool, &why, &what); - - /* - * The rules for reserved pool names were extended at a later point. - * But we need to support users with existing pools that may now be - * invalid. So we only check for this expanded set of names during a - * create (or import), and only in userland. - */ - if (ret == 0 && !isopen && - (strncmp(pool, "mirror", 6) == 0 || - strncmp(pool, "raidz", 5) == 0 || - strncmp(pool, "draid", 5) == 0 || - strncmp(pool, "spare", 5) == 0 || - strcmp(pool, "log") == 0)) { - if (hdl != NULL) - zfs_error_aux(hdl, - dgettext(TEXT_DOMAIN, "name is reserved")); - return (B_FALSE); - } - - - if (ret != 0) { - if (hdl != NULL) { - switch (why) { - case NAME_ERR_TOOLONG: - zfs_error_aux(hdl, - dgettext(TEXT_DOMAIN, "name is too long")); - break; - - case NAME_ERR_INVALCHAR: - zfs_error_aux(hdl, - dgettext(TEXT_DOMAIN, "invalid character " - "'%c' in pool name"), what); - break; - - case NAME_ERR_NOLETTER: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "name must begin with a letter")); - break; - - case NAME_ERR_RESERVED: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "name is reserved")); - break; - - case NAME_ERR_DISKLIKE: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "pool name is reserved")); - break; - - case NAME_ERR_LEADING_SLASH: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "leading slash in name")); - break; - - case NAME_ERR_EMPTY_COMPONENT: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "empty component in name")); - break; - - case NAME_ERR_TRAILING_SLASH: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "trailing slash in name")); - break; - - case NAME_ERR_MULTIPLE_DELIMITERS: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "multiple '@' and/or '#' delimiters in " - "name")); - break; - - case NAME_ERR_NO_AT: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "permission set is missing '@'")); - break; - - default: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "(%d) not defined"), why); - break; - } - } - return (B_FALSE); - } - - return (B_TRUE); -} - -/* - * Open a handle to the given pool, even if the pool is currently in the FAULTED - * state. - */ -zpool_handle_t * -zpool_open_canfail(libzfs_handle_t *hdl, const char *pool) -{ - zpool_handle_t *zhp; - boolean_t missing; - - /* - * Make sure the pool name is valid. - */ - if (!zpool_name_valid(hdl, B_TRUE, pool)) { - (void) zfs_error_fmt(hdl, EZFS_INVALIDNAME, - dgettext(TEXT_DOMAIN, "cannot open '%s'"), - pool); - return (NULL); - } - - zhp = zfs_alloc(hdl, sizeof (zpool_handle_t)); - - zhp->zpool_hdl = hdl; - (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); - - if (zpool_refresh_stats(zhp, &missing) != 0) { - zpool_close(zhp); - return (NULL); - } - - if (missing) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "no such pool")); - (void) zfs_error_fmt(hdl, EZFS_NOENT, - dgettext(TEXT_DOMAIN, "cannot open '%s'"), pool); - zpool_close(zhp); - return (NULL); - } - - return (zhp); -} - -/* - * Like the above, but silent on error. Used when iterating over pools (because - * the configuration cache may be out of date). - */ -int -zpool_open_silent(libzfs_handle_t *hdl, const char *pool, zpool_handle_t **ret) -{ - zpool_handle_t *zhp; - boolean_t missing; - - zhp = zfs_alloc(hdl, sizeof (zpool_handle_t)); - - zhp->zpool_hdl = hdl; - (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); - - if (zpool_refresh_stats(zhp, &missing) != 0) { - zpool_close(zhp); - return (-1); - } - - if (missing) { - zpool_close(zhp); - *ret = NULL; - return (0); - } - - *ret = zhp; - return (0); -} - -/* - * Similar to zpool_open_canfail(), but refuses to open pools in the faulted - * state. - */ -zpool_handle_t * -zpool_open(libzfs_handle_t *hdl, const char *pool) -{ - zpool_handle_t *zhp; - - if ((zhp = zpool_open_canfail(hdl, pool)) == NULL) - return (NULL); - - if (zhp->zpool_state == POOL_STATE_UNAVAIL) { - (void) zfs_error_fmt(hdl, EZFS_POOLUNAVAIL, - dgettext(TEXT_DOMAIN, "cannot open '%s'"), zhp->zpool_name); - zpool_close(zhp); - return (NULL); - } - - return (zhp); -} - -/* - * Close the handle. Simply frees the memory associated with the handle. - */ -void -zpool_close(zpool_handle_t *zhp) -{ - nvlist_free(zhp->zpool_config); - nvlist_free(zhp->zpool_old_config); - nvlist_free(zhp->zpool_props); - free(zhp); -} - -/* - * Return the name of the pool. - */ -const char * -zpool_get_name(zpool_handle_t *zhp) -{ - return (zhp->zpool_name); -} - - -/* - * Return the state of the pool (ACTIVE or UNAVAILABLE) - */ -int -zpool_get_state(zpool_handle_t *zhp) -{ - return (zhp->zpool_state); -} - -/* - * Check if vdev list contains a dRAID vdev - */ -static boolean_t -zpool_has_draid_vdev(nvlist_t *nvroot) -{ - nvlist_t **child; - uint_t children; - - if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, - &child, &children) == 0) { - for (uint_t c = 0; c < children; c++) { - const char *type; - - if (nvlist_lookup_string(child[c], - ZPOOL_CONFIG_TYPE, &type) == 0 && - strcmp(type, VDEV_TYPE_DRAID) == 0) { - return (B_TRUE); - } - } - } - return (B_FALSE); -} - -/* - * Output a dRAID top-level vdev name in to the provided buffer. - */ -static char * -zpool_draid_name(char *name, int len, uint64_t data, uint64_t parity, - uint64_t spares, uint64_t children) -{ - snprintf(name, len, "%s%llu:%llud:%lluc:%llus", - VDEV_TYPE_DRAID, (u_longlong_t)parity, (u_longlong_t)data, - (u_longlong_t)children, (u_longlong_t)spares); - - return (name); -} - -/* - * Return B_TRUE if the provided name is a dRAID spare name. - */ -boolean_t -zpool_is_draid_spare(const char *name) -{ - uint64_t spare_id, parity, vdev_id; - - if (sscanf(name, VDEV_TYPE_DRAID "%llu-%llu-%llu", - (u_longlong_t *)&parity, (u_longlong_t *)&vdev_id, - (u_longlong_t *)&spare_id) == 3) { - return (B_TRUE); - } - - return (B_FALSE); -} - -/* - * Create the named pool, using the provided vdev list. It is assumed - * that the consumer has already validated the contents of the nvlist, so we - * don't have to worry about error semantics. - */ -int -zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot, - nvlist_t *props, nvlist_t *fsprops) -{ - zfs_cmd_t zc = {"\0"}; - nvlist_t *zc_fsprops = NULL; - nvlist_t *zc_props = NULL; - nvlist_t *hidden_args = NULL; - uint8_t *wkeydata = NULL; - uint_t wkeylen = 0; - char errbuf[ERRBUFLEN]; - int ret = -1; - - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot create '%s'"), pool); - - if (!zpool_name_valid(hdl, B_FALSE, pool)) - return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); - - zcmd_write_conf_nvlist(hdl, &zc, nvroot); - - if (props) { - prop_flags_t flags = { .create = B_TRUE, .import = B_FALSE }; - - if ((zc_props = zpool_valid_proplist(hdl, pool, props, - SPA_VERSION_1, flags, errbuf)) == NULL) { - goto create_failed; - } - } - - if (fsprops) { - uint64_t zoned; - const char *zonestr; - - zoned = ((nvlist_lookup_string(fsprops, - zfs_prop_to_name(ZFS_PROP_ZONED), &zonestr) == 0) && - strcmp(zonestr, "on") == 0); - - if ((zc_fsprops = zfs_valid_proplist(hdl, ZFS_TYPE_FILESYSTEM, - fsprops, zoned, NULL, NULL, B_TRUE, errbuf)) == NULL) { - goto create_failed; - } - - if (!zc_props && - (nvlist_alloc(&zc_props, NV_UNIQUE_NAME, 0) != 0)) { - goto create_failed; - } - if (zfs_crypto_create(hdl, NULL, zc_fsprops, props, B_TRUE, - &wkeydata, &wkeylen) != 0) { - zfs_error(hdl, EZFS_CRYPTOFAILED, errbuf); - goto create_failed; - } - if (nvlist_add_nvlist(zc_props, - ZPOOL_ROOTFS_PROPS, zc_fsprops) != 0) { - goto create_failed; - } - if (wkeydata != NULL) { - if (nvlist_alloc(&hidden_args, NV_UNIQUE_NAME, 0) != 0) - goto create_failed; - - if (nvlist_add_uint8_array(hidden_args, "wkeydata", - wkeydata, wkeylen) != 0) - goto create_failed; - - if (nvlist_add_nvlist(zc_props, ZPOOL_HIDDEN_ARGS, - hidden_args) != 0) - goto create_failed; - } - } - - if (zc_props) - zcmd_write_src_nvlist(hdl, &zc, zc_props); - - (void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name)); - - if ((ret = zfs_ioctl(hdl, ZFS_IOC_POOL_CREATE, &zc)) != 0) { - - zcmd_free_nvlists(&zc); - nvlist_free(zc_props); - nvlist_free(zc_fsprops); - nvlist_free(hidden_args); - if (wkeydata != NULL) - free(wkeydata); - - switch (errno) { - case EBUSY: - /* - * This can happen if the user has specified the same - * device multiple times. We can't reliably detect this - * until we try to add it and see we already have a - * label. This can also happen under if the device is - * part of an active md or lvm device. - */ - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "one or more vdevs refer to the same device, or " - "one of\nthe devices is part of an active md or " - "lvm device")); - return (zfs_error(hdl, EZFS_BADDEV, errbuf)); - - case ERANGE: - /* - * This happens if the record size is smaller or larger - * than the allowed size range, or not a power of 2. - * - * NOTE: although zfs_valid_proplist is called earlier, - * this case may have slipped through since the - * pool does not exist yet and it is therefore - * impossible to read properties e.g. max blocksize - * from the pool. - */ - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "record size invalid")); - return (zfs_error(hdl, EZFS_BADPROP, errbuf)); - - case EOVERFLOW: - /* - * This occurs when one of the devices is below - * SPA_MINDEVSIZE. Unfortunately, we can't detect which - * device was the problem device since there's no - * reliable way to determine device size from userland. - */ - { - char buf[64]; - - zfs_nicebytes(SPA_MINDEVSIZE, buf, - sizeof (buf)); - - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "one or more devices is less than the " - "minimum size (%s)"), buf); - } - return (zfs_error(hdl, EZFS_BADDEV, errbuf)); - - case ENOSPC: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "one or more devices is out of space")); - return (zfs_error(hdl, EZFS_BADDEV, errbuf)); - - case EINVAL: - if (zpool_has_draid_vdev(nvroot) && - zfeature_lookup_name("draid", NULL) != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "dRAID vdevs are unsupported by the " - "kernel")); - return (zfs_error(hdl, EZFS_BADDEV, errbuf)); - } else { - return (zpool_standard_error(hdl, errno, - errbuf)); - } - - default: - return (zpool_standard_error(hdl, errno, errbuf)); - } - } - -create_failed: - zcmd_free_nvlists(&zc); - nvlist_free(zc_props); - nvlist_free(zc_fsprops); - nvlist_free(hidden_args); - if (wkeydata != NULL) - free(wkeydata); - return (ret); -} - -/* - * Destroy the given pool. It is up to the caller to ensure that there are no - * datasets left in the pool. - */ -int -zpool_destroy(zpool_handle_t *zhp, const char *log_str) -{ - zfs_cmd_t zc = {"\0"}; - zfs_handle_t *zfp = NULL; - libzfs_handle_t *hdl = zhp->zpool_hdl; - char errbuf[ERRBUFLEN]; - - if (zhp->zpool_state == POOL_STATE_ACTIVE && - (zfp = zfs_open(hdl, zhp->zpool_name, ZFS_TYPE_FILESYSTEM)) == NULL) - return (-1); - - (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); - zc.zc_history = (uint64_t)(uintptr_t)log_str; - - if (zfs_ioctl(hdl, ZFS_IOC_POOL_DESTROY, &zc) != 0) { - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot destroy '%s'"), zhp->zpool_name); - - if (errno == EROFS) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "one or more devices is read only")); - (void) zfs_error(hdl, EZFS_BADDEV, errbuf); - } else { - (void) zpool_standard_error(hdl, errno, errbuf); - } - - if (zfp) - zfs_close(zfp); - return (-1); - } - - if (zfp) { - remove_mountpoint(zfp); - zfs_close(zfp); - } - - return (0); -} - -/* - * Create a checkpoint in the given pool. - */ -int -zpool_checkpoint(zpool_handle_t *zhp) -{ - libzfs_handle_t *hdl = zhp->zpool_hdl; - char errbuf[ERRBUFLEN]; - int error; - - error = lzc_pool_checkpoint(zhp->zpool_name); - if (error != 0) { - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot checkpoint '%s'"), zhp->zpool_name); - (void) zpool_standard_error(hdl, error, errbuf); - return (-1); - } - - return (0); -} - -/* - * Discard the checkpoint from the given pool. - */ -int -zpool_discard_checkpoint(zpool_handle_t *zhp) -{ - libzfs_handle_t *hdl = zhp->zpool_hdl; - char errbuf[ERRBUFLEN]; - int error; - - error = lzc_pool_checkpoint_discard(zhp->zpool_name); - if (error != 0) { - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot discard checkpoint in '%s'"), zhp->zpool_name); - (void) zpool_standard_error(hdl, error, errbuf); - return (-1); - } - - return (0); -} - -/* - * Load data type for the given pool. - */ -int -zpool_prefetch(zpool_handle_t *zhp, zpool_prefetch_type_t type) -{ - libzfs_handle_t *hdl = zhp->zpool_hdl; - char msg[1024]; - int error; - - error = lzc_pool_prefetch(zhp->zpool_name, type); - if (error != 0) { - (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, - "cannot prefetch %s in '%s'"), - type == ZPOOL_PREFETCH_DDT ? "ddt" : "", zhp->zpool_name); - (void) zpool_standard_error(hdl, error, msg); - return (-1); - } - - return (0); -} - -/* - * Add the given vdevs to the pool. The caller must have already performed the - * necessary verification to ensure that the vdev specification is well-formed. - */ -int -zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot, boolean_t check_ashift) -{ - zfs_cmd_t zc = {"\0"}; - int ret; - libzfs_handle_t *hdl = zhp->zpool_hdl; - char errbuf[ERRBUFLEN]; - nvlist_t **spares, **l2cache; - uint_t nspares, nl2cache; - - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot add to '%s'"), zhp->zpool_name); - - if (zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL) < - SPA_VERSION_SPARES && - nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, - &spares, &nspares) == 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be " - "upgraded to add hot spares")); - return (zfs_error(hdl, EZFS_BADVERSION, errbuf)); - } - - if (zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL) < - SPA_VERSION_L2CACHE && - nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE, - &l2cache, &nl2cache) == 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be " - "upgraded to add cache devices")); - return (zfs_error(hdl, EZFS_BADVERSION, errbuf)); - } - - zcmd_write_conf_nvlist(hdl, &zc, nvroot); - (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); - zc.zc_flags = check_ashift; - - if (zfs_ioctl(hdl, ZFS_IOC_VDEV_ADD, &zc) != 0) { - switch (errno) { - case EBUSY: - /* - * This can happen if the user has specified the same - * device multiple times. We can't reliably detect this - * until we try to add it and see we already have a - * label. - */ - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "one or more vdevs refer to the same device")); - (void) zfs_error(hdl, EZFS_BADDEV, errbuf); - break; - - case EINVAL: - - if (zpool_has_draid_vdev(nvroot) && - zfeature_lookup_name("draid", NULL) != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "dRAID vdevs are unsupported by the " - "kernel")); - } else { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "invalid config; a pool with removing/" - "removed vdevs does not support adding " - "raidz or dRAID vdevs")); - } - - (void) zfs_error(hdl, EZFS_BADDEV, errbuf); - break; - - case EOVERFLOW: - /* - * This occurs when one of the devices is below - * SPA_MINDEVSIZE. Unfortunately, we can't detect which - * device was the problem device since there's no - * reliable way to determine device size from userland. - */ - { - char buf[64]; - - zfs_nicebytes(SPA_MINDEVSIZE, buf, - sizeof (buf)); - - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "device is less than the minimum " - "size (%s)"), buf); - } - (void) zfs_error(hdl, EZFS_BADDEV, errbuf); - break; - - case ENOTSUP: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "pool must be upgraded to add these vdevs")); - (void) zfs_error(hdl, EZFS_BADVERSION, errbuf); - break; - - default: - (void) zpool_standard_error(hdl, errno, errbuf); - } - - ret = -1; - } else { - ret = 0; - } - - zcmd_free_nvlists(&zc); - - return (ret); -} - -/* - * Exports the pool from the system. The caller must ensure that there are no - * mounted datasets in the pool. - */ -static int -zpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce, - const char *log_str) -{ - zfs_cmd_t zc = {"\0"}; - - (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); - zc.zc_cookie = force; - zc.zc_guid = hardforce; - zc.zc_history = (uint64_t)(uintptr_t)log_str; - - if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_EXPORT, &zc) != 0) { - switch (errno) { - case EXDEV: - zfs_error_aux(zhp->zpool_hdl, dgettext(TEXT_DOMAIN, - "use '-f' to override the following errors:\n" - "'%s' has an active shared spare which could be" - " used by other pools once '%s' is exported."), - zhp->zpool_name, zhp->zpool_name); - return (zfs_error_fmt(zhp->zpool_hdl, EZFS_ACTIVE_SPARE, - dgettext(TEXT_DOMAIN, "cannot export '%s'"), - zhp->zpool_name)); - default: - return (zpool_standard_error_fmt(zhp->zpool_hdl, errno, - dgettext(TEXT_DOMAIN, "cannot export '%s'"), - zhp->zpool_name)); - } - } - - return (0); -} - -int -zpool_export(zpool_handle_t *zhp, boolean_t force, const char *log_str) -{ - return (zpool_export_common(zhp, force, B_FALSE, log_str)); -} - -int -zpool_export_force(zpool_handle_t *zhp, const char *log_str) -{ - return (zpool_export_common(zhp, B_TRUE, B_TRUE, log_str)); -} - -static void -zpool_rewind_exclaim(libzfs_handle_t *hdl, const char *name, boolean_t dryrun, - nvlist_t *config) -{ - nvlist_t *nv = NULL; - uint64_t rewindto; - int64_t loss = -1; - struct tm t; - char timestr[128]; - - if (!hdl->libzfs_printerr || config == NULL) - return; - - if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nv) != 0 || - nvlist_lookup_nvlist(nv, ZPOOL_CONFIG_REWIND_INFO, &nv) != 0) { - return; - } - - if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_TIME, &rewindto) != 0) - return; - (void) nvlist_lookup_int64(nv, ZPOOL_CONFIG_REWIND_TIME, &loss); - - if (localtime_r((time_t *)&rewindto, &t) != NULL && - ctime_r((time_t *)&rewindto, timestr) != NULL) { - timestr[24] = 0; - if (dryrun) { - (void) printf(dgettext(TEXT_DOMAIN, - "Would be able to return %s " - "to its state as of %s.\n"), - name, timestr); - } else { - (void) printf(dgettext(TEXT_DOMAIN, - "Pool %s returned to its state as of %s.\n"), - name, timestr); - } - if (loss > 120) { - (void) printf(dgettext(TEXT_DOMAIN, - "%s approximately %lld "), - dryrun ? "Would discard" : "Discarded", - ((longlong_t)loss + 30) / 60); - (void) printf(dgettext(TEXT_DOMAIN, - "minutes of transactions.\n")); - } else if (loss > 0) { - (void) printf(dgettext(TEXT_DOMAIN, - "%s approximately %lld "), - dryrun ? "Would discard" : "Discarded", - (longlong_t)loss); - (void) printf(dgettext(TEXT_DOMAIN, - "seconds of transactions.\n")); - } - } -} - -void -zpool_explain_recover(libzfs_handle_t *hdl, const char *name, int reason, - nvlist_t *config, char *buf, size_t size) -{ - nvlist_t *nv = NULL; - int64_t loss = -1; - uint64_t edata = UINT64_MAX; - uint64_t rewindto; - struct tm t; - char timestr[128], temp[1024]; - - if (!hdl->libzfs_printerr) - return; - - /* All attempted rewinds failed if ZPOOL_CONFIG_LOAD_TIME missing */ - if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nv) != 0 || - nvlist_lookup_nvlist(nv, ZPOOL_CONFIG_REWIND_INFO, &nv) != 0 || - nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_TIME, &rewindto) != 0) - goto no_info; - - (void) nvlist_lookup_int64(nv, ZPOOL_CONFIG_REWIND_TIME, &loss); - (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_DATA_ERRORS, - &edata); - - (void) snprintf(buf, size, dgettext(TEXT_DOMAIN, - "Recovery is possible, but will result in some data loss.\n")); - - if (localtime_r((time_t *)&rewindto, &t) != NULL && - ctime_r((time_t *)&rewindto, timestr) != NULL) { - timestr[24] = 0; - (void) snprintf(temp, 1024, dgettext(TEXT_DOMAIN, - "\tReturning the pool to its state as of %s\n" - "\tshould correct the problem. "), timestr); - (void) strlcat(buf, temp, size); - } else { - (void) strlcat(buf, dgettext(TEXT_DOMAIN, - "\tReverting the pool to an earlier state " - "should correct the problem.\n\t"), size); - } - - if (loss > 120) { - (void) snprintf(temp, 1024, dgettext(TEXT_DOMAIN, - "Approximately %lld minutes of data\n" - "\tmust be discarded, irreversibly. "), - ((longlong_t)loss + 30) / 60); - (void) strlcat(buf, temp, size); - } else if (loss > 0) { - (void) snprintf(temp, 1024, dgettext(TEXT_DOMAIN, - "Approximately %lld seconds of data\n" - "\tmust be discarded, irreversibly. "), - (longlong_t)loss); - (void) strlcat(buf, temp, size); - } - if (edata != 0 && edata != UINT64_MAX) { - if (edata == 1) { - (void) strlcat(buf, dgettext(TEXT_DOMAIN, - "After rewind, at least\n" - "\tone persistent user-data error will remain. "), - size); - } else { - (void) strlcat(buf, dgettext(TEXT_DOMAIN, - "After rewind, several\n" - "\tpersistent user-data errors will remain. "), - size); - } - } - (void) snprintf(temp, 1024, dgettext(TEXT_DOMAIN, - "Recovery can be attempted\n\tby executing 'zpool %s -F %s'. "), - reason >= 0 ? "clear" : "import", name); - (void) strlcat(buf, temp, size); - - (void) strlcat(buf, dgettext(TEXT_DOMAIN, - "A scrub of the pool\n" - "\tis strongly recommended after recovery.\n"), size); - return; - -no_info: - (void) strlcat(buf, dgettext(TEXT_DOMAIN, - "Destroy and re-create the pool from\n\ta backup source.\n"), size); -} - -/* - * zpool_import() is a contracted interface. Should be kept the same - * if possible. - * - * Applications should use zpool_import_props() to import a pool with - * new properties value to be set. - */ -int -zpool_import(libzfs_handle_t *hdl, nvlist_t *config, const char *newname, - char *altroot) -{ - nvlist_t *props = NULL; - int ret; - - if (altroot != NULL) { - if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) { - return (zfs_error_fmt(hdl, EZFS_NOMEM, - dgettext(TEXT_DOMAIN, "cannot import '%s'"), - newname)); - } - - if (nvlist_add_string(props, - zpool_prop_to_name(ZPOOL_PROP_ALTROOT), altroot) != 0 || - nvlist_add_string(props, - zpool_prop_to_name(ZPOOL_PROP_CACHEFILE), "none") != 0) { - nvlist_free(props); - return (zfs_error_fmt(hdl, EZFS_NOMEM, - dgettext(TEXT_DOMAIN, "cannot import '%s'"), - newname)); - } - } - - ret = zpool_import_props(hdl, config, newname, props, - ZFS_IMPORT_NORMAL); - nvlist_free(props); - return (ret); -} - -static void -print_vdev_tree(libzfs_handle_t *hdl, const char *name, nvlist_t *nv, - int indent) -{ - nvlist_t **child; - uint_t c, children; - char *vname; - uint64_t is_log = 0; - - (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_LOG, - &is_log); - - if (name != NULL) - (void) printf("\t%*s%s%s\n", indent, "", name, - is_log ? " [log]" : ""); - - if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, - &child, &children) != 0) - return; - - for (c = 0; c < children; c++) { - vname = zpool_vdev_name(hdl, NULL, child[c], VDEV_NAME_TYPE_ID); - print_vdev_tree(hdl, vname, child[c], indent + 2); - free(vname); - } -} - -void -zpool_collect_unsup_feat(nvlist_t *config, char *buf, size_t size) -{ - nvlist_t *nvinfo, *unsup_feat; - char temp[512]; - - nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO); - unsup_feat = fnvlist_lookup_nvlist(nvinfo, ZPOOL_CONFIG_UNSUP_FEAT); - - for (nvpair_t *nvp = nvlist_next_nvpair(unsup_feat, NULL); - nvp != NULL; nvp = nvlist_next_nvpair(unsup_feat, nvp)) { - const char *desc = fnvpair_value_string(nvp); - if (strlen(desc) > 0) { - (void) snprintf(temp, 512, "\t%s (%s)\n", - nvpair_name(nvp), desc); - (void) strlcat(buf, temp, size); - } else { - (void) snprintf(temp, 512, "\t%s\n", nvpair_name(nvp)); - (void) strlcat(buf, temp, size); - } - } -} - -/* - * Import the given pool using the known configuration and a list of - * properties to be set. The configuration should have come from - * zpool_find_import(). The 'newname' parameters control whether the pool - * is imported with a different name. - */ -int -zpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname, - nvlist_t *props, int flags) -{ - zfs_cmd_t zc = {"\0"}; - zpool_load_policy_t policy; - nvlist_t *nv = NULL; - nvlist_t *nvinfo = NULL; - nvlist_t *missing = NULL; - const char *thename; - const char *origname; - int ret; - int error = 0; - char buf[2048]; - char errbuf[ERRBUFLEN]; - - origname = fnvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME); - - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot import pool '%s'"), origname); - - if (newname != NULL) { - if (!zpool_name_valid(hdl, B_FALSE, newname)) - return (zfs_error_fmt(hdl, EZFS_INVALIDNAME, - dgettext(TEXT_DOMAIN, "cannot import '%s'"), - newname)); - thename = newname; - } else { - thename = origname; - } - - if (props != NULL) { - uint64_t version; - prop_flags_t flags = { .create = B_FALSE, .import = B_TRUE }; - - version = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION); - - if ((props = zpool_valid_proplist(hdl, origname, - props, version, flags, errbuf)) == NULL) - return (-1); - zcmd_write_src_nvlist(hdl, &zc, props); - nvlist_free(props); - } - - (void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name)); - - zc.zc_guid = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID); - - zcmd_write_conf_nvlist(hdl, &zc, config); - zcmd_alloc_dst_nvlist(hdl, &zc, zc.zc_nvlist_conf_size * 2); - - zc.zc_cookie = flags; - while ((ret = zfs_ioctl(hdl, ZFS_IOC_POOL_IMPORT, &zc)) != 0 && - errno == ENOMEM) - zcmd_expand_dst_nvlist(hdl, &zc); - if (ret != 0) - error = errno; - - (void) zcmd_read_dst_nvlist(hdl, &zc, &nv); - - zcmd_free_nvlists(&zc); - - zpool_get_load_policy(config, &policy); - - if (error) { - char desc[1024]; - char aux[256]; - - /* - * Dry-run failed, but we print out what success - * looks like if we found a best txg - */ - if (policy.zlp_rewind & ZPOOL_TRY_REWIND) { - zpool_rewind_exclaim(hdl, newname ? origname : thename, - B_TRUE, nv); - nvlist_free(nv); - return (-1); - } - - if (newname == NULL) - (void) snprintf(desc, sizeof (desc), - dgettext(TEXT_DOMAIN, "cannot import '%s'"), - thename); - else - (void) snprintf(desc, sizeof (desc), - dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"), - origname, thename); - - switch (error) { - case ENOTSUP: - if (nv != NULL && nvlist_lookup_nvlist(nv, - ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0 && - nvlist_exists(nvinfo, ZPOOL_CONFIG_UNSUP_FEAT)) { - (void) printf(dgettext(TEXT_DOMAIN, "This " - "pool uses the following feature(s) not " - "supported by this system:\n")); - memset(buf, 0, 2048); - zpool_collect_unsup_feat(nv, buf, 2048); - (void) printf("%s", buf); - if (nvlist_exists(nvinfo, - ZPOOL_CONFIG_CAN_RDONLY)) { - (void) printf(dgettext(TEXT_DOMAIN, - "All unsupported features are only " - "required for writing to the pool." - "\nThe pool can be imported using " - "'-o readonly=on'.\n")); - } - } - /* - * Unsupported version. - */ - (void) zfs_error(hdl, EZFS_BADVERSION, desc); - break; - - case EREMOTEIO: - if (nv != NULL && nvlist_lookup_nvlist(nv, - ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0) { - const char *hostname = "<unknown>"; - uint64_t hostid = 0; - mmp_state_t mmp_state; - - mmp_state = fnvlist_lookup_uint64(nvinfo, - ZPOOL_CONFIG_MMP_STATE); - - if (nvlist_exists(nvinfo, - ZPOOL_CONFIG_MMP_HOSTNAME)) - hostname = fnvlist_lookup_string(nvinfo, - ZPOOL_CONFIG_MMP_HOSTNAME); - - if (nvlist_exists(nvinfo, - ZPOOL_CONFIG_MMP_HOSTID)) - hostid = fnvlist_lookup_uint64(nvinfo, - ZPOOL_CONFIG_MMP_HOSTID); - - if (mmp_state == MMP_STATE_ACTIVE) { - (void) snprintf(aux, sizeof (aux), - dgettext(TEXT_DOMAIN, "pool is imp" - "orted on host '%s' (hostid=%lx).\n" - "Export the pool on the other " - "system, then run 'zpool import'."), - hostname, (unsigned long) hostid); - } else if (mmp_state == MMP_STATE_NO_HOSTID) { - (void) snprintf(aux, sizeof (aux), - dgettext(TEXT_DOMAIN, "pool has " - "the multihost property on and " - "the\nsystem's hostid is not set. " - "Set a unique system hostid with " - "the zgenhostid(8) command.\n")); - } - - (void) zfs_error_aux(hdl, "%s", aux); - } - (void) zfs_error(hdl, EZFS_ACTIVE_POOL, desc); - break; - - case EINVAL: - (void) zfs_error(hdl, EZFS_INVALCONFIG, desc); - break; - - case EROFS: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "one or more devices is read only")); - (void) zfs_error(hdl, EZFS_BADDEV, desc); - break; - - case ENXIO: - if (nv && nvlist_lookup_nvlist(nv, - ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0 && - nvlist_lookup_nvlist(nvinfo, - ZPOOL_CONFIG_MISSING_DEVICES, &missing) == 0) { - (void) printf(dgettext(TEXT_DOMAIN, - "The devices below are missing or " - "corrupted, use '-m' to import the pool " - "anyway:\n")); - print_vdev_tree(hdl, NULL, missing, 2); - (void) printf("\n"); - } - (void) zpool_standard_error(hdl, error, desc); - break; - - case EEXIST: - (void) zpool_standard_error(hdl, error, desc); - break; - - case EBUSY: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "one or more devices are already in use\n")); - (void) zfs_error(hdl, EZFS_BADDEV, desc); - break; - case ENAMETOOLONG: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "new name of at least one dataset is longer than " - "the maximum allowable length")); - (void) zfs_error(hdl, EZFS_NAMETOOLONG, desc); - break; - default: - (void) zpool_standard_error(hdl, error, desc); - memset(buf, 0, 2048); - zpool_explain_recover(hdl, - newname ? origname : thename, -error, nv, - buf, 2048); - (void) printf("\t%s", buf); - break; - } - - nvlist_free(nv); - ret = -1; - } else { - zpool_handle_t *zhp; - - /* - * This should never fail, but play it safe anyway. - */ - if (zpool_open_silent(hdl, thename, &zhp) != 0) - ret = -1; - else if (zhp != NULL) - zpool_close(zhp); - if (policy.zlp_rewind & - (ZPOOL_DO_REWIND | ZPOOL_TRY_REWIND)) { - zpool_rewind_exclaim(hdl, newname ? origname : thename, - ((policy.zlp_rewind & ZPOOL_TRY_REWIND) != 0), nv); - } - nvlist_free(nv); - } - - return (ret); -} - -/* - * Translate vdev names to guids. If a vdev_path is determined to be - * unsuitable then a vd_errlist is allocated and the vdev path and errno - * are added to it. - */ -static int -zpool_translate_vdev_guids(zpool_handle_t *zhp, nvlist_t *vds, - nvlist_t *vdev_guids, nvlist_t *guids_to_paths, nvlist_t **vd_errlist) -{ - nvlist_t *errlist = NULL; - int error = 0; - - for (nvpair_t *elem = nvlist_next_nvpair(vds, NULL); elem != NULL; - elem = nvlist_next_nvpair(vds, elem)) { - boolean_t spare, cache; - - const char *vd_path = nvpair_name(elem); - nvlist_t *tgt = zpool_find_vdev(zhp, vd_path, &spare, &cache, - NULL); - - if ((tgt == NULL) || cache || spare) { - if (errlist == NULL) { - errlist = fnvlist_alloc(); - error = EINVAL; - } - - uint64_t err = (tgt == NULL) ? EZFS_NODEVICE : - (spare ? EZFS_ISSPARE : EZFS_ISL2CACHE); - fnvlist_add_int64(errlist, vd_path, err); - continue; - } - - uint64_t guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID); - fnvlist_add_uint64(vdev_guids, vd_path, guid); - - char msg[MAXNAMELEN]; - (void) snprintf(msg, sizeof (msg), "%llu", (u_longlong_t)guid); - fnvlist_add_string(guids_to_paths, msg, vd_path); - } - - if (error != 0) { - verify(errlist != NULL); - if (vd_errlist != NULL) - *vd_errlist = errlist; - else - fnvlist_free(errlist); - } - - return (error); -} - -static int -xlate_init_err(int err) -{ - switch (err) { - case ENODEV: - return (EZFS_NODEVICE); - case EINVAL: - case EROFS: - return (EZFS_BADDEV); - case EBUSY: - return (EZFS_INITIALIZING); - case ESRCH: - return (EZFS_NO_INITIALIZE); - } - return (err); -} - -int -zpool_initialize_one(zpool_handle_t *zhp, void *data) -{ - int error; - libzfs_handle_t *hdl = zpool_get_handle(zhp); - const char *pool_name = zpool_get_name(zhp); - if (zpool_open_silent(hdl, pool_name, &zhp) != 0) - return (-1); - initialize_cbdata_t *cb = data; - nvlist_t *vdevs = fnvlist_alloc(); - - nvlist_t *config = zpool_get_config(zhp, NULL); - nvlist_t *nvroot = fnvlist_lookup_nvlist(config, - ZPOOL_CONFIG_VDEV_TREE); - zpool_collect_leaves(zhp, nvroot, vdevs); - if (cb->wait) - error = zpool_initialize_wait(zhp, cb->cmd_type, vdevs); - else - error = zpool_initialize(zhp, cb->cmd_type, vdevs); - fnvlist_free(vdevs); - - return (error); -} - -/* - * Begin, suspend, cancel, or uninit (clear) the initialization (initializing - * of all free blocks) for the given vdevs in the given pool. - */ -static int -zpool_initialize_impl(zpool_handle_t *zhp, pool_initialize_func_t cmd_type, - nvlist_t *vds, boolean_t wait) -{ - int err; - - nvlist_t *vdev_guids = fnvlist_alloc(); - nvlist_t *guids_to_paths = fnvlist_alloc(); - nvlist_t *vd_errlist = NULL; - nvlist_t *errlist; - nvpair_t *elem; - - err = zpool_translate_vdev_guids(zhp, vds, vdev_guids, - guids_to_paths, &vd_errlist); - - if (err != 0) { - verify(vd_errlist != NULL); - goto list_errors; - } - - err = lzc_initialize(zhp->zpool_name, cmd_type, - vdev_guids, &errlist); - - if (err != 0) { - if (errlist != NULL && nvlist_lookup_nvlist(errlist, - ZPOOL_INITIALIZE_VDEVS, &vd_errlist) == 0) { - goto list_errors; - } - - if (err == EINVAL && cmd_type == POOL_INITIALIZE_UNINIT) { - zfs_error_aux(zhp->zpool_hdl, dgettext(TEXT_DOMAIN, - "uninitialize is not supported by kernel")); - } - - (void) zpool_standard_error(zhp->zpool_hdl, err, - dgettext(TEXT_DOMAIN, "operation failed")); - goto out; - } - - if (wait) { - for (elem = nvlist_next_nvpair(vdev_guids, NULL); elem != NULL; - elem = nvlist_next_nvpair(vdev_guids, elem)) { - - uint64_t guid = fnvpair_value_uint64(elem); - - err = lzc_wait_tag(zhp->zpool_name, - ZPOOL_WAIT_INITIALIZE, guid, NULL); - if (err != 0) { - (void) zpool_standard_error_fmt(zhp->zpool_hdl, - err, dgettext(TEXT_DOMAIN, "error " - "waiting for '%s' to initialize"), - nvpair_name(elem)); - - goto out; - } - } - } - goto out; - -list_errors: - for (elem = nvlist_next_nvpair(vd_errlist, NULL); elem != NULL; - elem = nvlist_next_nvpair(vd_errlist, elem)) { - int64_t vd_error = xlate_init_err(fnvpair_value_int64(elem)); - const char *path; - - if (nvlist_lookup_string(guids_to_paths, nvpair_name(elem), - &path) != 0) - path = nvpair_name(elem); - - (void) zfs_error_fmt(zhp->zpool_hdl, vd_error, - "cannot initialize '%s'", path); - } - -out: - fnvlist_free(vdev_guids); - fnvlist_free(guids_to_paths); - - if (vd_errlist != NULL) - fnvlist_free(vd_errlist); - - return (err == 0 ? 0 : -1); -} - -int -zpool_initialize(zpool_handle_t *zhp, pool_initialize_func_t cmd_type, - nvlist_t *vds) -{ - return (zpool_initialize_impl(zhp, cmd_type, vds, B_FALSE)); -} - -int -zpool_initialize_wait(zpool_handle_t *zhp, pool_initialize_func_t cmd_type, - nvlist_t *vds) -{ - return (zpool_initialize_impl(zhp, cmd_type, vds, B_TRUE)); -} - -static int -xlate_trim_err(int err) -{ - switch (err) { - case ENODEV: - return (EZFS_NODEVICE); - case EINVAL: - case EROFS: - return (EZFS_BADDEV); - case EBUSY: - return (EZFS_TRIMMING); - case ESRCH: - return (EZFS_NO_TRIM); - case EOPNOTSUPP: - return (EZFS_TRIM_NOTSUP); - } - return (err); -} - -void -zpool_collect_leaves(zpool_handle_t *zhp, nvlist_t *nvroot, nvlist_t *res) -{ - libzfs_handle_t *hdl = zhp->zpool_hdl; - uint_t children = 0; - nvlist_t **child; - uint_t i; - - (void) nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, - &child, &children); - - if (children == 0) { - char *path = zpool_vdev_name(hdl, zhp, nvroot, - VDEV_NAME_PATH); - - if (strcmp(path, VDEV_TYPE_INDIRECT) != 0 && - strcmp(path, VDEV_TYPE_HOLE) != 0) - fnvlist_add_boolean(res, path); - - free(path); - return; - } - - for (i = 0; i < children; i++) { - zpool_collect_leaves(zhp, child[i], res); - } -} - -int -zpool_trim_one(zpool_handle_t *zhp, void *data) -{ - int error; - libzfs_handle_t *hdl = zpool_get_handle(zhp); - const char *pool_name = zpool_get_name(zhp); - if (zpool_open_silent(hdl, pool_name, &zhp) != 0) - return (-1); - - trim_cbdata_t *cb = data; - nvlist_t *vdevs = fnvlist_alloc(); - - /* no individual leaf vdevs specified, so add them all */ - nvlist_t *config = zpool_get_config(zhp, NULL); - nvlist_t *nvroot = fnvlist_lookup_nvlist(config, - ZPOOL_CONFIG_VDEV_TREE); - - zpool_collect_leaves(zhp, nvroot, vdevs); - error = zpool_trim(zhp, cb->cmd_type, vdevs, &cb->trim_flags); - fnvlist_free(vdevs); - - return (error); -} - -static int -zpool_trim_wait(zpool_handle_t *zhp, nvlist_t *vdev_guids) -{ - int err; - nvpair_t *elem; - - for (elem = nvlist_next_nvpair(vdev_guids, NULL); elem != NULL; - elem = nvlist_next_nvpair(vdev_guids, elem)) { - - uint64_t guid = fnvpair_value_uint64(elem); - - err = lzc_wait_tag(zhp->zpool_name, - ZPOOL_WAIT_TRIM, guid, NULL); - if (err != 0) { - (void) zpool_standard_error_fmt(zhp->zpool_hdl, - err, dgettext(TEXT_DOMAIN, "error " - "waiting to trim '%s'"), nvpair_name(elem)); - - return (err); - } - } - return (0); -} - -/* - * Check errlist and report any errors, omitting ones which should be - * suppressed. Returns B_TRUE if any errors were reported. - */ -static boolean_t -check_trim_errs(zpool_handle_t *zhp, trimflags_t *trim_flags, - nvlist_t *guids_to_paths, nvlist_t *vds, nvlist_t *errlist) -{ - nvpair_t *elem; - boolean_t reported_errs = B_FALSE; - int num_vds = 0; - int num_suppressed_errs = 0; - - for (elem = nvlist_next_nvpair(vds, NULL); - elem != NULL; elem = nvlist_next_nvpair(vds, elem)) { - num_vds++; - } - - for (elem = nvlist_next_nvpair(errlist, NULL); - elem != NULL; elem = nvlist_next_nvpair(errlist, elem)) { - int64_t vd_error = xlate_trim_err(fnvpair_value_int64(elem)); - const char *path; - - /* - * If only the pool was specified, and it was not a secure - * trim then suppress warnings for individual vdevs which - * do not support trimming. - */ - if (vd_error == EZFS_TRIM_NOTSUP && - trim_flags->fullpool && - !trim_flags->secure) { - num_suppressed_errs++; - continue; - } - - reported_errs = B_TRUE; - if (nvlist_lookup_string(guids_to_paths, nvpair_name(elem), - &path) != 0) - path = nvpair_name(elem); - - (void) zfs_error_fmt(zhp->zpool_hdl, vd_error, - "cannot trim '%s'", path); - } - - if (num_suppressed_errs == num_vds) { - (void) zfs_error_aux(zhp->zpool_hdl, dgettext(TEXT_DOMAIN, - "no devices in pool support trim operations")); - (void) (zfs_error(zhp->zpool_hdl, EZFS_TRIM_NOTSUP, - dgettext(TEXT_DOMAIN, "cannot trim"))); - reported_errs = B_TRUE; - } - - return (reported_errs); -} - -/* - * Begin, suspend, or cancel the TRIM (discarding of all free blocks) for - * the given vdevs in the given pool. - */ -int -zpool_trim(zpool_handle_t *zhp, pool_trim_func_t cmd_type, nvlist_t *vds, - trimflags_t *trim_flags) -{ - int err; - int retval = 0; - - nvlist_t *vdev_guids = fnvlist_alloc(); - nvlist_t *guids_to_paths = fnvlist_alloc(); - nvlist_t *errlist = NULL; - - err = zpool_translate_vdev_guids(zhp, vds, vdev_guids, - guids_to_paths, &errlist); - if (err != 0) { - check_trim_errs(zhp, trim_flags, guids_to_paths, vds, errlist); - retval = -1; - goto out; - } - - err = lzc_trim(zhp->zpool_name, cmd_type, trim_flags->rate, - trim_flags->secure, vdev_guids, &errlist); - if (err != 0) { - nvlist_t *vd_errlist; - if (errlist != NULL && nvlist_lookup_nvlist(errlist, - ZPOOL_TRIM_VDEVS, &vd_errlist) == 0) { - if (check_trim_errs(zhp, trim_flags, guids_to_paths, - vds, vd_errlist)) { - retval = -1; - goto out; - } - } else { - char errbuf[ERRBUFLEN]; - - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "operation failed")); - zpool_standard_error(zhp->zpool_hdl, err, errbuf); - retval = -1; - goto out; - } - } - - - if (trim_flags->wait) - retval = zpool_trim_wait(zhp, vdev_guids); - -out: - if (errlist != NULL) - fnvlist_free(errlist); - fnvlist_free(vdev_guids); - fnvlist_free(guids_to_paths); - return (retval); -} - -/* - * Scan the pool. - */ -int -zpool_scan(zpool_handle_t *zhp, pool_scan_func_t func, pool_scrub_cmd_t cmd) { - return (zpool_scan_range(zhp, func, cmd, 0, 0)); -} - -int -zpool_scan_range(zpool_handle_t *zhp, pool_scan_func_t func, - pool_scrub_cmd_t cmd, time_t date_start, time_t date_end) -{ - char errbuf[ERRBUFLEN]; - int err; - libzfs_handle_t *hdl = zhp->zpool_hdl; - - nvlist_t *args = fnvlist_alloc(); - fnvlist_add_uint64(args, "scan_type", (uint64_t)func); - fnvlist_add_uint64(args, "scan_command", (uint64_t)cmd); - fnvlist_add_uint64(args, "scan_date_start", (uint64_t)date_start); - fnvlist_add_uint64(args, "scan_date_end", (uint64_t)date_end); - - err = lzc_scrub(ZFS_IOC_POOL_SCRUB, zhp->zpool_name, args, NULL); - fnvlist_free(args); - - if (err == 0) { - return (0); - } else if (err == ZFS_ERR_IOC_CMD_UNAVAIL) { - zfs_cmd_t zc = {"\0"}; - (void) strlcpy(zc.zc_name, zhp->zpool_name, - sizeof (zc.zc_name)); - zc.zc_cookie = func; - zc.zc_flags = cmd; - - if (zfs_ioctl(hdl, ZFS_IOC_POOL_SCAN, &zc) == 0) - return (0); - } - - /* - * An ECANCELED on a scrub means one of the following: - * 1. we resumed a paused scrub. - * 2. we resumed a paused error scrub. - * 3. Error scrub is not run because of no error log. - * - * Note that we no longer return ECANCELED in case 1 or 2. However, in - * order to prevent problems where we have a newer userland than - * kernel, we keep this check in place. That prevents erroneous - * failures when an older kernel returns ECANCELED in those cases. - */ - if (err == ECANCELED && (func == POOL_SCAN_SCRUB || - func == POOL_SCAN_ERRORSCRUB) && cmd == POOL_SCRUB_NORMAL) - return (0); - /* - * The following cases have been handled here: - * 1. Paused a scrub/error scrub if there is none in progress. - */ - if (err == ENOENT && func != POOL_SCAN_NONE && cmd == - POOL_SCRUB_PAUSE) { - return (0); - } - - ASSERT3U(func, >=, POOL_SCAN_NONE); - ASSERT3U(func, <, POOL_SCAN_FUNCS); - - if (func == POOL_SCAN_SCRUB || func == POOL_SCAN_ERRORSCRUB) { - if (cmd == POOL_SCRUB_PAUSE) { - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot pause scrubbing %s"), - zhp->zpool_name); - } else { - assert(cmd == POOL_SCRUB_NORMAL); - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot scrub %s"), - zhp->zpool_name); - } - } else if (func == POOL_SCAN_RESILVER) { - assert(cmd == POOL_SCRUB_NORMAL); - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot restart resilver on %s"), zhp->zpool_name); - } else if (func == POOL_SCAN_NONE) { - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot cancel scrubbing %s"), zhp->zpool_name); - } else { - assert(!"unexpected result"); - } - - /* - * With EBUSY, six cases are possible: - * - * Current state Requested - * 1. Normal Scrub Running Normal Scrub or Error Scrub - * 2. Normal Scrub Paused Error Scrub - * 3. Normal Scrub Paused Pause Normal Scrub - * 4. Error Scrub Running Normal Scrub or Error Scrub - * 5. Error Scrub Paused Pause Error Scrub - * 6. Resilvering Anything else - */ - if (err == EBUSY) { - nvlist_t *nvroot; - pool_scan_stat_t *ps = NULL; - uint_t psc; - - nvroot = fnvlist_lookup_nvlist(zhp->zpool_config, - ZPOOL_CONFIG_VDEV_TREE); - (void) nvlist_lookup_uint64_array(nvroot, - ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &psc); - if (ps && ps->pss_func == POOL_SCAN_SCRUB && - ps->pss_state == DSS_SCANNING) { - if (ps->pss_pass_scrub_pause == 0) { - /* handles case 1 */ - assert(cmd == POOL_SCRUB_NORMAL); - return (zfs_error(hdl, EZFS_SCRUBBING, - errbuf)); - } else { - if (func == POOL_SCAN_ERRORSCRUB) { - /* handles case 2 */ - ASSERT3U(cmd, ==, POOL_SCRUB_NORMAL); - return (zfs_error(hdl, - EZFS_SCRUB_PAUSED_TO_CANCEL, - errbuf)); - } else { - /* handles case 3 */ - ASSERT3U(func, ==, POOL_SCAN_SCRUB); - ASSERT3U(cmd, ==, POOL_SCRUB_PAUSE); - return (zfs_error(hdl, - EZFS_SCRUB_PAUSED, errbuf)); - } - } - } else if (ps && - ps->pss_error_scrub_func == POOL_SCAN_ERRORSCRUB && - ps->pss_error_scrub_state == DSS_ERRORSCRUBBING) { - if (ps->pss_pass_error_scrub_pause == 0) { - /* handles case 4 */ - ASSERT3U(cmd, ==, POOL_SCRUB_NORMAL); - return (zfs_error(hdl, EZFS_ERRORSCRUBBING, - errbuf)); - } else { - /* handles case 5 */ - ASSERT3U(func, ==, POOL_SCAN_ERRORSCRUB); - ASSERT3U(cmd, ==, POOL_SCRUB_PAUSE); - return (zfs_error(hdl, EZFS_ERRORSCRUB_PAUSED, - errbuf)); - } - } else { - /* handles case 6 */ - return (zfs_error(hdl, EZFS_RESILVERING, errbuf)); - } - } else if (err == ENOENT) { - return (zfs_error(hdl, EZFS_NO_SCRUB, errbuf)); - } else if (err == ENOTSUP && func == POOL_SCAN_RESILVER) { - return (zfs_error(hdl, EZFS_NO_RESILVER_DEFER, errbuf)); - } else { - return (zpool_standard_error(hdl, err, errbuf)); - } -} - -/* - * Find a vdev that matches the search criteria specified. We use the - * the nvpair name to determine how we should look for the device. - * 'avail_spare' is set to TRUE if the provided guid refers to an AVAIL - * spare; but FALSE if its an INUSE spare. - * - * If 'return_parent' is set, then return the *parent* of the vdev you're - * searching for rather than the vdev itself. - */ -static nvlist_t * -vdev_to_nvlist_iter(nvlist_t *nv, nvlist_t *search, boolean_t *avail_spare, - boolean_t *l2cache, boolean_t *log, boolean_t return_parent) -{ - uint_t c, children; - nvlist_t **child; - nvlist_t *ret; - uint64_t is_log; - const char *srchkey; - nvpair_t *pair = nvlist_next_nvpair(search, NULL); - const char *tmp = NULL; - boolean_t is_root; - - /* Nothing to look for */ - if (search == NULL || pair == NULL) - return (NULL); - - /* Obtain the key we will use to search */ - srchkey = nvpair_name(pair); - - nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &tmp); - if (strcmp(tmp, "root") == 0) - is_root = B_TRUE; - else - is_root = B_FALSE; - - switch (nvpair_type(pair)) { - case DATA_TYPE_UINT64: - if (strcmp(srchkey, ZPOOL_CONFIG_GUID) == 0) { - uint64_t srchval = fnvpair_value_uint64(pair); - uint64_t theguid = fnvlist_lookup_uint64(nv, - ZPOOL_CONFIG_GUID); - if (theguid == srchval) - return (nv); - } - break; - - case DATA_TYPE_STRING: { - const char *srchval, *val; - - srchval = fnvpair_value_string(pair); - if (nvlist_lookup_string(nv, srchkey, &val) != 0) - break; - - /* - * Search for the requested value. Special cases: - * - * - ZPOOL_CONFIG_PATH for whole disk entries. These end in - * "-part1", or "p1". The suffix is hidden from the user, - * but included in the string, so this matches around it. - * - ZPOOL_CONFIG_PATH for short names zfs_strcmp_shortname() - * is used to check all possible expanded paths. - * - looking for a top-level vdev name (i.e. ZPOOL_CONFIG_TYPE). - * - * Otherwise, all other searches are simple string compares. - */ - if (strcmp(srchkey, ZPOOL_CONFIG_PATH) == 0) { - uint64_t wholedisk = 0; - - (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, - &wholedisk); - if (zfs_strcmp_pathname(srchval, val, wholedisk) == 0) - return (nv); - - } else if (strcmp(srchkey, ZPOOL_CONFIG_TYPE) == 0) { - char *type, *idx, *end, *p; - uint64_t id, vdev_id; - - /* - * Determine our vdev type, keeping in mind - * that the srchval is composed of a type and - * vdev id pair (i.e. mirror-4). - */ - if ((type = strdup(srchval)) == NULL) - return (NULL); - - if ((p = strrchr(type, '-')) == NULL) { - free(type); - break; - } - idx = p + 1; - *p = '\0'; - - /* - * draid names are presented like: draid2:4d:6c:0s - * We match them up to the first ':' so we can still - * do the parity check below, but the other params - * are ignored. - */ - if ((p = strchr(type, ':')) != NULL) { - if (strncmp(type, VDEV_TYPE_DRAID, - strlen(VDEV_TYPE_DRAID)) == 0) - *p = '\0'; - } - - /* - * If the types don't match then keep looking. - */ - if (strncmp(val, type, strlen(val)) != 0) { - free(type); - break; - } - - verify(zpool_vdev_is_interior(type)); - - id = fnvlist_lookup_uint64(nv, ZPOOL_CONFIG_ID); - errno = 0; - vdev_id = strtoull(idx, &end, 10); - - /* - * If we are looking for a raidz and a parity is - * specified, make sure it matches. - */ - int rzlen = strlen(VDEV_TYPE_RAIDZ); - assert(rzlen == strlen(VDEV_TYPE_DRAID)); - int typlen = strlen(type); - if ((strncmp(type, VDEV_TYPE_RAIDZ, rzlen) == 0 || - strncmp(type, VDEV_TYPE_DRAID, rzlen) == 0) && - typlen != rzlen) { - uint64_t vdev_parity; - int parity = *(type + rzlen) - '0'; - - if (parity <= 0 || parity > 3 || - (typlen - rzlen) != 1) { - /* - * Nonsense parity specified, can - * never match - */ - free(type); - return (NULL); - } - vdev_parity = fnvlist_lookup_uint64(nv, - ZPOOL_CONFIG_NPARITY); - if ((int)vdev_parity != parity) { - free(type); - break; - } - } - - free(type); - if (errno != 0) - return (NULL); - - /* - * Now verify that we have the correct vdev id. - */ - if (vdev_id == id) - return (nv); - } - - /* - * Common case - */ - if (strcmp(srchval, val) == 0) - return (nv); - break; - } - - default: - break; - } - - if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, - &child, &children) != 0) - return (NULL); - - for (c = 0; c < children; c++) { - if ((ret = vdev_to_nvlist_iter(child[c], search, - avail_spare, l2cache, NULL, return_parent)) != NULL) { - /* - * The 'is_log' value is only set for the toplevel - * vdev, not the leaf vdevs. So we always lookup the - * log device from the root of the vdev tree (where - * 'log' is non-NULL). - */ - if (log != NULL && - nvlist_lookup_uint64(child[c], - ZPOOL_CONFIG_IS_LOG, &is_log) == 0 && - is_log) { - *log = B_TRUE; - } - return (ret && return_parent && !is_root ? nv : ret); - } - } - - if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, - &child, &children) == 0) { - for (c = 0; c < children; c++) { - if ((ret = vdev_to_nvlist_iter(child[c], search, - avail_spare, l2cache, NULL, return_parent)) - != NULL) { - *avail_spare = B_TRUE; - return (ret && return_parent && - !is_root ? nv : ret); - } - } - } - - if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, - &child, &children) == 0) { - for (c = 0; c < children; c++) { - if ((ret = vdev_to_nvlist_iter(child[c], search, - avail_spare, l2cache, NULL, return_parent)) - != NULL) { - *l2cache = B_TRUE; - return (ret && return_parent && - !is_root ? nv : ret); - } - } - } - - return (NULL); -} - -/* - * Given a physical path or guid, find the associated vdev. - */ -nvlist_t * -zpool_find_vdev_by_physpath(zpool_handle_t *zhp, const char *ppath, - boolean_t *avail_spare, boolean_t *l2cache, boolean_t *log) -{ - nvlist_t *search, *nvroot, *ret; - uint64_t guid; - char *end; - - search = fnvlist_alloc(); - - guid = strtoull(ppath, &end, 0); - if (guid != 0 && *end == '\0') { - fnvlist_add_uint64(search, ZPOOL_CONFIG_GUID, guid); - } else { - fnvlist_add_string(search, ZPOOL_CONFIG_PHYS_PATH, ppath); - } - - nvroot = fnvlist_lookup_nvlist(zhp->zpool_config, - ZPOOL_CONFIG_VDEV_TREE); - - *avail_spare = B_FALSE; - *l2cache = B_FALSE; - if (log != NULL) - *log = B_FALSE; - ret = vdev_to_nvlist_iter(nvroot, search, avail_spare, l2cache, log, - B_FALSE); - fnvlist_free(search); - - return (ret); -} - -/* - * Determine if we have an "interior" top-level vdev (i.e mirror/raidz). - */ -static boolean_t -zpool_vdev_is_interior(const char *name) -{ - if (strncmp(name, VDEV_TYPE_RAIDZ, strlen(VDEV_TYPE_RAIDZ)) == 0 || - strncmp(name, VDEV_TYPE_SPARE, strlen(VDEV_TYPE_SPARE)) == 0 || - strncmp(name, - VDEV_TYPE_REPLACING, strlen(VDEV_TYPE_REPLACING)) == 0 || - strncmp(name, VDEV_TYPE_ROOT, strlen(VDEV_TYPE_ROOT)) == 0 || - strncmp(name, VDEV_TYPE_MIRROR, strlen(VDEV_TYPE_MIRROR)) == 0) - return (B_TRUE); - - if (strncmp(name, VDEV_TYPE_DRAID, strlen(VDEV_TYPE_DRAID)) == 0 && - !zpool_is_draid_spare(name)) - return (B_TRUE); - - return (B_FALSE); -} - -/* - * Lookup the nvlist for a given vdev or vdev's parent (depending on - * if 'return_parent' is set). - */ -static nvlist_t * -__zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare, - boolean_t *l2cache, boolean_t *log, boolean_t return_parent) -{ - char *end; - nvlist_t *nvroot, *search, *ret; - uint64_t guid; - boolean_t __avail_spare, __l2cache, __log; - - search = fnvlist_alloc(); - - guid = strtoull(path, &end, 0); - if (guid != 0 && *end == '\0') { - fnvlist_add_uint64(search, ZPOOL_CONFIG_GUID, guid); - } else if (zpool_vdev_is_interior(path)) { - fnvlist_add_string(search, ZPOOL_CONFIG_TYPE, path); - } else { - fnvlist_add_string(search, ZPOOL_CONFIG_PATH, path); - } - - nvroot = fnvlist_lookup_nvlist(zhp->zpool_config, - ZPOOL_CONFIG_VDEV_TREE); - - /* - * User can pass NULL for avail_spare, l2cache, and log, but - * we still need to provide variables to vdev_to_nvlist_iter(), so - * just point them to junk variables here. - */ - if (!avail_spare) - avail_spare = &__avail_spare; - if (!l2cache) - l2cache = &__l2cache; - if (!log) - log = &__log; - - *avail_spare = B_FALSE; - *l2cache = B_FALSE; - if (log != NULL) - *log = B_FALSE; - ret = vdev_to_nvlist_iter(nvroot, search, avail_spare, l2cache, log, - return_parent); - fnvlist_free(search); - - return (ret); -} - -nvlist_t * -zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare, - boolean_t *l2cache, boolean_t *log) -{ - return (__zpool_find_vdev(zhp, path, avail_spare, l2cache, log, - B_FALSE)); -} - -/* Given a vdev path, return its parent's nvlist */ -nvlist_t * -zpool_find_parent_vdev(zpool_handle_t *zhp, const char *path, - boolean_t *avail_spare, boolean_t *l2cache, boolean_t *log) -{ - return (__zpool_find_vdev(zhp, path, avail_spare, l2cache, log, - B_TRUE)); -} - -/* - * Convert a vdev path to a GUID. Returns GUID or 0 on error. - * - * If is_spare, is_l2cache, or is_log is non-NULL, then store within it - * if the VDEV is a spare, l2cache, or log device. If they're NULL then - * ignore them. - */ -static uint64_t -zpool_vdev_path_to_guid_impl(zpool_handle_t *zhp, const char *path, - boolean_t *is_spare, boolean_t *is_l2cache, boolean_t *is_log) -{ - boolean_t spare = B_FALSE, l2cache = B_FALSE, log = B_FALSE; - nvlist_t *tgt; - - if ((tgt = zpool_find_vdev(zhp, path, &spare, &l2cache, - &log)) == NULL) - return (0); - - if (is_spare != NULL) - *is_spare = spare; - if (is_l2cache != NULL) - *is_l2cache = l2cache; - if (is_log != NULL) - *is_log = log; - - return (fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID)); -} - -/* Convert a vdev path to a GUID. Returns GUID or 0 on error. */ -uint64_t -zpool_vdev_path_to_guid(zpool_handle_t *zhp, const char *path) -{ - return (zpool_vdev_path_to_guid_impl(zhp, path, NULL, NULL, NULL)); -} - -/* - * Bring the specified vdev online. The 'flags' parameter is a set of the - * ZFS_ONLINE_* flags. - */ -int -zpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags, - vdev_state_t *newstate) -{ - zfs_cmd_t zc = {"\0"}; - char errbuf[ERRBUFLEN]; - nvlist_t *tgt; - boolean_t avail_spare, l2cache, islog; - libzfs_handle_t *hdl = zhp->zpool_hdl; - - if (flags & ZFS_ONLINE_EXPAND) { - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot expand %s"), path); - } else { - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot online %s"), path); - } - - (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); - if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache, - &islog)) == NULL) - return (zfs_error(hdl, EZFS_NODEVICE, errbuf)); - - zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID); - - if (!(flags & ZFS_ONLINE_SPARE) && avail_spare) - return (zfs_error(hdl, EZFS_ISSPARE, errbuf)); - -#ifndef __FreeBSD__ - const char *pathname; - if ((flags & ZFS_ONLINE_EXPAND || - zpool_get_prop_int(zhp, ZPOOL_PROP_AUTOEXPAND, NULL)) && - nvlist_lookup_string(tgt, ZPOOL_CONFIG_PATH, &pathname) == 0) { - uint64_t wholedisk = 0; - - (void) nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_WHOLE_DISK, - &wholedisk); - - /* - * XXX - L2ARC 1.0 devices can't support expansion. - */ - if (l2cache) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "cannot expand cache devices")); - return (zfs_error(hdl, EZFS_VDEVNOTSUP, errbuf)); - } - - if (wholedisk) { - const char *fullpath = path; - char buf[MAXPATHLEN]; - int error; - - if (path[0] != '/') { - error = zfs_resolve_shortname(path, buf, - sizeof (buf)); - if (error != 0) - return (zfs_error(hdl, EZFS_NODEVICE, - errbuf)); - - fullpath = buf; - } - - error = zpool_relabel_disk(hdl, fullpath, errbuf); - if (error != 0) - return (error); - } - } -#endif - - zc.zc_cookie = VDEV_STATE_ONLINE; - zc.zc_obj = flags; - - if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) != 0) { - if (errno == EINVAL) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "was split " - "from this pool into a new one. Use '%s' " - "instead"), "zpool detach"); - return (zfs_error(hdl, EZFS_POSTSPLIT_ONLINE, errbuf)); - } - return (zpool_standard_error(hdl, errno, errbuf)); - } - - *newstate = zc.zc_cookie; - return (0); -} - -/* - * Take the specified vdev offline - */ -int -zpool_vdev_offline(zpool_handle_t *zhp, const char *path, boolean_t istmp) -{ - zfs_cmd_t zc = {"\0"}; - char errbuf[ERRBUFLEN]; - nvlist_t *tgt; - boolean_t avail_spare, l2cache; - libzfs_handle_t *hdl = zhp->zpool_hdl; - - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot offline %s"), path); - - (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); - if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache, - NULL)) == NULL) - return (zfs_error(hdl, EZFS_NODEVICE, errbuf)); - - zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID); - - if (avail_spare) - return (zfs_error(hdl, EZFS_ISSPARE, errbuf)); - - zc.zc_cookie = VDEV_STATE_OFFLINE; - zc.zc_obj = istmp ? ZFS_OFFLINE_TEMPORARY : 0; - - if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) == 0) - return (0); - - switch (errno) { - case EBUSY: - - /* - * There are no other replicas of this device. - */ - return (zfs_error(hdl, EZFS_NOREPLICAS, errbuf)); - - case EEXIST: - /* - * The log device has unplayed logs - */ - return (zfs_error(hdl, EZFS_UNPLAYED_LOGS, errbuf)); - - default: - return (zpool_standard_error(hdl, errno, errbuf)); - } -} - -/* - * Remove the specified vdev asynchronously from the configuration, so - * that it may come ONLINE if reinserted. This is called from zed on - * Udev remove event. - * Note: We also have a similar function zpool_vdev_remove() that - * removes the vdev from the pool. - */ -int -zpool_vdev_remove_wanted(zpool_handle_t *zhp, const char *path) -{ - zfs_cmd_t zc = {"\0"}; - char errbuf[ERRBUFLEN]; - nvlist_t *tgt; - boolean_t avail_spare, l2cache; - libzfs_handle_t *hdl = zhp->zpool_hdl; - - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot remove %s"), path); - - (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); - if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache, - NULL)) == NULL) - return (zfs_error(hdl, EZFS_NODEVICE, errbuf)); - - zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID); - - zc.zc_cookie = VDEV_STATE_REMOVED; - - if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) == 0) - return (0); - - return (zpool_standard_error(hdl, errno, errbuf)); -} - -/* - * Mark the given vdev faulted. - */ -int -zpool_vdev_fault(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux) -{ - zfs_cmd_t zc = {"\0"}; - char errbuf[ERRBUFLEN]; - libzfs_handle_t *hdl = zhp->zpool_hdl; - - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot fault %llu"), (u_longlong_t)guid); - - (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); - zc.zc_guid = guid; - zc.zc_cookie = VDEV_STATE_FAULTED; - zc.zc_obj = aux; - - if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) == 0) - return (0); - - switch (errno) { - case EBUSY: - - /* - * There are no other replicas of this device. - */ - return (zfs_error(hdl, EZFS_NOREPLICAS, errbuf)); - - default: - return (zpool_standard_error(hdl, errno, errbuf)); - } - -} - -/* - * Generic set vdev state function - */ -static int -zpool_vdev_set_state(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux, - vdev_state_t state) -{ - zfs_cmd_t zc = {"\0"}; - char errbuf[ERRBUFLEN]; - libzfs_handle_t *hdl = zhp->zpool_hdl; - - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot set %s %llu"), - zpool_state_to_name(state, aux), (u_longlong_t)guid); - - (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); - zc.zc_guid = guid; - zc.zc_cookie = state; - zc.zc_obj = aux; - - if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) == 0) - return (0); - - return (zpool_standard_error(hdl, errno, errbuf)); -} - -/* - * Mark the given vdev degraded. - */ -int -zpool_vdev_degrade(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux) -{ - return (zpool_vdev_set_state(zhp, guid, aux, VDEV_STATE_DEGRADED)); -} - -/* - * Mark the given vdev as in a removed state (as if the device does not exist). - * - * This is different than zpool_vdev_remove() which does a removal of a device - * from the pool (but the device does exist). - */ -int -zpool_vdev_set_removed_state(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux) -{ - return (zpool_vdev_set_state(zhp, guid, aux, VDEV_STATE_REMOVED)); -} - -/* - * Returns TRUE if the given nvlist is a vdev that was originally swapped in as - * a hot spare. - */ -static boolean_t -is_replacing_spare(nvlist_t *search, nvlist_t *tgt, int which) -{ - nvlist_t **child; - uint_t c, children; - - if (nvlist_lookup_nvlist_array(search, ZPOOL_CONFIG_CHILDREN, &child, - &children) == 0) { - const char *type = fnvlist_lookup_string(search, - ZPOOL_CONFIG_TYPE); - if ((strcmp(type, VDEV_TYPE_SPARE) == 0 || - strcmp(type, VDEV_TYPE_DRAID_SPARE) == 0) && - children == 2 && child[which] == tgt) - return (B_TRUE); - - for (c = 0; c < children; c++) - if (is_replacing_spare(child[c], tgt, which)) - return (B_TRUE); - } - - return (B_FALSE); -} - -/* - * Attach new_disk (fully described by nvroot) to old_disk. - * If 'replacing' is specified, the new disk will replace the old one. - */ -int -zpool_vdev_attach(zpool_handle_t *zhp, const char *old_disk, - const char *new_disk, nvlist_t *nvroot, int replacing, boolean_t rebuild) -{ - zfs_cmd_t zc = {"\0"}; - char errbuf[ERRBUFLEN]; - int ret; - nvlist_t *tgt; - boolean_t avail_spare, l2cache, islog; - uint64_t val; - char *newname; - const char *type; - nvlist_t **child; - uint_t children; - nvlist_t *config_root; - libzfs_handle_t *hdl = zhp->zpool_hdl; - - if (replacing) - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot replace %s with %s"), old_disk, new_disk); - else - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot attach %s to %s"), new_disk, old_disk); - - (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); - if ((tgt = zpool_find_vdev(zhp, old_disk, &avail_spare, &l2cache, - &islog)) == NULL) - return (zfs_error(hdl, EZFS_NODEVICE, errbuf)); - - if (avail_spare) - return (zfs_error(hdl, EZFS_ISSPARE, errbuf)); - - if (l2cache) - return (zfs_error(hdl, EZFS_ISL2CACHE, errbuf)); - - zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID); - zc.zc_cookie = replacing; - zc.zc_simple = rebuild; - - if (rebuild && - zfeature_lookup_guid("org.openzfs:device_rebuild", NULL) != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "the loaded zfs module doesn't support device rebuilds")); - return (zfs_error(hdl, EZFS_POOL_NOTSUP, errbuf)); - } - - type = fnvlist_lookup_string(tgt, ZPOOL_CONFIG_TYPE); - if (strcmp(type, VDEV_TYPE_RAIDZ) == 0 && - zfeature_lookup_guid("org.openzfs:raidz_expansion", NULL) != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "the loaded zfs module doesn't support raidz expansion")); - return (zfs_error(hdl, EZFS_POOL_NOTSUP, errbuf)); - } - - if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, - &child, &children) != 0 || children != 1) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "new device must be a single disk")); - return (zfs_error(hdl, EZFS_INVALCONFIG, errbuf)); - } - - config_root = fnvlist_lookup_nvlist(zpool_get_config(zhp, NULL), - ZPOOL_CONFIG_VDEV_TREE); - - if ((newname = zpool_vdev_name(NULL, NULL, child[0], 0)) == NULL) - return (-1); - - /* - * If the target is a hot spare that has been swapped in, we can only - * replace it with another hot spare. - */ - if (replacing && - nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_SPARE, &val) == 0 && - (zpool_find_vdev(zhp, newname, &avail_spare, &l2cache, - NULL) == NULL || !avail_spare) && - is_replacing_spare(config_root, tgt, 1)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "can only be replaced by another hot spare")); - free(newname); - return (zfs_error(hdl, EZFS_BADTARGET, errbuf)); - } - - free(newname); - - zcmd_write_conf_nvlist(hdl, &zc, nvroot); - - ret = zfs_ioctl(hdl, ZFS_IOC_VDEV_ATTACH, &zc); - - zcmd_free_nvlists(&zc); - - if (ret == 0) - return (0); - - switch (errno) { - case ENOTSUP: - /* - * Can't attach to or replace this type of vdev. - */ - if (replacing) { - uint64_t version = zpool_get_prop_int(zhp, - ZPOOL_PROP_VERSION, NULL); - - if (islog) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "cannot replace a log with a spare")); - } else if (rebuild) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "only mirror and dRAID vdevs support " - "sequential reconstruction")); - } else if (zpool_is_draid_spare(new_disk)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "dRAID spares can only replace child " - "devices in their parent's dRAID vdev")); - } else if (version >= SPA_VERSION_MULTI_REPLACE) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "already in replacing/spare config; wait " - "for completion or use 'zpool detach'")); - } else { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "cannot replace a replacing device")); - } - } else if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "raidz_expansion feature must be enabled " - "in order to attach a device to raidz")); - } else { - char status[64] = {0}; - zpool_prop_get_feature(zhp, - "feature@device_rebuild", status, 63); - if (rebuild && - strncmp(status, ZFS_FEATURE_DISABLED, 64) == 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "device_rebuild feature must be enabled " - "in order to use sequential " - "reconstruction")); - } else { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "can only attach to mirrors and top-level " - "disks")); - } - } - (void) zfs_error(hdl, EZFS_BADTARGET, errbuf); - break; - - case EINVAL: - /* - * The new device must be a single disk. - */ - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "new device must be a single disk")); - (void) zfs_error(hdl, EZFS_INVALCONFIG, errbuf); - break; - - case EBUSY: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy"), - new_disk); - (void) zfs_error(hdl, EZFS_BADDEV, errbuf); - break; - - case EOVERFLOW: - /* - * The new device is too small. - */ - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "device is too small")); - (void) zfs_error(hdl, EZFS_BADDEV, errbuf); - break; - - case EDOM: - /* - * The new device has a different optimal sector size. - */ - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "new device has a different optimal sector size; use the " - "option '-o ashift=N' to override the optimal size")); - (void) zfs_error(hdl, EZFS_BADDEV, errbuf); - break; - - case ENAMETOOLONG: - /* - * The resulting top-level vdev spec won't fit in the label. - */ - (void) zfs_error(hdl, EZFS_DEVOVERFLOW, errbuf); - break; - - case ENXIO: - /* - * The existing raidz vdev has offline children - */ - if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "raidz vdev has devices that are are offline or " - "being replaced")); - (void) zfs_error(hdl, EZFS_BADDEV, errbuf); - break; - } else { - (void) zpool_standard_error(hdl, errno, errbuf); - } - break; - - case EADDRINUSE: - /* - * The boot reserved area is already being used (FreeBSD) - */ - if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "the reserved boot area needed for the expansion " - "is already being used by a boot loader")); - (void) zfs_error(hdl, EZFS_BADDEV, errbuf); - } else { - (void) zpool_standard_error(hdl, errno, errbuf); - } - break; - - case ZFS_ERR_ASHIFT_MISMATCH: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "The new device cannot have a higher alignment requirement " - "than the top-level vdev.")); - (void) zfs_error(hdl, EZFS_BADTARGET, errbuf); - break; - default: - (void) zpool_standard_error(hdl, errno, errbuf); - } - - return (-1); -} - -/* - * Detach the specified device. - */ -int -zpool_vdev_detach(zpool_handle_t *zhp, const char *path) -{ - zfs_cmd_t zc = {"\0"}; - char errbuf[ERRBUFLEN]; - nvlist_t *tgt; - boolean_t avail_spare, l2cache; - libzfs_handle_t *hdl = zhp->zpool_hdl; - - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot detach %s"), path); - - (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); - if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache, - NULL)) == NULL) - return (zfs_error(hdl, EZFS_NODEVICE, errbuf)); - - if (avail_spare) - return (zfs_error(hdl, EZFS_ISSPARE, errbuf)); - - if (l2cache) - return (zfs_error(hdl, EZFS_ISL2CACHE, errbuf)); - - zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID); - - if (zfs_ioctl(hdl, ZFS_IOC_VDEV_DETACH, &zc) == 0) - return (0); - - switch (errno) { - - case ENOTSUP: - /* - * Can't detach from this type of vdev. - */ - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only " - "applicable to mirror and replacing vdevs")); - (void) zfs_error(hdl, EZFS_BADTARGET, errbuf); - break; - - case EBUSY: - /* - * There are no other replicas of this device. - */ - (void) zfs_error(hdl, EZFS_NOREPLICAS, errbuf); - break; - - default: - (void) zpool_standard_error(hdl, errno, errbuf); - } - - return (-1); -} - -/* - * Find a mirror vdev in the source nvlist. - * - * The mchild array contains a list of disks in one of the top-level mirrors - * of the source pool. The schild array contains a list of disks that the - * user specified on the command line. We loop over the mchild array to - * see if any entry in the schild array matches. - * - * If a disk in the mchild array is found in the schild array, we return - * the index of that entry. Otherwise we return -1. - */ -static int -find_vdev_entry(zpool_handle_t *zhp, nvlist_t **mchild, uint_t mchildren, - nvlist_t **schild, uint_t schildren) -{ - uint_t mc; - - for (mc = 0; mc < mchildren; mc++) { - uint_t sc; - char *mpath = zpool_vdev_name(zhp->zpool_hdl, zhp, - mchild[mc], 0); - - for (sc = 0; sc < schildren; sc++) { - char *spath = zpool_vdev_name(zhp->zpool_hdl, zhp, - schild[sc], 0); - boolean_t result = (strcmp(mpath, spath) == 0); - - free(spath); - if (result) { - free(mpath); - return (mc); - } - } - - free(mpath); - } - - return (-1); -} - -/* - * Split a mirror pool. If newroot points to null, then a new nvlist - * is generated and it is the responsibility of the caller to free it. - */ -int -zpool_vdev_split(zpool_handle_t *zhp, char *newname, nvlist_t **newroot, - nvlist_t *props, splitflags_t flags) -{ - zfs_cmd_t zc = {"\0"}; - char errbuf[ERRBUFLEN]; - const char *bias; - nvlist_t *tree, *config, **child, **newchild, *newconfig = NULL; - nvlist_t **varray = NULL, *zc_props = NULL; - uint_t c, children, newchildren, lastlog = 0, vcount, found = 0; - libzfs_handle_t *hdl = zhp->zpool_hdl; - uint64_t vers, readonly = B_FALSE; - boolean_t freelist = B_FALSE, memory_err = B_TRUE; - int retval = 0; - - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "Unable to split %s"), zhp->zpool_name); - - if (!zpool_name_valid(hdl, B_FALSE, newname)) - return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); - - if ((config = zpool_get_config(zhp, NULL)) == NULL) { - (void) fprintf(stderr, gettext("Internal error: unable to " - "retrieve pool configuration\n")); - return (-1); - } - - tree = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE); - vers = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION); - - if (props) { - prop_flags_t flags = { .create = B_FALSE, .import = B_TRUE }; - if ((zc_props = zpool_valid_proplist(hdl, zhp->zpool_name, - props, vers, flags, errbuf)) == NULL) - return (-1); - (void) nvlist_lookup_uint64(zc_props, - zpool_prop_to_name(ZPOOL_PROP_READONLY), &readonly); - if (readonly) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "property %s can only be set at import time"), - zpool_prop_to_name(ZPOOL_PROP_READONLY)); - return (-1); - } - } - - if (nvlist_lookup_nvlist_array(tree, ZPOOL_CONFIG_CHILDREN, &child, - &children) != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Source pool is missing vdev tree")); - nvlist_free(zc_props); - return (-1); - } - - varray = zfs_alloc(hdl, children * sizeof (nvlist_t *)); - vcount = 0; - - if (*newroot == NULL || - nvlist_lookup_nvlist_array(*newroot, ZPOOL_CONFIG_CHILDREN, - &newchild, &newchildren) != 0) - newchildren = 0; - - for (c = 0; c < children; c++) { - uint64_t is_log = B_FALSE, is_hole = B_FALSE; - boolean_t is_special = B_FALSE, is_dedup = B_FALSE; - const char *type; - nvlist_t **mchild, *vdev; - uint_t mchildren; - int entry; - - /* - * Unlike cache & spares, slogs are stored in the - * ZPOOL_CONFIG_CHILDREN array. We filter them out here. - */ - (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, - &is_log); - (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE, - &is_hole); - if (is_log || is_hole) { - /* - * Create a hole vdev and put it in the config. - */ - if (nvlist_alloc(&vdev, NV_UNIQUE_NAME, 0) != 0) - goto out; - if (nvlist_add_string(vdev, ZPOOL_CONFIG_TYPE, - VDEV_TYPE_HOLE) != 0) - goto out; - if (nvlist_add_uint64(vdev, ZPOOL_CONFIG_IS_HOLE, - 1) != 0) - goto out; - if (lastlog == 0) - lastlog = vcount; - varray[vcount++] = vdev; - continue; - } - lastlog = 0; - type = fnvlist_lookup_string(child[c], ZPOOL_CONFIG_TYPE); - - if (strcmp(type, VDEV_TYPE_INDIRECT) == 0) { - vdev = child[c]; - if (nvlist_dup(vdev, &varray[vcount++], 0) != 0) - goto out; - continue; - } else if (strcmp(type, VDEV_TYPE_MIRROR) != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Source pool must be composed only of mirrors\n")); - retval = zfs_error(hdl, EZFS_INVALCONFIG, errbuf); - goto out; - } - - if (nvlist_lookup_string(child[c], - ZPOOL_CONFIG_ALLOCATION_BIAS, &bias) == 0) { - if (strcmp(bias, VDEV_ALLOC_BIAS_SPECIAL) == 0) - is_special = B_TRUE; - else if (strcmp(bias, VDEV_ALLOC_BIAS_DEDUP) == 0) - is_dedup = B_TRUE; - } - verify(nvlist_lookup_nvlist_array(child[c], - ZPOOL_CONFIG_CHILDREN, &mchild, &mchildren) == 0); - - /* find or add an entry for this top-level vdev */ - if (newchildren > 0 && - (entry = find_vdev_entry(zhp, mchild, mchildren, - newchild, newchildren)) >= 0) { - /* We found a disk that the user specified. */ - vdev = mchild[entry]; - ++found; - } else { - /* User didn't specify a disk for this vdev. */ - vdev = mchild[mchildren - 1]; - } - - if (nvlist_dup(vdev, &varray[vcount++], 0) != 0) - goto out; - - if (flags.dryrun != 0) { - if (is_dedup == B_TRUE) { - if (nvlist_add_string(varray[vcount - 1], - ZPOOL_CONFIG_ALLOCATION_BIAS, - VDEV_ALLOC_BIAS_DEDUP) != 0) - goto out; - } else if (is_special == B_TRUE) { - if (nvlist_add_string(varray[vcount - 1], - ZPOOL_CONFIG_ALLOCATION_BIAS, - VDEV_ALLOC_BIAS_SPECIAL) != 0) - goto out; - } - } - } - - /* did we find every disk the user specified? */ - if (found != newchildren) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "Device list must " - "include at most one disk from each mirror")); - retval = zfs_error(hdl, EZFS_INVALCONFIG, errbuf); - goto out; - } - - /* Prepare the nvlist for populating. */ - if (*newroot == NULL) { - if (nvlist_alloc(newroot, NV_UNIQUE_NAME, 0) != 0) - goto out; - freelist = B_TRUE; - if (nvlist_add_string(*newroot, ZPOOL_CONFIG_TYPE, - VDEV_TYPE_ROOT) != 0) - goto out; - } else { - verify(nvlist_remove_all(*newroot, ZPOOL_CONFIG_CHILDREN) == 0); - } - - /* Add all the children we found */ - if (nvlist_add_nvlist_array(*newroot, ZPOOL_CONFIG_CHILDREN, - (const nvlist_t **)varray, lastlog == 0 ? vcount : lastlog) != 0) - goto out; - - /* - * If we're just doing a dry run, exit now with success. - */ - if (flags.dryrun) { - memory_err = B_FALSE; - freelist = B_FALSE; - goto out; - } - - /* now build up the config list & call the ioctl */ - if (nvlist_alloc(&newconfig, NV_UNIQUE_NAME, 0) != 0) - goto out; - - if (nvlist_add_nvlist(newconfig, - ZPOOL_CONFIG_VDEV_TREE, *newroot) != 0 || - nvlist_add_string(newconfig, - ZPOOL_CONFIG_POOL_NAME, newname) != 0 || - nvlist_add_uint64(newconfig, ZPOOL_CONFIG_VERSION, vers) != 0) - goto out; - - /* - * The new pool is automatically part of the namespace unless we - * explicitly export it. - */ - if (!flags.import) - zc.zc_cookie = ZPOOL_EXPORT_AFTER_SPLIT; - (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); - (void) strlcpy(zc.zc_string, newname, sizeof (zc.zc_string)); - zcmd_write_conf_nvlist(hdl, &zc, newconfig); - if (zc_props != NULL) - zcmd_write_src_nvlist(hdl, &zc, zc_props); - - if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SPLIT, &zc) != 0) { - retval = zpool_standard_error(hdl, errno, errbuf); - goto out; - } - - freelist = B_FALSE; - memory_err = B_FALSE; - -out: - if (varray != NULL) { - int v; - - for (v = 0; v < vcount; v++) - nvlist_free(varray[v]); - free(varray); - } - zcmd_free_nvlists(&zc); - nvlist_free(zc_props); - nvlist_free(newconfig); - if (freelist) { - nvlist_free(*newroot); - *newroot = NULL; - } - - if (retval != 0) - return (retval); - - if (memory_err) - return (no_memory(hdl)); - - return (0); -} - -/* - * Remove the given device. - */ -int -zpool_vdev_remove(zpool_handle_t *zhp, const char *path) -{ - zfs_cmd_t zc = {"\0"}; - char errbuf[ERRBUFLEN]; - nvlist_t *tgt; - boolean_t avail_spare, l2cache, islog; - libzfs_handle_t *hdl = zhp->zpool_hdl; - uint64_t version; - - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot remove %s"), path); - - if (zpool_is_draid_spare(path)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "dRAID spares cannot be removed")); - return (zfs_error(hdl, EZFS_NODEVICE, errbuf)); - } - - (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); - if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache, - &islog)) == NULL) - return (zfs_error(hdl, EZFS_NODEVICE, errbuf)); - - version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL); - if (islog && version < SPA_VERSION_HOLES) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "pool must be upgraded to support log removal")); - return (zfs_error(hdl, EZFS_BADVERSION, errbuf)); - } - - zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID); - - if (zfs_ioctl(hdl, ZFS_IOC_VDEV_REMOVE, &zc) == 0) - return (0); - - switch (errno) { - - case EALREADY: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "removal for this vdev is already in progress.")); - (void) zfs_error(hdl, EZFS_BUSY, errbuf); - break; - - case EINVAL: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "invalid config; all top-level vdevs must " - "have the same sector size and not be raidz.")); - (void) zfs_error(hdl, EZFS_INVALCONFIG, errbuf); - break; - - case EBUSY: - if (islog) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Mount encrypted datasets to replay logs.")); - } else { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Pool busy; removal may already be in progress")); - } - (void) zfs_error(hdl, EZFS_BUSY, errbuf); - break; - - case EACCES: - if (islog) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Mount encrypted datasets to replay logs.")); - (void) zfs_error(hdl, EZFS_BUSY, errbuf); - } else { - (void) zpool_standard_error(hdl, errno, errbuf); - } - break; - - default: - (void) zpool_standard_error(hdl, errno, errbuf); - } - return (-1); -} - -int -zpool_vdev_remove_cancel(zpool_handle_t *zhp) -{ - zfs_cmd_t zc = {{0}}; - char errbuf[ERRBUFLEN]; - libzfs_handle_t *hdl = zhp->zpool_hdl; - - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot cancel removal")); - - (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); - zc.zc_cookie = 1; - - if (zfs_ioctl(hdl, ZFS_IOC_VDEV_REMOVE, &zc) == 0) - return (0); - - return (zpool_standard_error(hdl, errno, errbuf)); -} - -int -zpool_vdev_indirect_size(zpool_handle_t *zhp, const char *path, - uint64_t *sizep) -{ - char errbuf[ERRBUFLEN]; - nvlist_t *tgt; - boolean_t avail_spare, l2cache, islog; - libzfs_handle_t *hdl = zhp->zpool_hdl; - - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot determine indirect size of %s"), - path); - - if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache, - &islog)) == NULL) - return (zfs_error(hdl, EZFS_NODEVICE, errbuf)); - - if (avail_spare || l2cache || islog) { - *sizep = 0; - return (0); - } - - if (nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_INDIRECT_SIZE, sizep) != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "indirect size not available")); - return (zfs_error(hdl, EINVAL, errbuf)); - } - return (0); -} - -/* - * Clear the errors for the pool, or the particular device if specified. - */ -int -zpool_clear(zpool_handle_t *zhp, const char *path, nvlist_t *rewindnvl) -{ - zfs_cmd_t zc = {"\0"}; - char errbuf[ERRBUFLEN]; - nvlist_t *tgt; - zpool_load_policy_t policy; - boolean_t avail_spare, l2cache; - libzfs_handle_t *hdl = zhp->zpool_hdl; - nvlist_t *nvi = NULL; - int error; - - if (path) - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), - path); - else - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), - zhp->zpool_name); - - (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); - if (path) { - if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, - &l2cache, NULL)) == NULL) - return (zfs_error(hdl, EZFS_NODEVICE, errbuf)); - - /* - * Don't allow error clearing for hot spares. Do allow - * error clearing for l2cache devices. - */ - if (avail_spare) - return (zfs_error(hdl, EZFS_ISSPARE, errbuf)); - - zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID); - } - - zpool_get_load_policy(rewindnvl, &policy); - zc.zc_cookie = policy.zlp_rewind; - - zcmd_alloc_dst_nvlist(hdl, &zc, zhp->zpool_config_size * 2); - zcmd_write_src_nvlist(hdl, &zc, rewindnvl); - - while ((error = zfs_ioctl(hdl, ZFS_IOC_CLEAR, &zc)) != 0 && - errno == ENOMEM) - zcmd_expand_dst_nvlist(hdl, &zc); - - if (!error || ((policy.zlp_rewind & ZPOOL_TRY_REWIND) && - errno != EPERM && errno != EACCES)) { - if (policy.zlp_rewind & - (ZPOOL_DO_REWIND | ZPOOL_TRY_REWIND)) { - (void) zcmd_read_dst_nvlist(hdl, &zc, &nvi); - zpool_rewind_exclaim(hdl, zc.zc_name, - ((policy.zlp_rewind & ZPOOL_TRY_REWIND) != 0), - nvi); - nvlist_free(nvi); - } - zcmd_free_nvlists(&zc); - return (0); - } - - zcmd_free_nvlists(&zc); - return (zpool_standard_error(hdl, errno, errbuf)); -} - -/* - * Similar to zpool_clear(), but takes a GUID (used by fmd). - */ -int -zpool_vdev_clear(zpool_handle_t *zhp, uint64_t guid) -{ - zfs_cmd_t zc = {"\0"}; - char errbuf[ERRBUFLEN]; - libzfs_handle_t *hdl = zhp->zpool_hdl; - - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot clear errors for %llx"), - (u_longlong_t)guid); - - (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); - zc.zc_guid = guid; - zc.zc_cookie = ZPOOL_NO_REWIND; - - if (zfs_ioctl(hdl, ZFS_IOC_CLEAR, &zc) == 0) - return (0); - - return (zpool_standard_error(hdl, errno, errbuf)); -} - -/* - * Change the GUID for a pool. - * - * Similar to zpool_reguid(), but may take a GUID. - * - * If the guid argument is NULL, then no GUID is passed in the nvlist to the - * ioctl(). - */ -int -zpool_set_guid(zpool_handle_t *zhp, const uint64_t *guid) -{ - char errbuf[ERRBUFLEN]; - libzfs_handle_t *hdl = zhp->zpool_hdl; - nvlist_t *nvl = NULL; - zfs_cmd_t zc = {"\0"}; - int error; - - if (guid != NULL) { - if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) - return (no_memory(hdl)); - - if (nvlist_add_uint64(nvl, ZPOOL_REGUID_GUID, *guid) != 0) { - nvlist_free(nvl); - return (no_memory(hdl)); - } - - zcmd_write_src_nvlist(hdl, &zc, nvl); - } - - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot reguid '%s'"), zhp->zpool_name); - - (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); - error = zfs_ioctl(hdl, ZFS_IOC_POOL_REGUID, &zc); - if (error) { - return (zpool_standard_error(hdl, errno, errbuf)); - } - if (guid != NULL) { - zcmd_free_nvlists(&zc); - nvlist_free(nvl); - } - return (0); -} - -/* - * Change the GUID for a pool. - */ -int -zpool_reguid(zpool_handle_t *zhp) -{ - return (zpool_set_guid(zhp, NULL)); -} - -/* - * Reopen the pool. - */ -int -zpool_reopen_one(zpool_handle_t *zhp, void *data) -{ - libzfs_handle_t *hdl = zpool_get_handle(zhp); - const char *pool_name = zpool_get_name(zhp); - boolean_t *scrub_restart = data; - int error; - - error = lzc_reopen(pool_name, *scrub_restart); - if (error) { - return (zpool_standard_error_fmt(hdl, error, - dgettext(TEXT_DOMAIN, "cannot reopen '%s'"), pool_name)); - } - - return (0); -} - -/* call into libzfs_core to execute the sync IOCTL per pool */ -int -zpool_sync_one(zpool_handle_t *zhp, void *data) -{ - int ret; - libzfs_handle_t *hdl = zpool_get_handle(zhp); - const char *pool_name = zpool_get_name(zhp); - boolean_t *force = data; - nvlist_t *innvl = fnvlist_alloc(); - - fnvlist_add_boolean_value(innvl, "force", *force); - if ((ret = lzc_sync(pool_name, innvl, NULL)) != 0) { - nvlist_free(innvl); - return (zpool_standard_error_fmt(hdl, ret, - dgettext(TEXT_DOMAIN, "sync '%s' failed"), pool_name)); - } - nvlist_free(innvl); - - return (0); -} - -#define PATH_BUF_LEN 64 - -/* - * Given a vdev, return the name to display in iostat. If the vdev has a path, - * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type. - * We also check if this is a whole disk, in which case we strip off the - * trailing 's0' slice name. - * - * This routine is also responsible for identifying when disks have been - * reconfigured in a new location. The kernel will have opened the device by - * devid, but the path will still refer to the old location. To catch this, we - * first do a path -> devid translation (which is fast for the common case). If - * the devid matches, we're done. If not, we do a reverse devid -> path - * translation and issue the appropriate ioctl() to update the path of the vdev. - * If 'zhp' is NULL, then this is an exported pool, and we don't need to do any - * of these checks. - */ -char * -zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv, - int name_flags) -{ - const char *type, *tpath; - const char *path; - uint64_t value; - char buf[PATH_BUF_LEN]; - char tmpbuf[PATH_BUF_LEN * 2]; - - /* - * vdev_name will be "root"/"root-0" for the root vdev, but it is the - * zpool name that will be displayed to the user. - */ - type = fnvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE); - if (zhp != NULL && strcmp(type, "root") == 0) - return (zfs_strdup(hdl, zpool_get_name(zhp))); - - if (libzfs_envvar_is_set("ZPOOL_VDEV_NAME_PATH")) - name_flags |= VDEV_NAME_PATH; - if (libzfs_envvar_is_set("ZPOOL_VDEV_NAME_GUID")) - name_flags |= VDEV_NAME_GUID; - if (libzfs_envvar_is_set("ZPOOL_VDEV_NAME_FOLLOW_LINKS")) - name_flags |= VDEV_NAME_FOLLOW_LINKS; - - if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, &value) == 0 || - name_flags & VDEV_NAME_GUID) { - (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &value); - (void) snprintf(buf, sizeof (buf), "%llu", (u_longlong_t)value); - path = buf; - } else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &tpath) == 0) { - path = tpath; - - if (name_flags & VDEV_NAME_FOLLOW_LINKS) { - char *rp = realpath(path, NULL); - if (rp) { - strlcpy(buf, rp, sizeof (buf)); - path = buf; - free(rp); - } - } - - /* - * For a block device only use the name. - */ - if ((strcmp(type, VDEV_TYPE_DISK) == 0) && - !(name_flags & VDEV_NAME_PATH)) { - path = zfs_strip_path(path); - } - - /* - * Remove the partition from the path if this is a whole disk. - */ - if (strcmp(type, VDEV_TYPE_DRAID_SPARE) != 0 && - nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, &value) - == 0 && value && !(name_flags & VDEV_NAME_PATH)) { - return (zfs_strip_partition(path)); - } - } else { - path = type; - - /* - * If it's a raidz device, we need to stick in the parity level. - */ - if (strcmp(path, VDEV_TYPE_RAIDZ) == 0) { - value = fnvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY); - (void) snprintf(buf, sizeof (buf), "%s%llu", path, - (u_longlong_t)value); - path = buf; - } - - /* - * If it's a dRAID device, we add parity, groups, and spares. - */ - if (strcmp(path, VDEV_TYPE_DRAID) == 0) { - uint64_t ndata, nparity, nspares; - nvlist_t **child; - uint_t children; - - verify(nvlist_lookup_nvlist_array(nv, - ZPOOL_CONFIG_CHILDREN, &child, &children) == 0); - nparity = fnvlist_lookup_uint64(nv, - ZPOOL_CONFIG_NPARITY); - ndata = fnvlist_lookup_uint64(nv, - ZPOOL_CONFIG_DRAID_NDATA); - nspares = fnvlist_lookup_uint64(nv, - ZPOOL_CONFIG_DRAID_NSPARES); - - path = zpool_draid_name(buf, sizeof (buf), ndata, - nparity, nspares, children); - } - - /* - * We identify each top-level vdev by using a <type-id> - * naming convention. - */ - if (name_flags & VDEV_NAME_TYPE_ID) { - uint64_t id = fnvlist_lookup_uint64(nv, - ZPOOL_CONFIG_ID); - (void) snprintf(tmpbuf, sizeof (tmpbuf), "%s-%llu", - path, (u_longlong_t)id); - path = tmpbuf; - } - } - - return (zfs_strdup(hdl, path)); -} - -static int -zbookmark_mem_compare(const void *a, const void *b) -{ - return (memcmp(a, b, sizeof (zbookmark_phys_t))); -} - -void -zpool_add_propname(zpool_handle_t *zhp, const char *propname) -{ - assert(zhp->zpool_n_propnames < ZHP_MAX_PROPNAMES); - zhp->zpool_propnames[zhp->zpool_n_propnames] = propname; - zhp->zpool_n_propnames++; -} - -/* - * Retrieve the persistent error log, uniquify the members, and return to the - * caller. - */ -int -zpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp) -{ - zfs_cmd_t zc = {"\0"}; - libzfs_handle_t *hdl = zhp->zpool_hdl; - zbookmark_phys_t *buf; - uint64_t buflen = 10000; /* approx. 1MB of RAM */ - - if (fnvlist_lookup_uint64(zhp->zpool_config, - ZPOOL_CONFIG_ERRCOUNT) == 0) - return (0); - - /* - * Retrieve the raw error list from the kernel. If it doesn't fit, - * allocate a larger buffer and retry. - */ - (void) strcpy(zc.zc_name, zhp->zpool_name); - for (;;) { - buf = zfs_alloc(zhp->zpool_hdl, - buflen * sizeof (zbookmark_phys_t)); - zc.zc_nvlist_dst = (uintptr_t)buf; - zc.zc_nvlist_dst_size = buflen; - if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_ERROR_LOG, - &zc) != 0) { - free(buf); - if (errno == ENOMEM) { - buflen *= 2; - } else { - return (zpool_standard_error_fmt(hdl, errno, - dgettext(TEXT_DOMAIN, "errors: List of " - "errors unavailable"))); - } - } else { - break; - } - } - - /* - * Sort the resulting bookmarks. This is a little confusing due to the - * implementation of ZFS_IOC_ERROR_LOG. The bookmarks are copied last - * to first, and 'zc_nvlist_dst_size' indicates the number of bookmarks - * _not_ copied as part of the process. So we point the start of our - * array appropriate and decrement the total number of elements. - */ - zbookmark_phys_t *zb = buf + zc.zc_nvlist_dst_size; - uint64_t zblen = buflen - zc.zc_nvlist_dst_size; - - qsort(zb, zblen, sizeof (zbookmark_phys_t), zbookmark_mem_compare); - - verify(nvlist_alloc(nverrlistp, 0, KM_SLEEP) == 0); - - /* - * Fill in the nverrlistp with nvlist's of dataset and object numbers. - */ - for (uint64_t i = 0; i < zblen; i++) { - nvlist_t *nv; - - /* ignoring zb_blkid and zb_level for now */ - if (i > 0 && zb[i-1].zb_objset == zb[i].zb_objset && - zb[i-1].zb_object == zb[i].zb_object) - continue; - - if (nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) != 0) - goto nomem; - if (nvlist_add_uint64(nv, ZPOOL_ERR_DATASET, - zb[i].zb_objset) != 0) { - nvlist_free(nv); - goto nomem; - } - if (nvlist_add_uint64(nv, ZPOOL_ERR_OBJECT, - zb[i].zb_object) != 0) { - nvlist_free(nv); - goto nomem; - } - if (nvlist_add_nvlist(*nverrlistp, "ejk", nv) != 0) { - nvlist_free(nv); - goto nomem; - } - nvlist_free(nv); - } - - free(buf); - return (0); - -nomem: - free(buf); - return (no_memory(zhp->zpool_hdl)); -} - -/* - * Upgrade a ZFS pool to the latest on-disk version. - */ -int -zpool_upgrade(zpool_handle_t *zhp, uint64_t new_version) -{ - zfs_cmd_t zc = {"\0"}; - libzfs_handle_t *hdl = zhp->zpool_hdl; - - (void) strcpy(zc.zc_name, zhp->zpool_name); - zc.zc_cookie = new_version; - - if (zfs_ioctl(hdl, ZFS_IOC_POOL_UPGRADE, &zc) != 0) - return (zpool_standard_error_fmt(hdl, errno, - dgettext(TEXT_DOMAIN, "cannot upgrade '%s'"), - zhp->zpool_name)); - return (0); -} - -void -zfs_save_arguments(int argc, char **argv, char *string, int len) -{ - int i; - - (void) strlcpy(string, zfs_basename(argv[0]), len); - for (i = 1; i < argc; i++) { - (void) strlcat(string, " ", len); - (void) strlcat(string, argv[i], len); - } -} - -int -zpool_log_history(libzfs_handle_t *hdl, const char *message) -{ - zfs_cmd_t zc = {"\0"}; - nvlist_t *args; - - args = fnvlist_alloc(); - fnvlist_add_string(args, "message", message); - zcmd_write_src_nvlist(hdl, &zc, args); - int err = zfs_ioctl(hdl, ZFS_IOC_LOG_HISTORY, &zc); - nvlist_free(args); - zcmd_free_nvlists(&zc); - return (err); -} - -/* - * Perform ioctl to get some command history of a pool. - * - * 'buf' is the buffer to fill up to 'len' bytes. 'off' is the - * logical offset of the history buffer to start reading from. - * - * Upon return, 'off' is the next logical offset to read from and - * 'len' is the actual amount of bytes read into 'buf'. - */ -static int -get_history(zpool_handle_t *zhp, char *buf, uint64_t *off, uint64_t *len) -{ - zfs_cmd_t zc = {"\0"}; - libzfs_handle_t *hdl = zhp->zpool_hdl; - - (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); - - zc.zc_history = (uint64_t)(uintptr_t)buf; - zc.zc_history_len = *len; - zc.zc_history_offset = *off; - - if (zfs_ioctl(hdl, ZFS_IOC_POOL_GET_HISTORY, &zc) != 0) { - switch (errno) { - case EPERM: - return (zfs_error_fmt(hdl, EZFS_PERM, - dgettext(TEXT_DOMAIN, - "cannot show history for pool '%s'"), - zhp->zpool_name)); - case ENOENT: - return (zfs_error_fmt(hdl, EZFS_NOHISTORY, - dgettext(TEXT_DOMAIN, "cannot get history for pool " - "'%s'"), zhp->zpool_name)); - case ENOTSUP: - return (zfs_error_fmt(hdl, EZFS_BADVERSION, - dgettext(TEXT_DOMAIN, "cannot get history for pool " - "'%s', pool must be upgraded"), zhp->zpool_name)); - default: - return (zpool_standard_error_fmt(hdl, errno, - dgettext(TEXT_DOMAIN, - "cannot get history for '%s'"), zhp->zpool_name)); - } - } - - *len = zc.zc_history_len; - *off = zc.zc_history_offset; - - return (0); -} - -/* - * Retrieve the command history of a pool. - */ -int -zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp, uint64_t *off, - boolean_t *eof) -{ - libzfs_handle_t *hdl = zhp->zpool_hdl; - char *buf; - int buflen = 128 * 1024; - nvlist_t **records = NULL; - uint_t numrecords = 0; - int err = 0, i; - uint64_t start = *off; - - buf = zfs_alloc(hdl, buflen); - - /* process about 1MiB a time */ - while (*off - start < 1024 * 1024) { - uint64_t bytes_read = buflen; - uint64_t leftover; - - if ((err = get_history(zhp, buf, off, &bytes_read)) != 0) - break; - - /* if nothing else was read in, we're at EOF, just return */ - if (!bytes_read) { - *eof = B_TRUE; - break; - } - - if ((err = zpool_history_unpack(buf, bytes_read, - &leftover, &records, &numrecords)) != 0) { - zpool_standard_error_fmt(hdl, err, - dgettext(TEXT_DOMAIN, - "cannot get history for '%s'"), zhp->zpool_name); - break; - } - *off -= leftover; - if (leftover == bytes_read) { - /* - * no progress made, because buffer is not big enough - * to hold this record; resize and retry. - */ - buflen *= 2; - free(buf); - buf = zfs_alloc(hdl, buflen); - } - } - - free(buf); - - if (!err) { - *nvhisp = fnvlist_alloc(); - fnvlist_add_nvlist_array(*nvhisp, ZPOOL_HIST_RECORD, - (const nvlist_t **)records, numrecords); - } - for (i = 0; i < numrecords; i++) - nvlist_free(records[i]); - free(records); - - return (err); -} - -/* - * Retrieve the next event given the passed 'zevent_fd' file descriptor. - * If there is a new event available 'nvp' will contain a newly allocated - * nvlist and 'dropped' will be set to the number of missed events since - * the last call to this function. When 'nvp' is set to NULL it indicates - * no new events are available. In either case the function returns 0 and - * it is up to the caller to free 'nvp'. In the case of a fatal error the - * function will return a non-zero value. When the function is called in - * blocking mode (the default, unless the ZEVENT_NONBLOCK flag is passed), - * it will not return until a new event is available. - */ -int -zpool_events_next(libzfs_handle_t *hdl, nvlist_t **nvp, - int *dropped, unsigned flags, int zevent_fd) -{ - zfs_cmd_t zc = {"\0"}; - int error = 0; - - *nvp = NULL; - *dropped = 0; - zc.zc_cleanup_fd = zevent_fd; - - if (flags & ZEVENT_NONBLOCK) - zc.zc_guid = ZEVENT_NONBLOCK; - - zcmd_alloc_dst_nvlist(hdl, &zc, ZEVENT_SIZE); - -retry: - if (zfs_ioctl(hdl, ZFS_IOC_EVENTS_NEXT, &zc) != 0) { - switch (errno) { - case ESHUTDOWN: - error = zfs_error_fmt(hdl, EZFS_POOLUNAVAIL, - dgettext(TEXT_DOMAIN, "zfs shutdown")); - goto out; - case ENOENT: - /* Blocking error case should not occur */ - if (!(flags & ZEVENT_NONBLOCK)) - error = zpool_standard_error_fmt(hdl, errno, - dgettext(TEXT_DOMAIN, "cannot get event")); - - goto out; - case ENOMEM: - zcmd_expand_dst_nvlist(hdl, &zc); - goto retry; - default: - error = zpool_standard_error_fmt(hdl, errno, - dgettext(TEXT_DOMAIN, "cannot get event")); - goto out; - } - } - - error = zcmd_read_dst_nvlist(hdl, &zc, nvp); - if (error != 0) - goto out; - - *dropped = (int)zc.zc_cookie; -out: - zcmd_free_nvlists(&zc); - - return (error); -} - -/* - * Clear all events. - */ -int -zpool_events_clear(libzfs_handle_t *hdl, int *count) -{ - zfs_cmd_t zc = {"\0"}; - - if (zfs_ioctl(hdl, ZFS_IOC_EVENTS_CLEAR, &zc) != 0) - return (zpool_standard_error(hdl, errno, - dgettext(TEXT_DOMAIN, "cannot clear events"))); - - if (count != NULL) - *count = (int)zc.zc_cookie; /* # of events cleared */ - - return (0); -} - -/* - * Seek to a specific EID, ZEVENT_SEEK_START, or ZEVENT_SEEK_END for - * the passed zevent_fd file handle. On success zero is returned, - * otherwise -1 is returned and hdl->libzfs_error is set to the errno. - */ -int -zpool_events_seek(libzfs_handle_t *hdl, uint64_t eid, int zevent_fd) -{ - zfs_cmd_t zc = {"\0"}; - int error = 0; - - zc.zc_guid = eid; - zc.zc_cleanup_fd = zevent_fd; - - if (zfs_ioctl(hdl, ZFS_IOC_EVENTS_SEEK, &zc) != 0) { - switch (errno) { - case ENOENT: - error = zfs_error_fmt(hdl, EZFS_NOENT, - dgettext(TEXT_DOMAIN, "cannot get event")); - break; - - case ENOMEM: - error = zfs_error_fmt(hdl, EZFS_NOMEM, - dgettext(TEXT_DOMAIN, "cannot get event")); - break; - - default: - error = zpool_standard_error_fmt(hdl, errno, - dgettext(TEXT_DOMAIN, "cannot get event")); - break; - } - } - - return (error); -} - -static void -zpool_obj_to_path_impl(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj, - char *pathname, size_t len, boolean_t always_unmounted) -{ - zfs_cmd_t zc = {"\0"}; - boolean_t mounted = B_FALSE; - char *mntpnt = NULL; - char dsname[ZFS_MAX_DATASET_NAME_LEN]; - - if (dsobj == 0) { - /* special case for the MOS */ - (void) snprintf(pathname, len, "<metadata>:<0x%llx>", - (longlong_t)obj); - return; - } - - /* get the dataset's name */ - (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); - zc.zc_obj = dsobj; - if (zfs_ioctl(zhp->zpool_hdl, - ZFS_IOC_DSOBJ_TO_DSNAME, &zc) != 0) { - /* just write out a path of two object numbers */ - (void) snprintf(pathname, len, "<0x%llx>:<0x%llx>", - (longlong_t)dsobj, (longlong_t)obj); - return; - } - (void) strlcpy(dsname, zc.zc_value, sizeof (dsname)); - - /* find out if the dataset is mounted */ - mounted = !always_unmounted && is_mounted(zhp->zpool_hdl, dsname, - &mntpnt); - - /* get the corrupted object's path */ - (void) strlcpy(zc.zc_name, dsname, sizeof (zc.zc_name)); - zc.zc_obj = obj; - if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_OBJ_TO_PATH, - &zc) == 0) { - if (mounted) { - (void) snprintf(pathname, len, "%s%s", mntpnt, - zc.zc_value); - } else { - (void) snprintf(pathname, len, "%s:%s", - dsname, zc.zc_value); - } - } else { - (void) snprintf(pathname, len, "%s:<0x%llx>", dsname, - (longlong_t)obj); - } - free(mntpnt); -} - -void -zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj, - char *pathname, size_t len) -{ - zpool_obj_to_path_impl(zhp, dsobj, obj, pathname, len, B_FALSE); -} - -void -zpool_obj_to_path_ds(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj, - char *pathname, size_t len) -{ - zpool_obj_to_path_impl(zhp, dsobj, obj, pathname, len, B_TRUE); -} -/* - * Wait while the specified activity is in progress in the pool. - */ -int -zpool_wait(zpool_handle_t *zhp, zpool_wait_activity_t activity) -{ - boolean_t missing; - - int error = zpool_wait_status(zhp, activity, &missing, NULL); - - if (missing) { - (void) zpool_standard_error_fmt(zhp->zpool_hdl, ENOENT, - dgettext(TEXT_DOMAIN, "error waiting in pool '%s'"), - zhp->zpool_name); - return (ENOENT); - } else { - return (error); - } -} - -/* - * Wait for the given activity and return the status of the wait (whether or not - * any waiting was done) in the 'waited' parameter. Non-existent pools are - * reported via the 'missing' parameter, rather than by printing an error - * message. This is convenient when this function is called in a loop over a - * long period of time (as it is, for example, by zpool's wait cmd). In that - * scenario, a pool being exported or destroyed should be considered a normal - * event, so we don't want to print an error when we find that the pool doesn't - * exist. - */ -int -zpool_wait_status(zpool_handle_t *zhp, zpool_wait_activity_t activity, - boolean_t *missing, boolean_t *waited) -{ - int error = lzc_wait(zhp->zpool_name, activity, waited); - *missing = (error == ENOENT); - if (*missing) - return (0); - - if (error != 0) { - (void) zpool_standard_error_fmt(zhp->zpool_hdl, error, - dgettext(TEXT_DOMAIN, "error waiting in pool '%s'"), - zhp->zpool_name); - } - - return (error); -} - -int -zpool_set_bootenv(zpool_handle_t *zhp, const nvlist_t *envmap) -{ - int error = lzc_set_bootenv(zhp->zpool_name, envmap); - if (error != 0) { - (void) zpool_standard_error_fmt(zhp->zpool_hdl, error, - dgettext(TEXT_DOMAIN, - "error setting bootenv in pool '%s'"), zhp->zpool_name); - } - - return (error); -} - -int -zpool_get_bootenv(zpool_handle_t *zhp, nvlist_t **nvlp) -{ - nvlist_t *nvl; - int error; - - nvl = NULL; - error = lzc_get_bootenv(zhp->zpool_name, &nvl); - if (error != 0) { - (void) zpool_standard_error_fmt(zhp->zpool_hdl, error, - dgettext(TEXT_DOMAIN, - "error getting bootenv in pool '%s'"), zhp->zpool_name); - } else { - *nvlp = nvl; - } - - return (error); -} - -/* - * Attempt to read and parse feature file(s) (from "compatibility" property). - * Files contain zpool feature names, comma or whitespace-separated. - * Comments (# character to next newline) are discarded. - * - * Arguments: - * compatibility : string containing feature filenames - * features : either NULL or pointer to array of boolean - * report : either NULL or pointer to string buffer - * rlen : length of "report" buffer - * - * compatibility is NULL (unset), "", "off", "legacy", or list of - * comma-separated filenames. filenames should either be absolute, - * or relative to: - * 1) ZPOOL_SYSCONF_COMPAT_D (eg: /etc/zfs/compatibility.d) or - * 2) ZPOOL_DATA_COMPAT_D (eg: /usr/share/zfs/compatibility.d). - * (Unset), "" or "off" => enable all features - * "legacy" => disable all features - * - * Any feature names read from files which match unames in spa_feature_table - * will have the corresponding boolean set in the features array (if non-NULL). - * If more than one feature set specified, only features present in *all* of - * them will be set. - * - * "report" if not NULL will be populated with a suitable status message. - * - * Return values: - * ZPOOL_COMPATIBILITY_OK : files read and parsed ok - * ZPOOL_COMPATIBILITY_BADFILE : file too big or not a text file - * ZPOOL_COMPATIBILITY_BADTOKEN : SYSCONF file contains invalid feature name - * ZPOOL_COMPATIBILITY_WARNTOKEN : DATA file contains invalid feature name - * ZPOOL_COMPATIBILITY_NOFILES : no feature files found - */ -zpool_compat_status_t -zpool_load_compat(const char *compat, boolean_t *features, char *report, - size_t rlen) -{ - int sdirfd, ddirfd, featfd; - struct stat fs; - char *fc; - char *ps, *ls, *ws; - char *file, *line, *word; - - char l_compat[ZFS_MAXPROPLEN]; - - boolean_t ret_nofiles = B_TRUE; - boolean_t ret_badfile = B_FALSE; - boolean_t ret_badtoken = B_FALSE; - boolean_t ret_warntoken = B_FALSE; - - /* special cases (unset), "" and "off" => enable all features */ - if (compat == NULL || compat[0] == '\0' || - strcmp(compat, ZPOOL_COMPAT_OFF) == 0) { - if (features != NULL) { - for (uint_t i = 0; i < SPA_FEATURES; i++) - features[i] = B_TRUE; - } - if (report != NULL) - strlcpy(report, gettext("all features enabled"), rlen); - return (ZPOOL_COMPATIBILITY_OK); - } - - /* Final special case "legacy" => disable all features */ - if (strcmp(compat, ZPOOL_COMPAT_LEGACY) == 0) { - if (features != NULL) - for (uint_t i = 0; i < SPA_FEATURES; i++) - features[i] = B_FALSE; - if (report != NULL) - strlcpy(report, gettext("all features disabled"), rlen); - return (ZPOOL_COMPATIBILITY_OK); - } - - /* - * Start with all true; will be ANDed with results from each file - */ - if (features != NULL) - for (uint_t i = 0; i < SPA_FEATURES; i++) - features[i] = B_TRUE; - - char err_badfile[ZFS_MAXPROPLEN] = ""; - char err_badtoken[ZFS_MAXPROPLEN] = ""; - - /* - * We ignore errors from the directory open() - * as they're only needed if the filename is relative - * which will be checked during the openat(). - */ - -/* O_PATH safer than O_RDONLY if system allows it */ -#if defined(O_PATH) -#define ZC_DIR_FLAGS (O_DIRECTORY | O_CLOEXEC | O_PATH) -#else -#define ZC_DIR_FLAGS (O_DIRECTORY | O_CLOEXEC | O_RDONLY) -#endif - - sdirfd = open(ZPOOL_SYSCONF_COMPAT_D, ZC_DIR_FLAGS); - ddirfd = open(ZPOOL_DATA_COMPAT_D, ZC_DIR_FLAGS); - - (void) strlcpy(l_compat, compat, ZFS_MAXPROPLEN); - - for (file = strtok_r(l_compat, ",", &ps); - file != NULL; - file = strtok_r(NULL, ",", &ps)) { - - boolean_t l_features[SPA_FEATURES]; - - enum { Z_SYSCONF, Z_DATA } source; - - /* try sysconfdir first, then datadir */ - source = Z_SYSCONF; - if ((featfd = openat(sdirfd, file, O_RDONLY | O_CLOEXEC)) < 0) { - featfd = openat(ddirfd, file, O_RDONLY | O_CLOEXEC); - source = Z_DATA; - } - - /* File readable and correct size? */ - if (featfd < 0 || - fstat(featfd, &fs) < 0 || - fs.st_size < 1 || - fs.st_size > ZPOOL_COMPAT_MAXSIZE) { - (void) close(featfd); - strlcat(err_badfile, file, ZFS_MAXPROPLEN); - strlcat(err_badfile, " ", ZFS_MAXPROPLEN); - ret_badfile = B_TRUE; - continue; - } - -/* Prefault the file if system allows */ -#if defined(MAP_POPULATE) -#define ZC_MMAP_FLAGS (MAP_PRIVATE | MAP_POPULATE) -#elif defined(MAP_PREFAULT_READ) -#define ZC_MMAP_FLAGS (MAP_PRIVATE | MAP_PREFAULT_READ) -#else -#define ZC_MMAP_FLAGS (MAP_PRIVATE) -#endif - - /* private mmap() so we can strtok safely */ - fc = (char *)mmap(NULL, fs.st_size, PROT_READ | PROT_WRITE, - ZC_MMAP_FLAGS, featfd, 0); - (void) close(featfd); - - /* map ok, and last character == newline? */ - if (fc == MAP_FAILED || fc[fs.st_size - 1] != '\n') { - (void) munmap((void *) fc, fs.st_size); - strlcat(err_badfile, file, ZFS_MAXPROPLEN); - strlcat(err_badfile, " ", ZFS_MAXPROPLEN); - ret_badfile = B_TRUE; - continue; - } - - ret_nofiles = B_FALSE; - - for (uint_t i = 0; i < SPA_FEATURES; i++) - l_features[i] = B_FALSE; - - /* replace final newline with NULL to ensure string ends */ - fc[fs.st_size - 1] = '\0'; - - for (line = strtok_r(fc, "\n", &ls); - line != NULL; - line = strtok_r(NULL, "\n", &ls)) { - /* discard comments */ - char *r = strchr(line, '#'); - if (r != NULL) - *r = '\0'; - - for (word = strtok_r(line, ", \t", &ws); - word != NULL; - word = strtok_r(NULL, ", \t", &ws)) { - /* Find matching feature name */ - uint_t f; - for (f = 0; f < SPA_FEATURES; f++) { - zfeature_info_t *fi = - &spa_feature_table[f]; - if (strcmp(word, fi->fi_uname) == 0) { - l_features[f] = B_TRUE; - break; - } - } - if (f < SPA_FEATURES) - continue; - - /* found an unrecognized word */ - /* lightly sanitize it */ - if (strlen(word) > 32) - word[32] = '\0'; - for (char *c = word; *c != '\0'; c++) - if (!isprint(*c)) - *c = '?'; - - strlcat(err_badtoken, word, ZFS_MAXPROPLEN); - strlcat(err_badtoken, " ", ZFS_MAXPROPLEN); - if (source == Z_SYSCONF) - ret_badtoken = B_TRUE; - else - ret_warntoken = B_TRUE; - } - } - (void) munmap((void *) fc, fs.st_size); - - if (features != NULL) - for (uint_t i = 0; i < SPA_FEATURES; i++) - features[i] &= l_features[i]; - } - (void) close(sdirfd); - (void) close(ddirfd); - - /* Return the most serious error */ - if (ret_badfile) { - if (report != NULL) - snprintf(report, rlen, gettext("could not read/" - "parse feature file(s): %s"), err_badfile); - return (ZPOOL_COMPATIBILITY_BADFILE); - } - if (ret_nofiles) { - if (report != NULL) - strlcpy(report, - gettext("no valid compatibility files specified"), - rlen); - return (ZPOOL_COMPATIBILITY_NOFILES); - } - if (ret_badtoken) { - if (report != NULL) - snprintf(report, rlen, gettext("invalid feature " - "name(s) in local compatibility files: %s"), - err_badtoken); - return (ZPOOL_COMPATIBILITY_BADTOKEN); - } - if (ret_warntoken) { - if (report != NULL) - snprintf(report, rlen, gettext("unrecognized feature " - "name(s) in distribution compatibility files: %s"), - err_badtoken); - return (ZPOOL_COMPATIBILITY_WARNTOKEN); - } - if (report != NULL) - strlcpy(report, gettext("compatibility set ok"), rlen); - return (ZPOOL_COMPATIBILITY_OK); -} - -static int -zpool_vdev_guid(zpool_handle_t *zhp, const char *vdevname, uint64_t *vdev_guid) -{ - nvlist_t *tgt; - boolean_t avail_spare, l2cache; - - verify(zhp != NULL); - if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { - char errbuf[ERRBUFLEN]; - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "pool is in an unavailable state")); - return (zfs_error(zhp->zpool_hdl, EZFS_POOLUNAVAIL, errbuf)); - } - - if ((tgt = zpool_find_vdev(zhp, vdevname, &avail_spare, &l2cache, - NULL)) == NULL) { - char errbuf[ERRBUFLEN]; - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "can not find %s in %s"), - vdevname, zhp->zpool_name); - return (zfs_error(zhp->zpool_hdl, EZFS_NODEVICE, errbuf)); - } - - *vdev_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID); - return (0); -} - -/* - * Get a vdev property value for 'prop' and return the value in - * a pre-allocated buffer. - */ -int -zpool_get_vdev_prop_value(nvlist_t *nvprop, vdev_prop_t prop, char *prop_name, - char *buf, size_t len, zprop_source_t *srctype, boolean_t literal) -{ - nvlist_t *nv; - const char *strval; - uint64_t intval; - zprop_source_t src = ZPROP_SRC_NONE; - - if (prop == VDEV_PROP_USERPROP) { - /* user property, prop_name must contain the property name */ - assert(prop_name != NULL); - if (nvlist_lookup_nvlist(nvprop, prop_name, &nv) == 0) { - src = fnvlist_lookup_uint64(nv, ZPROP_SOURCE); - strval = fnvlist_lookup_string(nv, ZPROP_VALUE); - } else { - /* user prop not found */ - src = ZPROP_SRC_DEFAULT; - strval = "-"; - } - (void) strlcpy(buf, strval, len); - if (srctype) - *srctype = src; - return (0); - } - - if (prop_name == NULL) - prop_name = (char *)vdev_prop_to_name(prop); - - switch (vdev_prop_get_type(prop)) { - case PROP_TYPE_STRING: - if (nvlist_lookup_nvlist(nvprop, prop_name, &nv) == 0) { - src = fnvlist_lookup_uint64(nv, ZPROP_SOURCE); - strval = fnvlist_lookup_string(nv, ZPROP_VALUE); - } else { - src = ZPROP_SRC_DEFAULT; - if ((strval = vdev_prop_default_string(prop)) == NULL) - strval = "-"; - } - (void) strlcpy(buf, strval, len); - break; - - case PROP_TYPE_NUMBER: - if (nvlist_lookup_nvlist(nvprop, prop_name, &nv) == 0) { - src = fnvlist_lookup_uint64(nv, ZPROP_SOURCE); - intval = fnvlist_lookup_uint64(nv, ZPROP_VALUE); - } else { - src = ZPROP_SRC_DEFAULT; - intval = vdev_prop_default_numeric(prop); - } - - switch (prop) { - case VDEV_PROP_ASIZE: - case VDEV_PROP_PSIZE: - case VDEV_PROP_SIZE: - case VDEV_PROP_BOOTSIZE: - case VDEV_PROP_ALLOCATED: - case VDEV_PROP_FREE: - case VDEV_PROP_READ_ERRORS: - case VDEV_PROP_WRITE_ERRORS: - case VDEV_PROP_CHECKSUM_ERRORS: - case VDEV_PROP_INITIALIZE_ERRORS: - case VDEV_PROP_TRIM_ERRORS: - case VDEV_PROP_SLOW_IOS: - case VDEV_PROP_OPS_NULL: - case VDEV_PROP_OPS_READ: - case VDEV_PROP_OPS_WRITE: - case VDEV_PROP_OPS_FREE: - case VDEV_PROP_OPS_CLAIM: - case VDEV_PROP_OPS_TRIM: - case VDEV_PROP_BYTES_NULL: - case VDEV_PROP_BYTES_READ: - case VDEV_PROP_BYTES_WRITE: - case VDEV_PROP_BYTES_FREE: - case VDEV_PROP_BYTES_CLAIM: - case VDEV_PROP_BYTES_TRIM: - if (literal) { - (void) snprintf(buf, len, "%llu", - (u_longlong_t)intval); - } else { - (void) zfs_nicenum(intval, buf, len); - } - break; - case VDEV_PROP_EXPANDSZ: - if (intval == 0) { - (void) strlcpy(buf, "-", len); - } else if (literal) { - (void) snprintf(buf, len, "%llu", - (u_longlong_t)intval); - } else { - (void) zfs_nicenum(intval, buf, len); - } - break; - case VDEV_PROP_CAPACITY: - if (literal) { - (void) snprintf(buf, len, "%llu", - (u_longlong_t)intval); - } else { - (void) snprintf(buf, len, "%llu%%", - (u_longlong_t)intval); - } - break; - case VDEV_PROP_CHECKSUM_N: - case VDEV_PROP_CHECKSUM_T: - case VDEV_PROP_IO_N: - case VDEV_PROP_IO_T: - case VDEV_PROP_SLOW_IO_N: - case VDEV_PROP_SLOW_IO_T: - if (intval == UINT64_MAX) { - (void) strlcpy(buf, "-", len); - } else { - (void) snprintf(buf, len, "%llu", - (u_longlong_t)intval); - } - break; - case VDEV_PROP_FRAGMENTATION: - if (intval == UINT64_MAX) { - (void) strlcpy(buf, "-", len); - } else { - (void) snprintf(buf, len, "%llu%%", - (u_longlong_t)intval); - } - break; - case VDEV_PROP_STATE: - if (literal) { - (void) snprintf(buf, len, "%llu", - (u_longlong_t)intval); - } else { - (void) strlcpy(buf, zpool_state_to_name(intval, - VDEV_AUX_NONE), len); - } - break; - default: - (void) snprintf(buf, len, "%llu", - (u_longlong_t)intval); - } - break; - - case PROP_TYPE_INDEX: - if (nvlist_lookup_nvlist(nvprop, prop_name, &nv) == 0) { - src = fnvlist_lookup_uint64(nv, ZPROP_SOURCE); - intval = fnvlist_lookup_uint64(nv, ZPROP_VALUE); - } else { - /* 'trim_support' only valid for leaf vdevs */ - if (prop == VDEV_PROP_TRIM_SUPPORT) { - (void) strlcpy(buf, "-", len); - break; - } - src = ZPROP_SRC_DEFAULT; - intval = vdev_prop_default_numeric(prop); - /* Only use if provided by the RAIDZ VDEV above */ - if (prop == VDEV_PROP_RAIDZ_EXPANDING) - return (ENOENT); - if (prop == VDEV_PROP_SIT_OUT) - return (ENOENT); - } - if (vdev_prop_index_to_string(prop, intval, - (const char **)&strval) != 0) - return (-1); - (void) strlcpy(buf, strval, len); - break; - - default: - abort(); - } - - if (srctype) - *srctype = src; - - return (0); -} - -/* - * Get a vdev property value for 'prop_name' and return the value in - * a pre-allocated buffer. - */ -int -zpool_get_vdev_prop(zpool_handle_t *zhp, const char *vdevname, vdev_prop_t prop, - char *prop_name, char *buf, size_t len, zprop_source_t *srctype, - boolean_t literal) -{ - nvlist_t *reqnvl, *reqprops; - nvlist_t *retprops = NULL; - uint64_t vdev_guid = 0; - int ret; - - if ((ret = zpool_vdev_guid(zhp, vdevname, &vdev_guid)) != 0) - return (ret); - - if (nvlist_alloc(&reqnvl, NV_UNIQUE_NAME, 0) != 0) - return (no_memory(zhp->zpool_hdl)); - if (nvlist_alloc(&reqprops, NV_UNIQUE_NAME, 0) != 0) - return (no_memory(zhp->zpool_hdl)); - - fnvlist_add_uint64(reqnvl, ZPOOL_VDEV_PROPS_GET_VDEV, vdev_guid); - - if (prop != VDEV_PROP_USERPROP) { - /* prop_name overrides prop value */ - if (prop_name != NULL) - prop = vdev_name_to_prop(prop_name); - else - prop_name = (char *)vdev_prop_to_name(prop); - assert(prop < VDEV_NUM_PROPS); - } - - assert(prop_name != NULL); - if (nvlist_add_uint64(reqprops, prop_name, prop) != 0) { - nvlist_free(reqnvl); - nvlist_free(reqprops); - return (no_memory(zhp->zpool_hdl)); - } - - fnvlist_add_nvlist(reqnvl, ZPOOL_VDEV_PROPS_GET_PROPS, reqprops); - - ret = lzc_get_vdev_prop(zhp->zpool_name, reqnvl, &retprops); - - if (ret == 0) { - ret = zpool_get_vdev_prop_value(retprops, prop, prop_name, buf, - len, srctype, literal); - } else { - char errbuf[ERRBUFLEN]; - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot get vdev property %s from" - " %s in %s"), prop_name, vdevname, zhp->zpool_name); - (void) zpool_standard_error(zhp->zpool_hdl, ret, errbuf); - } - - nvlist_free(reqnvl); - nvlist_free(reqprops); - nvlist_free(retprops); - - return (ret); -} - -/* - * Get all vdev properties - */ -int -zpool_get_all_vdev_props(zpool_handle_t *zhp, const char *vdevname, - nvlist_t **outnvl) -{ - nvlist_t *nvl = NULL; - uint64_t vdev_guid = 0; - int ret; - - if ((ret = zpool_vdev_guid(zhp, vdevname, &vdev_guid)) != 0) - return (ret); - - if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) - return (no_memory(zhp->zpool_hdl)); - - fnvlist_add_uint64(nvl, ZPOOL_VDEV_PROPS_GET_VDEV, vdev_guid); - - ret = lzc_get_vdev_prop(zhp->zpool_name, nvl, outnvl); - - nvlist_free(nvl); - - if (ret) { - char errbuf[ERRBUFLEN]; - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot get vdev properties for" - " %s in %s"), vdevname, zhp->zpool_name); - (void) zpool_standard_error(zhp->zpool_hdl, errno, errbuf); - } - - return (ret); -} - -/* - * Set vdev property - */ -int -zpool_set_vdev_prop(zpool_handle_t *zhp, const char *vdevname, - const char *propname, const char *propval) -{ - int ret; - nvlist_t *nvl = NULL; - nvlist_t *outnvl = NULL; - nvlist_t *props; - nvlist_t *realprops; - prop_flags_t flags = { 0 }; - uint64_t version; - uint64_t vdev_guid; - - if ((ret = zpool_vdev_guid(zhp, vdevname, &vdev_guid)) != 0) - return (ret); - - if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) - return (no_memory(zhp->zpool_hdl)); - if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) - return (no_memory(zhp->zpool_hdl)); - - fnvlist_add_uint64(nvl, ZPOOL_VDEV_PROPS_SET_VDEV, vdev_guid); - - if (nvlist_add_string(props, propname, propval) != 0) { - nvlist_free(props); - return (no_memory(zhp->zpool_hdl)); - } - - char errbuf[ERRBUFLEN]; - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot set property %s for %s on %s"), - propname, vdevname, zhp->zpool_name); - - flags.vdevprop = 1; - version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL); - if ((realprops = zpool_valid_proplist(zhp->zpool_hdl, - zhp->zpool_name, props, version, flags, errbuf)) == NULL) { - nvlist_free(props); - nvlist_free(nvl); - return (-1); - } - - nvlist_free(props); - props = realprops; - - fnvlist_add_nvlist(nvl, ZPOOL_VDEV_PROPS_SET_PROPS, props); - - ret = lzc_set_vdev_prop(zhp->zpool_name, nvl, &outnvl); - - nvlist_free(props); - nvlist_free(nvl); - nvlist_free(outnvl); - - if (ret) { - if (errno == ENOTSUP) { - zfs_error_aux(zhp->zpool_hdl, dgettext(TEXT_DOMAIN, - "property not supported for this vdev")); - (void) zfs_error(zhp->zpool_hdl, EZFS_PROPTYPE, errbuf); - } else { - (void) zpool_standard_error(zhp->zpool_hdl, errno, - errbuf); - } - } - - return (ret); -} - -/* - * Prune older entries from the DDT to reclaim space under the quota - */ -int -zpool_ddt_prune(zpool_handle_t *zhp, zpool_ddt_prune_unit_t unit, - uint64_t amount) -{ - int error = lzc_ddt_prune(zhp->zpool_name, unit, amount); - if (error != 0) { - libzfs_handle_t *hdl = zhp->zpool_hdl; - char errbuf[ERRBUFLEN]; - - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot prune dedup table on '%s'"), zhp->zpool_name); - - if (error == EALREADY) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "a prune operation is already in progress")); - (void) zfs_error(hdl, EZFS_BUSY, errbuf); - } else { - (void) zpool_standard_error(hdl, errno, errbuf); - } - return (-1); - } - - return (0); -} diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c deleted file mode 100644 index 77134d197904..000000000000 --- a/lib/libzfs/libzfs_sendrecv.c +++ /dev/null @@ -1,5647 +0,0 @@ -// SPDX-License-Identifier: CDDL-1.0 -/* - * 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 - */ - -/* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2020 by Delphix. All rights reserved. - * Copyright (c) 2012, Joyent, Inc. All rights reserved. - * Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>. - * All rights reserved - * Copyright (c) 2013 Steven Hartland. All rights reserved. - * Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved. - * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com> - * Copyright (c) 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved. - * Copyright (c) 2019 Datto Inc. - * Copyright (c) 2024, Klara, Inc. - */ - -#include <assert.h> -#include <ctype.h> -#include <errno.h> -#include <libintl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <stddef.h> -#include <fcntl.h> -#include <sys/mount.h> -#include <sys/mntent.h> -#include <sys/mnttab.h> -#include <sys/avl.h> -#include <sys/debug.h> -#include <sys/stat.h> -#include <pthread.h> -#include <umem.h> -#include <time.h> - -#include <libzfs.h> -#include <libzfs_core.h> -#include <libzutil.h> - -#include "zfs_namecheck.h" -#include "zfs_prop.h" -#include "zfs_fletcher.h" -#include "libzfs_impl.h" -#include <cityhash.h> -#include <zlib.h> -#include <sys/zio_checksum.h> -#include <sys/dsl_crypt.h> -#include <sys/ddt.h> -#include <sys/socket.h> -#include <sys/sha2.h> - -static int zfs_receive_impl(libzfs_handle_t *, const char *, const char *, - recvflags_t *, int, const char *, nvlist_t *, avl_tree_t *, char **, - const char *, nvlist_t *); -static int guid_to_name_redact_snaps(libzfs_handle_t *hdl, const char *parent, - uint64_t guid, boolean_t bookmark_ok, uint64_t *redact_snap_guids, - uint64_t num_redact_snaps, char *name); -static int guid_to_name(libzfs_handle_t *, const char *, - uint64_t, boolean_t, char *); - -typedef struct progress_arg { - zfs_handle_t *pa_zhp; - int pa_fd; - boolean_t pa_parsable; - boolean_t pa_estimate; - int pa_verbosity; - boolean_t pa_astitle; - boolean_t pa_progress; - uint64_t pa_size; -} progress_arg_t; - -static int -dump_record(dmu_replay_record_t *drr, void *payload, size_t payload_len, - zio_cksum_t *zc, int outfd) -{ - ASSERT3U(offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum), - ==, sizeof (dmu_replay_record_t) - sizeof (zio_cksum_t)); - fletcher_4_incremental_native(drr, - offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum), zc); - if (drr->drr_type != DRR_BEGIN) { - ASSERT(ZIO_CHECKSUM_IS_ZERO(&drr->drr_u. - drr_checksum.drr_checksum)); - drr->drr_u.drr_checksum.drr_checksum = *zc; - } - fletcher_4_incremental_native(&drr->drr_u.drr_checksum.drr_checksum, - sizeof (zio_cksum_t), zc); - if (write(outfd, drr, sizeof (*drr)) == -1) - return (errno); - if (payload_len != 0) { - fletcher_4_incremental_native(payload, payload_len, zc); - if (write(outfd, payload, payload_len) == -1) - return (errno); - } - return (0); -} - -/* - * Routines for dealing with the AVL tree of fs-nvlists - */ -typedef struct fsavl_node { - avl_node_t fn_node; - nvlist_t *fn_nvfs; - const char *fn_snapname; - uint64_t fn_guid; -} fsavl_node_t; - -static int -fsavl_compare(const void *arg1, const void *arg2) -{ - const fsavl_node_t *fn1 = (const fsavl_node_t *)arg1; - const fsavl_node_t *fn2 = (const fsavl_node_t *)arg2; - - return (TREE_CMP(fn1->fn_guid, fn2->fn_guid)); -} - -/* - * Given the GUID of a snapshot, find its containing filesystem and - * (optionally) name. - */ -static nvlist_t * -fsavl_find(avl_tree_t *avl, uint64_t snapguid, const char **snapname) -{ - fsavl_node_t fn_find; - fsavl_node_t *fn; - - fn_find.fn_guid = snapguid; - - fn = avl_find(avl, &fn_find, NULL); - if (fn) { - if (snapname) - *snapname = fn->fn_snapname; - return (fn->fn_nvfs); - } - return (NULL); -} - -static void -fsavl_destroy(avl_tree_t *avl) -{ - fsavl_node_t *fn; - void *cookie; - - if (avl == NULL) - return; - - cookie = NULL; - while ((fn = avl_destroy_nodes(avl, &cookie)) != NULL) - free(fn); - avl_destroy(avl); - free(avl); -} - -/* - * Given an nvlist, produce an avl tree of snapshots, ordered by guid - */ -static avl_tree_t * -fsavl_create(nvlist_t *fss) -{ - avl_tree_t *fsavl; - nvpair_t *fselem = NULL; - - if ((fsavl = malloc(sizeof (avl_tree_t))) == NULL) - return (NULL); - - avl_create(fsavl, fsavl_compare, sizeof (fsavl_node_t), - offsetof(fsavl_node_t, fn_node)); - - while ((fselem = nvlist_next_nvpair(fss, fselem)) != NULL) { - nvlist_t *nvfs, *snaps; - nvpair_t *snapelem = NULL; - - nvfs = fnvpair_value_nvlist(fselem); - snaps = fnvlist_lookup_nvlist(nvfs, "snaps"); - - while ((snapelem = - nvlist_next_nvpair(snaps, snapelem)) != NULL) { - fsavl_node_t *fn; - - if ((fn = malloc(sizeof (fsavl_node_t))) == NULL) { - fsavl_destroy(fsavl); - return (NULL); - } - fn->fn_nvfs = nvfs; - fn->fn_snapname = nvpair_name(snapelem); - fn->fn_guid = fnvpair_value_uint64(snapelem); - - /* - * Note: if there are multiple snaps with the - * same GUID, we ignore all but one. - */ - avl_index_t where = 0; - if (avl_find(fsavl, fn, &where) == NULL) - avl_insert(fsavl, fn, where); - else - free(fn); - } - } - - return (fsavl); -} - -/* - * Routines for dealing with the giant nvlist of fs-nvlists, etc. - */ -typedef struct send_data { - /* - * assigned inside every recursive call, - * restored from *_save on return: - * - * guid of fromsnap snapshot in parent dataset - * txg of fromsnap snapshot in current dataset - * txg of tosnap snapshot in current dataset - */ - - uint64_t parent_fromsnap_guid; - uint64_t fromsnap_txg; - uint64_t tosnap_txg; - - /* the nvlists get accumulated during depth-first traversal */ - nvlist_t *parent_snaps; - nvlist_t *fss; - nvlist_t *snapprops; - nvlist_t *snapholds; /* user holds */ - - /* send-receive configuration, does not change during traversal */ - const char *fsname; - const char *fromsnap; - const char *tosnap; - boolean_t recursive; - boolean_t raw; - boolean_t doall; - boolean_t replicate; - boolean_t skipmissing; - boolean_t verbose; - boolean_t backup; - boolean_t seenfrom; - boolean_t seento; - boolean_t holds; /* were holds requested with send -h */ - boolean_t props; - - /* - * The header nvlist is of the following format: - * { - * "tosnap" -> string - * "fromsnap" -> string (if incremental) - * "fss" -> { - * id -> { - * - * "name" -> string (full name; for debugging) - * "parentfromsnap" -> number (guid of fromsnap in parent) - * - * "props" -> { name -> value (only if set here) } - * "snaps" -> { name (lastname) -> number (guid) } - * "snapprops" -> { name (lastname) -> { name -> value } } - * "snapholds" -> { name (lastname) -> { holdname -> crtime } } - * - * "origin" -> number (guid) (if clone) - * "is_encroot" -> boolean - * "sent" -> boolean (not on-disk) - * } - * } - * } - * - */ -} send_data_t; - -static void -send_iterate_prop(zfs_handle_t *zhp, boolean_t received_only, nvlist_t *nv); - -/* - * Collect guid, valid props, optionally holds, etc. of a snapshot. - * This interface is intended for use as a zfs_iter_snapshots_v2_sorted visitor. - */ -static int -send_iterate_snap(zfs_handle_t *zhp, void *arg) -{ - send_data_t *sd = arg; - uint64_t guid = zhp->zfs_dmustats.dds_guid; - uint64_t txg = zhp->zfs_dmustats.dds_creation_txg; - boolean_t isfromsnap, istosnap, istosnapwithnofrom; - char *snapname; - const char *from = sd->fromsnap; - const char *to = sd->tosnap; - - snapname = strrchr(zhp->zfs_name, '@'); - assert(snapname != NULL); - ++snapname; - - isfromsnap = (from != NULL && strcmp(from, snapname) == 0); - istosnap = (to != NULL && strcmp(to, snapname) == 0); - istosnapwithnofrom = (istosnap && from == NULL); - - if (sd->tosnap_txg != 0 && txg > sd->tosnap_txg) { - if (sd->verbose) { - (void) fprintf(stderr, dgettext(TEXT_DOMAIN, - "skipping snapshot %s because it was created " - "after the destination snapshot (%s)\n"), - zhp->zfs_name, to); - } - zfs_close(zhp); - return (0); - } - - fnvlist_add_uint64(sd->parent_snaps, snapname, guid); - - /* - * NB: if there is no fromsnap here (it's a newly created fs in - * an incremental replication), we will substitute the tosnap. - */ - if (isfromsnap || (sd->parent_fromsnap_guid == 0 && istosnap)) - sd->parent_fromsnap_guid = guid; - - if (!sd->recursive) { - /* - * To allow a doall stream to work properly - * with a NULL fromsnap - */ - if (sd->doall && from == NULL && !sd->seenfrom) - sd->seenfrom = B_TRUE; - - if (!sd->seenfrom && isfromsnap) { - sd->seenfrom = B_TRUE; - zfs_close(zhp); - return (0); - } - - if ((sd->seento || !sd->seenfrom) && !istosnapwithnofrom) { - zfs_close(zhp); - return (0); - } - - if (istosnap) - sd->seento = B_TRUE; - } - - nvlist_t *nv = fnvlist_alloc(); - send_iterate_prop(zhp, sd->backup, nv); - fnvlist_add_nvlist(sd->snapprops, snapname, nv); - fnvlist_free(nv); - - if (sd->holds) { - nvlist_t *holds; - if (lzc_get_holds(zhp->zfs_name, &holds) == 0) { - fnvlist_add_nvlist(sd->snapholds, snapname, holds); - fnvlist_free(holds); - } - } - - zfs_close(zhp); - return (0); -} - -/* - * Collect all valid props from the handle snap into an nvlist. - */ -static void -send_iterate_prop(zfs_handle_t *zhp, boolean_t received_only, nvlist_t *nv) -{ - nvlist_t *props; - - if (received_only) - props = zfs_get_recvd_props(zhp); - else - props = zhp->zfs_props; - - nvpair_t *elem = NULL; - while ((elem = nvlist_next_nvpair(props, elem)) != NULL) { - const char *propname = nvpair_name(elem); - zfs_prop_t prop = zfs_name_to_prop(propname); - - if (!zfs_prop_user(propname)) { - /* - * Realistically, this should never happen. However, - * we want the ability to add DSL properties without - * needing to make incompatible version changes. We - * need to ignore unknown properties to allow older - * software to still send datasets containing these - * properties, with the unknown properties elided. - */ - if (prop == ZPROP_INVAL) - continue; - - if (zfs_prop_readonly(prop)) - continue; - } - - nvlist_t *propnv = fnvpair_value_nvlist(elem); - - boolean_t isspacelimit = (prop == ZFS_PROP_QUOTA || - prop == ZFS_PROP_RESERVATION || - prop == ZFS_PROP_REFQUOTA || - prop == ZFS_PROP_REFRESERVATION); - if (isspacelimit && zhp->zfs_type == ZFS_TYPE_SNAPSHOT) - continue; - - const char *source; - if (nvlist_lookup_string(propnv, ZPROP_SOURCE, &source) == 0) { - if (strcmp(source, zhp->zfs_name) != 0 && - strcmp(source, ZPROP_SOURCE_VAL_RECVD) != 0) - continue; - } else { - /* - * May have no source before SPA_VERSION_RECVD_PROPS, - * but is still modifiable. - */ - if (!isspacelimit) - continue; - } - - if (zfs_prop_user(propname) || - zfs_prop_get_type(prop) == PROP_TYPE_STRING) { - const char *value; - value = fnvlist_lookup_string(propnv, ZPROP_VALUE); - fnvlist_add_string(nv, propname, value); - } else { - uint64_t value; - value = fnvlist_lookup_uint64(propnv, ZPROP_VALUE); - fnvlist_add_uint64(nv, propname, value); - } - } -} - -/* - * returns snapshot guid - * and returns 0 if the snapshot does not exist - */ -static uint64_t -get_snap_guid(libzfs_handle_t *hdl, const char *fs, const char *snap) -{ - char name[MAXPATHLEN + 1]; - uint64_t guid = 0; - - if (fs == NULL || fs[0] == '\0' || snap == NULL || snap[0] == '\0') - return (guid); - - (void) snprintf(name, sizeof (name), "%s@%s", fs, snap); - zfs_handle_t *zhp = zfs_open(hdl, name, ZFS_TYPE_SNAPSHOT); - if (zhp != NULL) { - guid = zfs_prop_get_int(zhp, ZFS_PROP_GUID); - zfs_close(zhp); - } - - return (guid); -} - -/* - * returns snapshot creation txg - * and returns 0 if the snapshot does not exist - */ -static uint64_t -get_snap_txg(libzfs_handle_t *hdl, const char *fs, const char *snap) -{ - char name[ZFS_MAX_DATASET_NAME_LEN]; - uint64_t txg = 0; - - if (fs == NULL || fs[0] == '\0' || snap == NULL || snap[0] == '\0') - return (txg); - - (void) snprintf(name, sizeof (name), "%s@%s", fs, snap); - if (zfs_dataset_exists(hdl, name, ZFS_TYPE_SNAPSHOT)) { - zfs_handle_t *zhp = zfs_open(hdl, name, ZFS_TYPE_SNAPSHOT); - if (zhp != NULL) { - txg = zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG); - zfs_close(zhp); - } - } - - return (txg); -} - -/* - * Recursively generate nvlists describing datasets. See comment - * for the data structure send_data_t above for description of contents - * of the nvlist. - */ -static int -send_iterate_fs(zfs_handle_t *zhp, void *arg) -{ - send_data_t *sd = arg; - nvlist_t *nvfs = NULL, *nv = NULL; - int rv = 0; - uint64_t min_txg = 0, max_txg = 0; - uint64_t txg = zhp->zfs_dmustats.dds_creation_txg; - uint64_t guid = zhp->zfs_dmustats.dds_guid; - uint64_t fromsnap_txg, tosnap_txg; - char guidstring[64]; - - /* These fields are restored on return from a recursive call. */ - uint64_t parent_fromsnap_guid_save = sd->parent_fromsnap_guid; - uint64_t fromsnap_txg_save = sd->fromsnap_txg; - uint64_t tosnap_txg_save = sd->tosnap_txg; - - fromsnap_txg = get_snap_txg(zhp->zfs_hdl, zhp->zfs_name, sd->fromsnap); - if (fromsnap_txg != 0) - sd->fromsnap_txg = fromsnap_txg; - - tosnap_txg = get_snap_txg(zhp->zfs_hdl, zhp->zfs_name, sd->tosnap); - if (tosnap_txg != 0) - sd->tosnap_txg = tosnap_txg; - - /* - * On the send side, if the current dataset does not have tosnap, - * perform two additional checks: - * - * - Skip sending the current dataset if it was created later than - * the parent tosnap. - * - Return error if the current dataset was created earlier than - * the parent tosnap, unless --skip-missing specified. Then - * just print a warning. - */ - if (sd->tosnap != NULL && tosnap_txg == 0) { - if (sd->tosnap_txg != 0 && txg > sd->tosnap_txg) { - if (sd->verbose) { - (void) fprintf(stderr, dgettext(TEXT_DOMAIN, - "skipping dataset %s: snapshot %s does " - "not exist\n"), zhp->zfs_name, sd->tosnap); - } - } else if (sd->skipmissing) { - (void) fprintf(stderr, dgettext(TEXT_DOMAIN, - "WARNING: skipping dataset %s and its children:" - " snapshot %s does not exist\n"), - zhp->zfs_name, sd->tosnap); - } else { - (void) fprintf(stderr, dgettext(TEXT_DOMAIN, - "cannot send %s@%s%s: snapshot %s@%s does not " - "exist\n"), sd->fsname, sd->tosnap, sd->recursive ? - dgettext(TEXT_DOMAIN, " recursively") : "", - zhp->zfs_name, sd->tosnap); - rv = EZFS_NOENT; - } - goto out; - } - - nvfs = fnvlist_alloc(); - fnvlist_add_string(nvfs, "name", zhp->zfs_name); - fnvlist_add_uint64(nvfs, "parentfromsnap", sd->parent_fromsnap_guid); - - if (zhp->zfs_dmustats.dds_origin[0] != '\0') { - zfs_handle_t *origin = zfs_open(zhp->zfs_hdl, - zhp->zfs_dmustats.dds_origin, ZFS_TYPE_SNAPSHOT); - if (origin == NULL) { - rv = -1; - goto out; - } - fnvlist_add_uint64(nvfs, "origin", - origin->zfs_dmustats.dds_guid); - zfs_close(origin); - } - - /* Iterate over props. */ - if (sd->props || sd->backup || sd->recursive) { - nv = fnvlist_alloc(); - send_iterate_prop(zhp, sd->backup, nv); - fnvlist_add_nvlist(nvfs, "props", nv); - } - if (zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION) != ZIO_CRYPT_OFF) { - boolean_t encroot; - - /* Determine if this dataset is an encryption root. */ - if (zfs_crypto_get_encryption_root(zhp, &encroot, NULL) != 0) { - rv = -1; - goto out; - } - - if (encroot) - fnvlist_add_boolean(nvfs, "is_encroot"); - - /* - * Encrypted datasets can only be sent with properties if - * the raw flag is specified because the receive side doesn't - * currently have a mechanism for recursively asking the user - * for new encryption parameters. - */ - if (!sd->raw) { - (void) fprintf(stderr, dgettext(TEXT_DOMAIN, - "cannot send %s@%s: encrypted dataset %s may not " - "be sent with properties without the raw flag\n"), - sd->fsname, sd->tosnap, zhp->zfs_name); - rv = -1; - goto out; - } - - } - - /* - * Iterate over snaps, and set sd->parent_fromsnap_guid. - * - * If this is a "doall" send, a replicate send or we're just trying - * to gather a list of previous snapshots, iterate through all the - * snaps in the txg range. Otherwise just look at the one we're - * interested in. - */ - sd->parent_fromsnap_guid = 0; - sd->parent_snaps = fnvlist_alloc(); - sd->snapprops = fnvlist_alloc(); - if (sd->holds) - sd->snapholds = fnvlist_alloc(); - if (sd->doall || sd->replicate || sd->tosnap == NULL) { - if (!sd->replicate && fromsnap_txg != 0) - min_txg = fromsnap_txg; - if (!sd->replicate && tosnap_txg != 0) - max_txg = tosnap_txg; - (void) zfs_iter_snapshots_sorted_v2(zhp, 0, send_iterate_snap, - sd, min_txg, max_txg); - } else { - char snapname[MAXPATHLEN] = { 0 }; - zfs_handle_t *snap; - - (void) snprintf(snapname, sizeof (snapname), "%s@%s", - zhp->zfs_name, sd->tosnap); - if (sd->fromsnap != NULL) - sd->seenfrom = B_TRUE; - snap = zfs_open(zhp->zfs_hdl, snapname, ZFS_TYPE_SNAPSHOT); - if (snap != NULL) - (void) send_iterate_snap(snap, sd); - } - - fnvlist_add_nvlist(nvfs, "snaps", sd->parent_snaps); - fnvlist_free(sd->parent_snaps); - fnvlist_add_nvlist(nvfs, "snapprops", sd->snapprops); - fnvlist_free(sd->snapprops); - if (sd->holds) { - fnvlist_add_nvlist(nvfs, "snapholds", sd->snapholds); - fnvlist_free(sd->snapholds); - } - - /* Do not allow the size of the properties list to exceed the limit */ - if ((fnvlist_size(nvfs) + fnvlist_size(sd->fss)) > - zhp->zfs_hdl->libzfs_max_nvlist) { - (void) fprintf(stderr, dgettext(TEXT_DOMAIN, - "warning: cannot send %s@%s: the size of the list of " - "snapshots and properties is too large to be received " - "successfully.\n" - "Select a smaller number of snapshots to send.\n"), - zhp->zfs_name, sd->tosnap); - rv = EZFS_NOSPC; - goto out; - } - /* Add this fs to nvlist. */ - (void) snprintf(guidstring, sizeof (guidstring), - "0x%llx", (longlong_t)guid); - fnvlist_add_nvlist(sd->fss, guidstring, nvfs); - - /* Iterate over children. */ - if (sd->recursive) - rv = zfs_iter_filesystems_v2(zhp, 0, send_iterate_fs, sd); - -out: - /* Restore saved fields. */ - sd->parent_fromsnap_guid = parent_fromsnap_guid_save; - sd->fromsnap_txg = fromsnap_txg_save; - sd->tosnap_txg = tosnap_txg_save; - - fnvlist_free(nv); - fnvlist_free(nvfs); - - zfs_close(zhp); - return (rv); -} - -static int -gather_nvlist(libzfs_handle_t *hdl, const char *fsname, const char *fromsnap, - const char *tosnap, boolean_t recursive, boolean_t raw, boolean_t doall, - boolean_t replicate, boolean_t skipmissing, boolean_t verbose, - boolean_t backup, boolean_t holds, boolean_t props, nvlist_t **nvlp, - avl_tree_t **avlp) -{ - zfs_handle_t *zhp; - send_data_t sd = { 0 }; - int error; - - zhp = zfs_open(hdl, fsname, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); - if (zhp == NULL) - return (EZFS_BADTYPE); - - sd.fss = fnvlist_alloc(); - sd.fsname = fsname; - sd.fromsnap = fromsnap; - sd.tosnap = tosnap; - sd.recursive = recursive; - sd.raw = raw; - sd.doall = doall; - sd.replicate = replicate; - sd.skipmissing = skipmissing; - sd.verbose = verbose; - sd.backup = backup; - sd.holds = holds; - sd.props = props; - - if ((error = send_iterate_fs(zhp, &sd)) != 0) { - fnvlist_free(sd.fss); - if (avlp != NULL) - *avlp = NULL; - *nvlp = NULL; - return (error); - } - - if (avlp != NULL && (*avlp = fsavl_create(sd.fss)) == NULL) { - fnvlist_free(sd.fss); - *nvlp = NULL; - return (EZFS_NOMEM); - } - - *nvlp = sd.fss; - return (0); -} - -/* - * Routines specific to "zfs send" - */ -typedef struct send_dump_data { - /* these are all just the short snapname (the part after the @) */ - const char *fromsnap; - const char *tosnap; - char prevsnap[ZFS_MAX_DATASET_NAME_LEN]; - uint64_t prevsnap_obj; - boolean_t seenfrom, seento, replicate, doall, fromorigin; - boolean_t dryrun, parsable, progress, embed_data, std_out; - boolean_t large_block, compress, raw, holds; - boolean_t progressastitle; - int outfd; - boolean_t err; - nvlist_t *fss; - nvlist_t *snapholds; - avl_tree_t *fsavl; - snapfilter_cb_t *filter_cb; - void *filter_cb_arg; - nvlist_t *debugnv; - char holdtag[ZFS_MAX_DATASET_NAME_LEN]; - int cleanup_fd; - int verbosity; - uint64_t size; -} send_dump_data_t; - -static int -zfs_send_space(zfs_handle_t *zhp, const char *snapname, const char *from, - enum lzc_send_flags flags, uint64_t *spacep) -{ - assert(snapname != NULL); - - int error = lzc_send_space(snapname, from, flags, spacep); - if (error == 0) - return (0); - - char errbuf[ERRBUFLEN]; - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "warning: cannot estimate space for '%s'"), snapname); - - libzfs_handle_t *hdl = zhp->zfs_hdl; - switch (error) { - case EXDEV: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "not an earlier snapshot from the same fs")); - return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf)); - - case ENOENT: - if (zfs_dataset_exists(hdl, snapname, - ZFS_TYPE_SNAPSHOT)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "incremental source (%s) does not exist"), - snapname); - } - return (zfs_error(hdl, EZFS_NOENT, errbuf)); - - case EDQUOT: - case EFBIG: - case EIO: - case ENOLINK: - case ENOSPC: - case ENOSTR: - case ENXIO: - case EPIPE: - case ERANGE: - case EFAULT: - case EROFS: - case EINVAL: - zfs_error_aux(hdl, "%s", zfs_strerror(error)); - return (zfs_error(hdl, EZFS_BADBACKUP, errbuf)); - - default: - return (zfs_standard_error(hdl, error, errbuf)); - } -} - -/* - * Dumps a backup of the given snapshot (incremental from fromsnap if it's not - * NULL) to the file descriptor specified by outfd. - */ -static int -dump_ioctl(zfs_handle_t *zhp, const char *fromsnap, uint64_t fromsnap_obj, - boolean_t fromorigin, int outfd, enum lzc_send_flags flags, - nvlist_t *debugnv) -{ - zfs_cmd_t zc = {"\0"}; - libzfs_handle_t *hdl = zhp->zfs_hdl; - nvlist_t *thisdbg; - - assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT); - assert(fromsnap_obj == 0 || !fromorigin); - - (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); - zc.zc_cookie = outfd; - zc.zc_obj = fromorigin; - zc.zc_sendobj = zfs_prop_get_int(zhp, ZFS_PROP_OBJSETID); - zc.zc_fromobj = fromsnap_obj; - zc.zc_flags = flags; - - if (debugnv != NULL) { - thisdbg = fnvlist_alloc(); - if (fromsnap != NULL && fromsnap[0] != '\0') - fnvlist_add_string(thisdbg, "fromsnap", fromsnap); - } - - if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_SEND, &zc) != 0) { - char errbuf[ERRBUFLEN]; - int error = errno; - - (void) snprintf(errbuf, sizeof (errbuf), "%s '%s'", - dgettext(TEXT_DOMAIN, "warning: cannot send"), - zhp->zfs_name); - - if (debugnv != NULL) { - fnvlist_add_uint64(thisdbg, "error", error); - fnvlist_add_nvlist(debugnv, zhp->zfs_name, thisdbg); - fnvlist_free(thisdbg); - } - - switch (error) { - case EXDEV: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "not an earlier snapshot from the same fs")); - return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf)); - - case EACCES: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "source key must be loaded")); - return (zfs_error(hdl, EZFS_CRYPTOFAILED, errbuf)); - - case ENOENT: - if (zfs_dataset_exists(hdl, zc.zc_name, - ZFS_TYPE_SNAPSHOT)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "incremental source (@%s) does not exist"), - zc.zc_value); - } - return (zfs_error(hdl, EZFS_NOENT, errbuf)); - - case EDQUOT: - case EFBIG: - case EIO: - case ENOLINK: - case ENOSPC: - case ENOSTR: - case ENXIO: - case EPIPE: - case ERANGE: - case EFAULT: - case EROFS: - case EINVAL: - zfs_error_aux(hdl, "%s", zfs_strerror(errno)); - return (zfs_error(hdl, EZFS_BADBACKUP, errbuf)); - - default: - return (zfs_standard_error(hdl, errno, errbuf)); - } - } - - if (debugnv != NULL) { - fnvlist_add_nvlist(debugnv, zhp->zfs_name, thisdbg); - fnvlist_free(thisdbg); - } - - return (0); -} - -static void -gather_holds(zfs_handle_t *zhp, send_dump_data_t *sdd) -{ - assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT); - - /* - * zfs_send() only sets snapholds for sends that need them, - * e.g. replication and doall. - */ - if (sdd->snapholds == NULL) - return; - - fnvlist_add_string(sdd->snapholds, zhp->zfs_name, sdd->holdtag); -} - -int -zfs_send_progress(zfs_handle_t *zhp, int fd, uint64_t *bytes_written, - uint64_t *blocks_visited) -{ - zfs_cmd_t zc = {"\0"}; - - if (bytes_written != NULL) - *bytes_written = 0; - if (blocks_visited != NULL) - *blocks_visited = 0; - (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); - zc.zc_cookie = fd; - if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_SEND_PROGRESS, &zc) != 0) - return (errno); - if (bytes_written != NULL) - *bytes_written = zc.zc_cookie; - if (blocks_visited != NULL) - *blocks_visited = zc.zc_objset_type; - return (0); -} - -static volatile boolean_t send_progress_thread_signal_duetotimer; -static void -send_progress_thread_act(int sig, siginfo_t *info, void *ucontext) -{ - (void) sig, (void) ucontext; - send_progress_thread_signal_duetotimer = info->si_code == SI_TIMER; -} - -struct timer_desirability { - timer_t timer; - boolean_t desired; -}; -static void -timer_delete_cleanup(void *timer) -{ - struct timer_desirability *td = timer; - if (td->desired) - timer_delete(td->timer); -} - -#ifdef SIGINFO -#define SEND_PROGRESS_THREAD_PARENT_BLOCK_SIGINFO sigaddset(&new, SIGINFO) -#else -#define SEND_PROGRESS_THREAD_PARENT_BLOCK_SIGINFO -#endif -#define SEND_PROGRESS_THREAD_PARENT_BLOCK(old) { \ - sigset_t new; \ - sigemptyset(&new); \ - sigaddset(&new, SIGUSR1); \ - SEND_PROGRESS_THREAD_PARENT_BLOCK_SIGINFO; \ - pthread_sigmask(SIG_BLOCK, &new, old); \ -} - -static void * -send_progress_thread(void *arg) -{ - progress_arg_t *pa = arg; - zfs_handle_t *zhp = pa->pa_zhp; - uint64_t bytes; - uint64_t blocks; - uint64_t total = pa->pa_size / 100; - char buf[16]; - time_t t; - struct tm tm; - int err; - - const struct sigaction signal_action = - {.sa_sigaction = send_progress_thread_act, .sa_flags = SA_SIGINFO}; - struct sigevent timer_cfg = - {.sigev_notify = SIGEV_SIGNAL, .sigev_signo = SIGUSR1}; - const struct itimerspec timer_time = - {.it_value = {.tv_sec = 1}, .it_interval = {.tv_sec = 1}}; - struct timer_desirability timer = {}; - - sigaction(SIGUSR1, &signal_action, NULL); -#ifdef SIGINFO - sigaction(SIGINFO, &signal_action, NULL); -#endif - - if ((timer.desired = pa->pa_progress || pa->pa_astitle)) { - if (timer_create(CLOCK_MONOTONIC, &timer_cfg, &timer.timer)) - return ((void *)(uintptr_t)errno); - (void) timer_settime(timer.timer, 0, &timer_time, NULL); - } - pthread_cleanup_push(timer_delete_cleanup, &timer); - - if (!pa->pa_parsable && pa->pa_progress) { - (void) fprintf(stderr, - "TIME %s %sSNAPSHOT %s\n", - pa->pa_estimate ? "BYTES" : " SENT", - pa->pa_verbosity >= 2 ? " BLOCKS " : "", - zhp->zfs_name); - } - - /* - * Print the progress from ZFS_IOC_SEND_PROGRESS every second. - */ - for (;;) { - pause(); - if ((err = zfs_send_progress(zhp, pa->pa_fd, &bytes, - &blocks)) != 0) { - if (err == EINTR || err == ENOENT) - err = 0; - pthread_exit(((void *)(uintptr_t)err)); - } - - (void) time(&t); - localtime_r(&t, &tm); - - if (pa->pa_astitle) { - char buf_bytes[16]; - char buf_size[16]; - int pct; - zfs_nicenum(bytes, buf_bytes, sizeof (buf_bytes)); - zfs_nicenum(pa->pa_size, buf_size, sizeof (buf_size)); - pct = (total > 0) ? bytes / total : 100; - zfs_setproctitle("sending %s (%d%%: %s/%s)", - zhp->zfs_name, MIN(pct, 100), buf_bytes, buf_size); - } - - if (pa->pa_verbosity >= 2 && pa->pa_parsable) { - (void) fprintf(stderr, - "%02d:%02d:%02d\t%llu\t%llu\t%s\n", - tm.tm_hour, tm.tm_min, tm.tm_sec, - (u_longlong_t)bytes, (u_longlong_t)blocks, - zhp->zfs_name); - } else if (pa->pa_verbosity >= 2) { - zfs_nicenum(bytes, buf, sizeof (buf)); - (void) fprintf(stderr, - "%02d:%02d:%02d %5s %8llu %s\n", - tm.tm_hour, tm.tm_min, tm.tm_sec, - buf, (u_longlong_t)blocks, zhp->zfs_name); - } else if (pa->pa_parsable) { - (void) fprintf(stderr, "%02d:%02d:%02d\t%llu\t%s\n", - tm.tm_hour, tm.tm_min, tm.tm_sec, - (u_longlong_t)bytes, zhp->zfs_name); - } else if (pa->pa_progress || - !send_progress_thread_signal_duetotimer) { - zfs_nicebytes(bytes, buf, sizeof (buf)); - (void) fprintf(stderr, "%02d:%02d:%02d %5s %s\n", - tm.tm_hour, tm.tm_min, tm.tm_sec, - buf, zhp->zfs_name); - } - } - pthread_cleanup_pop(B_TRUE); - return (NULL); -} - -static boolean_t -send_progress_thread_exit( - libzfs_handle_t *hdl, pthread_t ptid, sigset_t *oldmask) -{ - void *status = NULL; - (void) pthread_cancel(ptid); - (void) pthread_join(ptid, &status); - pthread_sigmask(SIG_SETMASK, oldmask, NULL); - int error = (int)(uintptr_t)status; - if (error != 0 && status != PTHREAD_CANCELED) - return (zfs_standard_error(hdl, error, - dgettext(TEXT_DOMAIN, "progress thread exited nonzero"))); - else - return (B_FALSE); -} - -static void -send_print_verbose(FILE *fout, const char *tosnap, const char *fromsnap, - uint64_t size, boolean_t parsable) -{ - if (parsable) { - if (fromsnap != NULL) { - (void) fprintf(fout, dgettext(TEXT_DOMAIN, - "incremental\t%s\t%s"), fromsnap, tosnap); - } else { -/* - * Workaround for GCC 12+ with UBSan enabled deficencies. - * - * GCC 12+ invoked with -fsanitize=undefined incorrectly reports the code - * below as violating -Wformat-overflow. - */ -#if defined(__GNUC__) && !defined(__clang__) && \ - defined(ZFS_UBSAN_ENABLED) && defined(HAVE_FORMAT_OVERFLOW) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wformat-overflow" -#endif - (void) fprintf(fout, dgettext(TEXT_DOMAIN, - "full\t%s"), tosnap); -#if defined(__GNUC__) && !defined(__clang__) && \ - defined(ZFS_UBSAN_ENABLED) && defined(HAVE_FORMAT_OVERFLOW) -#pragma GCC diagnostic pop -#endif - } - (void) fprintf(fout, "\t%llu", (longlong_t)size); - } else { - if (fromsnap != NULL) { - if (strchr(fromsnap, '@') == NULL && - strchr(fromsnap, '#') == NULL) { - (void) fprintf(fout, dgettext(TEXT_DOMAIN, - "send from @%s to %s"), fromsnap, tosnap); - } else { - (void) fprintf(fout, dgettext(TEXT_DOMAIN, - "send from %s to %s"), fromsnap, tosnap); - } - } else { - (void) fprintf(fout, dgettext(TEXT_DOMAIN, - "full send of %s"), tosnap); - } - if (size != 0) { - char buf[16]; - zfs_nicebytes(size, buf, sizeof (buf)); -/* - * Workaround for GCC 12+ with UBSan enabled deficencies. - * - * GCC 12+ invoked with -fsanitize=undefined incorrectly reports the code - * below as violating -Wformat-overflow. - */ -#if defined(__GNUC__) && !defined(__clang__) && \ - defined(ZFS_UBSAN_ENABLED) && defined(HAVE_FORMAT_OVERFLOW) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wformat-overflow" -#endif - (void) fprintf(fout, dgettext(TEXT_DOMAIN, - " estimated size is %s"), buf); -#if defined(__GNUC__) && !defined(__clang__) && \ - defined(ZFS_UBSAN_ENABLED) && defined(HAVE_FORMAT_OVERFLOW) -#pragma GCC diagnostic pop -#endif - } - } - (void) fprintf(fout, "\n"); -} - -/* - * Send a single filesystem snapshot, updating the send dump data. - * This interface is intended for use as a zfs_iter_snapshots_v2_sorted visitor. - */ -static int -dump_snapshot(zfs_handle_t *zhp, void *arg) -{ - send_dump_data_t *sdd = arg; - progress_arg_t pa = { 0 }; - pthread_t tid; - char *thissnap; - enum lzc_send_flags flags = 0; - int err; - boolean_t isfromsnap, istosnap, fromorigin; - boolean_t exclude = B_FALSE; - FILE *fout = sdd->std_out ? stdout : stderr; - - err = 0; - thissnap = strchr(zhp->zfs_name, '@') + 1; - isfromsnap = (sdd->fromsnap != NULL && - strcmp(sdd->fromsnap, thissnap) == 0); - - if (!sdd->seenfrom && isfromsnap) { - gather_holds(zhp, sdd); - sdd->seenfrom = B_TRUE; - (void) strlcpy(sdd->prevsnap, thissnap, sizeof (sdd->prevsnap)); - sdd->prevsnap_obj = zfs_prop_get_int(zhp, ZFS_PROP_OBJSETID); - zfs_close(zhp); - return (0); - } - - if (sdd->seento || !sdd->seenfrom) { - zfs_close(zhp); - return (0); - } - - istosnap = (strcmp(sdd->tosnap, thissnap) == 0); - if (istosnap) - sdd->seento = B_TRUE; - - if (sdd->large_block) - flags |= LZC_SEND_FLAG_LARGE_BLOCK; - if (sdd->embed_data) - flags |= LZC_SEND_FLAG_EMBED_DATA; - if (sdd->compress) - flags |= LZC_SEND_FLAG_COMPRESS; - if (sdd->raw) - flags |= LZC_SEND_FLAG_RAW; - - if (!sdd->doall && !isfromsnap && !istosnap) { - if (sdd->replicate) { - const char *snapname; - nvlist_t *snapprops; - /* - * Filter out all intermediate snapshots except origin - * snapshots needed to replicate clones. - */ - nvlist_t *nvfs = fsavl_find(sdd->fsavl, - zhp->zfs_dmustats.dds_guid, &snapname); - - if (nvfs != NULL) { - snapprops = fnvlist_lookup_nvlist(nvfs, - "snapprops"); - snapprops = fnvlist_lookup_nvlist(snapprops, - thissnap); - exclude = !nvlist_exists(snapprops, - "is_clone_origin"); - } - } else { - exclude = B_TRUE; - } - } - - /* - * If a filter function exists, call it to determine whether - * this snapshot will be sent. - */ - if (exclude || (sdd->filter_cb != NULL && - sdd->filter_cb(zhp, sdd->filter_cb_arg) == B_FALSE)) { - /* - * This snapshot is filtered out. Don't send it, and don't - * set prevsnap_obj, so it will be as if this snapshot didn't - * exist, and the next accepted snapshot will be sent as - * an incremental from the last accepted one, or as the - * first (and full) snapshot in the case of a replication, - * non-incremental send. - */ - zfs_close(zhp); - return (0); - } - - gather_holds(zhp, sdd); - fromorigin = sdd->prevsnap[0] == '\0' && - (sdd->fromorigin || sdd->replicate); - - if (sdd->verbosity != 0) { - uint64_t size = 0; - char fromds[ZFS_MAX_DATASET_NAME_LEN]; - - if (sdd->prevsnap[0] != '\0') { - (void) strlcpy(fromds, zhp->zfs_name, sizeof (fromds)); - *(strchr(fromds, '@') + 1) = '\0'; - (void) strlcat(fromds, sdd->prevsnap, sizeof (fromds)); - } - if (zfs_send_space(zhp, zhp->zfs_name, - sdd->prevsnap[0] ? fromds : NULL, flags, &size) == 0) { - send_print_verbose(fout, zhp->zfs_name, - sdd->prevsnap[0] ? sdd->prevsnap : NULL, - size, sdd->parsable); - sdd->size += size; - } - } - - if (!sdd->dryrun) { - /* - * If progress reporting is requested, spawn a new thread to - * poll ZFS_IOC_SEND_PROGRESS at a regular interval. - */ - sigset_t oldmask; - { - pa.pa_zhp = zhp; - pa.pa_fd = sdd->outfd; - pa.pa_parsable = sdd->parsable; - pa.pa_estimate = B_FALSE; - pa.pa_verbosity = sdd->verbosity; - pa.pa_size = sdd->size; - pa.pa_astitle = sdd->progressastitle; - pa.pa_progress = sdd->progress; - - if ((err = pthread_create(&tid, NULL, - send_progress_thread, &pa)) != 0) { - zfs_close(zhp); - return (err); - } - SEND_PROGRESS_THREAD_PARENT_BLOCK(&oldmask); - } - - err = dump_ioctl(zhp, sdd->prevsnap, sdd->prevsnap_obj, - fromorigin, sdd->outfd, flags, sdd->debugnv); - - if (send_progress_thread_exit(zhp->zfs_hdl, tid, &oldmask)) - return (-1); - } - - (void) strlcpy(sdd->prevsnap, thissnap, sizeof (sdd->prevsnap)); - sdd->prevsnap_obj = zfs_prop_get_int(zhp, ZFS_PROP_OBJSETID); - zfs_close(zhp); - return (err); -} - -/* - * Send all snapshots for a filesystem, updating the send dump data. - */ -static int -dump_filesystem(zfs_handle_t *zhp, send_dump_data_t *sdd) -{ - int rv = 0; - boolean_t missingfrom = B_FALSE; - zfs_cmd_t zc = {"\0"}; - uint64_t min_txg = 0, max_txg = 0; - - /* - * Make sure the tosnap exists. - */ - (void) snprintf(zc.zc_name, sizeof (zc.zc_name), "%s@%s", - zhp->zfs_name, sdd->tosnap); - if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_OBJSET_STATS, &zc) != 0) { - (void) fprintf(stderr, dgettext(TEXT_DOMAIN, - "WARNING: could not send %s@%s: does not exist\n"), - zhp->zfs_name, sdd->tosnap); - sdd->err = B_TRUE; - return (0); - } - - /* - * If this fs does not have fromsnap, and we're doing - * recursive, we need to send a full stream from the - * beginning (or an incremental from the origin if this - * is a clone). If we're doing non-recursive, then let - * them get the error. - */ - if (sdd->replicate && sdd->fromsnap) { - /* - * Make sure the fromsnap exists. - */ - (void) snprintf(zc.zc_name, sizeof (zc.zc_name), "%s@%s", - zhp->zfs_name, sdd->fromsnap); - if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_OBJSET_STATS, &zc) != 0) - missingfrom = B_TRUE; - } - - sdd->seenfrom = sdd->seento = B_FALSE; - sdd->prevsnap[0] = '\0'; - sdd->prevsnap_obj = 0; - if (sdd->fromsnap == NULL || missingfrom) - sdd->seenfrom = B_TRUE; - - /* - * Iterate through all snapshots and process the ones we will be - * sending. If we only have a "from" and "to" snapshot to deal - * with, we can avoid iterating through all the other snapshots. - */ - if (sdd->doall || sdd->replicate || sdd->tosnap == NULL) { - if (!sdd->replicate) { - if (sdd->fromsnap != NULL) { - min_txg = get_snap_txg(zhp->zfs_hdl, - zhp->zfs_name, sdd->fromsnap); - } - if (sdd->tosnap != NULL) { - max_txg = get_snap_txg(zhp->zfs_hdl, - zhp->zfs_name, sdd->tosnap); - } - } - rv = zfs_iter_snapshots_sorted_v2(zhp, 0, dump_snapshot, sdd, - min_txg, max_txg); - } else { - char snapname[MAXPATHLEN] = { 0 }; - zfs_handle_t *snap; - - /* Dump fromsnap. */ - if (!sdd->seenfrom) { - (void) snprintf(snapname, sizeof (snapname), - "%s@%s", zhp->zfs_name, sdd->fromsnap); - snap = zfs_open(zhp->zfs_hdl, snapname, - ZFS_TYPE_SNAPSHOT); - if (snap != NULL) - rv = dump_snapshot(snap, sdd); - else - rv = errno; - } - - /* Dump tosnap. */ - if (rv == 0) { - (void) snprintf(snapname, sizeof (snapname), - "%s@%s", zhp->zfs_name, sdd->tosnap); - snap = zfs_open(zhp->zfs_hdl, snapname, - ZFS_TYPE_SNAPSHOT); - if (snap != NULL) - rv = dump_snapshot(snap, sdd); - else - rv = errno; - } - } - - if (!sdd->seenfrom) { - (void) fprintf(stderr, dgettext(TEXT_DOMAIN, - "WARNING: could not send %s@%s:\n" - "incremental source (%s@%s) does not exist\n"), - zhp->zfs_name, sdd->tosnap, - zhp->zfs_name, sdd->fromsnap); - sdd->err = B_TRUE; - } else if (!sdd->seento) { - if (sdd->fromsnap) { - (void) fprintf(stderr, dgettext(TEXT_DOMAIN, - "WARNING: could not send %s@%s:\n" - "incremental source (%s@%s) " - "is not earlier than it\n"), - zhp->zfs_name, sdd->tosnap, - zhp->zfs_name, sdd->fromsnap); - } else { - (void) fprintf(stderr, dgettext(TEXT_DOMAIN, - "WARNING: " - "could not send %s@%s: does not exist\n"), - zhp->zfs_name, sdd->tosnap); - } - sdd->err = B_TRUE; - } - - return (rv); -} - -/* - * Send all snapshots for all filesystems in sdd. - */ -static int -dump_filesystems(zfs_handle_t *rzhp, send_dump_data_t *sdd) -{ - nvpair_t *fspair; - boolean_t needagain, progress; - - if (!sdd->replicate) - return (dump_filesystem(rzhp, sdd)); - - /* Mark the clone origin snapshots. */ - for (fspair = nvlist_next_nvpair(sdd->fss, NULL); fspair; - fspair = nvlist_next_nvpair(sdd->fss, fspair)) { - nvlist_t *nvfs; - uint64_t origin_guid = 0; - - nvfs = fnvpair_value_nvlist(fspair); - (void) nvlist_lookup_uint64(nvfs, "origin", &origin_guid); - if (origin_guid != 0) { - const char *snapname; - nvlist_t *origin_nv = fsavl_find(sdd->fsavl, - origin_guid, &snapname); - if (origin_nv != NULL) { - nvlist_t *snapprops; - snapprops = fnvlist_lookup_nvlist(origin_nv, - "snapprops"); - snapprops = fnvlist_lookup_nvlist(snapprops, - snapname); - fnvlist_add_boolean(snapprops, - "is_clone_origin"); - } - } - } -again: - needagain = progress = B_FALSE; - for (fspair = nvlist_next_nvpair(sdd->fss, NULL); fspair; - fspair = nvlist_next_nvpair(sdd->fss, fspair)) { - nvlist_t *fslist, *parent_nv; - const char *fsname; - zfs_handle_t *zhp; - int err; - uint64_t origin_guid = 0; - uint64_t parent_guid = 0; - - fslist = fnvpair_value_nvlist(fspair); - if (nvlist_lookup_boolean(fslist, "sent") == 0) - continue; - - fsname = fnvlist_lookup_string(fslist, "name"); - (void) nvlist_lookup_uint64(fslist, "origin", &origin_guid); - (void) nvlist_lookup_uint64(fslist, "parentfromsnap", - &parent_guid); - - if (parent_guid != 0) { - parent_nv = fsavl_find(sdd->fsavl, parent_guid, NULL); - if (!nvlist_exists(parent_nv, "sent")) { - /* Parent has not been sent; skip this one. */ - needagain = B_TRUE; - continue; - } - } - - if (origin_guid != 0) { - nvlist_t *origin_nv = fsavl_find(sdd->fsavl, - origin_guid, NULL); - if (origin_nv != NULL && - !nvlist_exists(origin_nv, "sent")) { - /* - * Origin has not been sent yet; - * skip this clone. - */ - needagain = B_TRUE; - continue; - } - } - - zhp = zfs_open(rzhp->zfs_hdl, fsname, ZFS_TYPE_DATASET); - if (zhp == NULL) - return (-1); - err = dump_filesystem(zhp, sdd); - fnvlist_add_boolean(fslist, "sent"); - progress = B_TRUE; - zfs_close(zhp); - if (err) - return (err); - } - if (needagain) { - assert(progress); - goto again; - } - - /* Clean out the sent flags in case we reuse this fss. */ - for (fspair = nvlist_next_nvpair(sdd->fss, NULL); fspair; - fspair = nvlist_next_nvpair(sdd->fss, fspair)) { - nvlist_t *fslist; - - fslist = fnvpair_value_nvlist(fspair); - (void) nvlist_remove_all(fslist, "sent"); - } - - return (0); -} - -nvlist_t * -zfs_send_resume_token_to_nvlist(libzfs_handle_t *hdl, const char *token) -{ - unsigned int version; - int nread, i; - unsigned long long checksum, packed_len; - - /* - * Decode token header, which is: - * <token version>-<checksum of payload>-<uncompressed payload length> - * Note that the only supported token version is 1. - */ - nread = sscanf(token, "%u-%llx-%llx-", - &version, &checksum, &packed_len); - if (nread != 3) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "resume token is corrupt (invalid format)")); - return (NULL); - } - - if (version != ZFS_SEND_RESUME_TOKEN_VERSION) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "resume token is corrupt (invalid version %u)"), - version); - return (NULL); - } - - /* Convert hexadecimal representation to binary. */ - token = strrchr(token, '-') + 1; - int len = strlen(token) / 2; - unsigned char *compressed = zfs_alloc(hdl, len); - for (i = 0; i < len; i++) { - nread = sscanf(token + i * 2, "%2hhx", compressed + i); - if (nread != 1) { - free(compressed); - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "resume token is corrupt " - "(payload is not hex-encoded)")); - return (NULL); - } - } - - /* Verify checksum. */ - zio_cksum_t cksum; - fletcher_4_native_varsize(compressed, len, &cksum); - if (cksum.zc_word[0] != checksum) { - free(compressed); - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "resume token is corrupt (incorrect checksum)")); - return (NULL); - } - - /* Uncompress. */ - void *packed = zfs_alloc(hdl, packed_len); - uLongf packed_len_long = packed_len; - if (uncompress(packed, &packed_len_long, compressed, len) != Z_OK || - packed_len_long != packed_len) { - free(packed); - free(compressed); - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "resume token is corrupt (decompression failed)")); - return (NULL); - } - - /* Unpack nvlist. */ - nvlist_t *nv; - int error = nvlist_unpack(packed, packed_len, &nv, KM_SLEEP); - free(packed); - free(compressed); - if (error != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "resume token is corrupt (nvlist_unpack failed)")); - return (NULL); - } - return (nv); -} - -static enum lzc_send_flags -lzc_flags_from_sendflags(const sendflags_t *flags) -{ - enum lzc_send_flags lzc_flags = 0; - - if (flags->largeblock) - lzc_flags |= LZC_SEND_FLAG_LARGE_BLOCK; - if (flags->embed_data) - lzc_flags |= LZC_SEND_FLAG_EMBED_DATA; - if (flags->compress) - lzc_flags |= LZC_SEND_FLAG_COMPRESS; - if (flags->raw) - lzc_flags |= LZC_SEND_FLAG_RAW; - if (flags->saved) - lzc_flags |= LZC_SEND_FLAG_SAVED; - - return (lzc_flags); -} - -static int -estimate_size(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags, - uint64_t resumeobj, uint64_t resumeoff, uint64_t bytes, - const char *redactbook, char *errbuf, uint64_t *sizep) -{ - uint64_t size; - FILE *fout = flags->dryrun ? stdout : stderr; - progress_arg_t pa = { 0 }; - int err = 0; - pthread_t ptid; - sigset_t oldmask; - - { - pa.pa_zhp = zhp; - pa.pa_fd = fd; - pa.pa_parsable = flags->parsable; - pa.pa_estimate = B_TRUE; - pa.pa_verbosity = flags->verbosity; - - err = pthread_create(&ptid, NULL, - send_progress_thread, &pa); - if (err != 0) { - zfs_error_aux(zhp->zfs_hdl, "%s", zfs_strerror(errno)); - return (zfs_error(zhp->zfs_hdl, - EZFS_THREADCREATEFAILED, errbuf)); - } - SEND_PROGRESS_THREAD_PARENT_BLOCK(&oldmask); - } - - err = lzc_send_space_resume_redacted(zhp->zfs_name, from, - lzc_flags_from_sendflags(flags), resumeobj, resumeoff, bytes, - redactbook, fd, &size); - *sizep = size; - - if (send_progress_thread_exit(zhp->zfs_hdl, ptid, &oldmask)) - return (-1); - - if (!flags->progress && !flags->parsable) - return (err); - - if (err != 0) { - zfs_error_aux(zhp->zfs_hdl, "%s", zfs_strerror(err)); - return (zfs_error(zhp->zfs_hdl, EZFS_BADBACKUP, - errbuf)); - } - send_print_verbose(fout, zhp->zfs_name, from, size, - flags->parsable); - - if (flags->parsable) { - (void) fprintf(fout, "size\t%llu\n", (longlong_t)size); - } else { - char buf[16]; - zfs_nicenum(size, buf, sizeof (buf)); - (void) fprintf(fout, dgettext(TEXT_DOMAIN, - "total estimated size is %s\n"), buf); - } - return (0); -} - -static boolean_t -redact_snaps_contains(const uint64_t *snaps, uint64_t num_snaps, uint64_t guid) -{ - for (int i = 0; i < num_snaps; i++) { - if (snaps[i] == guid) - return (B_TRUE); - } - return (B_FALSE); -} - -static boolean_t -redact_snaps_equal(const uint64_t *snaps1, uint64_t num_snaps1, - const uint64_t *snaps2, uint64_t num_snaps2) -{ - if (num_snaps1 != num_snaps2) - return (B_FALSE); - for (int i = 0; i < num_snaps1; i++) { - if (!redact_snaps_contains(snaps2, num_snaps2, snaps1[i])) - return (B_FALSE); - } - return (B_TRUE); -} - -static int -get_bookmarks(const char *path, nvlist_t **bmarksp) -{ - nvlist_t *props = fnvlist_alloc(); - int error; - - fnvlist_add_boolean(props, "redact_complete"); - fnvlist_add_boolean(props, zfs_prop_to_name(ZFS_PROP_REDACT_SNAPS)); - error = lzc_get_bookmarks(path, props, bmarksp); - fnvlist_free(props); - return (error); -} - -static nvpair_t * -find_redact_pair(nvlist_t *bmarks, const uint64_t *redact_snap_guids, - int num_redact_snaps) -{ - nvpair_t *pair; - - for (pair = nvlist_next_nvpair(bmarks, NULL); pair; - pair = nvlist_next_nvpair(bmarks, pair)) { - - nvlist_t *bmark = fnvpair_value_nvlist(pair); - nvlist_t *vallist = fnvlist_lookup_nvlist(bmark, - zfs_prop_to_name(ZFS_PROP_REDACT_SNAPS)); - uint_t len = 0; - uint64_t *bmarksnaps = fnvlist_lookup_uint64_array(vallist, - ZPROP_VALUE, &len); - if (redact_snaps_equal(redact_snap_guids, - num_redact_snaps, bmarksnaps, len)) { - break; - } - } - return (pair); -} - -static boolean_t -get_redact_complete(nvpair_t *pair) -{ - nvlist_t *bmark = fnvpair_value_nvlist(pair); - nvlist_t *vallist = fnvlist_lookup_nvlist(bmark, "redact_complete"); - boolean_t complete = fnvlist_lookup_boolean_value(vallist, - ZPROP_VALUE); - - return (complete); -} - -/* - * Check that the list of redaction snapshots in the bookmark matches the send - * we're resuming, and return whether or not it's complete. - * - * Note that the caller needs to free the contents of *bookname with free() if - * this function returns successfully. - */ -static int -find_redact_book(libzfs_handle_t *hdl, const char *path, - const uint64_t *redact_snap_guids, int num_redact_snaps, - char **bookname) -{ - char errbuf[ERRBUFLEN]; - nvlist_t *bmarks; - - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot resume send")); - - int error = get_bookmarks(path, &bmarks); - if (error != 0) { - if (error == ESRCH) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "nonexistent redaction bookmark provided")); - } else if (error == ENOENT) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "dataset to be sent no longer exists")); - } else { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "unknown error: %s"), zfs_strerror(error)); - } - return (zfs_error(hdl, EZFS_BADPROP, errbuf)); - } - nvpair_t *pair = find_redact_pair(bmarks, redact_snap_guids, - num_redact_snaps); - if (pair == NULL) { - fnvlist_free(bmarks); - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "no appropriate redaction bookmark exists")); - return (zfs_error(hdl, EZFS_BADPROP, errbuf)); - } - boolean_t complete = get_redact_complete(pair); - if (!complete) { - fnvlist_free(bmarks); - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "incomplete redaction bookmark provided")); - return (zfs_error(hdl, EZFS_BADPROP, errbuf)); - } - *bookname = strndup(nvpair_name(pair), ZFS_MAX_DATASET_NAME_LEN); - ASSERT3P(*bookname, !=, NULL); - fnvlist_free(bmarks); - return (0); -} - -static enum lzc_send_flags -lzc_flags_from_resume_nvl(nvlist_t *resume_nvl) -{ - enum lzc_send_flags lzc_flags = 0; - - if (nvlist_exists(resume_nvl, "largeblockok")) - lzc_flags |= LZC_SEND_FLAG_LARGE_BLOCK; - if (nvlist_exists(resume_nvl, "embedok")) - lzc_flags |= LZC_SEND_FLAG_EMBED_DATA; - if (nvlist_exists(resume_nvl, "compressok")) - lzc_flags |= LZC_SEND_FLAG_COMPRESS; - if (nvlist_exists(resume_nvl, "rawok")) - lzc_flags |= LZC_SEND_FLAG_RAW; - if (nvlist_exists(resume_nvl, "savedok")) - lzc_flags |= LZC_SEND_FLAG_SAVED; - - return (lzc_flags); -} - -static int -zfs_send_resume_impl_cb_impl(libzfs_handle_t *hdl, sendflags_t *flags, - int outfd, nvlist_t *resume_nvl) -{ - char errbuf[ERRBUFLEN]; - const char *toname; - const char *fromname = NULL; - uint64_t resumeobj, resumeoff, toguid, fromguid, bytes; - zfs_handle_t *zhp; - int error = 0; - char name[ZFS_MAX_DATASET_NAME_LEN]; - FILE *fout = (flags->verbosity > 0 && flags->dryrun) ? stdout : stderr; - uint64_t *redact_snap_guids = NULL; - int num_redact_snaps = 0; - char *redact_book = NULL; - uint64_t size = 0; - - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot resume send")); - - if (flags->verbosity != 0) { - (void) fprintf(fout, dgettext(TEXT_DOMAIN, - "resume token contents:\n")); - nvlist_print(fout, resume_nvl); - } - - if (nvlist_lookup_string(resume_nvl, "toname", &toname) != 0 || - nvlist_lookup_uint64(resume_nvl, "object", &resumeobj) != 0 || - nvlist_lookup_uint64(resume_nvl, "offset", &resumeoff) != 0 || - nvlist_lookup_uint64(resume_nvl, "bytes", &bytes) != 0 || - nvlist_lookup_uint64(resume_nvl, "toguid", &toguid) != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "resume token is corrupt")); - return (zfs_error(hdl, EZFS_FAULT, errbuf)); - } - fromguid = 0; - (void) nvlist_lookup_uint64(resume_nvl, "fromguid", &fromguid); - - if (flags->saved) { - (void) strlcpy(name, toname, sizeof (name)); - } else { - error = guid_to_name(hdl, toname, toguid, B_FALSE, name); - if (error != 0) { - if (zfs_dataset_exists(hdl, toname, ZFS_TYPE_DATASET)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "'%s' is no longer the same snapshot " - "used in the initial send"), toname); - } else { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "'%s' used in the initial send no " - "longer exists"), toname); - } - return (zfs_error(hdl, EZFS_BADPATH, errbuf)); - } - } - - zhp = zfs_open(hdl, name, ZFS_TYPE_DATASET); - if (zhp == NULL) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "unable to access '%s'"), name); - return (zfs_error(hdl, EZFS_BADPATH, errbuf)); - } - - if (nvlist_lookup_uint64_array(resume_nvl, "book_redact_snaps", - &redact_snap_guids, (uint_t *)&num_redact_snaps) != 0) { - num_redact_snaps = -1; - } - - if (fromguid != 0) { - if (guid_to_name_redact_snaps(hdl, toname, fromguid, B_TRUE, - redact_snap_guids, num_redact_snaps, name) != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "incremental source %#llx no longer exists"), - (longlong_t)fromguid); - return (zfs_error(hdl, EZFS_BADPATH, errbuf)); - } - fromname = name; - } - - redact_snap_guids = NULL; - - if (nvlist_lookup_uint64_array(resume_nvl, - zfs_prop_to_name(ZFS_PROP_REDACT_SNAPS), &redact_snap_guids, - (uint_t *)&num_redact_snaps) == 0) { - char path[ZFS_MAX_DATASET_NAME_LEN]; - - (void) strlcpy(path, toname, sizeof (path)); - char *at = strchr(path, '@'); - ASSERT3P(at, !=, NULL); - - *at = '\0'; - - if ((error = find_redact_book(hdl, path, redact_snap_guids, - num_redact_snaps, &redact_book)) != 0) { - return (error); - } - } - - enum lzc_send_flags lzc_flags = lzc_flags_from_sendflags(flags) | - lzc_flags_from_resume_nvl(resume_nvl); - - if (flags->verbosity != 0 || flags->progressastitle) { - /* - * Some of these may have come from the resume token, set them - * here for size estimate purposes. - */ - sendflags_t tmpflags = *flags; - if (lzc_flags & LZC_SEND_FLAG_LARGE_BLOCK) - tmpflags.largeblock = B_TRUE; - if (lzc_flags & LZC_SEND_FLAG_COMPRESS) - tmpflags.compress = B_TRUE; - if (lzc_flags & LZC_SEND_FLAG_EMBED_DATA) - tmpflags.embed_data = B_TRUE; - if (lzc_flags & LZC_SEND_FLAG_RAW) - tmpflags.raw = B_TRUE; - if (lzc_flags & LZC_SEND_FLAG_SAVED) - tmpflags.saved = B_TRUE; - error = estimate_size(zhp, fromname, outfd, &tmpflags, - resumeobj, resumeoff, bytes, redact_book, errbuf, &size); - } - - if (!flags->dryrun) { - progress_arg_t pa = { 0 }; - pthread_t tid; - sigset_t oldmask; - /* - * If progress reporting is requested, spawn a new thread to - * poll ZFS_IOC_SEND_PROGRESS at a regular interval. - */ - { - pa.pa_zhp = zhp; - pa.pa_fd = outfd; - pa.pa_parsable = flags->parsable; - pa.pa_estimate = B_FALSE; - pa.pa_verbosity = flags->verbosity; - pa.pa_size = size; - pa.pa_astitle = flags->progressastitle; - pa.pa_progress = flags->progress; - - error = pthread_create(&tid, NULL, - send_progress_thread, &pa); - if (error != 0) { - if (redact_book != NULL) - free(redact_book); - zfs_close(zhp); - return (error); - } - SEND_PROGRESS_THREAD_PARENT_BLOCK(&oldmask); - } - - error = lzc_send_resume_redacted(zhp->zfs_name, fromname, outfd, - lzc_flags, resumeobj, resumeoff, redact_book); - if (redact_book != NULL) - free(redact_book); - - if (send_progress_thread_exit(hdl, tid, &oldmask)) { - zfs_close(zhp); - return (-1); - } - - char errbuf[ERRBUFLEN]; - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "warning: cannot send '%s'"), zhp->zfs_name); - - zfs_close(zhp); - - switch (error) { - case 0: - return (0); - case EACCES: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "source key must be loaded")); - return (zfs_error(hdl, EZFS_CRYPTOFAILED, errbuf)); - case ESRCH: - if (lzc_exists(zhp->zfs_name)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "incremental source could not be found")); - } - return (zfs_error(hdl, EZFS_NOENT, errbuf)); - - case EXDEV: - case ENOENT: - case EDQUOT: - case EFBIG: - case EIO: - case ENOLINK: - case ENOSPC: - case ENOSTR: - case ENXIO: - case EPIPE: - case ERANGE: - case EFAULT: - case EROFS: - zfs_error_aux(hdl, "%s", zfs_strerror(errno)); - return (zfs_error(hdl, EZFS_BADBACKUP, errbuf)); - - default: - return (zfs_standard_error(hdl, errno, errbuf)); - } - } else { - if (redact_book != NULL) - free(redact_book); - } - - zfs_close(zhp); - - return (error); -} - -struct zfs_send_resume_impl { - libzfs_handle_t *hdl; - sendflags_t *flags; - nvlist_t *resume_nvl; -}; - -static int -zfs_send_resume_impl_cb(int outfd, void *arg) -{ - struct zfs_send_resume_impl *zsri = arg; - return (zfs_send_resume_impl_cb_impl(zsri->hdl, zsri->flags, outfd, - zsri->resume_nvl)); -} - -static int -zfs_send_resume_impl(libzfs_handle_t *hdl, sendflags_t *flags, int outfd, - nvlist_t *resume_nvl) -{ - struct zfs_send_resume_impl zsri = { - .hdl = hdl, - .flags = flags, - .resume_nvl = resume_nvl, - }; - return (lzc_send_wrapper(zfs_send_resume_impl_cb, outfd, &zsri)); -} - -int -zfs_send_resume(libzfs_handle_t *hdl, sendflags_t *flags, int outfd, - const char *resume_token) -{ - int ret; - char errbuf[ERRBUFLEN]; - nvlist_t *resume_nvl; - - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot resume send")); - - resume_nvl = zfs_send_resume_token_to_nvlist(hdl, resume_token); - if (resume_nvl == NULL) { - /* - * zfs_error_aux has already been set by - * zfs_send_resume_token_to_nvlist() - */ - return (zfs_error(hdl, EZFS_FAULT, errbuf)); - } - - ret = zfs_send_resume_impl(hdl, flags, outfd, resume_nvl); - fnvlist_free(resume_nvl); - - return (ret); -} - -int -zfs_send_saved(zfs_handle_t *zhp, sendflags_t *flags, int outfd, - const char *resume_token) -{ - int ret; - libzfs_handle_t *hdl = zhp->zfs_hdl; - nvlist_t *saved_nvl = NULL, *resume_nvl = NULL; - uint64_t saved_guid = 0, resume_guid = 0; - uint64_t obj = 0, off = 0, bytes = 0; - char token_buf[ZFS_MAXPROPLEN]; - char errbuf[ERRBUFLEN]; - - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "saved send failed")); - - ret = zfs_prop_get(zhp, ZFS_PROP_RECEIVE_RESUME_TOKEN, - token_buf, sizeof (token_buf), NULL, NULL, 0, B_TRUE); - if (ret != 0) - goto out; - - saved_nvl = zfs_send_resume_token_to_nvlist(hdl, token_buf); - if (saved_nvl == NULL) { - /* - * zfs_error_aux has already been set by - * zfs_send_resume_token_to_nvlist() - */ - ret = zfs_error(hdl, EZFS_FAULT, errbuf); - goto out; - } - - /* - * If a resume token is provided we use the object and offset - * from that instead of the default, which starts from the - * beginning. - */ - if (resume_token != NULL) { - resume_nvl = zfs_send_resume_token_to_nvlist(hdl, - resume_token); - if (resume_nvl == NULL) { - ret = zfs_error(hdl, EZFS_FAULT, errbuf); - goto out; - } - - if (nvlist_lookup_uint64(resume_nvl, "object", &obj) != 0 || - nvlist_lookup_uint64(resume_nvl, "offset", &off) != 0 || - nvlist_lookup_uint64(resume_nvl, "bytes", &bytes) != 0 || - nvlist_lookup_uint64(resume_nvl, "toguid", - &resume_guid) != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "provided resume token is corrupt")); - ret = zfs_error(hdl, EZFS_FAULT, errbuf); - goto out; - } - - if (nvlist_lookup_uint64(saved_nvl, "toguid", - &saved_guid)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "dataset's resume token is corrupt")); - ret = zfs_error(hdl, EZFS_FAULT, errbuf); - goto out; - } - - if (resume_guid != saved_guid) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "provided resume token does not match dataset")); - ret = zfs_error(hdl, EZFS_BADBACKUP, errbuf); - goto out; - } - } - - (void) nvlist_remove_all(saved_nvl, "object"); - fnvlist_add_uint64(saved_nvl, "object", obj); - - (void) nvlist_remove_all(saved_nvl, "offset"); - fnvlist_add_uint64(saved_nvl, "offset", off); - - (void) nvlist_remove_all(saved_nvl, "bytes"); - fnvlist_add_uint64(saved_nvl, "bytes", bytes); - - (void) nvlist_remove_all(saved_nvl, "toname"); - fnvlist_add_string(saved_nvl, "toname", zhp->zfs_name); - - ret = zfs_send_resume_impl(hdl, flags, outfd, saved_nvl); - -out: - fnvlist_free(saved_nvl); - fnvlist_free(resume_nvl); - return (ret); -} - -/* - * This function informs the target system that the recursive send is complete. - * The record is also expected in the case of a send -p. - */ -static int -send_conclusion_record(int fd, zio_cksum_t *zc) -{ - dmu_replay_record_t drr; - memset(&drr, 0, sizeof (dmu_replay_record_t)); - drr.drr_type = DRR_END; - if (zc != NULL) - drr.drr_u.drr_end.drr_checksum = *zc; - if (write(fd, &drr, sizeof (drr)) == -1) { - return (errno); - } - return (0); -} - -/* - * This function is responsible for sending the records that contain the - * necessary information for the target system's libzfs to be able to set the - * properties of the filesystem being received, or to be able to prepare for - * a recursive receive. - * - * The "zhp" argument is the handle of the snapshot we are sending - * (the "tosnap"). The "from" argument is the short snapshot name (the part - * after the @) of the incremental source. - */ -static int -send_prelim_records(zfs_handle_t *zhp, const char *from, int fd, - boolean_t gather_props, boolean_t recursive, boolean_t verbose, - boolean_t dryrun, boolean_t raw, boolean_t replicate, boolean_t skipmissing, - boolean_t backup, boolean_t holds, boolean_t props, boolean_t doall, - nvlist_t **fssp, avl_tree_t **fsavlp) -{ - int err = 0; - char *packbuf = NULL; - size_t buflen = 0; - zio_cksum_t zc = { {0} }; - int featureflags = 0; - /* name of filesystem/volume that contains snapshot we are sending */ - char tofs[ZFS_MAX_DATASET_NAME_LEN]; - /* short name of snap we are sending */ - const char *tosnap = ""; - - char errbuf[ERRBUFLEN]; - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "warning: cannot send '%s'"), zhp->zfs_name); - if (zhp->zfs_type == ZFS_TYPE_FILESYSTEM && zfs_prop_get_int(zhp, - ZFS_PROP_VERSION) >= ZPL_VERSION_SA) { - featureflags |= DMU_BACKUP_FEATURE_SA_SPILL; - } - - if (holds) - featureflags |= DMU_BACKUP_FEATURE_HOLDS; - - (void) strlcpy(tofs, zhp->zfs_name, ZFS_MAX_DATASET_NAME_LEN); - char *at = strchr(tofs, '@'); - if (at != NULL) { - *at = '\0'; - tosnap = at + 1; - } - - if (gather_props) { - nvlist_t *hdrnv = fnvlist_alloc(); - nvlist_t *fss = NULL; - - if (from != NULL) - fnvlist_add_string(hdrnv, "fromsnap", from); - fnvlist_add_string(hdrnv, "tosnap", tosnap); - if (!recursive) - fnvlist_add_boolean(hdrnv, "not_recursive"); - - if (raw) { - fnvlist_add_boolean(hdrnv, "raw"); - } - - if (gather_nvlist(zhp->zfs_hdl, tofs, - from, tosnap, recursive, raw, doall, replicate, skipmissing, - verbose, backup, holds, props, &fss, fsavlp) != 0) { - return (zfs_error(zhp->zfs_hdl, EZFS_BADBACKUP, - errbuf)); - } - /* - * Do not allow the size of the properties list to exceed - * the limit - */ - if ((fnvlist_size(fss) + fnvlist_size(hdrnv)) > - zhp->zfs_hdl->libzfs_max_nvlist) { - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "warning: cannot send '%s': " - "the size of the list of snapshots and properties " - "is too large to be received successfully.\n" - "Select a smaller number of snapshots to send.\n"), - zhp->zfs_name); - return (zfs_error(zhp->zfs_hdl, EZFS_NOSPC, - errbuf)); - } - fnvlist_add_nvlist(hdrnv, "fss", fss); - VERIFY0(nvlist_pack(hdrnv, &packbuf, &buflen, NV_ENCODE_XDR, - 0)); - if (fssp != NULL) { - *fssp = fss; - } else { - fnvlist_free(fss); - } - fnvlist_free(hdrnv); - } - - if (!dryrun) { - dmu_replay_record_t drr; - memset(&drr, 0, sizeof (dmu_replay_record_t)); - /* write first begin record */ - drr.drr_type = DRR_BEGIN; - drr.drr_u.drr_begin.drr_magic = DMU_BACKUP_MAGIC; - DMU_SET_STREAM_HDRTYPE(drr.drr_u.drr_begin. - drr_versioninfo, DMU_COMPOUNDSTREAM); - DMU_SET_FEATUREFLAGS(drr.drr_u.drr_begin. - drr_versioninfo, featureflags); - if (snprintf(drr.drr_u.drr_begin.drr_toname, - sizeof (drr.drr_u.drr_begin.drr_toname), "%s@%s", tofs, - tosnap) >= sizeof (drr.drr_u.drr_begin.drr_toname)) { - return (zfs_error(zhp->zfs_hdl, EZFS_BADBACKUP, - errbuf)); - } - drr.drr_payloadlen = buflen; - - err = dump_record(&drr, packbuf, buflen, &zc, fd); - free(packbuf); - if (err != 0) { - zfs_error_aux(zhp->zfs_hdl, "%s", zfs_strerror(err)); - return (zfs_error(zhp->zfs_hdl, EZFS_BADBACKUP, - errbuf)); - } - err = send_conclusion_record(fd, &zc); - if (err != 0) { - zfs_error_aux(zhp->zfs_hdl, "%s", zfs_strerror(err)); - return (zfs_error(zhp->zfs_hdl, EZFS_BADBACKUP, - errbuf)); - } - } - return (0); -} - -/* - * Generate a send stream. The "zhp" argument is the filesystem/volume - * that contains the snapshot to send. The "fromsnap" argument is the - * short name (the part after the '@') of the snapshot that is the - * incremental source to send from (if non-NULL). The "tosnap" argument - * is the short name of the snapshot to send. - * - * The content of the send stream is the snapshot identified by - * 'tosnap'. Incremental streams are requested in two ways: - * - from the snapshot identified by "fromsnap" (if non-null) or - * - from the origin of the dataset identified by zhp, which must - * be a clone. In this case, "fromsnap" is null and "fromorigin" - * is TRUE. - * - * The send stream is recursive (i.e. dumps a hierarchy of snapshots) and - * uses a special header (with a hdrtype field of DMU_COMPOUNDSTREAM) - * if "replicate" is set. If "doall" is set, dump all the intermediate - * snapshots. The DMU_COMPOUNDSTREAM header is used in the "doall" - * case too. If "props" is set, send properties. - * - * Pre-wrapped (cf. lzc_send_wrapper()). - */ -static int -zfs_send_cb_impl(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap, - sendflags_t *flags, int outfd, snapfilter_cb_t filter_func, - void *cb_arg, nvlist_t **debugnvp) -{ - char errbuf[ERRBUFLEN]; - send_dump_data_t sdd = { 0 }; - int err = 0; - nvlist_t *fss = NULL; - avl_tree_t *fsavl = NULL; - static uint64_t holdseq; - int spa_version; - FILE *fout; - - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot send '%s'"), zhp->zfs_name); - - if (fromsnap && fromsnap[0] == '\0') { - zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "zero-length incremental source")); - return (zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf)); - } - - if (fromsnap) { - char full_fromsnap_name[ZFS_MAX_DATASET_NAME_LEN]; - if (snprintf(full_fromsnap_name, sizeof (full_fromsnap_name), - "%s@%s", zhp->zfs_name, fromsnap) >= - sizeof (full_fromsnap_name)) { - err = EINVAL; - goto stderr_out; - } - zfs_handle_t *fromsnapn = zfs_open(zhp->zfs_hdl, - full_fromsnap_name, ZFS_TYPE_SNAPSHOT); - if (fromsnapn == NULL) { - err = -1; - goto err_out; - } - zfs_close(fromsnapn); - } - - if (flags->replicate || flags->doall || flags->props || - flags->holds || flags->backup) { - char full_tosnap_name[ZFS_MAX_DATASET_NAME_LEN]; - if (snprintf(full_tosnap_name, sizeof (full_tosnap_name), - "%s@%s", zhp->zfs_name, tosnap) >= - sizeof (full_tosnap_name)) { - err = EINVAL; - goto stderr_out; - } - zfs_handle_t *tosnap = zfs_open(zhp->zfs_hdl, - full_tosnap_name, ZFS_TYPE_SNAPSHOT); - if (tosnap == NULL) { - err = -1; - goto err_out; - } - err = send_prelim_records(tosnap, fromsnap, outfd, - flags->replicate || flags->props || flags->holds, - flags->replicate, flags->verbosity > 0, flags->dryrun, - flags->raw, flags->replicate, flags->skipmissing, - flags->backup, flags->holds, flags->props, flags->doall, - &fss, &fsavl); - zfs_close(tosnap); - if (err != 0) - goto err_out; - } - - /* dump each stream */ - sdd.fromsnap = fromsnap; - sdd.tosnap = tosnap; - sdd.outfd = outfd; - sdd.replicate = flags->replicate; - sdd.doall = flags->doall; - sdd.fromorigin = flags->fromorigin; - sdd.fss = fss; - sdd.fsavl = fsavl; - sdd.verbosity = flags->verbosity; - sdd.parsable = flags->parsable; - sdd.progress = flags->progress; - sdd.progressastitle = flags->progressastitle; - sdd.dryrun = flags->dryrun; - sdd.large_block = flags->largeblock; - sdd.embed_data = flags->embed_data; - sdd.compress = flags->compress; - sdd.raw = flags->raw; - sdd.holds = flags->holds; - sdd.filter_cb = filter_func; - sdd.filter_cb_arg = cb_arg; - if (debugnvp) - sdd.debugnv = *debugnvp; - if (sdd.verbosity != 0 && sdd.dryrun) - sdd.std_out = B_TRUE; - fout = sdd.std_out ? stdout : stderr; - - /* - * Some flags require that we place user holds on the datasets that are - * being sent so they don't get destroyed during the send. We can skip - * this step if the pool is imported read-only since the datasets cannot - * be destroyed. - */ - if (!flags->dryrun && !zpool_get_prop_int(zfs_get_pool_handle(zhp), - ZPOOL_PROP_READONLY, NULL) && - zfs_spa_version(zhp, &spa_version) == 0 && - spa_version >= SPA_VERSION_USERREFS && - (flags->doall || flags->replicate)) { - ++holdseq; - (void) snprintf(sdd.holdtag, sizeof (sdd.holdtag), - ".send-%d-%llu", getpid(), (u_longlong_t)holdseq); - sdd.cleanup_fd = open(ZFS_DEV, O_RDWR | O_CLOEXEC); - if (sdd.cleanup_fd < 0) { - err = errno; - goto stderr_out; - } - sdd.snapholds = fnvlist_alloc(); - } else { - sdd.cleanup_fd = -1; - sdd.snapholds = NULL; - } - - if (flags->verbosity != 0 || sdd.snapholds != NULL) { - /* - * Do a verbose no-op dry run to get all the verbose output - * or to gather snapshot hold's before generating any data, - * then do a non-verbose real run to generate the streams. - */ - sdd.dryrun = B_TRUE; - err = dump_filesystems(zhp, &sdd); - - if (err != 0) - goto stderr_out; - - if (flags->verbosity != 0) { - if (flags->parsable) { - (void) fprintf(fout, "size\t%llu\n", - (longlong_t)sdd.size); - } else { - char buf[16]; - zfs_nicebytes(sdd.size, buf, sizeof (buf)); - (void) fprintf(fout, dgettext(TEXT_DOMAIN, - "total estimated size is %s\n"), buf); - } - } - - /* Ensure no snaps found is treated as an error. */ - if (!sdd.seento) { - err = ENOENT; - goto err_out; - } - - /* Skip the second run if dryrun was requested. */ - if (flags->dryrun) - goto err_out; - - if (sdd.snapholds != NULL) { - err = zfs_hold_nvl(zhp, sdd.cleanup_fd, sdd.snapholds); - if (err != 0) - goto stderr_out; - - fnvlist_free(sdd.snapholds); - sdd.snapholds = NULL; - } - - sdd.dryrun = B_FALSE; - sdd.verbosity = 0; - } - - err = dump_filesystems(zhp, &sdd); - fsavl_destroy(fsavl); - fnvlist_free(fss); - - /* Ensure no snaps found is treated as an error. */ - if (err == 0 && !sdd.seento) - err = ENOENT; - - if (sdd.cleanup_fd != -1) { - VERIFY0(close(sdd.cleanup_fd)); - sdd.cleanup_fd = -1; - } - - if (!flags->dryrun && (flags->replicate || flags->doall || - flags->props || flags->backup || flags->holds)) { - /* - * write final end record. NB: want to do this even if - * there was some error, because it might not be totally - * failed. - */ - int err2 = send_conclusion_record(outfd, NULL); - if (err2 != 0) - return (zfs_standard_error(zhp->zfs_hdl, err2, errbuf)); - } - - return (err || sdd.err); - -stderr_out: - err = zfs_standard_error(zhp->zfs_hdl, err, errbuf); -err_out: - fsavl_destroy(fsavl); - fnvlist_free(fss); - fnvlist_free(sdd.snapholds); - - if (sdd.cleanup_fd != -1) - VERIFY0(close(sdd.cleanup_fd)); - return (err); -} - -struct zfs_send { - zfs_handle_t *zhp; - const char *fromsnap; - const char *tosnap; - sendflags_t *flags; - snapfilter_cb_t *filter_func; - void *cb_arg; - nvlist_t **debugnvp; -}; - -static int -zfs_send_cb(int outfd, void *arg) -{ - struct zfs_send *zs = arg; - return (zfs_send_cb_impl(zs->zhp, zs->fromsnap, zs->tosnap, zs->flags, - outfd, zs->filter_func, zs->cb_arg, zs->debugnvp)); -} - -int -zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap, - sendflags_t *flags, int outfd, snapfilter_cb_t filter_func, - void *cb_arg, nvlist_t **debugnvp) -{ - struct zfs_send arg = { - .zhp = zhp, - .fromsnap = fromsnap, - .tosnap = tosnap, - .flags = flags, - .filter_func = filter_func, - .cb_arg = cb_arg, - .debugnvp = debugnvp, - }; - return (lzc_send_wrapper(zfs_send_cb, outfd, &arg)); -} - - -static zfs_handle_t * -name_to_dir_handle(libzfs_handle_t *hdl, const char *snapname) -{ - char dirname[ZFS_MAX_DATASET_NAME_LEN]; - (void) strlcpy(dirname, snapname, ZFS_MAX_DATASET_NAME_LEN); - char *c = strchr(dirname, '@'); - if (c != NULL) - *c = '\0'; - return (zfs_open(hdl, dirname, ZFS_TYPE_DATASET)); -} - -/* - * Returns B_TRUE if earlier is an earlier snapshot in later's timeline; either - * an earlier snapshot in the same filesystem, or a snapshot before later's - * origin, or it's origin's origin, etc. - */ -static boolean_t -snapshot_is_before(zfs_handle_t *earlier, zfs_handle_t *later) -{ - boolean_t ret; - uint64_t later_txg = - (later->zfs_type == ZFS_TYPE_FILESYSTEM || - later->zfs_type == ZFS_TYPE_VOLUME ? - UINT64_MAX : zfs_prop_get_int(later, ZFS_PROP_CREATETXG)); - uint64_t earlier_txg = zfs_prop_get_int(earlier, ZFS_PROP_CREATETXG); - - if (earlier_txg >= later_txg) - return (B_FALSE); - - zfs_handle_t *earlier_dir = name_to_dir_handle(earlier->zfs_hdl, - earlier->zfs_name); - zfs_handle_t *later_dir = name_to_dir_handle(later->zfs_hdl, - later->zfs_name); - - if (strcmp(earlier_dir->zfs_name, later_dir->zfs_name) == 0) { - zfs_close(earlier_dir); - zfs_close(later_dir); - return (B_TRUE); - } - - char clonename[ZFS_MAX_DATASET_NAME_LEN]; - if (zfs_prop_get(later_dir, ZFS_PROP_ORIGIN, clonename, - ZFS_MAX_DATASET_NAME_LEN, NULL, NULL, 0, B_TRUE) != 0) { - zfs_close(earlier_dir); - zfs_close(later_dir); - return (B_FALSE); - } - - zfs_handle_t *origin = zfs_open(earlier->zfs_hdl, clonename, - ZFS_TYPE_DATASET); - uint64_t origin_txg = zfs_prop_get_int(origin, ZFS_PROP_CREATETXG); - - /* - * If "earlier" is exactly the origin, then - * snapshot_is_before(earlier, origin) will return false (because - * they're the same). - */ - if (origin_txg == earlier_txg && - strcmp(origin->zfs_name, earlier->zfs_name) == 0) { - zfs_close(earlier_dir); - zfs_close(later_dir); - zfs_close(origin); - return (B_TRUE); - } - zfs_close(earlier_dir); - zfs_close(later_dir); - - ret = snapshot_is_before(earlier, origin); - zfs_close(origin); - return (ret); -} - -/* - * The "zhp" argument is the handle of the dataset to send (typically a - * snapshot). The "from" argument is the full name of the snapshot or - * bookmark that is the incremental source. - * - * Pre-wrapped (cf. lzc_send_wrapper()). - */ -static int -zfs_send_one_cb_impl(zfs_handle_t *zhp, const char *from, int fd, - sendflags_t *flags, const char *redactbook) -{ - int err; - libzfs_handle_t *hdl = zhp->zfs_hdl; - char *name = zhp->zfs_name; - pthread_t ptid; - progress_arg_t pa = { 0 }; - uint64_t size = 0; - - char errbuf[ERRBUFLEN]; - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "warning: cannot send '%s'"), name); - - if (from != NULL && strchr(from, '@')) { - zfs_handle_t *from_zhp = zfs_open(hdl, from, - ZFS_TYPE_DATASET); - if (from_zhp == NULL) - return (-1); - if (!snapshot_is_before(from_zhp, zhp)) { - zfs_close(from_zhp); - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "not an earlier snapshot from the same fs")); - return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf)); - } - zfs_close(from_zhp); - } - - if (redactbook != NULL) { - char bookname[ZFS_MAX_DATASET_NAME_LEN]; - nvlist_t *redact_snaps; - zfs_handle_t *book_zhp; - char *at, *pound; - int dsnamelen; - - pound = strchr(redactbook, '#'); - if (pound != NULL) - redactbook = pound + 1; - at = strchr(name, '@'); - if (at == NULL) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "cannot do a redacted send to a filesystem")); - return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); - } - dsnamelen = at - name; - if (snprintf(bookname, sizeof (bookname), "%.*s#%s", - dsnamelen, name, redactbook) - >= sizeof (bookname)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "invalid bookmark name")); - return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); - } - book_zhp = zfs_open(hdl, bookname, ZFS_TYPE_BOOKMARK); - if (book_zhp == NULL) - return (-1); - if (nvlist_lookup_nvlist(book_zhp->zfs_props, - zfs_prop_to_name(ZFS_PROP_REDACT_SNAPS), - &redact_snaps) != 0 || redact_snaps == NULL) { - zfs_close(book_zhp); - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "not a redaction bookmark")); - return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); - } - zfs_close(book_zhp); - } - - /* - * Send fs properties - */ - if (flags->props || flags->holds || flags->backup) { - /* - * Note: the header generated by send_prelim_records() - * assumes that the incremental source is in the same - * filesystem/volume as the target (which is a requirement - * when doing "zfs send -R"). But that isn't always the - * case here (e.g. send from snap in origin, or send from - * bookmark). We pass from=NULL, which will omit this - * information from the prelim records; it isn't used - * when receiving this type of stream. - */ - err = send_prelim_records(zhp, NULL, fd, B_TRUE, B_FALSE, - flags->verbosity > 0, flags->dryrun, flags->raw, - flags->replicate, B_FALSE, flags->backup, flags->holds, - flags->props, flags->doall, NULL, NULL); - if (err != 0) - return (err); - } - - /* - * Perform size estimate if verbose was specified. - */ - if (flags->verbosity != 0 || flags->progressastitle) { - err = estimate_size(zhp, from, fd, flags, 0, 0, 0, redactbook, - errbuf, &size); - if (err != 0) - return (err); - } - - if (flags->dryrun) - return (0); - - /* - * If progress reporting is requested, spawn a new thread to poll - * ZFS_IOC_SEND_PROGRESS at a regular interval. - */ - sigset_t oldmask; - { - pa.pa_zhp = zhp; - pa.pa_fd = fd; - pa.pa_parsable = flags->parsable; - pa.pa_estimate = B_FALSE; - pa.pa_verbosity = flags->verbosity; - pa.pa_size = size; - pa.pa_astitle = flags->progressastitle; - pa.pa_progress = flags->progress; - - err = pthread_create(&ptid, NULL, - send_progress_thread, &pa); - if (err != 0) { - zfs_error_aux(zhp->zfs_hdl, "%s", zfs_strerror(errno)); - return (zfs_error(zhp->zfs_hdl, - EZFS_THREADCREATEFAILED, errbuf)); - } - SEND_PROGRESS_THREAD_PARENT_BLOCK(&oldmask); - } - - err = lzc_send_redacted(name, from, fd, - lzc_flags_from_sendflags(flags), redactbook); - - if (send_progress_thread_exit(hdl, ptid, &oldmask)) - return (-1); - - if (err == 0 && (flags->props || flags->holds || flags->backup)) { - /* Write the final end record. */ - err = send_conclusion_record(fd, NULL); - if (err != 0) - return (zfs_standard_error(hdl, err, errbuf)); - } - if (err != 0) { - switch (errno) { - case EXDEV: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "not an earlier snapshot from the same fs")); - return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf)); - - case ENOENT: - case ESRCH: - if (lzc_exists(name)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "incremental source (%s) does not exist"), - from); - } - return (zfs_error(hdl, EZFS_NOENT, errbuf)); - - case EACCES: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "dataset key must be loaded")); - return (zfs_error(hdl, EZFS_CRYPTOFAILED, errbuf)); - - case EBUSY: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "target is busy; if a filesystem, " - "it must not be mounted")); - return (zfs_error(hdl, EZFS_BUSY, errbuf)); - - case EDQUOT: - case EFAULT: - case EFBIG: - case EINVAL: - case EIO: - case ENOLINK: - case ENOSPC: - case ENOSTR: - case ENXIO: - case EPIPE: - case ERANGE: - case EROFS: - zfs_error_aux(hdl, "%s", zfs_strerror(errno)); - return (zfs_error(hdl, EZFS_BADBACKUP, errbuf)); - case ZFS_ERR_STREAM_LARGE_MICROZAP: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "source snapshot contains large microzaps, " - "need -L (--large-block) or -w (--raw) to " - "generate stream")); - return (zfs_error(hdl, EZFS_BADBACKUP, errbuf)); - default: - return (zfs_standard_error(hdl, errno, errbuf)); - } - } - return (err != 0); -} - -struct zfs_send_one { - zfs_handle_t *zhp; - const char *from; - sendflags_t *flags; - const char *redactbook; -}; - -static int -zfs_send_one_cb(int fd, void *arg) -{ - struct zfs_send_one *zso = arg; - return (zfs_send_one_cb_impl(zso->zhp, zso->from, fd, zso->flags, - zso->redactbook)); -} - -int -zfs_send_one(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags, - const char *redactbook) -{ - struct zfs_send_one zso = { - .zhp = zhp, - .from = from, - .flags = flags, - .redactbook = redactbook, - }; - return (lzc_send_wrapper(zfs_send_one_cb, fd, &zso)); -} - -/* - * Routines specific to "zfs recv" - */ - -static int -recv_read(libzfs_handle_t *hdl, int fd, void *buf, int ilen, - boolean_t byteswap, zio_cksum_t *zc) -{ - char *cp = buf; - int rv; - int len = ilen; - - do { - rv = read(fd, cp, len); - cp += rv; - len -= rv; - } while (rv > 0); - - if (rv < 0 || len != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "failed to read from stream")); - return (zfs_error(hdl, EZFS_BADSTREAM, dgettext(TEXT_DOMAIN, - "cannot receive"))); - } - - if (zc) { - if (byteswap) - fletcher_4_incremental_byteswap(buf, ilen, zc); - else - fletcher_4_incremental_native(buf, ilen, zc); - } - return (0); -} - -static int -recv_read_nvlist(libzfs_handle_t *hdl, int fd, int len, nvlist_t **nvp, - boolean_t byteswap, zio_cksum_t *zc) -{ - char *buf; - int err; - - buf = zfs_alloc(hdl, len); - - if (len > hdl->libzfs_max_nvlist) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "nvlist too large")); - free(buf); - return (ENOMEM); - } - - err = recv_read(hdl, fd, buf, len, byteswap, zc); - if (err != 0) { - free(buf); - return (err); - } - - err = nvlist_unpack(buf, len, nvp, 0); - free(buf); - if (err != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid " - "stream (malformed nvlist)")); - return (EINVAL); - } - return (0); -} - -/* - * Returns the grand origin (origin of origin of origin...) of a given handle. - * If this dataset is not a clone, it simply returns a copy of the original - * handle. - */ -static zfs_handle_t * -recv_open_grand_origin(zfs_handle_t *zhp) -{ - char origin[ZFS_MAX_DATASET_NAME_LEN]; - zprop_source_t src; - zfs_handle_t *ozhp = zfs_handle_dup(zhp); - - while (ozhp != NULL) { - if (zfs_prop_get(ozhp, ZFS_PROP_ORIGIN, origin, - sizeof (origin), &src, NULL, 0, B_FALSE) != 0) - break; - - (void) zfs_close(ozhp); - ozhp = zfs_open(zhp->zfs_hdl, origin, ZFS_TYPE_FILESYSTEM); - } - - return (ozhp); -} - -static int -recv_rename_impl(zfs_handle_t *zhp, const char *name, const char *newname) -{ - int err; - zfs_handle_t *ozhp = NULL; - - /* - * Attempt to rename the dataset. If it fails with EACCES we have - * attempted to rename the dataset outside of its encryption root. - * Force the dataset to become an encryption root and try again. - */ - err = lzc_rename(name, newname); - if (err == EACCES) { - ozhp = recv_open_grand_origin(zhp); - if (ozhp == NULL) { - err = ENOENT; - goto out; - } - - err = lzc_change_key(ozhp->zfs_name, DCP_CMD_FORCE_NEW_KEY, - NULL, NULL, 0); - if (err != 0) - goto out; - - err = lzc_rename(name, newname); - } - -out: - if (ozhp != NULL) - zfs_close(ozhp); - return (err); -} - -static int -recv_rename(libzfs_handle_t *hdl, const char *name, const char *tryname, - int baselen, char *newname, recvflags_t *flags) -{ - static int seq; - int err; - prop_changelist_t *clp = NULL; - zfs_handle_t *zhp = NULL; - - zhp = zfs_open(hdl, name, ZFS_TYPE_DATASET); - if (zhp == NULL) { - err = -1; - goto out; - } - clp = changelist_gather(zhp, ZFS_PROP_NAME, 0, - flags->force ? MS_FORCE : 0); - if (clp == NULL) { - err = -1; - goto out; - } - err = changelist_prefix(clp); - if (err) - goto out; - - if (tryname) { - (void) strlcpy(newname, tryname, ZFS_MAX_DATASET_NAME_LEN); - if (flags->verbose) { - (void) printf("attempting rename %s to %s\n", - name, newname); - } - err = recv_rename_impl(zhp, name, newname); - if (err == 0) - changelist_rename(clp, name, tryname); - } else { - err = ENOENT; - } - - if (err != 0 && strncmp(name + baselen, "recv-", 5) != 0) { - seq++; - - (void) snprintf(newname, ZFS_MAX_DATASET_NAME_LEN, - "%.*srecv-%u-%u", baselen, name, getpid(), seq); - - if (flags->verbose) { - (void) printf("failed - trying rename %s to %s\n", - name, newname); - } - err = recv_rename_impl(zhp, name, newname); - if (err == 0) - changelist_rename(clp, name, newname); - if (err && flags->verbose) { - (void) printf("failed (%u) - " - "will try again on next pass\n", errno); - } - err = EAGAIN; - } else if (flags->verbose) { - if (err == 0) - (void) printf("success\n"); - else - (void) printf("failed (%u)\n", errno); - } - - (void) changelist_postfix(clp); - -out: - if (clp != NULL) - changelist_free(clp); - if (zhp != NULL) - zfs_close(zhp); - - return (err); -} - -static int -recv_promote(libzfs_handle_t *hdl, const char *fsname, - const char *origin_fsname, recvflags_t *flags) -{ - int err; - zfs_cmd_t zc = {"\0"}; - zfs_handle_t *zhp = NULL, *ozhp = NULL; - - if (flags->verbose) - (void) printf("promoting %s\n", fsname); - - (void) strlcpy(zc.zc_value, origin_fsname, sizeof (zc.zc_value)); - (void) strlcpy(zc.zc_name, fsname, sizeof (zc.zc_name)); - - /* - * Attempt to promote the dataset. If it fails with EACCES the - * promotion would cause this dataset to leave its encryption root. - * Force the origin to become an encryption root and try again. - */ - err = zfs_ioctl(hdl, ZFS_IOC_PROMOTE, &zc); - if (err == EACCES) { - zhp = zfs_open(hdl, fsname, ZFS_TYPE_DATASET); - if (zhp == NULL) { - err = -1; - goto out; - } - - ozhp = recv_open_grand_origin(zhp); - if (ozhp == NULL) { - err = -1; - goto out; - } - - err = lzc_change_key(ozhp->zfs_name, DCP_CMD_FORCE_NEW_KEY, - NULL, NULL, 0); - if (err != 0) - goto out; - - err = zfs_ioctl(hdl, ZFS_IOC_PROMOTE, &zc); - } - -out: - if (zhp != NULL) - zfs_close(zhp); - if (ozhp != NULL) - zfs_close(ozhp); - - return (err); -} - -static int -recv_destroy(libzfs_handle_t *hdl, const char *name, int baselen, - char *newname, recvflags_t *flags) -{ - int err = 0; - prop_changelist_t *clp; - zfs_handle_t *zhp; - boolean_t defer = B_FALSE; - int spa_version; - - zhp = zfs_open(hdl, name, ZFS_TYPE_DATASET); - if (zhp == NULL) - return (-1); - zfs_type_t type = zfs_get_type(zhp); - if (type == ZFS_TYPE_SNAPSHOT && - zfs_spa_version(zhp, &spa_version) == 0 && - spa_version >= SPA_VERSION_USERREFS) - defer = B_TRUE; - clp = changelist_gather(zhp, ZFS_PROP_NAME, 0, - flags->force ? MS_FORCE : 0); - zfs_close(zhp); - if (clp == NULL) - return (-1); - - err = changelist_prefix(clp); - if (err) - return (err); - - if (flags->verbose) - (void) printf("attempting destroy %s\n", name); - if (type == ZFS_TYPE_SNAPSHOT) { - nvlist_t *nv = fnvlist_alloc(); - fnvlist_add_boolean(nv, name); - err = lzc_destroy_snaps(nv, defer, NULL); - fnvlist_free(nv); - } else { - err = lzc_destroy(name); - } - if (err == 0) { - if (flags->verbose) - (void) printf("success\n"); - changelist_remove(clp, name); - } - - (void) changelist_postfix(clp); - changelist_free(clp); - - /* - * Deferred destroy might destroy the snapshot or only mark it to be - * destroyed later, and it returns success in either case. - */ - if (err != 0 || (defer && zfs_dataset_exists(hdl, name, - ZFS_TYPE_SNAPSHOT))) { - err = recv_rename(hdl, name, NULL, baselen, newname, flags); - } - - return (err); -} - -typedef struct guid_to_name_data { - uint64_t guid; - boolean_t bookmark_ok; - char *name; - char *skip; - uint64_t *redact_snap_guids; - uint64_t num_redact_snaps; -} guid_to_name_data_t; - -static boolean_t -redact_snaps_match(zfs_handle_t *zhp, guid_to_name_data_t *gtnd) -{ - uint64_t *bmark_snaps; - uint_t bmark_num_snaps; - nvlist_t *nvl; - if (zhp->zfs_type != ZFS_TYPE_BOOKMARK) - return (B_FALSE); - - nvl = fnvlist_lookup_nvlist(zhp->zfs_props, - zfs_prop_to_name(ZFS_PROP_REDACT_SNAPS)); - bmark_snaps = fnvlist_lookup_uint64_array(nvl, ZPROP_VALUE, - &bmark_num_snaps); - if (bmark_num_snaps != gtnd->num_redact_snaps) - return (B_FALSE); - int i = 0; - for (; i < bmark_num_snaps; i++) { - int j = 0; - for (; j < bmark_num_snaps; j++) { - if (bmark_snaps[i] == gtnd->redact_snap_guids[j]) - break; - } - if (j == bmark_num_snaps) - break; - } - return (i == bmark_num_snaps); -} - -static int -guid_to_name_cb(zfs_handle_t *zhp, void *arg) -{ - guid_to_name_data_t *gtnd = arg; - const char *slash; - int err; - - if (gtnd->skip != NULL && - (slash = strrchr(zhp->zfs_name, '/')) != NULL && - strcmp(slash + 1, gtnd->skip) == 0) { - zfs_close(zhp); - return (0); - } - - if (zfs_prop_get_int(zhp, ZFS_PROP_GUID) == gtnd->guid && - (gtnd->num_redact_snaps == -1 || redact_snaps_match(zhp, gtnd))) { - (void) strcpy(gtnd->name, zhp->zfs_name); - zfs_close(zhp); - return (EEXIST); - } - - err = zfs_iter_children_v2(zhp, 0, guid_to_name_cb, gtnd); - if (err != EEXIST && gtnd->bookmark_ok) - err = zfs_iter_bookmarks_v2(zhp, 0, guid_to_name_cb, gtnd); - zfs_close(zhp); - return (err); -} - -/* - * Attempt to find the local dataset associated with this guid. In the case of - * multiple matches, we attempt to find the "best" match by searching - * progressively larger portions of the hierarchy. This allows one to send a - * tree of datasets individually and guarantee that we will find the source - * guid within that hierarchy, even if there are multiple matches elsewhere. - * - * If num_redact_snaps is not -1, we attempt to find a redaction bookmark with - * the specified number of redaction snapshots. If num_redact_snaps isn't 0 or - * -1, then redact_snap_guids will be an array of the guids of the snapshots the - * redaction bookmark was created with. If num_redact_snaps is -1, then we will - * attempt to find a snapshot or bookmark (if bookmark_ok is passed) with the - * given guid. Note that a redaction bookmark can be returned if - * num_redact_snaps == -1. - */ -static int -guid_to_name_redact_snaps(libzfs_handle_t *hdl, const char *parent, - uint64_t guid, boolean_t bookmark_ok, uint64_t *redact_snap_guids, - uint64_t num_redact_snaps, char *name) -{ - char pname[ZFS_MAX_DATASET_NAME_LEN]; - guid_to_name_data_t gtnd; - - gtnd.guid = guid; - gtnd.bookmark_ok = bookmark_ok; - gtnd.name = name; - gtnd.skip = NULL; - gtnd.redact_snap_guids = redact_snap_guids; - gtnd.num_redact_snaps = num_redact_snaps; - - /* - * Search progressively larger portions of the hierarchy, starting - * with the filesystem specified by 'parent'. This will - * select the "most local" version of the origin snapshot in the case - * that there are multiple matching snapshots in the system. - */ - (void) strlcpy(pname, parent, sizeof (pname)); - char *cp = strrchr(pname, '@'); - if (cp == NULL) - cp = strchr(pname, '\0'); - for (; cp != NULL; cp = strrchr(pname, '/')) { - /* Chop off the last component and open the parent */ - *cp = '\0'; - zfs_handle_t *zhp = make_dataset_handle(hdl, pname); - - if (zhp == NULL) - continue; - int err = guid_to_name_cb(zfs_handle_dup(zhp), >nd); - if (err != EEXIST) - err = zfs_iter_children_v2(zhp, 0, guid_to_name_cb, - >nd); - if (err != EEXIST && bookmark_ok) - err = zfs_iter_bookmarks_v2(zhp, 0, guid_to_name_cb, - >nd); - zfs_close(zhp); - if (err == EEXIST) - return (0); - - /* - * Remember the last portion of the dataset so we skip it next - * time through (as we've already searched that portion of the - * hierarchy). - */ - gtnd.skip = strrchr(pname, '/') + 1; - } - - return (ENOENT); -} - -static int -guid_to_name(libzfs_handle_t *hdl, const char *parent, uint64_t guid, - boolean_t bookmark_ok, char *name) -{ - return (guid_to_name_redact_snaps(hdl, parent, guid, bookmark_ok, NULL, - -1, name)); -} - -/* - * Return +1 if guid1 is before guid2, 0 if they are the same, and -1 if - * guid1 is after guid2. - */ -static int -created_before(libzfs_handle_t *hdl, avl_tree_t *avl, - uint64_t guid1, uint64_t guid2) -{ - nvlist_t *nvfs; - const char *fsname = NULL, *snapname = NULL; - char buf[ZFS_MAX_DATASET_NAME_LEN]; - int rv; - zfs_handle_t *guid1hdl, *guid2hdl; - uint64_t create1, create2; - - if (guid2 == 0) - return (0); - if (guid1 == 0) - return (1); - - nvfs = fsavl_find(avl, guid1, &snapname); - fsname = fnvlist_lookup_string(nvfs, "name"); - (void) snprintf(buf, sizeof (buf), "%s@%s", fsname, snapname); - guid1hdl = zfs_open(hdl, buf, ZFS_TYPE_SNAPSHOT); - if (guid1hdl == NULL) - return (-1); - - nvfs = fsavl_find(avl, guid2, &snapname); - fsname = fnvlist_lookup_string(nvfs, "name"); - (void) snprintf(buf, sizeof (buf), "%s@%s", fsname, snapname); - guid2hdl = zfs_open(hdl, buf, ZFS_TYPE_SNAPSHOT); - if (guid2hdl == NULL) { - zfs_close(guid1hdl); - return (-1); - } - - create1 = zfs_prop_get_int(guid1hdl, ZFS_PROP_CREATETXG); - create2 = zfs_prop_get_int(guid2hdl, ZFS_PROP_CREATETXG); - - if (create1 < create2) - rv = -1; - else if (create1 > create2) - rv = +1; - else - rv = 0; - - zfs_close(guid1hdl); - zfs_close(guid2hdl); - - return (rv); -} - -/* - * This function reestablishes the hierarchy of encryption roots after a - * recursive incremental receive has completed. This must be done after the - * second call to recv_incremental_replication() has renamed and promoted all - * sent datasets to their final locations in the dataset hierarchy. - */ -static int -recv_fix_encryption_hierarchy(libzfs_handle_t *hdl, const char *top_zfs, - nvlist_t *stream_nv, avl_tree_t *stream_avl) -{ - int err; - nvpair_t *fselem = NULL; - nvlist_t *local_nv; - avl_tree_t *local_avl; - boolean_t recursive; - - recursive = (nvlist_lookup_boolean(stream_nv, "not_recursive") == - ENOENT); - - /* Using top_zfs, gather the nvlists for all local filesystems. */ - if ((err = gather_nvlist(hdl, top_zfs, NULL, NULL, - recursive, B_TRUE, B_FALSE, recursive, B_FALSE, B_FALSE, B_FALSE, - B_FALSE, B_TRUE, &local_nv, &local_avl)) != 0) - return (err); - - /* - * Go through the nvlists of the local filesystems and check for - * encryption roots. - */ - while ((fselem = nvlist_next_nvpair(local_nv, fselem)) != NULL) { - zfs_handle_t *zhp = NULL; - uint64_t crypt; - nvlist_t *stream_props, *snaps, *stream_nvfs = NULL, - *nvfs = NULL; - boolean_t is_encroot, is_clone, stream_encroot; - const char *stream_keylocation = NULL, *fsname; - char keylocation[MAXNAMELEN]; - nvpair_t *snapelem; - - nvfs = fnvpair_value_nvlist(fselem); - snaps = fnvlist_lookup_nvlist(nvfs, "snaps"); - fsname = fnvlist_lookup_string(nvfs, "name"); - zhp = zfs_open(hdl, fsname, ZFS_TYPE_DATASET); - if (zhp == NULL) { - err = ENOENT; - goto error; - } - - /* we don't need to do anything for unencrypted datasets */ - crypt = zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION); - if (crypt == ZIO_CRYPT_OFF) { - zfs_close(zhp); - continue; - } - - is_clone = zhp->zfs_dmustats.dds_origin[0] != '\0'; - (void) zfs_crypto_get_encryption_root(zhp, &is_encroot, NULL); - keylocation[0] = '\0'; - - /* - * Go through the snapshots of the local filesystem and find - * the stream's filesystem. - */ - for (snapelem = nvlist_next_nvpair(snaps, NULL); - snapelem; snapelem = nvlist_next_nvpair(snaps, snapelem)) { - uint64_t thisguid; - - thisguid = fnvpair_value_uint64(snapelem); - stream_nvfs = fsavl_find(stream_avl, thisguid, NULL); - - if (stream_nvfs != NULL) - break; - } - - if (stream_nvfs == NULL) - continue; - - stream_props = fnvlist_lookup_nvlist(stream_nvfs, "props"); - stream_encroot = nvlist_exists(stream_nvfs, "is_encroot"); - - /* - * If the dataset is flagged as an encryption root, was not - * received as a clone and is not currently an encryption root, - * force it to become one. Fixup the keylocation if necessary. - */ - if (stream_encroot) { - if (!is_clone && !is_encroot) { - err = lzc_change_key(fsname, - DCP_CMD_FORCE_NEW_KEY, NULL, NULL, 0); - if (err != 0) { - zfs_close(zhp); - goto error; - } - } - - stream_keylocation = fnvlist_lookup_string(stream_props, - zfs_prop_to_name(ZFS_PROP_KEYLOCATION)); - - /* - * Refresh the properties in case the call to - * lzc_change_key() changed the value. - */ - zfs_refresh_properties(zhp); - err = zfs_prop_get(zhp, ZFS_PROP_KEYLOCATION, - keylocation, sizeof (keylocation), NULL, NULL, - 0, B_TRUE); - if (err != 0) { - zfs_close(zhp); - goto error; - } - - if (strcmp(keylocation, stream_keylocation) != 0) { - err = zfs_prop_set(zhp, - zfs_prop_to_name(ZFS_PROP_KEYLOCATION), - stream_keylocation); - if (err != 0) { - zfs_close(zhp); - goto error; - } - } - } - - /* - * If the dataset is not flagged as an encryption root and is - * currently an encryption root, force it to inherit from its - * parent. The root of a raw send should never be - * force-inherited. - */ - if (!stream_encroot && is_encroot && - strcmp(top_zfs, fsname) != 0) { - err = lzc_change_key(fsname, DCP_CMD_FORCE_INHERIT, - NULL, NULL, 0); - if (err != 0) { - zfs_close(zhp); - goto error; - } - } - - zfs_close(zhp); - } - - return (0); - -error: - return (err); -} - -static int -recv_incremental_replication(libzfs_handle_t *hdl, const char *tofs, - recvflags_t *flags, nvlist_t *stream_nv, avl_tree_t *stream_avl, - nvlist_t *renamed) -{ - nvlist_t *local_nv, *deleted = NULL; - avl_tree_t *local_avl; - nvpair_t *fselem, *nextfselem; - const char *fromsnap; - char newname[ZFS_MAX_DATASET_NAME_LEN]; - char guidname[32]; - int error; - boolean_t needagain, progress, recursive; - const char *s1, *s2; - - if (flags->dryrun) - return (0); - - fromsnap = fnvlist_lookup_string(stream_nv, "fromsnap"); - - recursive = (nvlist_lookup_boolean(stream_nv, "not_recursive") == - ENOENT); - -again: - needagain = progress = B_FALSE; - - deleted = fnvlist_alloc(); - - if ((error = gather_nvlist(hdl, tofs, fromsnap, NULL, - recursive, B_TRUE, B_FALSE, recursive, B_FALSE, B_FALSE, B_FALSE, - B_FALSE, B_TRUE, &local_nv, &local_avl)) != 0) - return (error); - - /* - * Process deletes and renames - */ - for (fselem = nvlist_next_nvpair(local_nv, NULL); - fselem; fselem = nextfselem) { - nvlist_t *nvfs, *snaps; - nvlist_t *stream_nvfs = NULL; - nvpair_t *snapelem, *nextsnapelem; - uint64_t fromguid = 0; - uint64_t originguid = 0; - uint64_t stream_originguid = 0; - uint64_t parent_fromsnap_guid, stream_parent_fromsnap_guid; - const char *fsname, *stream_fsname; - - nextfselem = nvlist_next_nvpair(local_nv, fselem); - - nvfs = fnvpair_value_nvlist(fselem); - snaps = fnvlist_lookup_nvlist(nvfs, "snaps"); - fsname = fnvlist_lookup_string(nvfs, "name"); - parent_fromsnap_guid = fnvlist_lookup_uint64(nvfs, - "parentfromsnap"); - (void) nvlist_lookup_uint64(nvfs, "origin", &originguid); - - /* - * First find the stream's fs, so we can check for - * a different origin (due to "zfs promote") - */ - for (snapelem = nvlist_next_nvpair(snaps, NULL); - snapelem; snapelem = nvlist_next_nvpair(snaps, snapelem)) { - uint64_t thisguid; - - thisguid = fnvpair_value_uint64(snapelem); - stream_nvfs = fsavl_find(stream_avl, thisguid, NULL); - - if (stream_nvfs != NULL) - break; - } - - /* check for promote */ - (void) nvlist_lookup_uint64(stream_nvfs, "origin", - &stream_originguid); - if (stream_nvfs && originguid != stream_originguid) { - switch (created_before(hdl, local_avl, - stream_originguid, originguid)) { - case 1: { - /* promote it! */ - nvlist_t *origin_nvfs; - const char *origin_fsname; - - origin_nvfs = fsavl_find(local_avl, originguid, - NULL); - origin_fsname = fnvlist_lookup_string( - origin_nvfs, "name"); - error = recv_promote(hdl, fsname, origin_fsname, - flags); - if (error == 0) - progress = B_TRUE; - break; - } - default: - break; - case -1: - fsavl_destroy(local_avl); - fnvlist_free(local_nv); - return (-1); - } - /* - * We had/have the wrong origin, therefore our - * list of snapshots is wrong. Need to handle - * them on the next pass. - */ - needagain = B_TRUE; - continue; - } - - for (snapelem = nvlist_next_nvpair(snaps, NULL); - snapelem; snapelem = nextsnapelem) { - uint64_t thisguid; - const char *stream_snapname; - nvlist_t *found, *props; - - nextsnapelem = nvlist_next_nvpair(snaps, snapelem); - - thisguid = fnvpair_value_uint64(snapelem); - found = fsavl_find(stream_avl, thisguid, - &stream_snapname); - - /* check for delete */ - if (found == NULL) { - char name[ZFS_MAX_DATASET_NAME_LEN]; - - if (!flags->force) - continue; - - (void) snprintf(name, sizeof (name), "%s@%s", - fsname, nvpair_name(snapelem)); - - error = recv_destroy(hdl, name, - strlen(fsname)+1, newname, flags); - if (error) - needagain = B_TRUE; - else - progress = B_TRUE; - sprintf(guidname, "%llu", - (u_longlong_t)thisguid); - nvlist_add_boolean(deleted, guidname); - continue; - } - - stream_nvfs = found; - - if (0 == nvlist_lookup_nvlist(stream_nvfs, "snapprops", - &props) && 0 == nvlist_lookup_nvlist(props, - stream_snapname, &props)) { - zfs_cmd_t zc = {"\0"}; - - zc.zc_cookie = B_TRUE; /* received */ - (void) snprintf(zc.zc_name, sizeof (zc.zc_name), - "%s@%s", fsname, nvpair_name(snapelem)); - zcmd_write_src_nvlist(hdl, &zc, props); - (void) zfs_ioctl(hdl, - ZFS_IOC_SET_PROP, &zc); - zcmd_free_nvlists(&zc); - } - - /* check for different snapname */ - if (strcmp(nvpair_name(snapelem), - stream_snapname) != 0) { - char name[ZFS_MAX_DATASET_NAME_LEN]; - char tryname[ZFS_MAX_DATASET_NAME_LEN]; - - (void) snprintf(name, sizeof (name), "%s@%s", - fsname, nvpair_name(snapelem)); - (void) snprintf(tryname, sizeof (name), "%s@%s", - fsname, stream_snapname); - - error = recv_rename(hdl, name, tryname, - strlen(fsname)+1, newname, flags); - if (error) - needagain = B_TRUE; - else - progress = B_TRUE; - } - - if (strcmp(stream_snapname, fromsnap) == 0) - fromguid = thisguid; - } - - /* check for delete */ - if (stream_nvfs == NULL) { - if (!flags->force) - continue; - - error = recv_destroy(hdl, fsname, strlen(tofs)+1, - newname, flags); - if (error) - needagain = B_TRUE; - else - progress = B_TRUE; - sprintf(guidname, "%llu", - (u_longlong_t)parent_fromsnap_guid); - nvlist_add_boolean(deleted, guidname); - continue; - } - - if (fromguid == 0) { - if (flags->verbose) { - (void) printf("local fs %s does not have " - "fromsnap (%s in stream); must have " - "been deleted locally; ignoring\n", - fsname, fromsnap); - } - continue; - } - - stream_fsname = fnvlist_lookup_string(stream_nvfs, "name"); - stream_parent_fromsnap_guid = fnvlist_lookup_uint64( - stream_nvfs, "parentfromsnap"); - - s1 = strrchr(fsname, '/'); - s2 = strrchr(stream_fsname, '/'); - - /* - * Check if we're going to rename based on parent guid change - * and the current parent guid was also deleted. If it was then - * rename will fail and is likely unneeded, so avoid this and - * force an early retry to determine the new - * parent_fromsnap_guid. - */ - if (stream_parent_fromsnap_guid != 0 && - parent_fromsnap_guid != 0 && - stream_parent_fromsnap_guid != parent_fromsnap_guid) { - sprintf(guidname, "%llu", - (u_longlong_t)parent_fromsnap_guid); - if (nvlist_exists(deleted, guidname)) { - progress = B_TRUE; - needagain = B_TRUE; - goto doagain; - } - } - - /* - * Check for rename. If the exact receive path is specified, it - * does not count as a rename, but we still need to check the - * datasets beneath it. - */ - if ((stream_parent_fromsnap_guid != 0 && - parent_fromsnap_guid != 0 && - stream_parent_fromsnap_guid != parent_fromsnap_guid) || - ((flags->isprefix || strcmp(tofs, fsname) != 0) && - (s1 != NULL) && (s2 != NULL) && strcmp(s1, s2) != 0)) { - nvlist_t *parent; - char tryname[ZFS_MAX_DATASET_NAME_LEN]; - - parent = fsavl_find(local_avl, - stream_parent_fromsnap_guid, NULL); - /* - * NB: parent might not be found if we used the - * tosnap for stream_parent_fromsnap_guid, - * because the parent is a newly-created fs; - * we'll be able to rename it after we recv the - * new fs. - */ - if (parent != NULL) { - const char *pname; - - pname = fnvlist_lookup_string(parent, "name"); - (void) snprintf(tryname, sizeof (tryname), - "%s%s", pname, strrchr(stream_fsname, '/')); - } else { - tryname[0] = '\0'; - if (flags->verbose) { - (void) printf("local fs %s new parent " - "not found\n", fsname); - } - } - - newname[0] = '\0'; - - error = recv_rename(hdl, fsname, tryname, - strlen(tofs)+1, newname, flags); - - if (renamed != NULL && newname[0] != '\0') { - fnvlist_add_boolean(renamed, newname); - } - - if (error) - needagain = B_TRUE; - else - progress = B_TRUE; - } - } - -doagain: - fsavl_destroy(local_avl); - fnvlist_free(local_nv); - fnvlist_free(deleted); - - if (needagain && progress) { - /* do another pass to fix up temporary names */ - if (flags->verbose) - (void) printf("another pass:\n"); - goto again; - } - - return (needagain || error != 0); -} - -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, nvlist_t *cmdprops) -{ - nvlist_t *stream_nv = NULL; - avl_tree_t *stream_avl = NULL; - const char *fromsnap = NULL; - const char *sendsnap = NULL; - char *cp; - char tofs[ZFS_MAX_DATASET_NAME_LEN]; - char sendfs[ZFS_MAX_DATASET_NAME_LEN]; - char errbuf[ERRBUFLEN]; - dmu_replay_record_t drre; - int error; - boolean_t anyerr = B_FALSE; - boolean_t softerr = B_FALSE; - boolean_t recursive, raw; - - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot receive")); - - assert(drr->drr_type == DRR_BEGIN); - assert(drr->drr_u.drr_begin.drr_magic == DMU_BACKUP_MAGIC); - assert(DMU_GET_STREAM_HDRTYPE(drr->drr_u.drr_begin.drr_versioninfo) == - DMU_COMPOUNDSTREAM); - - /* - * Read in the nvlist from the stream. - */ - if (drr->drr_payloadlen != 0) { - error = recv_read_nvlist(hdl, fd, drr->drr_payloadlen, - &stream_nv, flags->byteswap, zc); - if (error) { - error = zfs_error(hdl, EZFS_BADSTREAM, errbuf); - goto out; - } - } - - recursive = (nvlist_lookup_boolean(stream_nv, "not_recursive") == - ENOENT); - raw = (nvlist_lookup_boolean(stream_nv, "raw") == 0); - - if (recursive && strchr(destname, '@')) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "cannot specify snapshot name for multi-snapshot stream")); - error = zfs_error(hdl, EZFS_BADSTREAM, errbuf); - goto out; - } - - /* - * Read in the end record and verify checksum. - */ - if (0 != (error = recv_read(hdl, fd, &drre, sizeof (drre), - flags->byteswap, NULL))) - goto out; - if (flags->byteswap) { - drre.drr_type = BSWAP_32(drre.drr_type); - drre.drr_u.drr_end.drr_checksum.zc_word[0] = - BSWAP_64(drre.drr_u.drr_end.drr_checksum.zc_word[0]); - drre.drr_u.drr_end.drr_checksum.zc_word[1] = - BSWAP_64(drre.drr_u.drr_end.drr_checksum.zc_word[1]); - drre.drr_u.drr_end.drr_checksum.zc_word[2] = - BSWAP_64(drre.drr_u.drr_end.drr_checksum.zc_word[2]); - drre.drr_u.drr_end.drr_checksum.zc_word[3] = - BSWAP_64(drre.drr_u.drr_end.drr_checksum.zc_word[3]); - } - if (drre.drr_type != DRR_END) { - error = zfs_error(hdl, EZFS_BADSTREAM, errbuf); - goto out; - } - if (!ZIO_CHECKSUM_EQUAL(drre.drr_u.drr_end.drr_checksum, *zc)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "incorrect header checksum")); - error = zfs_error(hdl, EZFS_BADSTREAM, errbuf); - goto out; - } - - (void) nvlist_lookup_string(stream_nv, "fromsnap", &fromsnap); - - if (drr->drr_payloadlen != 0) { - nvlist_t *stream_fss; - - stream_fss = fnvlist_lookup_nvlist(stream_nv, "fss"); - if ((stream_avl = fsavl_create(stream_fss)) == NULL) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "couldn't allocate avl tree")); - error = zfs_error(hdl, EZFS_NOMEM, errbuf); - goto out; - } - - if (fromsnap != NULL && recursive) { - nvlist_t *renamed = NULL; - nvpair_t *pair = NULL; - - (void) strlcpy(tofs, destname, sizeof (tofs)); - if (flags->isprefix) { - struct drr_begin *drrb = &drr->drr_u.drr_begin; - int i; - - if (flags->istail) { - cp = strrchr(drrb->drr_toname, '/'); - if (cp == NULL) { - (void) strlcat(tofs, "/", - sizeof (tofs)); - i = 0; - } else { - i = (cp - drrb->drr_toname); - } - } else { - i = strcspn(drrb->drr_toname, "/@"); - } - /* zfs_receive_one() will create_parents() */ - (void) strlcat(tofs, &drrb->drr_toname[i], - sizeof (tofs)); - *strchr(tofs, '@') = '\0'; - } - - if (!flags->dryrun && !flags->nomount) { - renamed = fnvlist_alloc(); - } - - softerr = recv_incremental_replication(hdl, tofs, flags, - stream_nv, stream_avl, renamed); - - /* Unmount renamed filesystems before receiving. */ - while ((pair = nvlist_next_nvpair(renamed, - pair)) != NULL) { - zfs_handle_t *zhp; - prop_changelist_t *clp = NULL; - - zhp = zfs_open(hdl, nvpair_name(pair), - ZFS_TYPE_FILESYSTEM); - if (zhp != NULL) { - clp = changelist_gather(zhp, - ZFS_PROP_MOUNTPOINT, 0, - flags->forceunmount ? MS_FORCE : 0); - zfs_close(zhp); - if (clp != NULL) { - softerr |= - changelist_prefix(clp); - changelist_free(clp); - } - } - } - - fnvlist_free(renamed); - } - } - - /* - * Get the fs specified by the first path in the stream (the top level - * specified by 'zfs send') and pass it to each invocation of - * zfs_receive_one(). - */ - (void) strlcpy(sendfs, drr->drr_u.drr_begin.drr_toname, - sizeof (sendfs)); - if ((cp = strchr(sendfs, '@')) != NULL) { - *cp = '\0'; - /* - * Find the "sendsnap", the final snapshot in a replication - * stream. zfs_receive_one() handles certain errors - * differently, depending on if the contained stream is the - * last one or not. - */ - sendsnap = (cp + 1); - } - - /* Finally, receive each contained stream */ - do { - /* - * we should figure out if it has a recoverable - * error, in which case do a recv_skip() and drive on. - * Note, if we fail due to already having this guid, - * zfs_receive_one() will take care of it (ie, - * recv_skip() and return 0). - */ - error = zfs_receive_impl(hdl, destname, NULL, flags, fd, - sendfs, stream_nv, stream_avl, top_zfs, sendsnap, cmdprops); - if (error == ENODATA) { - error = 0; - break; - } - anyerr |= error; - } while (error == 0); - - if (drr->drr_payloadlen != 0 && recursive && fromsnap != NULL) { - /* - * Now that we have the fs's they sent us, try the - * renames again. - */ - softerr = recv_incremental_replication(hdl, tofs, flags, - stream_nv, stream_avl, NULL); - } - - if (raw && *top_zfs != NULL && !flags->dryrun) { - softerr = recv_fix_encryption_hierarchy(hdl, *top_zfs, - stream_nv, stream_avl); - } - -out: - fsavl_destroy(stream_avl); - fnvlist_free(stream_nv); - if (softerr) - error = -2; - if (anyerr) - error = -1; - return (error); -} - -static void -trunc_prop_errs(int truncated) -{ - ASSERT(truncated != 0); - - if (truncated == 1) - (void) fprintf(stderr, dgettext(TEXT_DOMAIN, - "1 more property could not be set\n")); - else - (void) fprintf(stderr, dgettext(TEXT_DOMAIN, - "%d more properties could not be set\n"), truncated); -} - -static int -recv_skip(libzfs_handle_t *hdl, int fd, boolean_t byteswap) -{ - dmu_replay_record_t *drr; - void *buf = zfs_alloc(hdl, SPA_MAXBLOCKSIZE); - uint64_t payload_size; - char errbuf[ERRBUFLEN]; - - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot receive")); - - /* XXX would be great to use lseek if possible... */ - drr = buf; - - while (recv_read(hdl, fd, drr, sizeof (dmu_replay_record_t), - byteswap, NULL) == 0) { - if (byteswap) - drr->drr_type = BSWAP_32(drr->drr_type); - - switch (drr->drr_type) { - case DRR_BEGIN: - if (drr->drr_payloadlen != 0) { - (void) recv_read(hdl, fd, buf, - drr->drr_payloadlen, B_FALSE, NULL); - } - break; - - case DRR_END: - free(buf); - return (0); - - case DRR_OBJECT: - if (byteswap) { - drr->drr_u.drr_object.drr_bonuslen = - BSWAP_32(drr->drr_u.drr_object. - drr_bonuslen); - drr->drr_u.drr_object.drr_raw_bonuslen = - BSWAP_32(drr->drr_u.drr_object. - drr_raw_bonuslen); - } - - payload_size = - DRR_OBJECT_PAYLOAD_SIZE(&drr->drr_u.drr_object); - (void) recv_read(hdl, fd, buf, payload_size, - B_FALSE, NULL); - break; - - case DRR_WRITE: - if (byteswap) { - drr->drr_u.drr_write.drr_logical_size = - BSWAP_64( - drr->drr_u.drr_write.drr_logical_size); - drr->drr_u.drr_write.drr_compressed_size = - BSWAP_64( - drr->drr_u.drr_write.drr_compressed_size); - } - payload_size = - DRR_WRITE_PAYLOAD_SIZE(&drr->drr_u.drr_write); - assert(payload_size <= SPA_MAXBLOCKSIZE); - (void) recv_read(hdl, fd, buf, - payload_size, B_FALSE, NULL); - break; - case DRR_SPILL: - if (byteswap) { - drr->drr_u.drr_spill.drr_length = - BSWAP_64(drr->drr_u.drr_spill.drr_length); - drr->drr_u.drr_spill.drr_compressed_size = - BSWAP_64(drr->drr_u.drr_spill. - drr_compressed_size); - } - - payload_size = - DRR_SPILL_PAYLOAD_SIZE(&drr->drr_u.drr_spill); - (void) recv_read(hdl, fd, buf, payload_size, - B_FALSE, NULL); - break; - case DRR_WRITE_EMBEDDED: - if (byteswap) { - drr->drr_u.drr_write_embedded.drr_psize = - BSWAP_32(drr->drr_u.drr_write_embedded. - drr_psize); - } - (void) recv_read(hdl, fd, buf, - P2ROUNDUP(drr->drr_u.drr_write_embedded.drr_psize, - 8), B_FALSE, NULL); - break; - case DRR_OBJECT_RANGE: - case DRR_WRITE_BYREF: - case DRR_FREEOBJECTS: - case DRR_FREE: - break; - - default: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "invalid record type")); - free(buf); - return (zfs_error(hdl, EZFS_BADSTREAM, errbuf)); - } - } - - free(buf); - return (-1); -} - -static void -recv_ecksum_set_aux(libzfs_handle_t *hdl, const char *target_snap, - boolean_t resumable, boolean_t checksum) -{ - char target_fs[ZFS_MAX_DATASET_NAME_LEN]; - - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, (checksum ? - "checksum mismatch" : "incomplete stream"))); - - if (!resumable) - return; - (void) strlcpy(target_fs, target_snap, sizeof (target_fs)); - *strchr(target_fs, '@') = '\0'; - zfs_handle_t *zhp = zfs_open(hdl, target_fs, - ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); - if (zhp == NULL) - return; - - char token_buf[ZFS_MAXPROPLEN]; - int error = zfs_prop_get(zhp, ZFS_PROP_RECEIVE_RESUME_TOKEN, - token_buf, sizeof (token_buf), - NULL, NULL, 0, B_TRUE); - if (error == 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "checksum mismatch or incomplete stream.\n" - "Partially received snapshot is saved.\n" - "A resuming stream can be generated on the sending " - "system by running:\n" - " zfs send -t %s"), - token_buf); - } - zfs_close(zhp); -} - -/* - * Prepare a new nvlist of properties that are to override (-o) or be excluded - * (-x) from the received dataset - * recvprops: received properties from the send stream - * cmdprops: raw input properties from command line - * origprops: properties, both locally-set and received, currently set on the - * target dataset if it exists, NULL otherwise. - * oxprops: valid output override (-o) and excluded (-x) properties - */ -static int -zfs_setup_cmdline_props(libzfs_handle_t *hdl, zfs_type_t type, - char *fsname, boolean_t zoned, boolean_t recursive, boolean_t newfs, - boolean_t raw, boolean_t toplevel, nvlist_t *recvprops, nvlist_t *cmdprops, - nvlist_t *origprops, nvlist_t **oxprops, uint8_t **wkeydata_out, - uint_t *wkeylen_out, const char *errbuf) -{ - nvpair_t *nvp; - nvlist_t *oprops, *voprops; - zfs_handle_t *zhp = NULL; - zpool_handle_t *zpool_hdl = NULL; - char *cp; - int ret = 0; - char namebuf[ZFS_MAX_DATASET_NAME_LEN]; - - if (nvlist_empty(cmdprops)) - return (0); /* No properties to override or exclude */ - - *oxprops = fnvlist_alloc(); - oprops = fnvlist_alloc(); - - strlcpy(namebuf, fsname, ZFS_MAX_DATASET_NAME_LEN); - - /* - * Get our dataset handle. The target dataset may not exist yet. - */ - if (zfs_dataset_exists(hdl, namebuf, ZFS_TYPE_DATASET)) { - zhp = zfs_open(hdl, namebuf, ZFS_TYPE_DATASET); - if (zhp == NULL) { - ret = -1; - goto error; - } - } - - /* open the zpool handle */ - cp = strchr(namebuf, '/'); - if (cp != NULL) - *cp = '\0'; - zpool_hdl = zpool_open(hdl, namebuf); - if (zpool_hdl == NULL) { - ret = -1; - goto error; - } - - /* restore namebuf to match fsname for later use */ - if (cp != NULL) - *cp = '/'; - - /* - * first iteration: process excluded (-x) properties now and gather - * added (-o) properties to be later processed by zfs_valid_proplist() - */ - nvp = NULL; - while ((nvp = nvlist_next_nvpair(cmdprops, nvp)) != NULL) { - const char *name = nvpair_name(nvp); - zfs_prop_t prop = zfs_name_to_prop(name); - - /* - * It turns out, if we don't normalize "aliased" names - * e.g. compress= against the "real" names (e.g. compression) - * here, then setting/excluding them does not work as - * intended. - * - * But since user-defined properties wouldn't have a valid - * mapping here, we do this conditional dance. - */ - const char *newname = name; - if (prop >= ZFS_PROP_TYPE) - newname = zfs_prop_to_name(prop); - - /* "origin" is processed separately, don't handle it here */ - if (prop == ZFS_PROP_ORIGIN) - continue; - - /* raw streams can't override encryption properties */ - if ((zfs_prop_encryption_key_param(prop) || - prop == ZFS_PROP_ENCRYPTION) && raw) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "encryption property '%s' cannot " - "be set or excluded for raw streams."), name); - ret = zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - - /* - * For plain replicated send, we can ignore encryption - * properties other than first stream - */ - if ((zfs_prop_encryption_key_param(prop) || prop == - ZFS_PROP_ENCRYPTION) && !newfs && recursive && !raw) { - continue; - } - - /* incremental streams can only exclude encryption properties */ - if ((zfs_prop_encryption_key_param(prop) || - prop == ZFS_PROP_ENCRYPTION) && !newfs && - nvpair_type(nvp) != DATA_TYPE_BOOLEAN) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "encryption property '%s' cannot " - "be set for incremental streams."), name); - ret = zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - - switch (nvpair_type(nvp)) { - case DATA_TYPE_BOOLEAN: /* -x property */ - /* - * DATA_TYPE_BOOLEAN is the way we're asked to "exclude" - * a property: this is done by forcing an explicit - * inherit on the destination so the effective value is - * not the one we received from the send stream. - */ - if (!zfs_prop_valid_for_type(prop, type, B_FALSE) && - !zfs_prop_user(name)) { - (void) fprintf(stderr, dgettext(TEXT_DOMAIN, - "Warning: %s: property '%s' does not " - "apply to datasets of this type\n"), - fsname, name); - continue; - } - /* - * We do this only if the property is not already - * locally-set, in which case its value will take - * priority over the received anyway. - */ - if (nvlist_exists(origprops, newname)) { - nvlist_t *attrs; - const char *source = NULL; - - attrs = fnvlist_lookup_nvlist(origprops, - newname); - if (nvlist_lookup_string(attrs, - ZPROP_SOURCE, &source) == 0 && - strcmp(source, ZPROP_SOURCE_VAL_RECVD) != 0) - continue; - } - /* - * We can't force an explicit inherit on non-inheritable - * properties: if we're asked to exclude this kind of - * values we remove them from "recvprops" input nvlist. - */ - if (!zfs_prop_user(name) && /* can be inherited too */ - !zfs_prop_inheritable(prop) && - nvlist_exists(recvprops, newname)) - fnvlist_remove(recvprops, newname); - else - fnvlist_add_boolean(*oxprops, newname); - break; - case DATA_TYPE_STRING: /* -o property=value */ - /* - * we're trying to override a property that does not - * make sense for this type of dataset, but we don't - * want to fail if the receive is recursive: this comes - * in handy when the send stream contains, for - * instance, a child ZVOL and we're trying to receive - * it with "-o atime=on" - */ - if (!zfs_prop_valid_for_type(prop, type, B_FALSE) && - !zfs_prop_user(name)) { - if (recursive) - continue; - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "property '%s' does not apply to datasets " - "of this type"), name); - ret = zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - fnvlist_add_string(oprops, newname, - fnvpair_value_string(nvp)); - break; - default: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "property '%s' must be a string or boolean"), name); - ret = zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - } - - if (toplevel) { - /* convert override strings properties to native */ - if ((voprops = zfs_valid_proplist(hdl, ZFS_TYPE_DATASET, - oprops, zoned, zhp, zpool_hdl, B_FALSE, errbuf)) == NULL) { - ret = zfs_error(hdl, EZFS_BADPROP, errbuf); - goto error; - } - - /* - * zfs_crypto_create() requires the parent name. Get it - * by truncating the fsname copy stored in namebuf. - */ - cp = strrchr(namebuf, '/'); - if (cp != NULL) - *cp = '\0'; - - if (!raw && !(!newfs && recursive) && - zfs_crypto_create(hdl, namebuf, voprops, NULL, - B_FALSE, wkeydata_out, wkeylen_out) != 0) { - fnvlist_free(voprops); - ret = zfs_error(hdl, EZFS_CRYPTOFAILED, errbuf); - goto error; - } - - /* second pass: process "-o" properties */ - fnvlist_merge(*oxprops, voprops); - fnvlist_free(voprops); - } else { - /* override props on child dataset are inherited */ - nvp = NULL; - while ((nvp = nvlist_next_nvpair(oprops, nvp)) != NULL) { - const char *name = nvpair_name(nvp); - fnvlist_add_boolean(*oxprops, name); - } - } - -error: - if (zhp != NULL) - zfs_close(zhp); - if (zpool_hdl != NULL) - zpool_close(zpool_hdl); - fnvlist_free(oprops); - return (ret); -} - -/* - * Restores a backup of tosnap from the file descriptor specified by infd. - */ -static int -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, - const char *finalsnap, nvlist_t *cmdprops) -{ - struct timespec begin_time; - int ioctl_err, ioctl_errno, err; - char *cp; - struct drr_begin *drrb = &drr->drr_u.drr_begin; - char errbuf[ERRBUFLEN]; - const char *chopprefix; - boolean_t newfs = B_FALSE; - boolean_t stream_wantsnewfs, stream_resumingnewfs; - boolean_t newprops = B_FALSE; - uint64_t read_bytes = 0; - uint64_t errflags = 0; - uint64_t parent_snapguid = 0; - prop_changelist_t *clp = NULL; - nvlist_t *snapprops_nvlist = NULL; - nvlist_t *snapholds_nvlist = NULL; - zprop_errflags_t prop_errflags; - nvlist_t *prop_errors = NULL; - boolean_t recursive; - const char *snapname = NULL; - char destsnap[MAXPATHLEN * 2]; - char origin[MAXNAMELEN] = {0}; - char name[MAXPATHLEN]; - char tmp_keylocation[MAXNAMELEN] = {0}; - nvlist_t *rcvprops = NULL; /* props received from the send stream */ - nvlist_t *oxprops = NULL; /* override (-o) and exclude (-x) props */ - nvlist_t *origprops = NULL; /* original props (if destination exists) */ - zfs_type_t type = ZFS_TYPE_INVALID; - boolean_t toplevel = B_FALSE; - boolean_t zoned = B_FALSE; - boolean_t hastoken = B_FALSE; - boolean_t redacted; - uint8_t *wkeydata = NULL; - uint_t wkeylen = 0; - -#ifndef CLOCK_MONOTONIC_RAW -#define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC -#endif - clock_gettime(CLOCK_MONOTONIC_RAW, &begin_time); - - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot receive")); - - recursive = (nvlist_lookup_boolean(stream_nv, "not_recursive") == - ENOENT); - - /* Did the user request holds be skipped via zfs recv -k? */ - boolean_t holds = flags->holds && !flags->skipholds; - - if (stream_avl != NULL) { - const char *keylocation = NULL; - nvlist_t *lookup = NULL; - nvlist_t *fs = fsavl_find(stream_avl, drrb->drr_toguid, - &snapname); - - (void) nvlist_lookup_uint64(fs, "parentfromsnap", - &parent_snapguid); - err = nvlist_lookup_nvlist(fs, "props", &rcvprops); - if (err) { - rcvprops = fnvlist_alloc(); - newprops = B_TRUE; - } - - /* - * The keylocation property may only be set on encryption roots, - * but this dataset might not become an encryption root until - * recv_fix_encryption_hierarchy() is called. That function - * will fixup the keylocation anyway, so we temporarily unset - * the keylocation for now to avoid any errors from the receive - * ioctl. - */ - err = nvlist_lookup_string(rcvprops, - zfs_prop_to_name(ZFS_PROP_KEYLOCATION), &keylocation); - if (err == 0) { - strlcpy(tmp_keylocation, keylocation, MAXNAMELEN); - (void) nvlist_remove_all(rcvprops, - zfs_prop_to_name(ZFS_PROP_KEYLOCATION)); - } - - if (flags->canmountoff) { - fnvlist_add_uint64(rcvprops, - zfs_prop_to_name(ZFS_PROP_CANMOUNT), 0); - } else if (newprops) { /* nothing in rcvprops, eliminate it */ - fnvlist_free(rcvprops); - rcvprops = NULL; - newprops = B_FALSE; - } - if (0 == nvlist_lookup_nvlist(fs, "snapprops", &lookup)) { - snapprops_nvlist = fnvlist_lookup_nvlist(lookup, - snapname); - } - if (holds) { - if (0 == nvlist_lookup_nvlist(fs, "snapholds", - &lookup)) { - snapholds_nvlist = fnvlist_lookup_nvlist( - lookup, snapname); - } - } - } - - cp = NULL; - - /* - * Determine how much of the snapshot name stored in the stream - * we are going to tack on to the name they specified on the - * command line, and how much we are going to chop off. - * - * If they specified a snapshot, chop the entire name stored in - * the stream. - */ - if (flags->istail) { - /* - * A filesystem was specified with -e. We want to tack on only - * the tail of the sent snapshot path. - */ - if (strchr(tosnap, '@')) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid " - "argument - snapshot not allowed with -e")); - err = zfs_error(hdl, EZFS_INVALIDNAME, errbuf); - goto out; - } - - chopprefix = strrchr(sendfs, '/'); - - if (chopprefix == NULL) { - /* - * The tail is the poolname, so we need to - * prepend a path separator. - */ - int len = strlen(drrb->drr_toname); - cp = umem_alloc(len + 2, UMEM_NOFAIL); - cp[0] = '/'; - (void) strcpy(&cp[1], drrb->drr_toname); - chopprefix = cp; - } else { - chopprefix = drrb->drr_toname + (chopprefix - sendfs); - } - } else if (flags->isprefix) { - /* - * A filesystem was specified with -d. We want to tack on - * everything but the first element of the sent snapshot path - * (all but the pool name). - */ - if (strchr(tosnap, '@')) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid " - "argument - snapshot not allowed with -d")); - err = zfs_error(hdl, EZFS_INVALIDNAME, errbuf); - goto out; - } - - chopprefix = strchr(drrb->drr_toname, '/'); - if (chopprefix == NULL) - chopprefix = strchr(drrb->drr_toname, '@'); - } else if (strchr(tosnap, '@') == NULL) { - /* - * If a filesystem was specified without -d or -e, we want to - * tack on everything after the fs specified by 'zfs send'. - */ - chopprefix = drrb->drr_toname + strlen(sendfs); - } else { - /* A snapshot was specified as an exact path (no -d or -e). */ - if (recursive) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "cannot specify snapshot name for multi-snapshot " - "stream")); - err = zfs_error(hdl, EZFS_BADSTREAM, errbuf); - goto out; - } - chopprefix = drrb->drr_toname + strlen(drrb->drr_toname); - } - - ASSERT(strstr(drrb->drr_toname, sendfs) == drrb->drr_toname); - ASSERT(chopprefix > drrb->drr_toname || strchr(sendfs, '/') == NULL); - ASSERT(chopprefix <= drrb->drr_toname + strlen(drrb->drr_toname) || - strchr(sendfs, '/') == NULL); - ASSERT(chopprefix[0] == '/' || chopprefix[0] == '@' || - chopprefix[0] == '\0'); - - /* - * Determine name of destination snapshot. - */ - (void) strlcpy(destsnap, tosnap, sizeof (destsnap)); - (void) strlcat(destsnap, chopprefix, sizeof (destsnap)); - if (cp != NULL) - umem_free(cp, strlen(cp) + 1); - if (!zfs_name_valid(destsnap, ZFS_TYPE_SNAPSHOT)) { - err = zfs_error(hdl, EZFS_INVALIDNAME, errbuf); - goto out; - } - - /* - * Determine the name of the origin snapshot. - */ - if (originsnap) { - (void) strlcpy(origin, originsnap, sizeof (origin)); - if (flags->verbose) - (void) printf("using provided clone origin %s\n", - origin); - } else if (drrb->drr_flags & DRR_FLAG_CLONE) { - if (guid_to_name(hdl, destsnap, - drrb->drr_fromguid, B_FALSE, origin) != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "local origin for clone %s does not exist"), - destsnap); - err = zfs_error(hdl, EZFS_NOENT, errbuf); - goto out; - } - if (flags->verbose) - (void) printf("found clone origin %s\n", origin); - } - - if ((DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo) & - DMU_BACKUP_FEATURE_DEDUP)) { - (void) fprintf(stderr, - gettext("ERROR: \"zfs receive\" no longer supports " - "deduplicated send streams. Use\n" - "the \"zstream redup\" command to convert this stream " - "to a regular,\n" - "non-deduplicated stream.\n")); - err = zfs_error(hdl, EZFS_NOTSUP, errbuf); - goto out; - } - - boolean_t resuming = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo) & - DMU_BACKUP_FEATURE_RESUMING; - boolean_t raw = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo) & - DMU_BACKUP_FEATURE_RAW; - boolean_t embedded = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo) & - DMU_BACKUP_FEATURE_EMBED_DATA; - stream_wantsnewfs = (drrb->drr_fromguid == 0 || - (drrb->drr_flags & DRR_FLAG_CLONE) || originsnap) && !resuming; - stream_resumingnewfs = (drrb->drr_fromguid == 0 || - (drrb->drr_flags & DRR_FLAG_CLONE) || originsnap) && resuming; - - if (stream_wantsnewfs) { - /* - * if the parent fs does not exist, look for it based on - * the parent snap GUID - */ - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot receive new filesystem stream")); - - (void) strlcpy(name, destsnap, sizeof (name)); - cp = strrchr(name, '/'); - if (cp) - *cp = '\0'; - if (cp && - !zfs_dataset_exists(hdl, name, ZFS_TYPE_DATASET)) { - char suffix[ZFS_MAX_DATASET_NAME_LEN]; - (void) strlcpy(suffix, strrchr(destsnap, '/'), - sizeof (suffix)); - if (guid_to_name(hdl, name, parent_snapguid, - B_FALSE, destsnap) == 0) { - *strchr(destsnap, '@') = '\0'; - (void) strlcat(destsnap, suffix, - sizeof (destsnap)); - } - } - } else { - /* - * If the fs does not exist, look for it based on the - * fromsnap GUID. - */ - if (resuming) { - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, - "cannot receive resume stream")); - } else { - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, - "cannot receive incremental stream")); - } - - (void) strlcpy(name, destsnap, sizeof (name)); - *strchr(name, '@') = '\0'; - - /* - * If the exact receive path was specified and this is the - * topmost path in the stream, then if the fs does not exist we - * should look no further. - */ - if ((flags->isprefix || (*(chopprefix = drrb->drr_toname + - strlen(sendfs)) != '\0' && *chopprefix != '@')) && - !zfs_dataset_exists(hdl, name, ZFS_TYPE_DATASET)) { - char snap[ZFS_MAX_DATASET_NAME_LEN]; - (void) strlcpy(snap, strchr(destsnap, '@'), - sizeof (snap)); - if (guid_to_name(hdl, name, drrb->drr_fromguid, - B_FALSE, destsnap) == 0) { - *strchr(destsnap, '@') = '\0'; - (void) strlcat(destsnap, snap, - sizeof (destsnap)); - } - } - } - - (void) strlcpy(name, destsnap, sizeof (name)); - *strchr(name, '@') = '\0'; - - redacted = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo) & - DMU_BACKUP_FEATURE_REDACTED; - - if (flags->heal) { - if (flags->isprefix || flags->istail || flags->force || - flags->canmountoff || flags->resumable || flags->nomount || - flags->skipholds) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "corrective recv can not be used when combined with" - " this flag")); - err = zfs_error(hdl, EZFS_INVALIDNAME, errbuf); - goto out; - } - uint64_t guid = - get_snap_guid(hdl, name, strchr(destsnap, '@') + 1); - if (guid == 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "corrective recv must specify an existing snapshot" - " to heal")); - err = zfs_error(hdl, EZFS_INVALIDNAME, errbuf); - goto out; - } else if (guid != drrb->drr_toguid) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "local snapshot doesn't match the snapshot" - " in the provided stream")); - err = zfs_error(hdl, EZFS_WRONG_PARENT, errbuf); - goto out; - } - } else if (zfs_dataset_exists(hdl, name, ZFS_TYPE_DATASET)) { - zfs_cmd_t zc = {"\0"}; - zfs_handle_t *zhp = NULL; - boolean_t encrypted; - - (void) strcpy(zc.zc_name, name); - - /* - * Destination fs exists. It must be one of these cases: - * - an incremental send stream - * - the stream specifies a new fs (full stream or clone) - * and they want us to blow away the existing fs (and - * have therefore specified -F and removed any snapshots) - * - we are resuming a failed receive. - */ - if (stream_wantsnewfs) { - boolean_t is_volume = drrb->drr_type == DMU_OST_ZVOL; - if (!flags->force) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "destination '%s' exists\n" - "must specify -F to overwrite it"), name); - err = zfs_error(hdl, EZFS_EXISTS, errbuf); - goto out; - } - if (zfs_ioctl(hdl, ZFS_IOC_SNAPSHOT_LIST_NEXT, - &zc) == 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "destination has snapshots (eg. %s)\n" - "must destroy them to overwrite it"), - zc.zc_name); - err = zfs_error(hdl, EZFS_EXISTS, errbuf); - goto out; - } - if (is_volume && strrchr(name, '/') == NULL) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "destination %s is the root dataset\n" - "cannot overwrite with a ZVOL"), - name); - err = zfs_error(hdl, EZFS_EXISTS, errbuf); - goto out; - } - if (is_volume && - zfs_ioctl(hdl, ZFS_IOC_DATASET_LIST_NEXT, - &zc) == 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "destination has children (eg. %s)\n" - "cannot overwrite with a ZVOL"), - zc.zc_name); - err = zfs_error(hdl, EZFS_WRONG_PARENT, errbuf); - goto out; - } - } - - if ((zhp = zfs_open(hdl, name, - ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)) == NULL) { - err = -1; - goto out; - } - - /* - * When receiving full/newfs on existing dataset, then it - * should be done with "-F" flag. Its enforced for initial - * receive in previous checks in this function. - * Similarly, on resuming full/newfs recv on existing dataset, - * it should be done with "-F" flag. - * - * When dataset doesn't exist, then full/newfs recv is done on - * newly created dataset and it's marked INCONSISTENT. But - * When receiving on existing dataset, recv is first done on - * %recv and its marked INCONSISTENT. Existing dataset is not - * marked INCONSISTENT. - * Resume of full/newfs receive with dataset not INCONSISTENT - * indicates that its resuming newfs on existing dataset. So, - * enforce "-F" flag in this case. - */ - if (stream_resumingnewfs && - !zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT) && - !flags->force) { - zfs_close(zhp); - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Resuming recv on existing destination '%s'\n" - "must specify -F to overwrite it"), name); - err = zfs_error(hdl, EZFS_RESUME_EXISTS, errbuf); - goto out; - } - - if (stream_wantsnewfs && - zhp->zfs_dmustats.dds_origin[0]) { - zfs_close(zhp); - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "destination '%s' is a clone\n" - "must destroy it to overwrite it"), name); - err = zfs_error(hdl, EZFS_EXISTS, errbuf); - goto out; - } - - /* - * Raw sends can not be performed as an incremental on top - * of existing unencrypted datasets. zfs recv -F can't be - * used to blow away an existing encrypted filesystem. This - * is because it would require the dsl dir to point to the - * new key (or lack of a key) and the old key at the same - * time. The -F flag may still be used for deleting - * intermediate snapshots that would otherwise prevent the - * receive from working. - */ - encrypted = zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION) != - ZIO_CRYPT_OFF; - if (!stream_wantsnewfs && !encrypted && raw) { - zfs_close(zhp); - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "cannot perform raw receive on top of " - "existing unencrypted dataset")); - err = zfs_error(hdl, EZFS_BADRESTORE, errbuf); - goto out; - } - - if (stream_wantsnewfs && flags->force && - ((raw && !encrypted) || encrypted)) { - zfs_close(zhp); - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "zfs receive -F cannot be used to destroy an " - "encrypted filesystem or overwrite an " - "unencrypted one with an encrypted one")); - err = zfs_error(hdl, EZFS_BADRESTORE, errbuf); - goto out; - } - - if (!flags->dryrun && zhp->zfs_type == ZFS_TYPE_FILESYSTEM && - (stream_wantsnewfs || stream_resumingnewfs)) { - /* We can't do online recv in this case */ - clp = changelist_gather(zhp, ZFS_PROP_NAME, 0, - flags->forceunmount ? MS_FORCE : 0); - if (clp == NULL) { - zfs_close(zhp); - err = -1; - goto out; - } - if (changelist_prefix(clp) != 0) { - changelist_free(clp); - zfs_close(zhp); - err = -1; - goto out; - } - } - - /* - * If we are resuming a newfs, set newfs here so that we will - * mount it if the recv succeeds this time. We can tell - * that it was a newfs on the first recv because the fs - * itself will be inconsistent (if the fs existed when we - * did the first recv, we would have received it into - * .../%recv). - */ - if (resuming && zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT)) - newfs = B_TRUE; - - /* we want to know if we're zoned when validating -o|-x props */ - zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED); - - /* may need this info later, get it now we have zhp around */ - if (zfs_prop_get(zhp, ZFS_PROP_RECEIVE_RESUME_TOKEN, NULL, 0, - NULL, NULL, 0, B_TRUE) == 0) - hastoken = B_TRUE; - - /* gather existing properties on destination */ - origprops = fnvlist_alloc(); - fnvlist_merge(origprops, zhp->zfs_props); - fnvlist_merge(origprops, zhp->zfs_user_props); - - 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 - * a clone). It would therefore be invalid if the user - * specified only the pool name (i.e. if the destination name - * contained no slash character). - */ - cp = strrchr(name, '/'); - - if (!stream_wantsnewfs || cp == NULL) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "destination '%s' does not exist"), name); - err = zfs_error(hdl, EZFS_NOENT, errbuf); - goto out; - } - - /* - * Trim off the final dataset component so we perform the - * recvbackup ioctl to the filesystems's parent. - */ - *cp = '\0'; - - if (flags->isprefix && !flags->istail && !flags->dryrun && - create_parents(hdl, destsnap, strlen(tosnap)) != 0) { - err = zfs_error(hdl, EZFS_BADRESTORE, errbuf); - goto out; - } - - /* validate parent */ - zhp = zfs_open(hdl, name, ZFS_TYPE_DATASET); - if (zhp == NULL) { - err = zfs_error(hdl, EZFS_BADRESTORE, errbuf); - goto out; - } - if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "parent '%s' is not a filesystem"), name); - err = zfs_error(hdl, EZFS_WRONG_PARENT, errbuf); - zfs_close(zhp); - goto out; - } - - zfs_close(zhp); - - newfs = B_TRUE; - *cp = '/'; - } - - if (flags->verbose) { - (void) printf("%s %s%s stream of %s into %s\n", - flags->dryrun ? "would receive" : "receiving", - flags->heal ? "corrective " : "", - drrb->drr_fromguid ? "incremental" : "full", - drrb->drr_toname, destsnap); - (void) fflush(stdout); - } - - /* - * If this is the top-level dataset, record it so we can use it - * for recursive operations later. - */ - if (top_zfs != NULL && - (*top_zfs == NULL || strcmp(*top_zfs, name) == 0)) { - toplevel = B_TRUE; - if (*top_zfs == NULL) - *top_zfs = zfs_strdup(hdl, name); - } - - if (drrb->drr_type == DMU_OST_ZVOL) { - type = ZFS_TYPE_VOLUME; - } else if (drrb->drr_type == DMU_OST_ZFS) { - type = ZFS_TYPE_FILESYSTEM; - } else { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "invalid record type: 0x%d"), drrb->drr_type); - err = zfs_error(hdl, EZFS_BADSTREAM, errbuf); - goto out; - } - if ((err = zfs_setup_cmdline_props(hdl, type, name, zoned, recursive, - stream_wantsnewfs, raw, toplevel, rcvprops, cmdprops, origprops, - &oxprops, &wkeydata, &wkeylen, errbuf)) != 0) - 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); - } - - if (flags->dryrun) { - void *buf = zfs_alloc(hdl, SPA_MAXBLOCKSIZE); - - /* - * We have read the DRR_BEGIN record, but we have - * not yet read the payload. For non-dryrun sends - * this will be done by the kernel, so we must - * emulate that here, before attempting to read - * more records. - */ - err = recv_read(hdl, infd, buf, drr->drr_payloadlen, - flags->byteswap, NULL); - free(buf); - if (err != 0) - goto out; - - err = recv_skip(hdl, infd, flags->byteswap); - goto out; - } - - if (flags->heal) { - err = ioctl_err = lzc_receive_with_heal(destsnap, rcvprops, - oxprops, wkeydata, wkeylen, origin, flags->force, - flags->heal, flags->resumable, raw, infd, drr_noswap, -1, - &read_bytes, &errflags, NULL, &prop_errors); - } else { - err = ioctl_err = lzc_receive_with_cmdprops(destsnap, rcvprops, - oxprops, wkeydata, wkeylen, origin, flags->force, - flags->resumable, raw, infd, drr_noswap, -1, &read_bytes, - &errflags, NULL, &prop_errors); - } - ioctl_errno = ioctl_err; - prop_errflags = errflags; - - if (err == 0) { - nvpair_t *prop_err = NULL; - - while ((prop_err = nvlist_next_nvpair(prop_errors, - prop_err)) != NULL) { - char tbuf[1024]; - zfs_prop_t prop; - int intval; - - prop = zfs_name_to_prop(nvpair_name(prop_err)); - (void) nvpair_value_int32(prop_err, &intval); - if (strcmp(nvpair_name(prop_err), - ZPROP_N_MORE_ERRORS) == 0) { - trunc_prop_errs(intval); - break; - } else if (snapname == NULL || finalsnap == NULL || - strcmp(finalsnap, snapname) == 0 || - strcmp(nvpair_name(prop_err), - zfs_prop_to_name(ZFS_PROP_REFQUOTA)) != 0) { - /* - * Skip the special case of, for example, - * "refquota", errors on intermediate - * snapshots leading up to a final one. - * That's why we have all of the checks above. - * - * See zfs_ioctl.c's extract_delay_props() for - * a list of props which can fail on - * intermediate snapshots, but shouldn't - * affect the overall receive. - */ - (void) snprintf(tbuf, sizeof (tbuf), - dgettext(TEXT_DOMAIN, - "cannot receive %s property on %s"), - nvpair_name(prop_err), name); - zfs_setprop_error(hdl, prop, intval, tbuf); - } - } - } - - if (err == 0 && snapprops_nvlist) { - zfs_cmd_t zc = {"\0"}; - - (void) strlcpy(zc.zc_name, destsnap, sizeof (zc.zc_name)); - zc.zc_cookie = B_TRUE; /* received */ - zcmd_write_src_nvlist(hdl, &zc, snapprops_nvlist); - (void) zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc); - zcmd_free_nvlists(&zc); - } - if (err == 0 && snapholds_nvlist) { - nvpair_t *pair; - nvlist_t *holds, *errors = NULL; - int cleanup_fd = -1; - - VERIFY0(nvlist_alloc(&holds, 0, KM_SLEEP)); - for (pair = nvlist_next_nvpair(snapholds_nvlist, NULL); - pair != NULL; - pair = nvlist_next_nvpair(snapholds_nvlist, pair)) { - fnvlist_add_string(holds, destsnap, nvpair_name(pair)); - } - (void) lzc_hold(holds, cleanup_fd, &errors); - fnvlist_free(snapholds_nvlist); - fnvlist_free(holds); - } - - if (err && (ioctl_errno == ENOENT || ioctl_errno == EEXIST)) { - /* - * It may be that this snapshot already exists, - * in which case we want to consume & ignore it - * rather than failing. - */ - avl_tree_t *local_avl; - nvlist_t *local_nv, *fs; - cp = strchr(destsnap, '@'); - - /* - * XXX Do this faster by just iterating over snaps in - * this fs. Also if zc_value does not exist, we will - * get a strange "does not exist" error message. - */ - *cp = '\0'; - if (gather_nvlist(hdl, destsnap, NULL, NULL, B_FALSE, B_TRUE, - B_FALSE, B_FALSE, B_FALSE, B_FALSE, B_FALSE, B_FALSE, - B_TRUE, &local_nv, &local_avl) == 0) { - *cp = '@'; - fs = fsavl_find(local_avl, drrb->drr_toguid, NULL); - fsavl_destroy(local_avl); - fnvlist_free(local_nv); - - if (fs != NULL) { - if (flags->verbose) { - (void) printf("snap %s already exists; " - "ignoring\n", destsnap); - } - err = ioctl_err = recv_skip(hdl, infd, - flags->byteswap); - } - } - *cp = '@'; - } - - if (ioctl_err != 0) { - switch (ioctl_errno) { - case ENODEV: - cp = strchr(destsnap, '@'); - *cp = '\0'; - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "most recent snapshot of %s does not\n" - "match incremental source"), destsnap); - (void) zfs_error(hdl, EZFS_BADRESTORE, errbuf); - *cp = '@'; - break; - case ETXTBSY: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "destination %s has been modified\n" - "since most recent snapshot"), name); - (void) zfs_error(hdl, EZFS_BADRESTORE, errbuf); - break; - case EACCES: - if (flags->heal) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "key must be loaded to do a non-raw " - "corrective recv on an encrypted " - "dataset.")); - } else if (raw && stream_wantsnewfs) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "failed to create encryption key")); - } else if (raw && !stream_wantsnewfs) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "encryption key does not match " - "existing key")); - } else { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "inherited key must be loaded")); - } - (void) zfs_error(hdl, EZFS_CRYPTOFAILED, errbuf); - break; - case EEXIST: - cp = strchr(destsnap, '@'); - if (newfs) { - /* it's the containing fs that exists */ - *cp = '\0'; - } - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "destination already exists")); - (void) zfs_error_fmt(hdl, EZFS_EXISTS, - dgettext(TEXT_DOMAIN, "cannot restore to %s"), - destsnap); - *cp = '@'; - break; - case EINVAL: - if (embedded && !raw) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "incompatible embedded data stream " - "feature with encrypted receive.")); - } else if (flags->resumable) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "kernel modules must be upgraded to " - "receive this stream.")); - } - (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf); - break; - case ECKSUM: - case ZFS_ERR_STREAM_TRUNCATED: - if (flags->heal) - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "corrective receive was not able to " - "reconstruct the data needed for " - "healing.")); - else - recv_ecksum_set_aux(hdl, destsnap, - flags->resumable, ioctl_err == ECKSUM); - (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf); - break; - case ZFS_ERR_STREAM_LARGE_BLOCK_MISMATCH: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "incremental send stream requires -L " - "(--large-block), to match previous receive.")); - (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf); - break; - case ENOTSUP: - if (flags->heal) - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "stream is not compatible with the " - "data in the pool.")); - else - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "pool must be upgraded to receive this " - "stream.")); - (void) zfs_error(hdl, EZFS_BADVERSION, errbuf); - break; - case ZFS_ERR_CRYPTO_NOTSUP: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "stream uses crypto parameters not compatible with " - "this pool")); - (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf); - break; - case EDQUOT: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "destination %s space quota exceeded."), name); - (void) zfs_error(hdl, EZFS_NOSPC, errbuf); - break; - case ZFS_ERR_FROM_IVSET_GUID_MISSING: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "IV set guid missing. See errata %u at " - "https://openzfs.github.io/openzfs-docs/msg/" - "ZFS-8000-ER."), - ZPOOL_ERRATA_ZOL_8308_ENCRYPTION); - (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf); - break; - case ZFS_ERR_FROM_IVSET_GUID_MISMATCH: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "IV set guid mismatch. See the 'zfs receive' " - "man page section\n discussing the limitations " - "of raw encrypted send streams.")); - (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf); - break; - case ZFS_ERR_SPILL_BLOCK_FLAG_MISSING: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Spill block flag missing for raw send.\n" - "The zfs software on the sending system must " - "be updated.")); - (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf); - break; - case ZFS_ERR_RESUME_EXISTS: - cp = strchr(destsnap, '@'); - if (newfs) { - /* it's the containing fs that exists */ - *cp = '\0'; - } - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Resuming recv on existing dataset without force")); - (void) zfs_error_fmt(hdl, EZFS_RESUME_EXISTS, - dgettext(TEXT_DOMAIN, "cannot resume recv %s"), - destsnap); - *cp = '@'; - break; - case E2BIG: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "zfs receive required kernel memory allocation " - "larger than the system can support. Please file " - "an issue at the OpenZFS issue tracker:\n" - "https://github.com/openzfs/zfs/issues/new")); - (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf); - break; - case EBUSY: - if (hastoken) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "destination %s contains " - "partially-complete state from " - "\"zfs receive -s\"."), name); - (void) zfs_error(hdl, EZFS_BUSY, errbuf); - break; - } - zfs_fallthrough; - default: - (void) zfs_standard_error(hdl, ioctl_errno, errbuf); - } - } - - /* - * Mount the target filesystem (if created). Also mount any - * children of the target filesystem if we did a replication - * receive (indicated by stream_avl being non-NULL). - */ - if (clp) { - if (!flags->nomount) - err |= changelist_postfix(clp); - changelist_free(clp); - } - - if ((newfs || stream_avl) && type == ZFS_TYPE_FILESYSTEM && !redacted) - flags->domount = B_TRUE; - - if (prop_errflags & ZPROP_ERR_NOCLEAR) { - (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "Warning: " - "failed to clear unreceived properties on %s"), name); - (void) fprintf(stderr, "\n"); - } - if (prop_errflags & ZPROP_ERR_NORESTORE) { - (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "Warning: " - "failed to restore original properties on %s"), name); - (void) fprintf(stderr, "\n"); - } - - if (err || ioctl_err) { - err = -1; - goto out; - } - - if (flags->verbose) { - char buf1[64]; - char buf2[64]; - uint64_t bytes = read_bytes; - struct timespec delta; - clock_gettime(CLOCK_MONOTONIC_RAW, &delta); - if (begin_time.tv_nsec > delta.tv_nsec) { - delta.tv_nsec = - 1000000000 + delta.tv_nsec - begin_time.tv_nsec; - delta.tv_sec -= 1; - } else - delta.tv_nsec -= begin_time.tv_nsec; - delta.tv_sec -= begin_time.tv_sec; - if (delta.tv_sec == 0 && delta.tv_nsec == 0) - delta.tv_nsec = 1; - double delta_f = delta.tv_sec + (delta.tv_nsec / 1e9); - zfs_nicebytes(bytes, buf1, sizeof (buf1)); - zfs_nicebytes(bytes / delta_f, buf2, sizeof (buf2)); - - (void) printf("received %s stream in %.2f seconds (%s/sec)\n", - buf1, delta_f, buf2); - } - - err = 0; -out: - if (prop_errors != NULL) - fnvlist_free(prop_errors); - - if (tmp_keylocation[0] != '\0') { - fnvlist_add_string(rcvprops, - zfs_prop_to_name(ZFS_PROP_KEYLOCATION), tmp_keylocation); - } - - if (newprops) - fnvlist_free(rcvprops); - - fnvlist_free(oxprops); - fnvlist_free(origprops); - - return (err); -} - -/* - * Check properties we were asked to override (both -o|-x) - */ -static boolean_t -zfs_receive_checkprops(libzfs_handle_t *hdl, nvlist_t *props, - const char *errbuf) -{ - nvpair_t *nvp = NULL; - zfs_prop_t prop; - const char *name; - - while ((nvp = nvlist_next_nvpair(props, nvp)) != NULL) { - name = nvpair_name(nvp); - prop = zfs_name_to_prop(name); - - if (prop == ZPROP_USERPROP) { - if (!zfs_prop_user(name)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "%s: invalid property '%s'"), errbuf, name); - return (B_FALSE); - } - continue; - } - /* - * "origin" is readonly but is used to receive datasets as - * clones so we don't raise an error here - */ - if (prop == ZFS_PROP_ORIGIN) - continue; - - /* encryption params have their own verification later */ - if (prop == ZFS_PROP_ENCRYPTION || - zfs_prop_encryption_key_param(prop)) - continue; - - /* - * cannot override readonly, set-once and other specific - * settable properties - */ - if (zfs_prop_readonly(prop) || prop == ZFS_PROP_VERSION || - prop == ZFS_PROP_VOLSIZE) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "%s: invalid property '%s'"), errbuf, name); - return (B_FALSE); - } - } - - return (B_TRUE); -} - -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, - const char *finalsnap, nvlist_t *cmdprops) -{ - int err; - dmu_replay_record_t drr, drr_noswap; - struct drr_begin *drrb = &drr.drr_u.drr_begin; - char errbuf[ERRBUFLEN]; - zio_cksum_t zcksum = { { 0 } }; - uint64_t featureflags; - int hdrtype; - - (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "cannot receive")); - - /* check cmdline props, raise an error if they cannot be received */ - if (!zfs_receive_checkprops(hdl, cmdprops, errbuf)) - return (zfs_error(hdl, EZFS_BADPROP, errbuf)); - - if (flags->isprefix && - !zfs_dataset_exists(hdl, tosnap, ZFS_TYPE_DATASET)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "specified fs " - "(%s) does not exist"), tosnap); - return (zfs_error(hdl, EZFS_NOENT, errbuf)); - } - if (originsnap && - !zfs_dataset_exists(hdl, originsnap, ZFS_TYPE_DATASET)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "specified origin fs " - "(%s) does not exist"), originsnap); - return (zfs_error(hdl, EZFS_NOENT, errbuf)); - } - - /* read in the BEGIN record */ - if (0 != (err = recv_read(hdl, infd, &drr, sizeof (drr), B_FALSE, - &zcksum))) - return (err); - - if (drr.drr_type == DRR_END || drr.drr_type == BSWAP_32(DRR_END)) { - /* It's the double end record at the end of a package */ - return (ENODATA); - } - - /* the kernel needs the non-byteswapped begin record */ - drr_noswap = drr; - - flags->byteswap = B_FALSE; - if (drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC)) { - /* - * We computed the checksum in the wrong byteorder in - * recv_read() above; do it again correctly. - */ - memset(&zcksum, 0, sizeof (zio_cksum_t)); - fletcher_4_incremental_byteswap(&drr, sizeof (drr), &zcksum); - flags->byteswap = B_TRUE; - - drr.drr_type = BSWAP_32(drr.drr_type); - drr.drr_payloadlen = BSWAP_32(drr.drr_payloadlen); - drrb->drr_magic = BSWAP_64(drrb->drr_magic); - drrb->drr_versioninfo = BSWAP_64(drrb->drr_versioninfo); - drrb->drr_creation_time = BSWAP_64(drrb->drr_creation_time); - drrb->drr_type = BSWAP_32(drrb->drr_type); - drrb->drr_flags = BSWAP_32(drrb->drr_flags); - drrb->drr_toguid = BSWAP_64(drrb->drr_toguid); - drrb->drr_fromguid = BSWAP_64(drrb->drr_fromguid); - } - - if (drrb->drr_magic != DMU_BACKUP_MAGIC || drr.drr_type != DRR_BEGIN) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid " - "stream (bad magic number)")); - return (zfs_error(hdl, EZFS_BADSTREAM, errbuf)); - } - - featureflags = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo); - hdrtype = DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo); - - if (!DMU_STREAM_SUPPORTED(featureflags) || - (hdrtype != DMU_SUBSTREAM && hdrtype != DMU_COMPOUNDSTREAM)) { - /* - * Let's be explicit about this one, since rather than - * being a new feature we can't know, it's an old - * feature we dropped. - */ - if (featureflags & DMU_BACKUP_FEATURE_DEDUP) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "stream has deprecated feature: dedup, try " - "'zstream redup [send in a file] | zfs recv " - "[...]'")); - } else { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "stream has unsupported feature, feature flags = " - "%llx (unknown flags = %llx)"), - (u_longlong_t)featureflags, - (u_longlong_t)((featureflags) & - ~DMU_BACKUP_FEATURE_MASK)); - } - return (zfs_error(hdl, EZFS_BADSTREAM, errbuf)); - } - - /* Holds feature is set once in the compound stream header. */ - if (featureflags & DMU_BACKUP_FEATURE_HOLDS) - flags->holds = B_TRUE; - - if (strchr(drrb->drr_toname, '@') == NULL) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid " - "stream (bad snapshot name)")); - return (zfs_error(hdl, EZFS_BADSTREAM, errbuf)); - } - - if (DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) == DMU_SUBSTREAM) { - char nonpackage_sendfs[ZFS_MAX_DATASET_NAME_LEN]; - if (sendfs == NULL) { - /* - * We were not called from zfs_receive_package(). Get - * the fs specified by 'zfs send'. - */ - char *cp; - (void) strlcpy(nonpackage_sendfs, - drr.drr_u.drr_begin.drr_toname, - sizeof (nonpackage_sendfs)); - if ((cp = strchr(nonpackage_sendfs, '@')) != NULL) - *cp = '\0'; - sendfs = nonpackage_sendfs; - VERIFY0P(finalsnap); - } - return (zfs_receive_one(hdl, infd, tosnap, originsnap, flags, - &drr, &drr_noswap, sendfs, stream_nv, stream_avl, top_zfs, - 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, cmdprops)); - } -} - -/* - * Restores a backup of tosnap from the file descriptor specified by infd. - * Return 0 on total success, -2 if some things couldn't be - * destroyed/renamed/promoted, -1 if some things couldn't be received. - * (-1 will override -2, if -1 and the resumable flag was specified the - * transfer can be resumed if the sending side supports it). - */ -int -zfs_receive(libzfs_handle_t *hdl, const char *tosnap, nvlist_t *props, - recvflags_t *flags, int infd, avl_tree_t *stream_avl) -{ - char *top_zfs = NULL; - int err; - struct stat sb; - const char *originsnap = NULL; - - /* - * The only way fstat can fail is if we do not have a valid file - * descriptor. - */ - if (fstat(infd, &sb) == -1) { - perror("fstat"); - return (-2); - } - - if (props) { - err = nvlist_lookup_string(props, "origin", &originsnap); - if (err && err != ENOENT) - return (err); - } - - err = zfs_receive_impl(hdl, tosnap, originsnap, flags, infd, NULL, NULL, - stream_avl, &top_zfs, NULL, props); - - if (err == 0 && !flags->nomount && flags->domount && top_zfs) { - zfs_handle_t *zhp = NULL; - prop_changelist_t *clp = NULL; - - zhp = zfs_open(hdl, top_zfs, - ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); - if (zhp == NULL) { - err = -1; - goto out; - } else { - if (zhp->zfs_type == ZFS_TYPE_VOLUME) { - zfs_close(zhp); - goto out; - } - - clp = changelist_gather(zhp, ZFS_PROP_MOUNTPOINT, - CL_GATHER_MOUNT_ALWAYS, - flags->forceunmount ? MS_FORCE : 0); - zfs_close(zhp); - if (clp == NULL) { - err = -1; - goto out; - } - - /* mount and share received datasets */ - err = changelist_postfix(clp); - changelist_free(clp); - if (err != 0) - err = -1; - } - } - -out: - if (top_zfs) - free(top_zfs); - - return (err); -} diff --git a/lib/libzfs/libzfs_status.c b/lib/libzfs/libzfs_status.c deleted file mode 100644 index bdddefb92165..000000000000 --- a/lib/libzfs/libzfs_status.c +++ /dev/null @@ -1,537 +0,0 @@ -// SPDX-License-Identifier: CDDL-1.0 -/* - * 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 - */ - -/* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012 by Delphix. All rights reserved. - * Copyright (c) 2013 Steven Hartland. All rights reserved. - * Copyright (c) 2021, Colm Buckley <colm@tuatha.org> - */ - -/* - * This file contains the functions which analyze the status of a pool. This - * include both the status of an active pool, as well as the status exported - * pools. Returns one of the ZPOOL_STATUS_* defines describing the status of - * the pool. This status is independent (to a certain degree) from the state of - * the pool. A pool's state describes only whether or not it is capable of - * providing the necessary fault tolerance for data. The status describes the - * overall status of devices. A pool that is online can still have a device - * that is experiencing errors. - * - * Only a subset of the possible faults can be detected using 'zpool status', - * and not all possible errors correspond to a FMA message ID. The explanation - * is left up to the caller, depending on whether it is a live pool or an - * import. - */ - -#include <libzfs.h> -#include <libzutil.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/systeminfo.h> -#include "libzfs_impl.h" -#include "zfeature_common.h" - -/* - * Message ID table. This must be kept in sync with the ZPOOL_STATUS_* defines - * in include/libzfs.h. Note that there are some status results which go past - * the end of this table, and hence have no associated message ID. - */ -static const char *const zfs_msgid_table[] = { - "ZFS-8000-14", /* ZPOOL_STATUS_CORRUPT_CACHE */ - "ZFS-8000-2Q", /* ZPOOL_STATUS_MISSING_DEV_R */ - "ZFS-8000-3C", /* ZPOOL_STATUS_MISSING_DEV_NR */ - "ZFS-8000-4J", /* ZPOOL_STATUS_CORRUPT_LABEL_R */ - "ZFS-8000-5E", /* ZPOOL_STATUS_CORRUPT_LABEL_NR */ - "ZFS-8000-6X", /* ZPOOL_STATUS_BAD_GUID_SUM */ - "ZFS-8000-72", /* ZPOOL_STATUS_CORRUPT_POOL */ - "ZFS-8000-8A", /* ZPOOL_STATUS_CORRUPT_DATA */ - "ZFS-8000-9P", /* ZPOOL_STATUS_FAILING_DEV */ - "ZFS-8000-A5", /* ZPOOL_STATUS_VERSION_NEWER */ - "ZFS-8000-EY", /* ZPOOL_STATUS_HOSTID_MISMATCH */ - "ZFS-8000-EY", /* ZPOOL_STATUS_HOSTID_ACTIVE */ - "ZFS-8000-EY", /* ZPOOL_STATUS_HOSTID_REQUIRED */ - "ZFS-8000-HC", /* ZPOOL_STATUS_IO_FAILURE_WAIT */ - "ZFS-8000-JQ", /* ZPOOL_STATUS_IO_FAILURE_CONTINUE */ - "ZFS-8000-MM", /* ZPOOL_STATUS_IO_FAILURE_MMP */ - "ZFS-8000-K4", /* ZPOOL_STATUS_BAD_LOG */ - "ZFS-8000-ER", /* ZPOOL_STATUS_ERRATA */ - /* - * The following results have no message ID. - * ZPOOL_STATUS_UNSUP_FEAT_READ - * ZPOOL_STATUS_UNSUP_FEAT_WRITE - * ZPOOL_STATUS_FAULTED_DEV_R - * ZPOOL_STATUS_FAULTED_DEV_NR - * ZPOOL_STATUS_VERSION_OLDER - * ZPOOL_STATUS_FEAT_DISABLED - * ZPOOL_STATUS_RESILVERING - * ZPOOL_STATUS_OFFLINE_DEV - * ZPOOL_STATUS_REMOVED_DEV - * ZPOOL_STATUS_REBUILDING - * ZPOOL_STATUS_REBUILD_SCRUB - * ZPOOL_STATUS_COMPATIBILITY_ERR - * ZPOOL_STATUS_INCOMPATIBLE_FEAT - * ZPOOL_STATUS_OK - */ -}; - -#define NMSGID (sizeof (zfs_msgid_table) / sizeof (zfs_msgid_table[0])) - -static int -vdev_missing(vdev_stat_t *vs, uint_t vsc) -{ - (void) vsc; - return (vs->vs_state == VDEV_STATE_CANT_OPEN && - vs->vs_aux == VDEV_AUX_OPEN_FAILED); -} - -static int -vdev_faulted(vdev_stat_t *vs, uint_t vsc) -{ - (void) vsc; - return (vs->vs_state == VDEV_STATE_FAULTED); -} - -static int -vdev_errors(vdev_stat_t *vs, uint_t vsc) -{ - (void) vsc; - return (vs->vs_state == VDEV_STATE_DEGRADED || - vs->vs_read_errors != 0 || vs->vs_write_errors != 0 || - vs->vs_checksum_errors != 0); -} - -static int -vdev_broken(vdev_stat_t *vs, uint_t vsc) -{ - (void) vsc; - return (vs->vs_state == VDEV_STATE_CANT_OPEN); -} - -static int -vdev_offlined(vdev_stat_t *vs, uint_t vsc) -{ - (void) vsc; - return (vs->vs_state == VDEV_STATE_OFFLINE); -} - -static int -vdev_removed(vdev_stat_t *vs, uint_t vsc) -{ - (void) vsc; - return (vs->vs_state == VDEV_STATE_REMOVED); -} - -static int -vdev_non_native_ashift(vdev_stat_t *vs, uint_t vsc) -{ - if (getenv("ZPOOL_STATUS_NON_NATIVE_ASHIFT_IGNORE") != NULL) - return (0); - - return (VDEV_STAT_VALID(vs_physical_ashift, vsc) && - vs->vs_configured_ashift < vs->vs_physical_ashift); -} - -/* - * Detect if any leaf devices that have seen errors or could not be opened. - */ -static boolean_t -find_vdev_problem(nvlist_t *vdev, int (*func)(vdev_stat_t *, uint_t), - boolean_t ignore_replacing) -{ - nvlist_t **child; - uint_t c, children; - - /* - * Ignore problems within a 'replacing' vdev, since we're presumably in - * the process of repairing any such errors, and don't want to call them - * out again. We'll pick up the fact that a resilver is happening - * later. - */ - if (ignore_replacing == B_TRUE) { - const char *type = fnvlist_lookup_string(vdev, - ZPOOL_CONFIG_TYPE); - if (strcmp(type, VDEV_TYPE_REPLACING) == 0) - return (B_FALSE); - } - - if (nvlist_lookup_nvlist_array(vdev, ZPOOL_CONFIG_CHILDREN, &child, - &children) == 0) { - for (c = 0; c < children; c++) - if (find_vdev_problem(child[c], func, ignore_replacing)) - return (B_TRUE); - } else { - uint_t vsc; - vdev_stat_t *vs = (vdev_stat_t *)fnvlist_lookup_uint64_array( - vdev, ZPOOL_CONFIG_VDEV_STATS, &vsc); - if (func(vs, vsc) != 0) - return (B_TRUE); - } - - /* - * Check any L2 cache devs - */ - if (nvlist_lookup_nvlist_array(vdev, ZPOOL_CONFIG_L2CACHE, &child, - &children) == 0) { - for (c = 0; c < children; c++) - if (find_vdev_problem(child[c], func, ignore_replacing)) - return (B_TRUE); - } - - return (B_FALSE); -} - -/* - * Active pool health status. - * - * To determine the status for a pool, we make several passes over the config, - * picking the most egregious error we find. In order of importance, we do the - * following: - * - * - Check for a complete and valid configuration - * - Look for any faulted or missing devices in a non-replicated config - * - Check for any data errors - * - Check for any faulted or missing devices in a replicated config - * - Look for any devices showing errors - * - Check for any resilvering or rebuilding devices - * - * There can obviously be multiple errors within a single pool, so this routine - * only picks the most damaging of all the current errors to report. - */ -static zpool_status_t -check_status(nvlist_t *config, boolean_t isimport, - zpool_errata_t *erratap, const char *compat) -{ - pool_scan_stat_t *ps = NULL; - uint_t vsc, psc; - uint64_t suspended; - uint64_t hostid = 0; - uint64_t errata = 0; - unsigned long system_hostid = get_system_hostid(); - - uint64_t version = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION); - nvlist_t *nvroot = fnvlist_lookup_nvlist(config, - ZPOOL_CONFIG_VDEV_TREE); - vdev_stat_t *vs = (vdev_stat_t *)fnvlist_lookup_uint64_array(nvroot, - ZPOOL_CONFIG_VDEV_STATS, &vsc); - uint64_t stateval = fnvlist_lookup_uint64(config, - ZPOOL_CONFIG_POOL_STATE); - - /* - * Currently resilvering a vdev - */ - (void) nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_SCAN_STATS, - (uint64_t **)&ps, &psc); - if (ps != NULL && ps->pss_func == POOL_SCAN_RESILVER && - ps->pss_state == DSS_SCANNING) - return (ZPOOL_STATUS_RESILVERING); - - /* - * Currently rebuilding a vdev, check top-level vdevs. - */ - vdev_rebuild_stat_t *vrs = NULL; - nvlist_t **child; - uint_t c, i, children; - uint64_t rebuild_end_time = 0; - if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, - &child, &children) == 0) { - for (c = 0; c < children; c++) { - if ((nvlist_lookup_uint64_array(child[c], - ZPOOL_CONFIG_REBUILD_STATS, - (uint64_t **)&vrs, &i) == 0) && (vrs != NULL)) { - uint64_t state = vrs->vrs_state; - - if (state == VDEV_REBUILD_ACTIVE) { - return (ZPOOL_STATUS_REBUILDING); - } else if (state == VDEV_REBUILD_COMPLETE && - vrs->vrs_end_time > rebuild_end_time) { - rebuild_end_time = vrs->vrs_end_time; - } - } - } - - /* - * If we can determine when the last scrub was run, and it - * was before the last rebuild completed, then recommend - * that the pool be scrubbed to verify all checksums. When - * ps is NULL we can infer the pool has never been scrubbed. - */ - if (rebuild_end_time > 0) { - if (ps != NULL) { - if ((ps->pss_state == DSS_FINISHED && - ps->pss_func == POOL_SCAN_SCRUB && - rebuild_end_time > ps->pss_end_time) || - ps->pss_state == DSS_NONE) - return (ZPOOL_STATUS_REBUILD_SCRUB); - } else { - return (ZPOOL_STATUS_REBUILD_SCRUB); - } - } - } - - /* - * The multihost property is set and the pool may be active. - */ - if (vs->vs_state == VDEV_STATE_CANT_OPEN && - vs->vs_aux == VDEV_AUX_ACTIVE) { - mmp_state_t mmp_state; - nvlist_t *nvinfo; - - nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO); - mmp_state = fnvlist_lookup_uint64(nvinfo, - ZPOOL_CONFIG_MMP_STATE); - - if (mmp_state == MMP_STATE_ACTIVE) - return (ZPOOL_STATUS_HOSTID_ACTIVE); - else if (mmp_state == MMP_STATE_NO_HOSTID) - return (ZPOOL_STATUS_HOSTID_REQUIRED); - else - return (ZPOOL_STATUS_HOSTID_MISMATCH); - } - - /* - * Pool last accessed by another system. - */ - (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid); - if (hostid != 0 && (unsigned long)hostid != system_hostid && - stateval == POOL_STATE_ACTIVE) - return (ZPOOL_STATUS_HOSTID_MISMATCH); - - /* - * Newer on-disk version. - */ - if (vs->vs_state == VDEV_STATE_CANT_OPEN && - vs->vs_aux == VDEV_AUX_VERSION_NEWER) - return (ZPOOL_STATUS_VERSION_NEWER); - - /* - * Unsupported feature(s). - */ - if (vs->vs_state == VDEV_STATE_CANT_OPEN && - vs->vs_aux == VDEV_AUX_UNSUP_FEAT) { - nvlist_t *nvinfo = fnvlist_lookup_nvlist(config, - ZPOOL_CONFIG_LOAD_INFO); - if (nvlist_exists(nvinfo, ZPOOL_CONFIG_CAN_RDONLY)) - return (ZPOOL_STATUS_UNSUP_FEAT_WRITE); - return (ZPOOL_STATUS_UNSUP_FEAT_READ); - } - - /* - * Check that the config is complete. - */ - if (vs->vs_state == VDEV_STATE_CANT_OPEN && - vs->vs_aux == VDEV_AUX_BAD_GUID_SUM) - return (ZPOOL_STATUS_BAD_GUID_SUM); - - /* - * Check whether the pool has suspended. - */ - if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_SUSPENDED, - &suspended) == 0) { - uint64_t reason; - - if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_SUSPENDED_REASON, - &reason) == 0 && reason == ZIO_SUSPEND_MMP) - return (ZPOOL_STATUS_IO_FAILURE_MMP); - - if (suspended == ZIO_FAILURE_MODE_CONTINUE) - return (ZPOOL_STATUS_IO_FAILURE_CONTINUE); - return (ZPOOL_STATUS_IO_FAILURE_WAIT); - } - - /* - * Could not read a log. - */ - if (vs->vs_state == VDEV_STATE_CANT_OPEN && - vs->vs_aux == VDEV_AUX_BAD_LOG) { - return (ZPOOL_STATUS_BAD_LOG); - } - - /* - * Bad devices in non-replicated config. - */ - if (vs->vs_state == VDEV_STATE_CANT_OPEN && - find_vdev_problem(nvroot, vdev_faulted, B_TRUE)) - return (ZPOOL_STATUS_FAULTED_DEV_NR); - - if (vs->vs_state == VDEV_STATE_CANT_OPEN && - find_vdev_problem(nvroot, vdev_missing, B_TRUE)) - return (ZPOOL_STATUS_MISSING_DEV_NR); - - if (vs->vs_state == VDEV_STATE_CANT_OPEN && - find_vdev_problem(nvroot, vdev_broken, B_TRUE)) - return (ZPOOL_STATUS_CORRUPT_LABEL_NR); - - /* - * Corrupted pool metadata - */ - if (vs->vs_state == VDEV_STATE_CANT_OPEN && - vs->vs_aux == VDEV_AUX_CORRUPT_DATA) - return (ZPOOL_STATUS_CORRUPT_POOL); - - /* - * Persistent data errors. - */ - if (!isimport) { - uint64_t nerr; - if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT, - &nerr) == 0 && nerr != 0) - return (ZPOOL_STATUS_CORRUPT_DATA); - } - - /* - * Missing devices in a replicated config. - */ - if (find_vdev_problem(nvroot, vdev_faulted, B_TRUE)) - return (ZPOOL_STATUS_FAULTED_DEV_R); - if (find_vdev_problem(nvroot, vdev_missing, B_TRUE)) - return (ZPOOL_STATUS_MISSING_DEV_R); - if (find_vdev_problem(nvroot, vdev_broken, B_TRUE)) - return (ZPOOL_STATUS_CORRUPT_LABEL_R); - - /* - * Devices with errors - */ - if (!isimport && find_vdev_problem(nvroot, vdev_errors, B_TRUE)) - return (ZPOOL_STATUS_FAILING_DEV); - - /* - * Offlined devices - */ - if (find_vdev_problem(nvroot, vdev_offlined, B_TRUE)) - return (ZPOOL_STATUS_OFFLINE_DEV); - - /* - * Removed device - */ - if (find_vdev_problem(nvroot, vdev_removed, B_TRUE)) - return (ZPOOL_STATUS_REMOVED_DEV); - - /* - * Suboptimal, but usable, ashift configuration. - */ - if (find_vdev_problem(nvroot, vdev_non_native_ashift, B_FALSE)) - return (ZPOOL_STATUS_NON_NATIVE_ASHIFT); - - /* - * Informational errata available. - */ - (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRATA, &errata); - if (errata) { - *erratap = errata; - return (ZPOOL_STATUS_ERRATA); - } - - /* - * Outdated, but usable, version - */ - if (SPA_VERSION_IS_SUPPORTED(version) && version != SPA_VERSION) { - /* "legacy" compatibility disables old version reporting */ - if (compat != NULL && strcmp(compat, ZPOOL_COMPAT_LEGACY) == 0) - return (ZPOOL_STATUS_OK); - else - return (ZPOOL_STATUS_VERSION_OLDER); - } - - /* - * Usable pool with disabled or superfluous features - * (superfluous = beyond what's requested by 'compatibility') - */ - if (version >= SPA_VERSION_FEATURES) { - int i; - nvlist_t *feat; - - if (isimport) { - feat = fnvlist_lookup_nvlist(config, - ZPOOL_CONFIG_LOAD_INFO); - if (nvlist_exists(feat, ZPOOL_CONFIG_ENABLED_FEAT)) - feat = fnvlist_lookup_nvlist(feat, - ZPOOL_CONFIG_ENABLED_FEAT); - } else { - feat = fnvlist_lookup_nvlist(config, - ZPOOL_CONFIG_FEATURE_STATS); - } - - /* check against all features, or limited set? */ - boolean_t c_features[SPA_FEATURES]; - - switch (zpool_load_compat(compat, c_features, NULL, 0)) { - case ZPOOL_COMPATIBILITY_OK: - case ZPOOL_COMPATIBILITY_WARNTOKEN: - break; - default: - return (ZPOOL_STATUS_COMPATIBILITY_ERR); - } - for (i = 0; i < SPA_FEATURES; i++) { - zfeature_info_t *fi = &spa_feature_table[i]; - if (!fi->fi_zfs_mod_supported || - (fi->fi_flags & ZFEATURE_FLAG_NO_UPGRADE)) - continue; - if (c_features[i] && !nvlist_exists(feat, fi->fi_guid)) - return (ZPOOL_STATUS_FEAT_DISABLED); - if (!c_features[i] && nvlist_exists(feat, fi->fi_guid)) - return (ZPOOL_STATUS_INCOMPATIBLE_FEAT); - } - } - - return (ZPOOL_STATUS_OK); -} - -zpool_status_t -zpool_get_status(zpool_handle_t *zhp, const char **msgid, - zpool_errata_t *errata) -{ - /* - * pass in the desired feature set, as - * it affects check for disabled features - */ - char compatibility[ZFS_MAXPROPLEN]; - if (zpool_get_prop(zhp, ZPOOL_PROP_COMPATIBILITY, compatibility, - ZFS_MAXPROPLEN, NULL, B_FALSE) != 0) - compatibility[0] = '\0'; - - zpool_status_t ret = check_status(zhp->zpool_config, B_FALSE, errata, - compatibility); - - if (msgid != NULL) { - if (ret >= NMSGID) - *msgid = NULL; - else - *msgid = zfs_msgid_table[ret]; - } - return (ret); -} - -zpool_status_t -zpool_import_status(nvlist_t *config, const char **msgid, - zpool_errata_t *errata) -{ - zpool_status_t ret = check_status(config, B_TRUE, errata, NULL); - - if (ret >= NMSGID) - *msgid = NULL; - else - *msgid = zfs_msgid_table[ret]; - - return (ret); -} diff --git a/lib/libzfs/libzfs_util.c b/lib/libzfs/libzfs_util.c deleted file mode 100644 index 26f5135dff62..000000000000 --- a/lib/libzfs/libzfs_util.c +++ /dev/null @@ -1,2462 +0,0 @@ -// SPDX-License-Identifier: CDDL-1.0 -/* - * 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 - */ - -/* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2020 Joyent, Inc. All rights reserved. - * Copyright (c) 2011, 2024 by Delphix. All rights reserved. - * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com> - * Copyright (c) 2017 Datto Inc. - * Copyright (c) 2020 The FreeBSD Foundation - * - * Portions of this software were developed by Allan Jude - * under sponsorship from the FreeBSD Foundation. - */ - -/* - * Internal utility routines for the ZFS library. - */ - -#include <errno.h> -#include <fcntl.h> -#include <libintl.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <strings.h> -#include <unistd.h> -#include <math.h> -#if LIBFETCH_DYNAMIC -#include <dlfcn.h> -#endif -#include <sys/stat.h> -#include <sys/mnttab.h> -#include <sys/mntent.h> -#include <sys/types.h> -#include <sys/wait.h> - -#include <libzfs.h> -#include <libzfs_core.h> - -#include "libzfs_impl.h" -#include "zfs_prop.h" -#include "zfeature_common.h" -#include <zfs_fletcher.h> -#include <libzutil.h> - -/* - * We only care about the scheme in order to match the scheme - * with the handler. Each handler should validate the full URI - * as necessary. - */ -#define URI_REGEX "^\\([A-Za-z][A-Za-z0-9+.\\-]*\\):" -#define STR_NUMS "0123456789" - -int -libzfs_errno(libzfs_handle_t *hdl) -{ - return (hdl->libzfs_error); -} - -const char * -libzfs_error_action(libzfs_handle_t *hdl) -{ - return (hdl->libzfs_action); -} - -const char * -libzfs_error_description(libzfs_handle_t *hdl) -{ - if (hdl->libzfs_desc[0] != '\0') - return (hdl->libzfs_desc); - - switch (hdl->libzfs_error) { - case EZFS_NOMEM: - return (dgettext(TEXT_DOMAIN, "out of memory")); - case EZFS_BADPROP: - return (dgettext(TEXT_DOMAIN, "invalid property value")); - case EZFS_PROPREADONLY: - return (dgettext(TEXT_DOMAIN, "read-only property")); - case EZFS_PROPTYPE: - return (dgettext(TEXT_DOMAIN, "property doesn't apply to " - "datasets of this type")); - case EZFS_PROPNONINHERIT: - return (dgettext(TEXT_DOMAIN, "property cannot be inherited")); - case EZFS_PROPSPACE: - return (dgettext(TEXT_DOMAIN, "invalid quota or reservation")); - case EZFS_BADTYPE: - return (dgettext(TEXT_DOMAIN, "operation not applicable to " - "datasets of this type")); - case EZFS_BUSY: - return (dgettext(TEXT_DOMAIN, "pool or dataset is busy")); - case EZFS_EXISTS: - return (dgettext(TEXT_DOMAIN, "pool or dataset exists")); - case EZFS_NOENT: - return (dgettext(TEXT_DOMAIN, "no such pool or dataset")); - case EZFS_BADSTREAM: - return (dgettext(TEXT_DOMAIN, "invalid backup stream")); - case EZFS_DSREADONLY: - return (dgettext(TEXT_DOMAIN, "dataset is read-only")); - case EZFS_VOLTOOBIG: - return (dgettext(TEXT_DOMAIN, "volume size exceeds limit for " - "this system")); - case EZFS_INVALIDNAME: - return (dgettext(TEXT_DOMAIN, "invalid name")); - case EZFS_BADRESTORE: - return (dgettext(TEXT_DOMAIN, "unable to restore to " - "destination")); - case EZFS_BADBACKUP: - return (dgettext(TEXT_DOMAIN, "backup failed")); - case EZFS_BADTARGET: - return (dgettext(TEXT_DOMAIN, "invalid target vdev")); - case EZFS_NODEVICE: - return (dgettext(TEXT_DOMAIN, "no such device in pool")); - case EZFS_BADDEV: - return (dgettext(TEXT_DOMAIN, "invalid device")); - case EZFS_NOREPLICAS: - return (dgettext(TEXT_DOMAIN, "no valid replicas")); - case EZFS_RESILVERING: - return (dgettext(TEXT_DOMAIN, "currently resilvering")); - case EZFS_BADVERSION: - return (dgettext(TEXT_DOMAIN, "unsupported version or " - "feature")); - case EZFS_POOLUNAVAIL: - return (dgettext(TEXT_DOMAIN, "pool is unavailable")); - case EZFS_DEVOVERFLOW: - return (dgettext(TEXT_DOMAIN, "too many devices in one vdev")); - case EZFS_BADPATH: - return (dgettext(TEXT_DOMAIN, "must be an absolute path")); - case EZFS_CROSSTARGET: - return (dgettext(TEXT_DOMAIN, "operation crosses datasets or " - "pools")); - case EZFS_ZONED: - return (dgettext(TEXT_DOMAIN, "dataset in use by local zone")); - case EZFS_MOUNTFAILED: - return (dgettext(TEXT_DOMAIN, "mount failed")); - case EZFS_UMOUNTFAILED: - return (dgettext(TEXT_DOMAIN, "unmount failed")); - case EZFS_UNSHARENFSFAILED: - return (dgettext(TEXT_DOMAIN, "NFS share removal failed")); - case EZFS_SHARENFSFAILED: - return (dgettext(TEXT_DOMAIN, "NFS share creation failed")); - case EZFS_UNSHARESMBFAILED: - return (dgettext(TEXT_DOMAIN, "SMB share removal failed")); - case EZFS_SHARESMBFAILED: - return (dgettext(TEXT_DOMAIN, "SMB share creation failed")); - case EZFS_PERM: - return (dgettext(TEXT_DOMAIN, "permission denied")); - case EZFS_NOSPC: - return (dgettext(TEXT_DOMAIN, "out of space")); - case EZFS_FAULT: - return (dgettext(TEXT_DOMAIN, "bad address")); - case EZFS_IO: - return (dgettext(TEXT_DOMAIN, "I/O error")); - case EZFS_INTR: - return (dgettext(TEXT_DOMAIN, "signal received")); - case EZFS_CKSUM: - return (dgettext(TEXT_DOMAIN, "insufficient replicas")); - case EZFS_ISSPARE: - return (dgettext(TEXT_DOMAIN, "device is reserved as a hot " - "spare")); - case EZFS_INVALCONFIG: - return (dgettext(TEXT_DOMAIN, "invalid vdev configuration")); - case EZFS_RECURSIVE: - return (dgettext(TEXT_DOMAIN, "recursive dataset dependency")); - case EZFS_NOHISTORY: - return (dgettext(TEXT_DOMAIN, "no history available")); - case EZFS_POOLPROPS: - return (dgettext(TEXT_DOMAIN, "failed to retrieve " - "pool properties")); - case EZFS_POOL_NOTSUP: - return (dgettext(TEXT_DOMAIN, "operation not supported " - "on this type of pool")); - case EZFS_POOL_INVALARG: - return (dgettext(TEXT_DOMAIN, "invalid argument for " - "this pool operation")); - case EZFS_NAMETOOLONG: - return (dgettext(TEXT_DOMAIN, "dataset name is too long")); - case EZFS_OPENFAILED: - return (dgettext(TEXT_DOMAIN, "open failed")); - case EZFS_NOCAP: - return (dgettext(TEXT_DOMAIN, - "disk capacity information could not be retrieved")); - case EZFS_LABELFAILED: - return (dgettext(TEXT_DOMAIN, "write of label failed")); - case EZFS_BADWHO: - return (dgettext(TEXT_DOMAIN, "invalid user/group")); - case EZFS_BADPERM: - return (dgettext(TEXT_DOMAIN, "invalid permission")); - case EZFS_BADPERMSET: - return (dgettext(TEXT_DOMAIN, "invalid permission set name")); - case EZFS_NODELEGATION: - return (dgettext(TEXT_DOMAIN, "delegated administration is " - "disabled on pool")); - case EZFS_BADCACHE: - return (dgettext(TEXT_DOMAIN, "invalid or missing cache file")); - case EZFS_ISL2CACHE: - return (dgettext(TEXT_DOMAIN, "device is in use as a cache")); - case EZFS_VDEVNOTSUP: - return (dgettext(TEXT_DOMAIN, "vdev specification is not " - "supported")); - case EZFS_NOTSUP: - return (dgettext(TEXT_DOMAIN, "operation not supported " - "on this dataset")); - case EZFS_IOC_NOTSUPPORTED: - return (dgettext(TEXT_DOMAIN, "operation not supported by " - "zfs kernel module")); - case EZFS_ACTIVE_SPARE: - return (dgettext(TEXT_DOMAIN, "pool has active shared spare " - "device")); - case EZFS_UNPLAYED_LOGS: - return (dgettext(TEXT_DOMAIN, "log device has unplayed intent " - "logs")); - case EZFS_REFTAG_RELE: - return (dgettext(TEXT_DOMAIN, "no such tag on this dataset")); - case EZFS_REFTAG_HOLD: - return (dgettext(TEXT_DOMAIN, "tag already exists on this " - "dataset")); - case EZFS_TAGTOOLONG: - return (dgettext(TEXT_DOMAIN, "tag too long")); - case EZFS_PIPEFAILED: - return (dgettext(TEXT_DOMAIN, "pipe create failed")); - case EZFS_THREADCREATEFAILED: - return (dgettext(TEXT_DOMAIN, "thread create failed")); - case EZFS_POSTSPLIT_ONLINE: - return (dgettext(TEXT_DOMAIN, "disk was split from this pool " - "into a new one")); - case EZFS_SCRUB_PAUSED: - return (dgettext(TEXT_DOMAIN, "scrub is paused; " - "use 'zpool scrub' to resume scrub")); - case EZFS_SCRUB_PAUSED_TO_CANCEL: - return (dgettext(TEXT_DOMAIN, "scrub is paused; " - "use 'zpool scrub' to resume or 'zpool scrub -s' to " - "cancel scrub")); - case EZFS_SCRUBBING: - return (dgettext(TEXT_DOMAIN, "currently scrubbing; " - "use 'zpool scrub -s' to cancel scrub")); - case EZFS_ERRORSCRUBBING: - return (dgettext(TEXT_DOMAIN, "currently error scrubbing; " - "use 'zpool scrub -s' to cancel error scrub")); - case EZFS_ERRORSCRUB_PAUSED: - return (dgettext(TEXT_DOMAIN, "error scrub is paused; " - "use 'zpool scrub -e' to resume error scrub")); - case EZFS_NO_SCRUB: - return (dgettext(TEXT_DOMAIN, "there is no active scrub")); - case EZFS_DIFF: - return (dgettext(TEXT_DOMAIN, "unable to generate diffs")); - case EZFS_DIFFDATA: - return (dgettext(TEXT_DOMAIN, "invalid diff data")); - case EZFS_POOLREADONLY: - return (dgettext(TEXT_DOMAIN, "pool is read-only")); - case EZFS_NO_PENDING: - return (dgettext(TEXT_DOMAIN, "operation is not " - "in progress")); - case EZFS_CHECKPOINT_EXISTS: - return (dgettext(TEXT_DOMAIN, "checkpoint exists")); - case EZFS_DISCARDING_CHECKPOINT: - return (dgettext(TEXT_DOMAIN, "currently discarding " - "checkpoint")); - case EZFS_NO_CHECKPOINT: - return (dgettext(TEXT_DOMAIN, "checkpoint does not exist")); - case EZFS_DEVRM_IN_PROGRESS: - return (dgettext(TEXT_DOMAIN, "device removal in progress")); - case EZFS_VDEV_TOO_BIG: - return (dgettext(TEXT_DOMAIN, "device exceeds supported size")); - case EZFS_ACTIVE_POOL: - return (dgettext(TEXT_DOMAIN, "pool is imported on a " - "different host")); - case EZFS_CRYPTOFAILED: - return (dgettext(TEXT_DOMAIN, "encryption failure")); - case EZFS_TOOMANY: - return (dgettext(TEXT_DOMAIN, "argument list too long")); - case EZFS_INITIALIZING: - return (dgettext(TEXT_DOMAIN, "currently initializing")); - case EZFS_NO_INITIALIZE: - return (dgettext(TEXT_DOMAIN, "there is no active " - "initialization")); - case EZFS_WRONG_PARENT: - return (dgettext(TEXT_DOMAIN, "invalid parent dataset")); - case EZFS_TRIMMING: - return (dgettext(TEXT_DOMAIN, "currently trimming")); - case EZFS_NO_TRIM: - return (dgettext(TEXT_DOMAIN, "there is no active trim")); - case EZFS_TRIM_NOTSUP: - return (dgettext(TEXT_DOMAIN, "trim operations are not " - "supported by this device")); - case EZFS_NO_RESILVER_DEFER: - return (dgettext(TEXT_DOMAIN, "this action requires the " - "resilver_defer feature")); - case EZFS_EXPORT_IN_PROGRESS: - return (dgettext(TEXT_DOMAIN, "pool export in progress")); - case EZFS_REBUILDING: - return (dgettext(TEXT_DOMAIN, "currently sequentially " - "resilvering")); - case EZFS_VDEV_NOTSUP: - return (dgettext(TEXT_DOMAIN, "operation not supported " - "on this type of vdev")); - case EZFS_NOT_USER_NAMESPACE: - return (dgettext(TEXT_DOMAIN, "the provided file " - "was not a user namespace file")); - case EZFS_RESUME_EXISTS: - return (dgettext(TEXT_DOMAIN, "Resuming recv on existing " - "dataset without force")); - case EZFS_RAIDZ_EXPAND_IN_PROGRESS: - return (dgettext(TEXT_DOMAIN, "raidz expansion in progress")); - case EZFS_ASHIFT_MISMATCH: - return (dgettext(TEXT_DOMAIN, "adding devices with " - "different physical sector sizes is not allowed")); - case EZFS_UNKNOWN: - return (dgettext(TEXT_DOMAIN, "unknown error")); - default: - assert(hdl->libzfs_error == 0); - return (dgettext(TEXT_DOMAIN, "no error")); - } -} - -void -zfs_error_aux(libzfs_handle_t *hdl, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - - (void) vsnprintf(hdl->libzfs_desc, sizeof (hdl->libzfs_desc), - fmt, ap); - hdl->libzfs_desc_active = 1; - - va_end(ap); -} - -static void -zfs_verror(libzfs_handle_t *hdl, int error, const char *fmt, va_list ap) -{ - (void) vsnprintf(hdl->libzfs_action, sizeof (hdl->libzfs_action), - fmt, ap); - hdl->libzfs_error = error; - - if (hdl->libzfs_desc_active) - hdl->libzfs_desc_active = 0; - else - hdl->libzfs_desc[0] = '\0'; - - if (hdl->libzfs_printerr) { - if (error == EZFS_UNKNOWN) { - (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "internal " - "error: %s: %s\n"), hdl->libzfs_action, - libzfs_error_description(hdl)); - abort(); - } - - (void) fprintf(stderr, "%s: %s\n", hdl->libzfs_action, - libzfs_error_description(hdl)); - if (error == EZFS_NOMEM) - exit(1); - } -} - -int -zfs_error(libzfs_handle_t *hdl, int error, const char *msg) -{ - return (zfs_error_fmt(hdl, error, "%s", msg)); -} - -int -zfs_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - - zfs_verror(hdl, error, fmt, ap); - - va_end(ap); - - return (-1); -} - -static int -zfs_common_error(libzfs_handle_t *hdl, int error, const char *fmt, - va_list ap) -{ - switch (error) { - case EPERM: - case EACCES: - zfs_verror(hdl, EZFS_PERM, fmt, ap); - return (-1); - - case ECANCELED: - zfs_verror(hdl, EZFS_NODELEGATION, fmt, ap); - return (-1); - - case EIO: - zfs_verror(hdl, EZFS_IO, fmt, ap); - return (-1); - - case EFAULT: - zfs_verror(hdl, EZFS_FAULT, fmt, ap); - return (-1); - - case EINTR: - zfs_verror(hdl, EZFS_INTR, fmt, ap); - return (-1); - - case ECKSUM: - zfs_verror(hdl, EZFS_CKSUM, fmt, ap); - return (-1); - } - - return (0); -} - -int -zfs_standard_error(libzfs_handle_t *hdl, int error, const char *msg) -{ - return (zfs_standard_error_fmt(hdl, error, "%s", msg)); -} - -int -zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - - if (zfs_common_error(hdl, error, fmt, ap) != 0) { - va_end(ap); - return (-1); - } - - switch (error) { - case ENXIO: - case ENODEV: - case EPIPE: - zfs_verror(hdl, EZFS_IO, fmt, ap); - break; - - case ENOENT: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "dataset does not exist")); - zfs_verror(hdl, EZFS_NOENT, fmt, ap); - break; - - case ENOSPC: - case EDQUOT: - zfs_verror(hdl, EZFS_NOSPC, fmt, ap); - break; - - case EEXIST: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "dataset already exists")); - zfs_verror(hdl, EZFS_EXISTS, fmt, ap); - break; - - case EBUSY: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "dataset is busy")); - zfs_verror(hdl, EZFS_BUSY, fmt, ap); - break; - case EROFS: - zfs_verror(hdl, EZFS_POOLREADONLY, fmt, ap); - break; - case ENAMETOOLONG: - zfs_verror(hdl, EZFS_NAMETOOLONG, fmt, ap); - break; - case ENOTSUP: - zfs_verror(hdl, EZFS_BADVERSION, fmt, ap); - break; - case EAGAIN: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "pool I/O is currently suspended")); - zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap); - break; - case EREMOTEIO: - zfs_verror(hdl, EZFS_ACTIVE_POOL, fmt, ap); - break; - case ZFS_ERR_UNKNOWN_SEND_STREAM_FEATURE: - case ZFS_ERR_IOC_CMD_UNAVAIL: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "the loaded zfs " - "module does not support this operation. A reboot may " - "be required to enable this operation.")); - zfs_verror(hdl, EZFS_IOC_NOTSUPPORTED, fmt, ap); - break; - case ZFS_ERR_IOC_ARG_UNAVAIL: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "the loaded zfs " - "module does not support an option for this operation. " - "A reboot may be required to enable this option.")); - zfs_verror(hdl, EZFS_IOC_NOTSUPPORTED, fmt, ap); - break; - case ZFS_ERR_IOC_ARG_REQUIRED: - case ZFS_ERR_IOC_ARG_BADTYPE: - zfs_verror(hdl, EZFS_IOC_NOTSUPPORTED, fmt, ap); - break; - case ZFS_ERR_WRONG_PARENT: - zfs_verror(hdl, EZFS_WRONG_PARENT, fmt, ap); - break; - case ZFS_ERR_BADPROP: - zfs_verror(hdl, EZFS_BADPROP, fmt, ap); - break; - case ZFS_ERR_NOT_USER_NAMESPACE: - zfs_verror(hdl, EZFS_NOT_USER_NAMESPACE, fmt, ap); - break; - default: - zfs_error_aux(hdl, "%s", zfs_strerror(error)); - zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap); - break; - } - - va_end(ap); - return (-1); -} - -void -zfs_setprop_error(libzfs_handle_t *hdl, zfs_prop_t prop, int err, - char *errbuf) -{ - switch (err) { - - case ENOSPC: - /* - * For quotas and reservations, ENOSPC indicates - * something different; setting a quota or reservation - * doesn't use any disk space. - */ - switch (prop) { - case ZFS_PROP_QUOTA: - case ZFS_PROP_REFQUOTA: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "size is less than current used or " - "reserved space")); - (void) zfs_error(hdl, EZFS_PROPSPACE, errbuf); - break; - - case ZFS_PROP_RESERVATION: - case ZFS_PROP_REFRESERVATION: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "size is greater than available space")); - (void) zfs_error(hdl, EZFS_PROPSPACE, errbuf); - break; - - default: - (void) zfs_standard_error(hdl, err, errbuf); - break; - } - break; - - case EBUSY: - (void) zfs_standard_error(hdl, EBUSY, errbuf); - break; - - case EROFS: - (void) zfs_error(hdl, EZFS_DSREADONLY, errbuf); - break; - - case E2BIG: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "property value too long")); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - break; - - case ENOTSUP: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "pool and or dataset must be upgraded to set this " - "property or value")); - (void) zfs_error(hdl, EZFS_BADVERSION, errbuf); - break; - - case ERANGE: - if (prop == ZFS_PROP_COMPRESSION || - prop == ZFS_PROP_DNODESIZE || - prop == ZFS_PROP_RECORDSIZE) { - (void) zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "property setting is not allowed on " - "bootable datasets")); - (void) zfs_error(hdl, EZFS_NOTSUP, errbuf); - } else if (prop == ZFS_PROP_CHECKSUM || - prop == ZFS_PROP_DEDUP) { - (void) zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "property setting is not allowed on " - "root pools")); - (void) zfs_error(hdl, EZFS_NOTSUP, errbuf); - } else { - (void) zfs_standard_error(hdl, err, errbuf); - } - break; - - case EINVAL: - if (prop == ZPROP_INVAL) { - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - } else { - (void) zfs_standard_error(hdl, err, errbuf); - } - break; - - case ZFS_ERR_BADPROP: - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - break; - - case EACCES: - if (prop == ZFS_PROP_KEYLOCATION) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "keylocation may only be set on encryption roots")); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - } else { - (void) zfs_standard_error(hdl, err, errbuf); - } - break; - - case EOVERFLOW: - /* - * This platform can't address a volume this big. - */ -#ifdef _ILP32 - if (prop == ZFS_PROP_VOLSIZE) { - (void) zfs_error(hdl, EZFS_VOLTOOBIG, errbuf); - break; - } - zfs_fallthrough; -#endif - default: - (void) zfs_standard_error(hdl, err, errbuf); - } -} - -int -zpool_standard_error(libzfs_handle_t *hdl, int error, const char *msg) -{ - return (zpool_standard_error_fmt(hdl, error, "%s", msg)); -} - -int -zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - - if (zfs_common_error(hdl, error, fmt, ap) != 0) { - va_end(ap); - return (-1); - } - - switch (error) { - case ENODEV: - zfs_verror(hdl, EZFS_NODEVICE, fmt, ap); - break; - - case ENOENT: - zfs_error_aux(hdl, - dgettext(TEXT_DOMAIN, "no such pool or dataset")); - zfs_verror(hdl, EZFS_NOENT, fmt, ap); - break; - - case EEXIST: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "pool already exists")); - zfs_verror(hdl, EZFS_EXISTS, fmt, ap); - break; - - case EBUSY: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool is busy")); - zfs_verror(hdl, EZFS_BUSY, fmt, ap); - break; - - /* There is no pending operation to cancel */ - case ENOTACTIVE: - zfs_verror(hdl, EZFS_NO_PENDING, fmt, ap); - break; - - case ENXIO: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "one or more devices is currently unavailable")); - zfs_verror(hdl, EZFS_BADDEV, fmt, ap); - break; - - case ENAMETOOLONG: - zfs_verror(hdl, EZFS_DEVOVERFLOW, fmt, ap); - break; - - case ENOTSUP: - zfs_verror(hdl, EZFS_POOL_NOTSUP, fmt, ap); - break; - - case EINVAL: - zfs_verror(hdl, EZFS_POOL_INVALARG, fmt, ap); - break; - - case ENOSPC: - case EDQUOT: - zfs_verror(hdl, EZFS_NOSPC, fmt, ap); - break; - - case EAGAIN: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "pool I/O is currently suspended")); - zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap); - break; - - case EROFS: - zfs_verror(hdl, EZFS_POOLREADONLY, fmt, ap); - break; - case EDOM: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "block size out of range or does not match")); - zfs_verror(hdl, EZFS_BADPROP, fmt, ap); - break; - case EREMOTEIO: - zfs_verror(hdl, EZFS_ACTIVE_POOL, fmt, ap); - break; - case ZFS_ERR_CHECKPOINT_EXISTS: - zfs_verror(hdl, EZFS_CHECKPOINT_EXISTS, fmt, ap); - break; - case ZFS_ERR_DISCARDING_CHECKPOINT: - zfs_verror(hdl, EZFS_DISCARDING_CHECKPOINT, fmt, ap); - break; - case ZFS_ERR_NO_CHECKPOINT: - zfs_verror(hdl, EZFS_NO_CHECKPOINT, fmt, ap); - break; - case ZFS_ERR_DEVRM_IN_PROGRESS: - zfs_verror(hdl, EZFS_DEVRM_IN_PROGRESS, fmt, ap); - break; - case ZFS_ERR_VDEV_TOO_BIG: - zfs_verror(hdl, EZFS_VDEV_TOO_BIG, fmt, ap); - break; - case ZFS_ERR_EXPORT_IN_PROGRESS: - zfs_verror(hdl, EZFS_EXPORT_IN_PROGRESS, fmt, ap); - break; - case ZFS_ERR_RESILVER_IN_PROGRESS: - zfs_verror(hdl, EZFS_RESILVERING, fmt, ap); - break; - case ZFS_ERR_REBUILD_IN_PROGRESS: - zfs_verror(hdl, EZFS_REBUILDING, fmt, ap); - break; - case ZFS_ERR_BADPROP: - zfs_verror(hdl, EZFS_BADPROP, fmt, ap); - break; - case ZFS_ERR_VDEV_NOTSUP: - zfs_verror(hdl, EZFS_VDEV_NOTSUP, fmt, ap); - break; - case ZFS_ERR_IOC_CMD_UNAVAIL: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "the loaded zfs " - "module does not support this operation. A reboot may " - "be required to enable this operation.")); - zfs_verror(hdl, EZFS_IOC_NOTSUPPORTED, fmt, ap); - break; - case ZFS_ERR_IOC_ARG_UNAVAIL: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "the loaded zfs " - "module does not support an option for this operation. " - "A reboot may be required to enable this option.")); - zfs_verror(hdl, EZFS_IOC_NOTSUPPORTED, fmt, ap); - break; - case ZFS_ERR_IOC_ARG_REQUIRED: - case ZFS_ERR_IOC_ARG_BADTYPE: - zfs_verror(hdl, EZFS_IOC_NOTSUPPORTED, fmt, ap); - break; - case ZFS_ERR_RAIDZ_EXPAND_IN_PROGRESS: - zfs_verror(hdl, EZFS_RAIDZ_EXPAND_IN_PROGRESS, fmt, ap); - break; - case ZFS_ERR_ASHIFT_MISMATCH: - zfs_verror(hdl, EZFS_ASHIFT_MISMATCH, fmt, ap); - break; - case ZFS_ERR_TOO_MANY_SITOUTS: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "too many disks " - "already sitting out")); - zfs_verror(hdl, EZFS_BUSY, fmt, ap); - break; - default: - zfs_error_aux(hdl, "%s", zfs_strerror(error)); - zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap); - } - - va_end(ap); - return (-1); -} - -int -zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc) -{ - return (lzc_ioctl_fd(hdl->libzfs_fd, request, zc)); -} - -/* - * Display an out of memory error message and abort the current program. - */ -int -no_memory(libzfs_handle_t *hdl) -{ - return (zfs_error(hdl, EZFS_NOMEM, "internal error")); -} - -/* - * A safe form of malloc() which will die if the allocation fails. - */ -void * -zfs_alloc(libzfs_handle_t *hdl, size_t size) -{ - void *data; - - if ((data = calloc(1, size)) == NULL) - (void) no_memory(hdl); - - return (data); -} - -/* - * A safe form of asprintf() which will die if the allocation fails. - */ -char * -zfs_asprintf(libzfs_handle_t *hdl, const char *fmt, ...) -{ - va_list ap; - char *ret; - int err; - - va_start(ap, fmt); - - err = vasprintf(&ret, fmt, ap); - - va_end(ap); - - if (err < 0) { - (void) no_memory(hdl); - ret = NULL; - } - - return (ret); -} - -/* - * A safe form of realloc(), which also zeroes newly allocated space. - */ -void * -zfs_realloc(libzfs_handle_t *hdl, void *ptr, size_t oldsize, size_t newsize) -{ - void *ret; - - if ((ret = realloc(ptr, newsize)) == NULL) { - (void) no_memory(hdl); - return (NULL); - } - - memset((char *)ret + oldsize, 0, newsize - oldsize); - return (ret); -} - -/* - * A safe form of strdup() which will die if the allocation fails. - */ -char * -zfs_strdup(libzfs_handle_t *hdl, const char *str) -{ - char *ret; - - if ((ret = strdup(str)) == NULL) - (void) no_memory(hdl); - - return (ret); -} - -void -libzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr) -{ - hdl->libzfs_printerr = printerr; -} - -/* - * Read lines from an open file descriptor and store them in an array of - * strings until EOF. lines[] will be allocated and populated with all the - * lines read. All newlines are replaced with NULL terminators for - * convenience. lines[] must be freed after use with libzfs_free_str_array(). - * - * Returns the number of lines read. - */ -static int -libzfs_read_stdout_from_fd(int fd, char **lines[]) -{ - - FILE *fp; - int lines_cnt = 0; - size_t len = 0; - char *line = NULL; - char **tmp_lines = NULL, **tmp; - - fp = fdopen(fd, "r"); - if (fp == NULL) { - close(fd); - return (0); - } - while (getline(&line, &len, fp) != -1) { - tmp = realloc(tmp_lines, sizeof (*tmp_lines) * (lines_cnt + 1)); - if (tmp == NULL) { - /* Return the lines we were able to process */ - break; - } - tmp_lines = tmp; - - /* Remove newline if not EOF */ - if (line[strlen(line) - 1] == '\n') - line[strlen(line) - 1] = '\0'; - - tmp_lines[lines_cnt] = strdup(line); - if (tmp_lines[lines_cnt] == NULL) - break; - ++lines_cnt; - } - free(line); - fclose(fp); - *lines = tmp_lines; - return (lines_cnt); -} - -static int -libzfs_run_process_impl(const char *path, char *argv[], char *env[], int flags, - char **lines[], int *lines_cnt) -{ - pid_t pid; - int error, devnull_fd; - int link[2]; - - /* - * Setup a pipe between our child and parent process if we're - * reading stdout. - */ - if (lines != NULL && pipe2(link, O_NONBLOCK | O_CLOEXEC) == -1) - return (-EPIPE); - - pid = fork(); - if (pid == 0) { - /* Child process */ - setpgid(0, 0); - devnull_fd = open("/dev/null", O_WRONLY | O_CLOEXEC); - - if (devnull_fd < 0) - _exit(-1); - - if (!(flags & STDOUT_VERBOSE) && (lines == NULL)) - (void) dup2(devnull_fd, STDOUT_FILENO); - else if (lines != NULL) { - /* Save the output to lines[] */ - dup2(link[1], STDOUT_FILENO); - } - - if (!(flags & STDERR_VERBOSE)) - (void) dup2(devnull_fd, STDERR_FILENO); - - if (flags & NO_DEFAULT_PATH) { - if (env == NULL) - execv(path, argv); - else - execve(path, argv, env); - } else { - if (env == NULL) - execvp(path, argv); - else - execvpe(path, argv, env); - } - - _exit(-1); - } else if (pid > 0) { - /* Parent process */ - int status; - - while ((error = waitpid(pid, &status, 0)) == -1 && - errno == EINTR) - ; - if (error < 0 || !WIFEXITED(status)) - return (-1); - - if (lines != NULL) { - close(link[1]); - *lines_cnt = libzfs_read_stdout_from_fd(link[0], lines); - } - return (WEXITSTATUS(status)); - } - - return (-1); -} - -int -libzfs_run_process(const char *path, char *argv[], int flags) -{ - return (libzfs_run_process_impl(path, argv, NULL, flags, NULL, NULL)); -} - -/* - * Run a command and store its stdout lines in an array of strings (lines[]). - * lines[] is allocated and populated for you, and the number of lines is set in - * lines_cnt. lines[] must be freed after use with libzfs_free_str_array(). - * All newlines (\n) in lines[] are terminated for convenience. - */ -int -libzfs_run_process_get_stdout(const char *path, char *argv[], char *env[], - char **lines[], int *lines_cnt) -{ - return (libzfs_run_process_impl(path, argv, env, 0, lines, lines_cnt)); -} - -/* - * Same as libzfs_run_process_get_stdout(), but run without $PATH set. This - * means that *path needs to be the full path to the executable. - */ -int -libzfs_run_process_get_stdout_nopath(const char *path, char *argv[], - char *env[], char **lines[], int *lines_cnt) -{ - return (libzfs_run_process_impl(path, argv, env, NO_DEFAULT_PATH, - lines, lines_cnt)); -} - -/* - * Free an array of strings. Free both the strings contained in the array and - * the array itself. - */ -void -libzfs_free_str_array(char **strs, int count) -{ - while (--count >= 0) - free(strs[count]); - - free(strs); -} - -/* - * Returns 1 if environment variable is set to "YES", "yes", "ON", "on", or - * a non-zero number. - * - * Returns 0 otherwise. - */ -boolean_t -libzfs_envvar_is_set(const char *envvar) -{ - char *env = getenv(envvar); - return (env && (strtoul(env, NULL, 0) > 0 || - (!strncasecmp(env, "YES", 3) && strnlen(env, 4) == 3) || - (!strncasecmp(env, "ON", 2) && strnlen(env, 3) == 2))); -} - -libzfs_handle_t * -libzfs_init(void) -{ - libzfs_handle_t *hdl; - int error; - char *env; - - if ((error = libzfs_load_module()) != 0) { - errno = error; - return (NULL); - } - - if ((hdl = calloc(1, sizeof (libzfs_handle_t))) == NULL) { - return (NULL); - } - - if (regcomp(&hdl->libzfs_urire, URI_REGEX, 0) != 0) { - free(hdl); - return (NULL); - } - - if ((hdl->libzfs_fd = open(ZFS_DEV, O_RDWR|O_EXCL|O_CLOEXEC)) < 0) { - free(hdl); - return (NULL); - } - - if (libzfs_core_init() != 0) { - (void) close(hdl->libzfs_fd); - free(hdl); - return (NULL); - } - - zfs_prop_init(); - zpool_prop_init(); - zpool_feature_init(); - vdev_prop_init(); - libzfs_mnttab_init(hdl); - fletcher_4_init(); - - if (getenv("ZFS_PROP_DEBUG") != NULL) { - hdl->libzfs_prop_debug = B_TRUE; - } - if ((env = getenv("ZFS_SENDRECV_MAX_NVLIST")) != NULL) { - if ((error = zfs_nicestrtonum(hdl, env, - &hdl->libzfs_max_nvlist))) { - errno = error; - (void) close(hdl->libzfs_fd); - free(hdl); - return (NULL); - } - } else { - hdl->libzfs_max_nvlist = (SPA_MAXBLOCKSIZE * 4); - } - - /* - * For testing, remove some settable properties and features - */ - if (libzfs_envvar_is_set("ZFS_SYSFS_PROP_SUPPORT_TEST")) { - zprop_desc_t *proptbl; - - proptbl = zpool_prop_get_table(); - proptbl[ZPOOL_PROP_COMMENT].pd_zfs_mod_supported = B_FALSE; - - proptbl = zfs_prop_get_table(); - proptbl[ZFS_PROP_DNODESIZE].pd_zfs_mod_supported = B_FALSE; - - zfeature_info_t *ftbl = spa_feature_table; - ftbl[SPA_FEATURE_LARGE_BLOCKS].fi_zfs_mod_supported = B_FALSE; - } - - return (hdl); -} - -void -libzfs_fini(libzfs_handle_t *hdl) -{ - (void) close(hdl->libzfs_fd); - zpool_free_handles(hdl); - namespace_clear(hdl); - libzfs_mnttab_fini(hdl); - libzfs_core_fini(); - regfree(&hdl->libzfs_urire); - fletcher_4_fini(); -#if LIBFETCH_DYNAMIC - if (hdl->libfetch != (void *)-1 && hdl->libfetch != NULL) - (void) dlclose(hdl->libfetch); - free(hdl->libfetch_load_error); -#endif - free(hdl); -} - -libzfs_handle_t * -zpool_get_handle(zpool_handle_t *zhp) -{ - return (zhp->zpool_hdl); -} - -libzfs_handle_t * -zfs_get_handle(zfs_handle_t *zhp) -{ - return (zhp->zfs_hdl); -} - -zpool_handle_t * -zfs_get_pool_handle(const zfs_handle_t *zhp) -{ - return (zhp->zpool_hdl); -} - -/* - * Given a name, determine whether or not it's a valid path - * (starts with '/' or "./"). If so, walk the mnttab trying - * to match the device number. If not, treat the path as an - * fs/vol/snap/bkmark name. - */ -zfs_handle_t * -zfs_path_to_zhandle(libzfs_handle_t *hdl, const char *path, zfs_type_t argtype) -{ - struct stat64 statbuf; - struct extmnttab entry; - - if (path[0] != '/' && strncmp(path, "./", strlen("./")) != 0) { - /* - * It's not a valid path, assume it's a name of type 'argtype'. - */ - return (zfs_open(hdl, path, argtype)); - } - - if (getextmntent(path, &entry, &statbuf) != 0) - return (NULL); - - if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) { - (void) fprintf(stderr, gettext("'%s': not a ZFS filesystem\n"), - path); - return (NULL); - } - - return (zfs_open(hdl, entry.mnt_special, ZFS_TYPE_FILESYSTEM)); -} - -/* - * Initialize the zc_nvlist_dst member to prepare for receiving an nvlist from - * an ioctl(). - */ -void -zcmd_alloc_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, size_t len) -{ - if (len == 0) - len = 256 * 1024; - zc->zc_nvlist_dst_size = len; - zc->zc_nvlist_dst = - (uint64_t)(uintptr_t)zfs_alloc(hdl, zc->zc_nvlist_dst_size); -} - -/* - * Called when an ioctl() which returns an nvlist fails with ENOMEM. This will - * expand the nvlist to the size specified in 'zc_nvlist_dst_size', which was - * filled in by the kernel to indicate the actual required size. - */ -void -zcmd_expand_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc) -{ - free((void *)(uintptr_t)zc->zc_nvlist_dst); - zc->zc_nvlist_dst = - (uint64_t)(uintptr_t)zfs_alloc(hdl, zc->zc_nvlist_dst_size); -} - -/* - * Called to free the src and dst nvlists stored in the command structure. - */ -void -zcmd_free_nvlists(zfs_cmd_t *zc) -{ - free((void *)(uintptr_t)zc->zc_nvlist_conf); - free((void *)(uintptr_t)zc->zc_nvlist_src); - free((void *)(uintptr_t)zc->zc_nvlist_dst); - zc->zc_nvlist_conf = 0; - zc->zc_nvlist_src = 0; - zc->zc_nvlist_dst = 0; -} - -static void -zcmd_write_nvlist_com(libzfs_handle_t *hdl, uint64_t *outnv, uint64_t *outlen, - nvlist_t *nvl) -{ - char *packed; - - size_t len = fnvlist_size(nvl); - packed = zfs_alloc(hdl, len); - - verify(nvlist_pack(nvl, &packed, &len, NV_ENCODE_NATIVE, 0) == 0); - - *outnv = (uint64_t)(uintptr_t)packed; - *outlen = len; -} - -void -zcmd_write_conf_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl) -{ - zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_conf, - &zc->zc_nvlist_conf_size, nvl); -} - -void -zcmd_write_src_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl) -{ - zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_src, - &zc->zc_nvlist_src_size, nvl); -} - -/* - * Unpacks an nvlist from the ZFS ioctl command structure. - */ -int -zcmd_read_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t **nvlp) -{ - if (nvlist_unpack((void *)(uintptr_t)zc->zc_nvlist_dst, - zc->zc_nvlist_dst_size, nvlp, 0) != 0) - return (no_memory(hdl)); - - return (0); -} - -/* - * ================================================================ - * API shared by zfs and zpool property management - * ================================================================ - */ - -void -zcmd_print_json(nvlist_t *nvl) -{ - nvlist_print_json(stdout, nvl); - (void) putchar('\n'); - nvlist_free(nvl); -} - -static void -zprop_print_headers(zprop_get_cbdata_t *cbp, zfs_type_t type) -{ - zprop_list_t *pl; - int i; - char *title; - size_t len; - - cbp->cb_first = B_FALSE; - if (cbp->cb_scripted) - return; - - /* - * Start with the length of the column headers. - */ - cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN, "NAME")); - cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN, - "PROPERTY")); - cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN, - "VALUE")); - cbp->cb_colwidths[GET_COL_RECVD] = strlen(dgettext(TEXT_DOMAIN, - "RECEIVED")); - cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN, - "SOURCE")); - - /* first property is always NAME */ - assert(cbp->cb_proplist->pl_prop == - ((type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME : - ((type == ZFS_TYPE_VDEV) ? VDEV_PROP_NAME : ZFS_PROP_NAME))); - - /* - * Go through and calculate the widths for each column. For the - * 'source' column, we kludge it up by taking the worst-case scenario of - * inheriting from the longest name. This is acceptable because in the - * majority of cases 'SOURCE' is the last column displayed, and we don't - * use the width anyway. Note that the 'VALUE' column can be oversized, - * if the name of the property is much longer than any values we find. - */ - for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) { - /* - * 'PROPERTY' column - */ - if (pl->pl_prop != ZPROP_USERPROP) { - const char *propname = (type == ZFS_TYPE_POOL) ? - zpool_prop_to_name(pl->pl_prop) : - ((type == ZFS_TYPE_VDEV) ? - vdev_prop_to_name(pl->pl_prop) : - zfs_prop_to_name(pl->pl_prop)); - - assert(propname != NULL); - len = strlen(propname); - if (len > cbp->cb_colwidths[GET_COL_PROPERTY]) - cbp->cb_colwidths[GET_COL_PROPERTY] = len; - } else { - assert(pl->pl_user_prop != NULL); - len = strlen(pl->pl_user_prop); - if (len > cbp->cb_colwidths[GET_COL_PROPERTY]) - cbp->cb_colwidths[GET_COL_PROPERTY] = len; - } - - /* - * 'VALUE' column. The first property is always the 'name' - * property that was tacked on either by /sbin/zfs's - * zfs_do_get() or when calling zprop_expand_list(), so we - * ignore its width. If the user specified the name property - * to display, then it will be later in the list in any case. - */ - if (pl != cbp->cb_proplist && - pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE]) - cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width; - - /* 'RECEIVED' column. */ - if (pl != cbp->cb_proplist && - pl->pl_recvd_width > cbp->cb_colwidths[GET_COL_RECVD]) - cbp->cb_colwidths[GET_COL_RECVD] = pl->pl_recvd_width; - - /* - * 'NAME' and 'SOURCE' columns - */ - if (pl->pl_prop == ((type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME : - ((type == ZFS_TYPE_VDEV) ? VDEV_PROP_NAME : - ZFS_PROP_NAME)) && pl->pl_width > - cbp->cb_colwidths[GET_COL_NAME]) { - cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width; - cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width + - strlen(dgettext(TEXT_DOMAIN, "inherited from")); - } - } - - /* - * Now go through and print the headers. - */ - for (i = 0; i < ZFS_GET_NCOLS; i++) { - switch (cbp->cb_columns[i]) { - case GET_COL_NAME: - title = dgettext(TEXT_DOMAIN, "NAME"); - break; - case GET_COL_PROPERTY: - title = dgettext(TEXT_DOMAIN, "PROPERTY"); - break; - case GET_COL_VALUE: - title = dgettext(TEXT_DOMAIN, "VALUE"); - break; - case GET_COL_RECVD: - title = dgettext(TEXT_DOMAIN, "RECEIVED"); - break; - case GET_COL_SOURCE: - title = dgettext(TEXT_DOMAIN, "SOURCE"); - break; - default: - title = NULL; - } - - if (title != NULL) { - if (i == (ZFS_GET_NCOLS - 1) || - cbp->cb_columns[i + 1] == GET_COL_NONE) - (void) printf("%s", title); - else - (void) printf("%-*s ", - cbp->cb_colwidths[cbp->cb_columns[i]], - title); - } - } - (void) printf("\n"); -} - -/* - * Add property value and source to provided nvlist, according to - * settings in cb structure. Later to be printed in JSON format. - */ -int -zprop_nvlist_one_property(const char *propname, - const char *value, zprop_source_t sourcetype, const char *source, - const char *recvd_value, nvlist_t *nvl, boolean_t as_int) -{ - int ret = 0; - nvlist_t *src_nv, *prop; - boolean_t all_numeric = strspn(value, STR_NUMS) == strlen(value); - src_nv = prop = NULL; - - if ((nvlist_alloc(&prop, NV_UNIQUE_NAME, 0) != 0) || - (nvlist_alloc(&src_nv, NV_UNIQUE_NAME, 0) != 0)) { - ret = -1; - goto err; - } - - if (as_int && all_numeric) { - uint64_t val; - sscanf(value, "%lld", (u_longlong_t *)&val); - if (nvlist_add_uint64(prop, "value", val) != 0) { - ret = -1; - goto err; - } - } else { - if (nvlist_add_string(prop, "value", value) != 0) { - ret = -1; - goto err; - } - } - - switch (sourcetype) { - case ZPROP_SRC_NONE: - if (nvlist_add_string(src_nv, "type", "NONE") != 0 || - (nvlist_add_string(src_nv, "data", "-") != 0)) { - ret = -1; - goto err; - } - break; - case ZPROP_SRC_DEFAULT: - if (nvlist_add_string(src_nv, "type", "DEFAULT") != 0 || - (nvlist_add_string(src_nv, "data", "-") != 0)) { - ret = -1; - goto err; - } - break; - case ZPROP_SRC_LOCAL: - if (nvlist_add_string(src_nv, "type", "LOCAL") != 0 || - (nvlist_add_string(src_nv, "data", "-") != 0)) { - ret = -1; - goto err; - } - break; - case ZPROP_SRC_TEMPORARY: - if (nvlist_add_string(src_nv, "type", "TEMPORARY") != 0 || - (nvlist_add_string(src_nv, "data", "-") != 0)) { - ret = -1; - goto err; - } - break; - case ZPROP_SRC_INHERITED: - if (nvlist_add_string(src_nv, "type", "INHERITED") != 0 || - (nvlist_add_string(src_nv, "data", source) != 0)) { - ret = -1; - goto err; - } - break; - case ZPROP_SRC_RECEIVED: - if (nvlist_add_string(src_nv, "type", "RECEIVED") != 0 || - (nvlist_add_string(src_nv, "data", - (recvd_value == NULL ? "-" : recvd_value)) != 0)) { - ret = -1; - goto err; - } - break; - default: - assert(!"unhandled zprop_source_t"); - if (nvlist_add_string(src_nv, "type", - "unhandled zprop_source_t") != 0) { - ret = -1; - goto err; - } - } - if ((nvlist_add_nvlist(prop, "source", src_nv) != 0) || - (nvlist_add_nvlist(nvl, propname, prop)) != 0) { - ret = -1; - goto err; - } -err: - nvlist_free(src_nv); - nvlist_free(prop); - return (ret); -} - -/* - * Display a single line of output, according to the settings in the callback - * structure. - */ -void -zprop_print_one_property(const char *name, zprop_get_cbdata_t *cbp, - const char *propname, const char *value, zprop_source_t sourcetype, - const char *source, const char *recvd_value) -{ - int i; - const char *str = NULL; - char buf[128]; - - /* - * Ignore those source types that the user has chosen to ignore. - */ - if ((sourcetype & cbp->cb_sources) == 0) - return; - - if (cbp->cb_first) - zprop_print_headers(cbp, cbp->cb_type); - - for (i = 0; i < ZFS_GET_NCOLS; i++) { - switch (cbp->cb_columns[i]) { - case GET_COL_NAME: - str = name; - break; - - case GET_COL_PROPERTY: - str = propname; - break; - - case GET_COL_VALUE: - str = value; - break; - - case GET_COL_SOURCE: - switch (sourcetype) { - case ZPROP_SRC_NONE: - str = "-"; - break; - - case ZPROP_SRC_DEFAULT: - str = "default"; - break; - - case ZPROP_SRC_LOCAL: - str = "local"; - break; - - case ZPROP_SRC_TEMPORARY: - str = "temporary"; - break; - - case ZPROP_SRC_INHERITED: - (void) snprintf(buf, sizeof (buf), - "inherited from %s", source); - str = buf; - break; - case ZPROP_SRC_RECEIVED: - str = "received"; - break; - - default: - str = NULL; - assert(!"unhandled zprop_source_t"); - } - break; - - case GET_COL_RECVD: - str = (recvd_value == NULL ? "-" : recvd_value); - break; - - default: - continue; - } - - if (i == (ZFS_GET_NCOLS - 1) || - cbp->cb_columns[i + 1] == GET_COL_NONE) - (void) printf("%s", str); - else if (cbp->cb_scripted) - (void) printf("%s\t", str); - else - (void) printf("%-*s ", - cbp->cb_colwidths[cbp->cb_columns[i]], - str); - } - - (void) printf("\n"); -} - -int -zprop_collect_property(const char *name, zprop_get_cbdata_t *cbp, - const char *propname, const char *value, zprop_source_t sourcetype, - const char *source, const char *recvd_value, nvlist_t *nvl) -{ - if (cbp->cb_json) { - if ((sourcetype & cbp->cb_sources) == 0) - return (0); - else { - return (zprop_nvlist_one_property(propname, value, - sourcetype, source, recvd_value, nvl, - cbp->cb_json_as_int)); - } - } else { - zprop_print_one_property(name, cbp, - propname, value, sourcetype, source, recvd_value); - return (0); - } -} - -/* - * Given a numeric suffix, convert the value into a number of bits that the - * resulting value must be shifted. - */ -static int -str2shift(libzfs_handle_t *hdl, const char *buf) -{ - const char *ends = "BKMGTPEZ"; - int i, len; - - if (buf[0] == '\0') - return (0); - - len = strlen(ends); - for (i = 0; i < len; i++) { - if (toupper(buf[0]) == ends[i]) - break; - } - if (i == len) { - if (hdl) - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "invalid numeric suffix '%s'"), buf); - return (-1); - } - - /* - * Allow 'G' = 'GB' = 'GiB', case-insensitively. - * However, 'BB' and 'BiB' are disallowed. - */ - if (buf[1] == '\0' || - (toupper(buf[0]) != 'B' && - ((toupper(buf[1]) == 'B' && buf[2] == '\0') || - (toupper(buf[1]) == 'I' && toupper(buf[2]) == 'B' && - buf[3] == '\0')))) - return (10 * i); - - if (hdl) - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "invalid numeric suffix '%s'"), buf); - return (-1); -} - -/* - * Convert a string of the form '100G' into a real number. Used when setting - * properties or creating a volume. 'buf' is used to place an extended error - * message for the caller to use. - */ -int -zfs_nicestrtonum(libzfs_handle_t *hdl, const char *value, uint64_t *num) -{ - char *end; - int shift; - - *num = 0; - - /* Check to see if this looks like a number. */ - if ((value[0] < '0' || value[0] > '9') && value[0] != '.') { - if (hdl) - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "bad numeric value '%s'"), value); - return (-1); - } - - /* Rely on strtoull() to process the numeric portion. */ - errno = 0; - *num = strtoull(value, &end, 10); - - /* - * Check for ERANGE, which indicates that the value is too large to fit - * in a 64-bit value. - */ - if (errno == ERANGE) { - if (hdl) - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "numeric value is too large")); - return (-1); - } - - /* - * If we have a decimal value, then do the computation with floating - * point arithmetic. Otherwise, use standard arithmetic. - */ - if (*end == '.') { - double fval = strtod(value, &end); - - if ((shift = str2shift(hdl, end)) == -1) - return (-1); - - fval *= pow(2, shift); - - /* - * UINT64_MAX is not exactly representable as a double. - * The closest representation is UINT64_MAX + 1, so we - * use a >= comparison instead of > for the bounds check. - */ - if (fval >= (double)UINT64_MAX) { - if (hdl) - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "numeric value is too large")); - return (-1); - } - - *num = (uint64_t)fval; - } else { - if ((shift = str2shift(hdl, end)) == -1) - return (-1); - - /* Check for overflow */ - if (shift >= 64 || (*num << shift) >> shift != *num) { - if (hdl) - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "numeric value is too large")); - return (-1); - } - - *num <<= shift; - } - - return (0); -} - -/* - * Given a propname=value nvpair to set, parse any numeric properties - * (index, boolean, etc) if they are specified as strings and add the - * resulting nvpair to the returned nvlist. - * - * At the DSL layer, all properties are either 64-bit numbers or strings. - * We want the user to be able to ignore this fact and specify properties - * as native values (numbers, for example) or as strings (to simplify - * command line utilities). This also handles converting index types - * (compression, checksum, etc) from strings to their on-disk index. - */ -int -zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop, - zfs_type_t type, nvlist_t *ret, const char **svalp, uint64_t *ivalp, - const char *errbuf) -{ - data_type_t datatype = nvpair_type(elem); - zprop_type_t proptype; - const char *propname; - const char *value; - boolean_t isnone = B_FALSE; - boolean_t isauto = B_FALSE; - int err = 0; - - if (type == ZFS_TYPE_POOL) { - proptype = zpool_prop_get_type(prop); - propname = zpool_prop_to_name(prop); - } else if (type == ZFS_TYPE_VDEV) { - proptype = vdev_prop_get_type(prop); - propname = vdev_prop_to_name(prop); - } else { - proptype = zfs_prop_get_type(prop); - propname = zfs_prop_to_name(prop); - } - - /* - * Convert any properties to the internal DSL value types. - */ - *svalp = NULL; - *ivalp = 0; - - switch (proptype) { - case PROP_TYPE_STRING: - if (datatype != DATA_TYPE_STRING) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "'%s' must be a string"), nvpair_name(elem)); - goto error; - } - err = nvpair_value_string(elem, svalp); - if (err != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "'%s' is invalid"), nvpair_name(elem)); - goto error; - } - if (strlen(*svalp) >= ZFS_MAXPROPLEN) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "'%s' is too long"), nvpair_name(elem)); - goto error; - } - break; - - case PROP_TYPE_NUMBER: - if (datatype == DATA_TYPE_STRING) { - (void) nvpair_value_string(elem, &value); - if (strcmp(value, "none") == 0) { - isnone = B_TRUE; - } else if (strcmp(value, "auto") == 0) { - isauto = B_TRUE; - } else if (zfs_nicestrtonum(hdl, value, ivalp) != 0) { - goto error; - } - } else if (datatype == DATA_TYPE_UINT64) { - (void) nvpair_value_uint64(elem, ivalp); - } else { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "'%s' must be a number"), nvpair_name(elem)); - goto error; - } - - /* - * Quota special: force 'none' and don't allow 0. - */ - if ((type & ZFS_TYPE_DATASET) && *ivalp == 0 && !isnone && - (prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_REFQUOTA)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "use 'none' to disable quota/refquota")); - goto error; - } - /* - * Pool dedup table quota; force use of 'none' instead of 0 - */ - if ((type & ZFS_TYPE_POOL) && *ivalp == 0 && - (!isnone && !isauto) && - prop == ZPOOL_PROP_DEDUP_TABLE_QUOTA) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "use 'none' to disable ddt table quota")); - goto error; - } - - /* - * Special handling for "*_limit=none". In this case it's not - * 0 but UINT64_MAX. - */ - if ((type & ZFS_TYPE_DATASET) && isnone && - (prop == ZFS_PROP_FILESYSTEM_LIMIT || - prop == ZFS_PROP_SNAPSHOT_LIMIT)) { - *ivalp = UINT64_MAX; - } - - /* - * Special handling for "checksum_*=none". In this case it's not - * 0 but UINT64_MAX. - */ - if ((type & ZFS_TYPE_VDEV) && isnone && - (prop == VDEV_PROP_CHECKSUM_N || - prop == VDEV_PROP_CHECKSUM_T || - prop == VDEV_PROP_IO_N || - prop == VDEV_PROP_IO_T || - prop == VDEV_PROP_SLOW_IO_N || - prop == VDEV_PROP_SLOW_IO_T)) { - *ivalp = UINT64_MAX; - } - - /* - * Special handling for setting 'refreservation' to 'auto'. Use - * UINT64_MAX to tell the caller to use zfs_fix_auto_resv(). - * 'auto' is only allowed on volumes. - */ - if (isauto) { - switch (prop) { - case ZFS_PROP_REFRESERVATION: - if ((type & ZFS_TYPE_VOLUME) == 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "'%s=auto' only allowed on " - "volumes"), nvpair_name(elem)); - goto error; - } - *ivalp = UINT64_MAX; - break; - case ZPOOL_PROP_DEDUP_TABLE_QUOTA: - ASSERT(type & ZFS_TYPE_POOL); - *ivalp = UINT64_MAX; - break; - default: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "'auto' is invalid value for '%s'"), - nvpair_name(elem)); - goto error; - } - } - - break; - - case PROP_TYPE_INDEX: - if (datatype != DATA_TYPE_STRING) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "'%s' must be a string"), nvpair_name(elem)); - goto error; - } - - (void) nvpair_value_string(elem, &value); - - if (zprop_string_to_index(prop, value, ivalp, type) != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "'%s' must be one of '%s'"), propname, - zprop_values(prop, type)); - goto error; - } - break; - - default: - abort(); - } - - /* - * Add the result to our return set of properties. - */ - if (*svalp != NULL) { - if (nvlist_add_string(ret, propname, *svalp) != 0) { - (void) no_memory(hdl); - return (-1); - } - } else { - if (nvlist_add_uint64(ret, propname, *ivalp) != 0) { - (void) no_memory(hdl); - return (-1); - } - } - - return (0); -error: - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - return (-1); -} - -static int -addlist(libzfs_handle_t *hdl, const char *propname, zprop_list_t **listp, - zfs_type_t type) -{ - int prop = zprop_name_to_prop(propname, type); - if (prop != ZPROP_INVAL && !zprop_valid_for_type(prop, type, B_FALSE)) - prop = ZPROP_INVAL; - - /* - * Return failure if no property table entry was found and this isn't - * a user-defined property. - */ - if (prop == ZPROP_USERPROP && ((type == ZFS_TYPE_POOL && - !zfs_prop_user(propname) && - !zpool_prop_feature(propname) && - !zpool_prop_unsupported(propname)) || - ((type == ZFS_TYPE_DATASET) && !zfs_prop_user(propname) && - !zfs_prop_userquota(propname) && !zfs_prop_written(propname)) || - ((type == ZFS_TYPE_VDEV) && !vdev_prop_user(propname)))) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "invalid property '%s'"), propname); - return (zfs_error(hdl, EZFS_BADPROP, - dgettext(TEXT_DOMAIN, "bad property list"))); - } - - zprop_list_t *entry = zfs_alloc(hdl, sizeof (*entry)); - - entry->pl_prop = prop; - if (prop == ZPROP_USERPROP) { - entry->pl_user_prop = zfs_strdup(hdl, propname); - entry->pl_width = strlen(propname); - } else { - entry->pl_width = zprop_width(prop, &entry->pl_fixed, - type); - } - - *listp = entry; - - return (0); -} - -/* - * Given a comma-separated list of properties, construct a property list - * containing both user-defined and native properties. This function will - * return a NULL list if 'all' is specified, which can later be expanded - * by zprop_expand_list(). - */ -int -zprop_get_list(libzfs_handle_t *hdl, char *props, zprop_list_t **listp, - zfs_type_t type) -{ - *listp = NULL; - - /* - * If 'all' is specified, return a NULL list. - */ - if (strcmp(props, "all") == 0) - return (0); - - /* - * If no props were specified, return an error. - */ - if (props[0] == '\0') { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "no properties specified")); - return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN, - "bad property list"))); - } - - for (char *p; (p = strsep(&props, ",")); ) - if (strcmp(p, "space") == 0) { - static const char *const spaceprops[] = { - "name", "avail", "used", "usedbysnapshots", - "usedbydataset", "usedbyrefreservation", - "usedbychildren" - }; - - for (int i = 0; i < ARRAY_SIZE(spaceprops); i++) { - if (addlist(hdl, spaceprops[i], listp, type)) - return (-1); - listp = &(*listp)->pl_next; - } - } else { - if (addlist(hdl, p, listp, type)) - return (-1); - listp = &(*listp)->pl_next; - } - - return (0); -} - -void -zprop_free_list(zprop_list_t *pl) -{ - zprop_list_t *next; - - while (pl != NULL) { - next = pl->pl_next; - free(pl->pl_user_prop); - free(pl); - pl = next; - } -} - -typedef struct expand_data { - zprop_list_t **last; - libzfs_handle_t *hdl; - zfs_type_t type; -} expand_data_t; - -static int -zprop_expand_list_cb(int prop, void *cb) -{ - zprop_list_t *entry; - expand_data_t *edp = cb; - - entry = zfs_alloc(edp->hdl, sizeof (zprop_list_t)); - - entry->pl_prop = prop; - entry->pl_width = zprop_width(prop, &entry->pl_fixed, edp->type); - entry->pl_all = B_TRUE; - - *(edp->last) = entry; - edp->last = &entry->pl_next; - - return (ZPROP_CONT); -} - -int -zprop_expand_list(libzfs_handle_t *hdl, zprop_list_t **plp, zfs_type_t type) -{ - zprop_list_t *entry; - zprop_list_t **last; - expand_data_t exp; - - if (*plp == NULL) { - /* - * If this is the very first time we've been called for an 'all' - * specification, expand the list to include all native - * properties. - */ - last = plp; - - exp.last = last; - exp.hdl = hdl; - exp.type = type; - - if (zprop_iter_common(zprop_expand_list_cb, &exp, B_FALSE, - B_FALSE, type) == ZPROP_INVAL) - return (-1); - - /* - * Add 'name' to the beginning of the list, which is handled - * specially. - */ - entry = zfs_alloc(hdl, sizeof (zprop_list_t)); - entry->pl_prop = ((type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME : - ((type == ZFS_TYPE_VDEV) ? VDEV_PROP_NAME : ZFS_PROP_NAME)); - entry->pl_width = zprop_width(entry->pl_prop, - &entry->pl_fixed, type); - entry->pl_all = B_TRUE; - entry->pl_next = *plp; - *plp = entry; - } - return (0); -} - -int -zprop_iter(zprop_func func, void *cb, boolean_t show_all, boolean_t ordered, - zfs_type_t type) -{ - return (zprop_iter_common(func, cb, show_all, ordered, type)); -} - -const char * -zfs_version_userland(void) -{ - return (ZFS_META_ALIAS); -} - -/* - * Prints both zfs userland and kernel versions - * Returns 0 on success, and -1 on error - */ -int -zfs_version_print(void) -{ - (void) puts(ZFS_META_ALIAS); - - char *kver = zfs_version_kernel(); - if (kver == NULL) { - fprintf(stderr, "zfs_version_kernel() failed: %s\n", - zfs_strerror(errno)); - return (-1); - } - - (void) printf("zfs-kmod-%s\n", kver); - free(kver); - return (0); -} - -/* - * Returns an nvlist with both zfs userland and kernel versions. - * Returns NULL on error. - */ -nvlist_t * -zfs_version_nvlist(void) -{ - nvlist_t *nvl; - char kmod_ver[64]; - if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) - return (NULL); - if (nvlist_add_string(nvl, "userland", ZFS_META_ALIAS) != 0) - goto err; - char *kver = zfs_version_kernel(); - if (kver == NULL) { - fprintf(stderr, "zfs_version_kernel() failed: %s\n", - zfs_strerror(errno)); - goto err; - } - (void) snprintf(kmod_ver, 64, "zfs-kmod-%s", kver); - if (nvlist_add_string(nvl, "kernel", kmod_ver) != 0) - goto err; - return (nvl); -err: - nvlist_free(nvl); - return (NULL); -} - -/* - * Return 1 if the user requested ANSI color output, and our terminal supports - * it. Return 0 for no color. - */ -int -use_color(void) -{ - static int use_color = -1; - char *term; - - /* - * Optimization: - * - * For each zpool invocation, we do a single check to see if we should - * be using color or not, and cache that value for the lifetime of the - * the zpool command. That makes it cheap to call use_color() when - * we're printing with color. We assume that the settings are not going - * to change during the invocation of a zpool command (the user isn't - * going to change the ZFS_COLOR value while zpool is running, for - * example). - */ - if (use_color != -1) { - /* - * We've already figured out if we should be using color or - * not. Return the cached value. - */ - return (use_color); - } - - term = getenv("TERM"); - /* - * The user sets the ZFS_COLOR env var set to enable zpool ANSI color - * output. However if NO_COLOR is set (https://no-color.org/) then - * don't use it. Also, don't use color if terminal doesn't support - * it. - */ - if (libzfs_envvar_is_set("ZFS_COLOR") && - !libzfs_envvar_is_set("NO_COLOR") && - isatty(STDOUT_FILENO) && term && strcmp("dumb", term) != 0 && - strcmp("unknown", term) != 0) { - /* Color supported */ - use_color = 1; - } else { - use_color = 0; - } - - return (use_color); -} - -/* - * The functions color_start() and color_end() are used for when you want - * to colorize a block of text. - * - * For example: - * color_start(ANSI_RED) - * printf("hello"); - * printf("world"); - * color_end(); - */ -void -color_start(const char *color) -{ - if (color && use_color()) { - fputs(color, stdout); - fflush(stdout); - } -} - -void -color_end(void) -{ - if (use_color()) { - fputs(ANSI_RESET, stdout); - fflush(stdout); - } - -} - -/* - * printf() with a color. If color is NULL, then do a normal printf. - */ -int -printf_color(const char *color, const char *format, ...) -{ - va_list aptr; - int rc; - - if (color) - color_start(color); - - va_start(aptr, format); - rc = vprintf(format, aptr); - va_end(aptr); - - if (color) - color_end(); - - return (rc); -} - -/* PATH + 5 env vars + a NULL entry = 7 */ -#define ZPOOL_VDEV_SCRIPT_ENV_COUNT 7 - -/* - * There's a few places where ZFS will call external scripts (like the script - * in zpool.d/ and `zfs_prepare_disk`). These scripts are called with a - * reduced $PATH, and some vdev specific environment vars set. This function - * will allocate an populate the environment variable array that is passed to - * these scripts. The user must free the arrays with zpool_vdev_free_env() when - * they are done. - * - * The following env vars will be set (but value could be blank): - * - * POOL_NAME - * VDEV_PATH - * VDEV_UPATH - * VDEV_ENC_SYSFS_PATH - * - * In addition, you can set an optional environment variable named 'opt_key' - * to 'opt_val' if you want. - * - * Returns allocated env[] array on success, NULL otherwise. - */ -char ** -zpool_vdev_script_alloc_env(const char *pool_name, - const char *vdev_path, const char *vdev_upath, - const char *vdev_enc_sysfs_path, const char *opt_key, const char *opt_val) -{ - char **env = NULL; - int rc; - - env = calloc(ZPOOL_VDEV_SCRIPT_ENV_COUNT, sizeof (*env)); - if (!env) - return (NULL); - - env[0] = strdup("PATH=/bin:/sbin:/usr/bin:/usr/sbin"); - if (!env[0]) - goto error; - - /* Setup our custom environment variables */ - rc = asprintf(&env[1], "POOL_NAME=%s", pool_name ? pool_name : ""); - if (rc == -1) { - env[1] = NULL; - goto error; - } - - rc = asprintf(&env[2], "VDEV_PATH=%s", vdev_path ? vdev_path : ""); - if (rc == -1) { - env[2] = NULL; - goto error; - } - - rc = asprintf(&env[3], "VDEV_UPATH=%s", vdev_upath ? vdev_upath : ""); - if (rc == -1) { - env[3] = NULL; - goto error; - } - - rc = asprintf(&env[4], "VDEV_ENC_SYSFS_PATH=%s", - vdev_enc_sysfs_path ? vdev_enc_sysfs_path : ""); - if (rc == -1) { - env[4] = NULL; - goto error; - } - - if (opt_key != NULL) { - rc = asprintf(&env[5], "%s=%s", opt_key, - opt_val ? opt_val : ""); - if (rc == -1) { - env[5] = NULL; - goto error; - } - } - - return (env); - -error: - for (int i = 0; i < ZPOOL_VDEV_SCRIPT_ENV_COUNT; i++) - free(env[i]); - - free(env); - - return (NULL); -} - -/* - * Free the env[] array that was allocated by zpool_vdev_script_alloc_env(). - */ -void -zpool_vdev_script_free_env(char **env) -{ - for (int i = 0; i < ZPOOL_VDEV_SCRIPT_ENV_COUNT; i++) - free(env[i]); - - free(env); -} - -/* - * Prepare a disk by (optionally) running a program before labeling the disk. - * This can be useful for installing disk firmware or doing some pre-flight - * checks on the disk before it becomes part of the pool. The program run is - * located at ZFSEXECDIR/zfs_prepare_disk - * (E.x: /usr/local/libexec/zfs/zfs_prepare_disk). - * - * Return 0 on success, non-zero on failure. - */ -int -zpool_prepare_disk(zpool_handle_t *zhp, nvlist_t *vdev_nv, - const char *prepare_str, char **lines[], int *lines_cnt) -{ - const char *script_path = ZFSEXECDIR "/zfs_prepare_disk"; - const char *pool_name; - int rc = 0; - - /* Path to script and a NULL entry */ - char *argv[2] = {(char *)script_path}; - char **env = NULL; - const char *path = NULL, *enc_sysfs_path = NULL; - char *upath; - *lines_cnt = 0; - - if (access(script_path, X_OK) != 0) { - /* No script, nothing to do */ - return (0); - } - - (void) nvlist_lookup_string(vdev_nv, ZPOOL_CONFIG_PATH, &path); - (void) nvlist_lookup_string(vdev_nv, ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH, - &enc_sysfs_path); - - upath = zfs_get_underlying_path(path); - pool_name = zhp ? zpool_get_name(zhp) : NULL; - - env = zpool_vdev_script_alloc_env(pool_name, path, upath, - enc_sysfs_path, "VDEV_PREPARE", prepare_str); - - free(upath); - - if (env == NULL) { - return (ENOMEM); - } - - rc = libzfs_run_process_get_stdout(script_path, argv, env, lines, - lines_cnt); - - zpool_vdev_script_free_env(env); - - return (rc); -} - -/* - * Optionally run a script and then label a disk. The script can be used to - * prepare a disk for inclusion into the pool. For example, it might update - * the disk's firmware or check its health. - * - * The 'name' provided is the short name, stripped of any leading - * /dev path, and is passed to zpool_label_disk. vdev_nv is the nvlist for - * the vdev. prepare_str is a string that gets passed as the VDEV_PREPARE - * env variable to the script. - * - * The following env vars are passed to the script: - * - * POOL_NAME: The pool name (blank during zpool create) - * VDEV_PREPARE: Reason why the disk is being prepared for inclusion: - * "create", "add", "replace", or "autoreplace" - * VDEV_PATH: Path to the disk - * VDEV_UPATH: One of the 'underlying paths' to the disk. This is - * useful for DM devices. - * VDEV_ENC_SYSFS_PATH: Path to the disk's enclosure sysfs path, if available. - * - * Note, some of these values can be blank. - * - * Return 0 on success, non-zero otherwise. - */ -int -zpool_prepare_and_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, - const char *name, nvlist_t *vdev_nv, const char *prepare_str, - char **lines[], int *lines_cnt) -{ - int rc; - char vdev_path[MAXPATHLEN]; - (void) snprintf(vdev_path, sizeof (vdev_path), "%s/%s", DISK_ROOT, - name); - - /* zhp will be NULL when creating a pool */ - rc = zpool_prepare_disk(zhp, vdev_nv, prepare_str, lines, lines_cnt); - if (rc != 0) - return (rc); - - rc = zpool_label_disk(hdl, zhp, name); - return (rc); -} diff --git a/lib/libzfs/os/freebsd/libzfs_compat.c b/lib/libzfs/os/freebsd/libzfs_compat.c deleted file mode 100644 index e772e3e12262..000000000000 --- a/lib/libzfs/os/freebsd/libzfs_compat.c +++ /dev/null @@ -1,369 +0,0 @@ -// SPDX-License-Identifier: CDDL-1.0 -/* - * 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 - */ - -/* - * Copyright (c) 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved. - */ -#include "../../libzfs_impl.h" -#include <libzfs.h> -#include <libzutil.h> -#include <sys/sysctl.h> -#include <libintl.h> -#include <sys/linker.h> -#include <sys/module.h> -#include <sys/stat.h> -#include <sys/param.h> - -#ifdef IN_BASE -#define ZFS_KMOD "zfs" -#else -#define ZFS_KMOD "openzfs" -#endif - -#ifndef HAVE_EXECVPE -/* FreeBSD prior to 15 lacks execvpe */ -static int -execvPe(const char *name, const char *path, char * const *argv, - char * const *envp) -{ - const char **memp; - size_t cnt, lp, ln; - int eacces, save_errno; - char buf[MAXPATHLEN]; - const char *bp, *np, *op, *p; - struct stat sb; - - eacces = 0; - - /* If it's an absolute or relative path name, it's easy. */ - if (strchr(name, '/')) { - bp = name; - op = NULL; - goto retry; - } - bp = buf; - - /* If it's an empty path name, fail in the usual POSIX way. */ - if (*name == '\0') { - errno = ENOENT; - return (-1); - } - - op = path; - ln = strlen(name); - while (op != NULL) { - np = strchrnul(op, ':'); - - /* - * It's a SHELL path -- double, leading and trailing colons - * mean the current directory. - */ - if (np == op) { - /* Empty component. */ - p = "."; - lp = 1; - } else { - /* Non-empty component. */ - p = op; - lp = np - op; - } - - /* Advance to the next component or terminate after this. */ - if (*np == '\0') - op = NULL; - else - op = np + 1; - - /* - * If the path is too long complain. This is a possible - * security issue; given a way to make the path too long - * the user may execute the wrong program. - */ - if (lp + ln + 2 > sizeof (buf)) { - (void) write(STDERR_FILENO, "execvP: ", 8); - (void) write(STDERR_FILENO, p, lp); - (void) write(STDERR_FILENO, ": path too long\n", - 16); - continue; - } - memcpy(buf, p, lp); - buf[lp] = '/'; - memcpy(buf + lp + 1, name, ln); - buf[lp + ln + 1] = '\0'; - -retry: (void) execve(bp, argv, envp); - switch (errno) { - case E2BIG: - goto done; - case ELOOP: - case ENAMETOOLONG: - case ENOENT: - break; - case ENOEXEC: - for (cnt = 0; argv[cnt]; ++cnt) - ; - - /* - * cnt may be 0 above; always allocate at least - * 3 entries so that we can at least fit "sh", bp, and - * the NULL terminator. We can rely on cnt to take into - * account the NULL terminator in all other scenarios, - * as we drop argv[0]. - */ - memp = alloca(MAX(3, cnt + 2) * sizeof (char *)); - if (memp == NULL) { - /* errno = ENOMEM; XXX override ENOEXEC? */ - goto done; - } - if (cnt > 0) { - memp[0] = argv[0]; - memp[1] = bp; - memcpy(memp + 2, argv + 1, - cnt * sizeof (char *)); - } else { - memp[0] = "sh"; - memp[1] = bp; - memp[2] = NULL; - } - (void) execve(_PATH_BSHELL, - __DECONST(char **, memp), envp); - goto done; - case ENOMEM: - goto done; - case ENOTDIR: - break; - case ETXTBSY: - /* - * We used to retry here, but sh(1) doesn't. - */ - goto done; - default: - /* - * EACCES may be for an inaccessible directory or - * a non-executable file. Call stat() to decide - * which. This also handles ambiguities for EFAULT - * and EIO, and undocumented errors like ESTALE. - * We hope that the race for a stat() is unimportant. - */ - save_errno = errno; - if (stat(bp, &sb) != 0) - break; - if (save_errno == EACCES) { - eacces = 1; - continue; - } - errno = save_errno; - goto done; - } - } - if (eacces) - errno = EACCES; - else - errno = ENOENT; -done: - return (-1); -} - -int -execvpe(const char *name, char * const argv[], char * const envp[]) -{ - const char *path; - - /* Get the path we're searching. */ - if ((path = getenv("PATH")) == NULL) - path = _PATH_DEFPATH; - - return (execvPe(name, path, argv, envp)); -} -#endif /* !HAVE_EXECVPE */ - -static __thread char errbuf[ERRBUFLEN]; - -const char * -libzfs_error_init(int error) -{ - char *msg = errbuf; - size_t msglen = sizeof (errbuf); - - if (modfind("zfs") < 0) { - size_t len = snprintf(msg, msglen, dgettext(TEXT_DOMAIN, - "Failed to load %s module: "), ZFS_KMOD); - if (len >= msglen) - len = msglen - 1; - msg += len; - msglen -= len; - } - - (void) snprintf(msg, msglen, "%s", zfs_strerror(error)); - - return (errbuf); -} - -/* - * Verify the required ZFS_DEV device is available and optionally attempt - * to load the ZFS modules. Under normal circumstances the modules - * should already have been loaded by some external mechanism. - */ -int -libzfs_load_module(void) -{ - /* - * XXX: kldfind(ZFS_KMOD) would be nice here, but we retain - * modfind("zfs") so out-of-base openzfs userland works with the - * in-base module. - */ - if (modfind("zfs") < 0) { - /* Not present in kernel, try loading it. */ - if (kldload(ZFS_KMOD) < 0 && errno != EEXIST) { - return (errno); - } - } - return (0); -} - -int -zpool_relabel_disk(libzfs_handle_t *hdl, const char *path, const char *msg) -{ - (void) hdl, (void) path, (void) msg; - return (0); -} - -int -zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, const char *name) -{ - (void) hdl, (void) zhp, (void) name; - return (0); -} - -int -find_shares_object(differ_info_t *di) -{ - (void) di; - return (0); -} - -int -zfs_destroy_snaps_nvl_os(libzfs_handle_t *hdl, nvlist_t *snaps) -{ - (void) hdl, (void) snaps; - return (0); -} - -/* - * Attach/detach the given filesystem to/from the given jail. - */ -int -zfs_jail(zfs_handle_t *zhp, int jailid, int attach) -{ - libzfs_handle_t *hdl = zhp->zfs_hdl; - zfs_cmd_t zc = {"\0"}; - unsigned long cmd; - int ret; - - if (attach) { - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot jail '%s'"), zhp->zfs_name); - } else { - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot unjail '%s'"), zhp->zfs_name); - } - - switch (zhp->zfs_type) { - case ZFS_TYPE_VOLUME: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "volumes can not be jailed")); - return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); - case ZFS_TYPE_SNAPSHOT: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "snapshots can not be jailed")); - return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); - case ZFS_TYPE_BOOKMARK: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "bookmarks can not be jailed")); - return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); - case ZFS_TYPE_VDEV: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "vdevs can not be jailed")); - return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); - case ZFS_TYPE_INVALID: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "invalid zfs_type_t: ZFS_TYPE_INVALID")); - return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); - case ZFS_TYPE_POOL: - case ZFS_TYPE_FILESYSTEM: - /* OK */ - ; - } - assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM); - - (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); - zc.zc_objset_type = DMU_OST_ZFS; - zc.zc_zoneid = jailid; - - cmd = attach ? ZFS_IOC_JAIL : ZFS_IOC_UNJAIL; - if ((ret = zfs_ioctl(hdl, cmd, &zc)) != 0) - zfs_standard_error(hdl, errno, errbuf); - - return (ret); -} - -/* - * Set loader options for next boot. - */ -int -zpool_nextboot(libzfs_handle_t *hdl, uint64_t pool_guid, uint64_t dev_guid, - const char *command) -{ - zfs_cmd_t zc = {"\0"}; - nvlist_t *args; - - args = fnvlist_alloc(); - fnvlist_add_uint64(args, ZPOOL_CONFIG_POOL_GUID, pool_guid); - fnvlist_add_uint64(args, ZPOOL_CONFIG_GUID, dev_guid); - fnvlist_add_string(args, "command", command); - zcmd_write_src_nvlist(hdl, &zc, args); - int error = zfs_ioctl(hdl, ZFS_IOC_NEXTBOOT, &zc); - zcmd_free_nvlists(&zc); - nvlist_free(args); - return (error); -} - -/* - * Return allocated loaded module version, or NULL on error (with errno set) - */ -char * -zfs_version_kernel(void) -{ - size_t l; - if (sysctlbyname("vfs.zfs.version.module", - NULL, &l, NULL, 0) == -1) - return (NULL); - char *version = malloc(l); - if (version == NULL) - return (NULL); - if (sysctlbyname("vfs.zfs.version.module", - version, &l, NULL, 0) == -1) { - free(version); - return (NULL); - } - return (version); -} diff --git a/lib/libzfs/os/freebsd/libzfs_zmount.c b/lib/libzfs/os/freebsd/libzfs_zmount.c deleted file mode 100644 index bc7d68b17eb1..000000000000 --- a/lib/libzfs/os/freebsd/libzfs_zmount.c +++ /dev/null @@ -1,137 +0,0 @@ -// SPDX-License-Identifier: BSD-2-Clause -/* - * Copyright (c) 2006 Pawel Jakub Dawidek <pjd@FreeBSD.org> - * All rights reserved. - * - * 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 AUTHORS 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 AUTHORS 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. - */ - -/* - * This file implements Solaris compatible zmount() function. - */ - -#include <sys/param.h> -#include <sys/mount.h> -#include <sys/uio.h> -#include <sys/mntent.h> -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/mnttab.h> -#include <sys/errno.h> -#include <libzfs.h> - -#include "../../libzfs_impl.h" - -static void -build_iovec(struct iovec **iov, int *iovlen, const char *name, void *val, - size_t len) -{ - int i; - - if (*iovlen < 0) - return; - i = *iovlen; - *iov = realloc(*iov, sizeof (**iov) * (i + 2)); - if (*iov == NULL) { - *iovlen = -1; - return; - } - (*iov)[i].iov_base = strdup(name); - (*iov)[i].iov_len = strlen(name) + 1; - i++; - (*iov)[i].iov_base = val; - if (len == (size_t)-1) { - if (val != NULL) - len = strlen(val) + 1; - else - len = 0; - } - (*iov)[i].iov_len = (int)len; - *iovlen = ++i; -} - -int -do_mount(zfs_handle_t *zhp, const char *mntpt, const char *opts, int flags) -{ - struct iovec *iov; - char *optstr, *p, *tofree; - int iovlen, rv; - const char *spec = zfs_get_name(zhp); - - assert(spec != NULL); - assert(mntpt != NULL); - assert(opts != NULL); - - tofree = optstr = strdup(opts); - assert(optstr != NULL); - - iov = NULL; - iovlen = 0; - if (strstr(optstr, MNTOPT_REMOUNT) != NULL) - build_iovec(&iov, &iovlen, "update", NULL, 0); - if (flags & MS_RDONLY) - build_iovec(&iov, &iovlen, "ro", NULL, 0); - build_iovec(&iov, &iovlen, "fstype", __DECONST(char *, MNTTYPE_ZFS), - (size_t)-1); - build_iovec(&iov, &iovlen, "fspath", __DECONST(char *, mntpt), - (size_t)-1); - build_iovec(&iov, &iovlen, "from", __DECONST(char *, spec), (size_t)-1); - while ((p = strsep(&optstr, ",/")) != NULL) - build_iovec(&iov, &iovlen, p, NULL, (size_t)-1); - rv = nmount(iov, iovlen, 0); - free(tofree); - if (rv < 0) - return (errno); - return (rv); - -} - -int -do_unmount(zfs_handle_t *zhp, const char *mntpt, int flags) -{ - (void) zhp; - if (unmount(mntpt, flags) < 0) - return (errno); - return (0); -} - -int -zfs_mount_delegation_check(void) -{ - return (0); -} - -/* Called from the tail end of zpool_disable_datasets() */ -void -zpool_disable_datasets_os(zpool_handle_t *zhp, boolean_t force) -{ - (void) zhp, (void) force; -} - -/* Called from the tail end of zfs_unmount() */ -void -zpool_disable_volume_os(const char *name) -{ - (void) name; -} diff --git a/lib/libzfs/os/linux/libzfs_mount_os.c b/lib/libzfs/os/linux/libzfs_mount_os.c deleted file mode 100644 index 585d22d9e5b3..000000000000 --- a/lib/libzfs/os/linux/libzfs_mount_os.c +++ /dev/null @@ -1,431 +0,0 @@ -// SPDX-License-Identifier: CDDL-1.0 -/* - * 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 - */ - -/* - * Copyright 2015 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2014, 2021 by Delphix. All rights reserved. - * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com> - * Copyright 2017 RackTop Systems. - * Copyright (c) 2018 Datto Inc. - * Copyright 2018 OmniOS Community Edition (OmniOSce) Association. - */ - -#include <dirent.h> -#include <dlfcn.h> -#include <errno.h> -#include <fcntl.h> -#include <libgen.h> -#include <libintl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <zone.h> -#include <sys/mntent.h> -#include <sys/mount.h> -#include <sys/stat.h> -#include <sys/vfs.h> -#include <sys/dsl_crypt.h> -#include <libzfs.h> - -#include "../../libzfs_impl.h" -#include <thread_pool.h> - -#define ZS_COMMENT 0x00000000 /* comment */ -#define ZS_ZFSUTIL 0x00000001 /* caller is zfs(8) */ - -typedef struct option_map { - const char *name; - unsigned long mntmask; - unsigned long zfsmask; -} option_map_t; - -static const option_map_t option_map[] = { - /* Canonicalized filesystem independent options from mount(8) */ - { MNTOPT_NOAUTO, MS_COMMENT, ZS_COMMENT }, - { MNTOPT_DEFAULTS, MS_COMMENT, ZS_COMMENT }, - { MNTOPT_NODEVICES, MS_NODEV, ZS_COMMENT }, - { MNTOPT_DEVICES, MS_COMMENT, ZS_COMMENT }, - { MNTOPT_DIRSYNC, MS_DIRSYNC, ZS_COMMENT }, - { MNTOPT_NOEXEC, MS_NOEXEC, ZS_COMMENT }, - { MNTOPT_EXEC, MS_COMMENT, ZS_COMMENT }, - { MNTOPT_GROUP, MS_GROUP, ZS_COMMENT }, - { MNTOPT_NETDEV, MS_COMMENT, ZS_COMMENT }, - { MNTOPT_NOFAIL, MS_COMMENT, ZS_COMMENT }, - { MNTOPT_NOSUID, MS_NOSUID, ZS_COMMENT }, - { MNTOPT_SUID, MS_COMMENT, ZS_COMMENT }, - { MNTOPT_OWNER, MS_OWNER, ZS_COMMENT }, - { MNTOPT_REMOUNT, MS_REMOUNT, ZS_COMMENT }, - { MNTOPT_RO, MS_RDONLY, ZS_COMMENT }, - { MNTOPT_RW, MS_COMMENT, ZS_COMMENT }, - { MNTOPT_SYNC, MS_SYNCHRONOUS, ZS_COMMENT }, - { MNTOPT_USER, MS_USERS, ZS_COMMENT }, - { MNTOPT_USERS, MS_USERS, ZS_COMMENT }, - /* acl flags passed with util-linux-2.24 mount command */ - { MNTOPT_ACL, MS_POSIXACL, ZS_COMMENT }, - { MNTOPT_NOACL, MS_COMMENT, ZS_COMMENT }, - { MNTOPT_POSIXACL, MS_POSIXACL, ZS_COMMENT }, - /* - * Case sensitive options are just listed here to silently - * ignore the error if passed with zfs mount command. - */ - { MNTOPT_CASESENSITIVE, MS_COMMENT, ZS_COMMENT }, - { MNTOPT_CASEINSENSITIVE, MS_COMMENT, ZS_COMMENT }, - { MNTOPT_CASEMIXED, MS_COMMENT, ZS_COMMENT }, -#ifdef MS_NOATIME - { MNTOPT_NOATIME, MS_NOATIME, ZS_COMMENT }, - { MNTOPT_ATIME, MS_COMMENT, ZS_COMMENT }, -#endif -#ifdef MS_NODIRATIME - { MNTOPT_NODIRATIME, MS_NODIRATIME, ZS_COMMENT }, - { MNTOPT_DIRATIME, MS_COMMENT, ZS_COMMENT }, -#endif -#ifdef MS_RELATIME - { MNTOPT_RELATIME, MS_RELATIME, ZS_COMMENT }, - { MNTOPT_NORELATIME, MS_COMMENT, ZS_COMMENT }, -#endif -#ifdef MS_STRICTATIME - { MNTOPT_STRICTATIME, MS_STRICTATIME, ZS_COMMENT }, - { MNTOPT_NOSTRICTATIME, MS_COMMENT, ZS_COMMENT }, -#endif -#ifdef MS_LAZYTIME - { MNTOPT_LAZYTIME, MS_LAZYTIME, ZS_COMMENT }, -#endif - { MNTOPT_CONTEXT, MS_COMMENT, ZS_COMMENT }, - { MNTOPT_FSCONTEXT, MS_COMMENT, ZS_COMMENT }, - { MNTOPT_DEFCONTEXT, MS_COMMENT, ZS_COMMENT }, - { MNTOPT_ROOTCONTEXT, MS_COMMENT, ZS_COMMENT }, -#ifdef MS_I_VERSION - { MNTOPT_IVERSION, MS_I_VERSION, ZS_COMMENT }, -#endif -#ifdef MS_MANDLOCK - { MNTOPT_NBMAND, MS_MANDLOCK, ZS_COMMENT }, - { MNTOPT_NONBMAND, MS_COMMENT, ZS_COMMENT }, -#endif - /* Valid options not found in mount(8) */ - { MNTOPT_BIND, MS_BIND, ZS_COMMENT }, -#ifdef MS_REC - { MNTOPT_RBIND, MS_BIND|MS_REC, ZS_COMMENT }, -#endif - { MNTOPT_COMMENT, MS_COMMENT, ZS_COMMENT }, -#ifdef MS_NOSUB - { MNTOPT_NOSUB, MS_NOSUB, ZS_COMMENT }, -#endif -#ifdef MS_SILENT - { MNTOPT_QUIET, MS_SILENT, ZS_COMMENT }, -#endif - /* Custom zfs options */ - { MNTOPT_XATTR, MS_COMMENT, ZS_COMMENT }, - { MNTOPT_NOXATTR, MS_COMMENT, ZS_COMMENT }, - { MNTOPT_ZFSUTIL, MS_COMMENT, ZS_ZFSUTIL }, - { NULL, 0, 0 } }; - -/* - * Break the mount option in to a name/value pair. The name is - * validated against the option map and mount flags set accordingly. - */ -static int -parse_option(char *mntopt, unsigned long *mntflags, - unsigned long *zfsflags, int sloppy) -{ - const option_map_t *opt; - char *ptr, *name, *value = NULL; - int error = 0; - - name = strdup(mntopt); - if (name == NULL) - return (ENOMEM); - - for (ptr = name; ptr && *ptr; ptr++) { - if (*ptr == '=') { - *ptr = '\0'; - value = ptr+1; - VERIFY3P(value, !=, NULL); - break; - } - } - - for (opt = option_map; opt->name != NULL; opt++) { - if (strncmp(name, opt->name, strlen(name)) == 0) { - *mntflags |= opt->mntmask; - *zfsflags |= opt->zfsmask; - error = 0; - goto out; - } - } - - if (!sloppy) - error = ENOENT; -out: - /* If required further process on the value may be done here */ - free(name); - return (error); -} - -/* - * Translate the mount option string in to MS_* mount flags for the - * kernel vfs. When sloppy is non-zero unknown options will be ignored - * otherwise they are considered fatal are copied in to badopt. - */ -int -zfs_parse_mount_options(const char *mntopts, unsigned long *mntflags, - unsigned long *zfsflags, int sloppy, char *badopt, char *mtabopt) -{ - int error = 0, quote = 0, flag = 0, count = 0; - char *ptr, *opt, *opts; - - opts = strdup(mntopts); - if (opts == NULL) - return (ENOMEM); - - *mntflags = 0; - opt = NULL; - - /* - * Scan through all mount options which must be comma delimited. - * We must be careful to notice regions which are double quoted - * and skip commas in these regions. Each option is then checked - * to determine if it is a known option. - */ - for (ptr = opts; ptr && !flag; ptr++) { - if (opt == NULL) - opt = ptr; - - if (*ptr == '"') - quote = !quote; - - if (quote) - continue; - - if (*ptr == '\0') - flag = 1; - - if ((*ptr == ',') || (*ptr == '\0')) { - *ptr = '\0'; - - error = parse_option(opt, mntflags, zfsflags, sloppy); - if (error) { - strcpy(badopt, opt); - goto out; - - } - - if (!(*mntflags & MS_REMOUNT) && - !(*zfsflags & ZS_ZFSUTIL) && - mtabopt != NULL) { - if (count > 0) - strlcat(mtabopt, ",", MNT_LINE_MAX); - - strlcat(mtabopt, opt, MNT_LINE_MAX); - count++; - } - - opt = NULL; - } - } - -out: - free(opts); - return (error); -} - -static void -append_mntopt(const char *name, const char *val, char *mntopts, - char *mtabopt, boolean_t quote) -{ - char tmp[MNT_LINE_MAX]; - - snprintf(tmp, MNT_LINE_MAX, quote ? ",%s=\"%s\"" : ",%s=%s", name, val); - - if (mntopts) - strlcat(mntopts, tmp, MNT_LINE_MAX); - - if (mtabopt) - strlcat(mtabopt, tmp, MNT_LINE_MAX); -} - -static void -zfs_selinux_setcontext(zfs_handle_t *zhp, zfs_prop_t zpt, const char *name, - char *mntopts, char *mtabopt) -{ - char context[ZFS_MAXPROPLEN]; - - if (zfs_prop_get(zhp, zpt, context, sizeof (context), - NULL, NULL, 0, B_FALSE) == 0) { - if (strcmp(context, "none") != 0) - append_mntopt(name, context, mntopts, mtabopt, B_TRUE); - } -} - -void -zfs_adjust_mount_options(zfs_handle_t *zhp, const char *mntpoint, - char *mntopts, char *mtabopt) -{ - char prop[ZFS_MAXPROPLEN]; - - /* - * Checks to see if the ZFS_PROP_SELINUX_CONTEXT exists - * if it does, create a tmp variable in case it's needed - * checks to see if the selinux context is set to the default - * if it is, allow the setting of the other context properties - * this is needed because the 'context' property overrides others - * if it is not the default, set the 'context' property - */ - if (zfs_prop_get(zhp, ZFS_PROP_SELINUX_CONTEXT, prop, sizeof (prop), - NULL, NULL, 0, B_FALSE) == 0) { - if (strcmp(prop, "none") == 0) { - zfs_selinux_setcontext(zhp, ZFS_PROP_SELINUX_FSCONTEXT, - MNTOPT_FSCONTEXT, mntopts, mtabopt); - zfs_selinux_setcontext(zhp, ZFS_PROP_SELINUX_DEFCONTEXT, - MNTOPT_DEFCONTEXT, mntopts, mtabopt); - zfs_selinux_setcontext(zhp, - ZFS_PROP_SELINUX_ROOTCONTEXT, MNTOPT_ROOTCONTEXT, - mntopts, mtabopt); - } else { - append_mntopt(MNTOPT_CONTEXT, prop, - mntopts, mtabopt, B_TRUE); - } - } - - /* A hint used to determine an auto-mounted snapshot mount point */ - append_mntopt(MNTOPT_MNTPOINT, mntpoint, mntopts, NULL, B_FALSE); -} - -/* - * By default the filesystem by preparing the mount options (i.e. parsing - * some flags from the "opts" parameter into the "flags" parameter) and then - * directly calling the system call mount(2). We don't need the mount utility - * or update /etc/mtab, because this is a symlink on all modern systems. - * - * If the environment variable ZFS_MOUNT_HELPER is set, we fall back to the - * previous behavior: - * The filesystem is mounted by invoking the system mount utility rather - * than by the system call mount(2). This ensures that the /etc/mtab - * file is correctly locked for the update. Performing our own locking - * and /etc/mtab update requires making an unsafe assumption about how - * the mount utility performs its locking. Unfortunately, this also means - * in the case of a mount failure we do not have the exact errno. We must - * make due with return value from the mount process. - */ -int -do_mount(zfs_handle_t *zhp, const char *mntpt, const char *opts, int flags) -{ - const char *src = zfs_get_name(zhp); - int error = 0; - - if (!libzfs_envvar_is_set("ZFS_MOUNT_HELPER")) { - char badopt[MNT_LINE_MAX] = {0}; - unsigned long mntflags = flags, zfsflags = 0; - char myopts[MNT_LINE_MAX] = {0}; - - if (zfs_parse_mount_options(opts, &mntflags, - &zfsflags, 0, badopt, NULL)) { - return (EINVAL); - } - strlcat(myopts, opts, MNT_LINE_MAX); - zfs_adjust_mount_options(zhp, mntpt, myopts, NULL); - if (mount(src, mntpt, MNTTYPE_ZFS, mntflags, myopts)) { - return (errno); - } - } else { - char *argv[9] = { - (char *)"/bin/mount", - (char *)"--no-canonicalize", - (char *)"-t", (char *)MNTTYPE_ZFS, - (char *)"-o", (char *)opts, - (char *)src, - (char *)mntpt, - (char *)NULL }; - - /* Return only the most critical mount error */ - error = libzfs_run_process(argv[0], argv, - STDOUT_VERBOSE|STDERR_VERBOSE); - if (error) { - if (error & MOUNT_FILEIO) { - error = EIO; - } else if (error & MOUNT_USER) { - error = EINTR; - } else if (error & MOUNT_SOFTWARE) { - error = EPIPE; - } else if (error & MOUNT_BUSY) { - error = EBUSY; - } else if (error & MOUNT_SYSERR) { - error = EAGAIN; - } else if (error & MOUNT_USAGE) { - error = EINVAL; - } else - error = ENXIO; /* Generic error */ - } - } - - return (error); -} - -int -do_unmount(zfs_handle_t *zhp, const char *mntpt, int flags) -{ - (void) zhp; - - if (!libzfs_envvar_is_set("ZFS_MOUNT_HELPER")) { - int rv = umount2(mntpt, flags); - - return (rv < 0 ? errno : 0); - } - - char *argv[7] = { - (char *)"/bin/umount", - (char *)"-t", (char *)MNTTYPE_ZFS, - NULL, NULL, NULL, NULL }; - int rc, count = 3; - - if (flags & MS_FORCE) - argv[count++] = (char *)"-f"; - - if (flags & MS_DETACH) - argv[count++] = (char *)"-l"; - - argv[count] = (char *)mntpt; - rc = libzfs_run_process(argv[0], argv, STDOUT_VERBOSE|STDERR_VERBOSE); - - return (rc ? EINVAL : 0); -} - -int -zfs_mount_delegation_check(void) -{ - return ((geteuid() != 0) ? EACCES : 0); -} - -/* Called from the tail end of zpool_disable_datasets() */ -void -zpool_disable_datasets_os(zpool_handle_t *zhp, boolean_t force) -{ - (void) zhp, (void) force; -} - -/* Called from the tail end of zfs_unmount() */ -void -zpool_disable_volume_os(const char *name) -{ - (void) name; -} diff --git a/lib/libzfs/os/linux/libzfs_pool_os.c b/lib/libzfs/os/linux/libzfs_pool_os.c deleted file mode 100644 index aef169a3f880..000000000000 --- a/lib/libzfs/os/linux/libzfs_pool_os.c +++ /dev/null @@ -1,352 +0,0 @@ -// SPDX-License-Identifier: CDDL-1.0 -/* - * 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 - */ - -/* - * Copyright 2015 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2018 by Delphix. All rights reserved. - * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com> - * Copyright (c) 2018 Datto Inc. - * Copyright (c) 2017 Open-E, Inc. All Rights Reserved. - * Copyright (c) 2017, Intel Corporation. - * Copyright (c) 2018, loli10K <ezomori.nozomu@gmail.com> - */ - -#include <errno.h> -#include <libintl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <libgen.h> -#include <zone.h> -#include <sys/stat.h> -#include <sys/efi_partition.h> -#include <sys/systeminfo.h> -#include <sys/zfs_ioctl.h> -#include <sys/vdev_disk.h> -#include <dlfcn.h> -#include <libzutil.h> - -#include "zfs_namecheck.h" -#include "zfs_prop.h" -#include "../../libzfs_impl.h" -#include "zfs_comutil.h" -#include "zfeature_common.h" - -/* - * If the device has being dynamically expanded then we need to relabel - * the disk to use the new unallocated space. - */ -int -zpool_relabel_disk(libzfs_handle_t *hdl, const char *path, const char *msg) -{ - int fd, error; - - if ((fd = open(path, O_RDWR|O_DIRECT|O_CLOEXEC)) < 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot " - "relabel '%s': unable to open device: %d"), path, errno); - return (zfs_error(hdl, EZFS_OPENFAILED, msg)); - } - - /* - * It's possible that we might encounter an error if the device - * does not have any unallocated space left. If so, we simply - * ignore that error and continue on. - */ - error = efi_use_whole_disk(fd); - - /* Flush the buffers to disk and invalidate the page cache. */ - (void) fsync(fd); - (void) ioctl(fd, BLKFLSBUF); - - (void) close(fd); - if (error && error != VT_ENOSPC) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot " - "relabel '%s': unable to read disk capacity"), path); - return (zfs_error(hdl, EZFS_NOCAP, msg)); - } - return (0); -} - -/* - * Read the EFI label from the config, if a label does not exist then - * pass back the error to the caller. If the caller has passed a non-NULL - * diskaddr argument then we set it to the starting address of the EFI - * partition. - */ -static int -read_efi_label(nvlist_t *config, diskaddr_t *sb) -{ - const char *path; - int fd; - char diskname[MAXPATHLEN]; - int err = -1; - - if (nvlist_lookup_string(config, ZPOOL_CONFIG_PATH, &path) != 0) - return (err); - - (void) snprintf(diskname, sizeof (diskname), "%s%s", DISK_ROOT, - strrchr(path, '/')); - if ((fd = open(diskname, O_RDONLY|O_DIRECT|O_CLOEXEC)) >= 0) { - struct dk_gpt *vtoc; - - if ((err = efi_alloc_and_read(fd, &vtoc)) >= 0) { - if (sb != NULL) - *sb = vtoc->efi_parts[0].p_start; - efi_free(vtoc); - } - (void) close(fd); - } - return (err); -} - -/* - * determine where a partition starts on a disk in the current - * configuration - */ -static diskaddr_t -find_start_block(nvlist_t *config) -{ - nvlist_t **child; - uint_t c, children; - diskaddr_t sb = MAXOFFSET_T; - uint64_t wholedisk; - - if (nvlist_lookup_nvlist_array(config, - ZPOOL_CONFIG_CHILDREN, &child, &children) != 0) { - if (nvlist_lookup_uint64(config, - ZPOOL_CONFIG_WHOLE_DISK, - &wholedisk) != 0 || !wholedisk) { - return (MAXOFFSET_T); - } - if (read_efi_label(config, &sb) < 0) - sb = MAXOFFSET_T; - return (sb); - } - - for (c = 0; c < children; c++) { - sb = find_start_block(child[c]); - if (sb != MAXOFFSET_T) { - return (sb); - } - } - return (MAXOFFSET_T); -} - -static int -zpool_label_disk_check(char *path) -{ - struct dk_gpt *vtoc; - int fd, err; - - if ((fd = open(path, O_RDONLY|O_DIRECT|O_CLOEXEC)) < 0) - return (errno); - - if ((err = efi_alloc_and_read(fd, &vtoc)) != 0) { - (void) close(fd); - return (err); - } - - if (vtoc->efi_flags & EFI_GPT_PRIMARY_CORRUPT) { - efi_free(vtoc); - (void) close(fd); - return (EIDRM); - } - - efi_free(vtoc); - (void) close(fd); - return (0); -} - -/* - * Generate a unique partition name for the ZFS member. Partitions must - * have unique names to ensure udev will be able to create symlinks under - * /dev/disk/by-partlabel/ for all pool members. The partition names are - * of the form <pool>-<unique-id>. - */ -static void -zpool_label_name(char *label_name, int label_size) -{ - uint64_t id = 0; - int fd; - - fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC); - if (fd >= 0) { - if (read(fd, &id, sizeof (id)) != sizeof (id)) - id = 0; - - close(fd); - } - - if (id == 0) - id = (((uint64_t)rand()) << 32) | (uint64_t)rand(); - - snprintf(label_name, label_size, "zfs-%016llx", (u_longlong_t)id); -} - -/* - * Label an individual disk. The name provided is the short name, - * stripped of any leading /dev path. - */ -int -zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, const char *name) -{ - char path[MAXPATHLEN]; - struct dk_gpt *vtoc; - int rval, fd; - size_t resv = EFI_MIN_RESV_SIZE; - uint64_t slice_size; - diskaddr_t start_block; - char errbuf[ERRBUFLEN]; - - /* prepare an error message just in case */ - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot label '%s'"), name); - - if (zhp) { - nvlist_t *nvroot = fnvlist_lookup_nvlist(zhp->zpool_config, - ZPOOL_CONFIG_VDEV_TREE); - - if (zhp->zpool_start_block == 0) - start_block = find_start_block(nvroot); - else - start_block = zhp->zpool_start_block; - zhp->zpool_start_block = start_block; - } else { - /* new pool */ - start_block = NEW_START_BLOCK; - } - - (void) snprintf(path, sizeof (path), "%s/%s", DISK_ROOT, name); - - if ((fd = open(path, O_RDWR|O_DIRECT|O_EXCL|O_CLOEXEC)) < 0) { - /* - * This shouldn't happen. We've long since verified that this - * is a valid device. - */ - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot " - "label '%s': unable to open device: %d"), path, errno); - return (zfs_error(hdl, EZFS_OPENFAILED, errbuf)); - } - - if (efi_alloc_and_init(fd, EFI_NUMPAR, &vtoc) != 0) { - /* - * The only way this can fail is if we run out of memory, or we - * were unable to read the disk's capacity - */ - if (errno == ENOMEM) - (void) no_memory(hdl); - - (void) close(fd); - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot " - "label '%s': unable to read disk capacity"), path); - - return (zfs_error(hdl, EZFS_NOCAP, errbuf)); - } - - slice_size = vtoc->efi_last_u_lba + 1; - slice_size -= EFI_MIN_RESV_SIZE; - if (start_block == MAXOFFSET_T) - start_block = NEW_START_BLOCK; - slice_size -= start_block; - slice_size = P2ALIGN_TYPED(slice_size, PARTITION_END_ALIGNMENT, - uint64_t); - - vtoc->efi_parts[0].p_start = start_block; - vtoc->efi_parts[0].p_size = slice_size; - - if (vtoc->efi_parts[0].p_size * vtoc->efi_lbasize < SPA_MINDEVSIZE) { - (void) close(fd); - efi_free(vtoc); - - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot " - "label '%s': partition would be less than the minimum " - "device size (64M)"), path); - return (zfs_error(hdl, EZFS_LABELFAILED, errbuf)); - } - - /* - * Why we use V_USR: V_BACKUP confuses users, and is considered - * disposable by some EFI utilities (since EFI doesn't have a backup - * slice). V_UNASSIGNED is supposed to be used only for zero size - * partitions, and efi_write() will fail if we use it. - * Other available types were all pretty specific. - * V_USR is as close to reality as we - * can get, in the absence of V_OTHER. - */ - vtoc->efi_parts[0].p_tag = V_USR; - zpool_label_name(vtoc->efi_parts[0].p_name, EFI_PART_NAME_LEN); - - vtoc->efi_parts[8].p_start = slice_size + start_block; - vtoc->efi_parts[8].p_size = resv; - vtoc->efi_parts[8].p_tag = V_RESERVED; - - rval = efi_write(fd, vtoc); - - /* Flush the buffers to disk and invalidate the page cache. */ - (void) fsync(fd); - (void) ioctl(fd, BLKFLSBUF); - - if (rval == 0) - rval = efi_rescan(fd); - - /* - * Some block drivers (like pcata) may not support EFI GPT labels. - * Print out a helpful error message directing the user to manually - * label the disk and give a specific slice. - */ - if (rval != 0) { - (void) close(fd); - efi_free(vtoc); - - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "try using " - "parted(8) and then provide a specific slice: %d"), rval); - return (zfs_error(hdl, EZFS_LABELFAILED, errbuf)); - } - - (void) close(fd); - efi_free(vtoc); - - (void) snprintf(path, sizeof (path), "%s/%s", DISK_ROOT, name); - (void) zfs_append_partition(path, MAXPATHLEN); - - /* Wait to udev to signal use the device has settled. */ - rval = zpool_label_disk_wait(path, DISK_LABEL_WAIT); - if (rval) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "failed to " - "detect device partitions on '%s': %d"), path, rval); - return (zfs_error(hdl, EZFS_LABELFAILED, errbuf)); - } - - /* We can't be to paranoid. Read the label back and verify it. */ - (void) snprintf(path, sizeof (path), "%s/%s", DISK_ROOT, name); - rval = zpool_label_disk_check(path); - if (rval) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "freshly written " - "EFI label on '%s' is damaged. Ensure\nthis device " - "is not in use, and is functioning properly: %d"), - path, rval); - return (zfs_error(hdl, EZFS_LABELFAILED, errbuf)); - } - return (0); -} diff --git a/lib/libzfs/os/linux/libzfs_util_os.c b/lib/libzfs/os/linux/libzfs_util_os.c deleted file mode 100644 index 55dfdf3723bd..000000000000 --- a/lib/libzfs/os/linux/libzfs_util_os.c +++ /dev/null @@ -1,275 +0,0 @@ -// SPDX-License-Identifier: CDDL-1.0 -/* - * 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 - */ - -/* - * Copyright (c) 2021 Klara, Inc. - */ - -#include <alloca.h> -#include <errno.h> -#include <fcntl.h> -#include <libintl.h> -#include <math.h> -#include <poll.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <strings.h> -#include <sys/inotify.h> -#include <sys/mntent.h> -#include <sys/mnttab.h> -#include <sys/stat.h> -#include <sys/timerfd.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <unistd.h> - -#include <libzfs.h> -#include <libzfs_core.h> - -#include "../../libzfs_impl.h" -#include "zfs_prop.h" -#include <libzutil.h> -#include <sys/zfs_sysfs.h> - -#define ZDIFF_SHARESDIR "/.zfs/shares/" - -const char * -libzfs_error_init(int error) -{ - switch (error) { - case ENXIO: - return (dgettext(TEXT_DOMAIN, "The ZFS modules are not " - "loaded.\nTry running 'modprobe zfs' as root " - "to load them.")); - case ENOENT: - return (dgettext(TEXT_DOMAIN, "/dev/zfs and /proc/self/mounts " - "are required.\nTry running 'udevadm trigger' and 'mount " - "-t proc proc /proc' as root.")); - case ENOEXEC: - return (dgettext(TEXT_DOMAIN, "The ZFS modules cannot be " - "auto-loaded.\nTry running 'modprobe zfs' as " - "root to manually load them.")); - case EACCES: - return (dgettext(TEXT_DOMAIN, "Permission denied the " - "ZFS utilities must be run as root.")); - default: - return (dgettext(TEXT_DOMAIN, "Failed to initialize the " - "libzfs library.")); - } -} - -/* - * zfs(4) is loaded by udev if there's a fstype=zfs device present, - * but if there isn't, load them automatically; - * always wait for ZFS_DEV to appear via udev. - * - * Environment variables: - * - ZFS_MODULE_TIMEOUT="<seconds>" - Seconds to wait for ZFS_DEV, - * defaults to 10, max. 10 min. - */ -int -libzfs_load_module(void) -{ - if (access(ZFS_DEV, F_OK) == 0) - return (0); - - if (access(ZFS_SYSFS_DIR, F_OK) != 0) { - char *argv[] = {(char *)"modprobe", (char *)"zfs", NULL}; - if (libzfs_run_process("modprobe", argv, 0)) - return (ENOEXEC); - - if (access(ZFS_SYSFS_DIR, F_OK) != 0) - return (ENXIO); - } - - const char *timeout_str = getenv("ZFS_MODULE_TIMEOUT"); - int seconds = 10; - if (timeout_str) - seconds = MIN(strtol(timeout_str, NULL, 0), 600); - struct itimerspec timeout = {.it_value.tv_sec = MAX(seconds, 0)}; - - int ino = inotify_init1(IN_CLOEXEC); - if (ino == -1) - return (ENOENT); - inotify_add_watch(ino, ZFS_DEVDIR, IN_CREATE); - - if (access(ZFS_DEV, F_OK) == 0) { - close(ino); - return (0); - } else if (seconds == 0) { - close(ino); - return (ENOENT); - } - - size_t evsz = sizeof (struct inotify_event) + NAME_MAX + 1; - struct inotify_event *ev = alloca(evsz); - - int tout = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); - if (tout == -1) { - close(ino); - return (ENOENT); - } - timerfd_settime(tout, 0, &timeout, NULL); - - int ret = ENOENT; - struct pollfd pfds[] = { - {.fd = ino, .events = POLLIN}, - {.fd = tout, .events = POLLIN}, - }; - while (poll(pfds, ARRAY_SIZE(pfds), -1) != -1) { - if (pfds[0].revents & POLLIN) { - verify(read(ino, ev, evsz) > - sizeof (struct inotify_event)); - if (strncmp(ev->name, &ZFS_DEV[sizeof (ZFS_DEVDIR)], - ev->len) == 0) { - ret = 0; - break; - } - } - if (pfds[1].revents & POLLIN) - break; - } - close(tout); - close(ino); - return (ret); -} - -int -find_shares_object(differ_info_t *di) -{ - char fullpath[MAXPATHLEN]; - struct stat64 sb = { 0 }; - - (void) strlcpy(fullpath, di->dsmnt, MAXPATHLEN); - (void) strlcat(fullpath, ZDIFF_SHARESDIR, MAXPATHLEN); - - if (stat64(fullpath, &sb) != 0) { - (void) snprintf(di->errbuf, sizeof (di->errbuf), - dgettext(TEXT_DOMAIN, "Cannot stat %s"), fullpath); - return (zfs_error(di->zhp->zfs_hdl, EZFS_DIFF, di->errbuf)); - } - - di->shares = (uint64_t)sb.st_ino; - return (0); -} - -int -zfs_destroy_snaps_nvl_os(libzfs_handle_t *hdl, nvlist_t *snaps) -{ - (void) hdl, (void) snaps; - return (0); -} - -/* - * Return allocated loaded module version, or NULL on error (with errno set) - */ -char * -zfs_version_kernel(void) -{ - FILE *f = fopen(ZFS_SYSFS_DIR "/version", "re"); - if (f == NULL) - return (NULL); - - char *ret = NULL; - size_t l; - ssize_t read; - if ((read = getline(&ret, &l, f)) == -1) { - int err = errno; - fclose(f); - errno = err; - return (NULL); - } - - fclose(f); - if (ret[read - 1] == '\n') - ret[read - 1] = '\0'; - return (ret); -} - -/* - * Add or delete the given filesystem to/from the given user namespace. - */ -int -zfs_userns(zfs_handle_t *zhp, const char *nspath, int attach) -{ - libzfs_handle_t *hdl = zhp->zfs_hdl; - zfs_cmd_t zc = {"\0"}; - char errbuf[1024]; - unsigned long cmd; - int ret; - - if (attach) { - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot add '%s' to namespace"), - zhp->zfs_name); - } else { - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot remove '%s' from namespace"), - zhp->zfs_name); - } - - switch (zhp->zfs_type) { - case ZFS_TYPE_VOLUME: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "volumes can not be namespaced")); - return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); - case ZFS_TYPE_SNAPSHOT: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "snapshots can not be namespaced")); - return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); - case ZFS_TYPE_BOOKMARK: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "bookmarks can not be namespaced")); - return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); - case ZFS_TYPE_VDEV: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "vdevs can not be namespaced")); - return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); - case ZFS_TYPE_INVALID: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "invalid zfs_type_t: ZFS_TYPE_INVALID")); - return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); - case ZFS_TYPE_POOL: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "pools can not be namespaced")); - return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); - case ZFS_TYPE_FILESYSTEM: - break; - } - assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM); - - (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); - zc.zc_objset_type = DMU_OST_ZFS; - zc.zc_cleanup_fd = open(nspath, O_RDONLY); - if (zc.zc_cleanup_fd < 0) { - return (zfs_error(hdl, EZFS_NOT_USER_NAMESPACE, errbuf)); - } - - cmd = attach ? ZFS_IOC_USERNS_ATTACH : ZFS_IOC_USERNS_DETACH; - if ((ret = zfs_ioctl(hdl, cmd, &zc)) != 0) - zfs_standard_error(hdl, errno, errbuf); - - (void) close(zc.zc_cleanup_fd); - - return (ret); -} |