diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c index 650b4fc9b74f..1a113c5c0382 100644 --- a/cmd/zfs/zfs_main.c +++ b/cmd/zfs/zfs_main.c @@ -311,7 +311,8 @@ get_usage(zfs_help_t idx) case HELP_RENAME: return (gettext("\trename [-f] " "\n" - "\trename [-f] -p \n" + "\trename -p [-f] \n" + "\trename -u [-f] \n" "\trename -r \n")); case HELP_ROLLBACK: return (gettext("\trollback [-rRf] \n")); @@ -401,7 +402,7 @@ get_usage(zfs_help_t idx) "<-a | filesystem|volume>\n")); case HELP_CHANGE_KEY: return (gettext("\tchange-key [-l] [-o keyformat=]\n" - "\t [-o keylocation=] [-o pbkfd2iters=]\n" + "\t [-o keylocation=] [-o pbkdf2iters=]\n" "\t \n" "\tchange-key -i [-l] \n")); case HELP_VERSION: @@ -3603,36 +3604,40 @@ zfs_do_list(int argc, char **argv) } /* - * zfs rename [-f] + * zfs rename [-fu] * zfs rename [-f] -p - * zfs rename -r + * zfs rename [-u] -r * * Renames the given dataset to another of the same type. * * The '-p' flag creates all the non-existing ancestors of the target first. + * The '-u' flag prevents file systems from being remounted during rename. */ /* ARGSUSED */ static int zfs_do_rename(int argc, char **argv) { zfs_handle_t *zhp; + renameflags_t flags = { 0 }; int c; int ret = 0; - boolean_t recurse = B_FALSE; + int types; boolean_t parents = B_FALSE; - boolean_t force_unmount = B_FALSE; /* check options */ - while ((c = getopt(argc, argv, "prf")) != -1) { + while ((c = getopt(argc, argv, "pruf")) != -1) { switch (c) { case 'p': parents = B_TRUE; break; case 'r': - recurse = B_TRUE; + flags.recursive = B_TRUE; + break; + case 'u': + flags.nounmount = B_TRUE; break; case 'f': - force_unmount = B_TRUE; + flags.forceunmount = B_TRUE; break; case '?': default: @@ -3661,20 +3666,32 @@ zfs_do_rename(int argc, char **argv) usage(B_FALSE); } - if (recurse && parents) { + if (flags.recursive && parents) { (void) fprintf(stderr, gettext("-p and -r options are mutually " "exclusive\n")); usage(B_FALSE); } - if (recurse && strchr(argv[0], '@') == 0) { + if (flags.nounmount && parents) { + (void) fprintf(stderr, gettext("-u and -p options are mutually " + "exclusive\n")); + usage(B_FALSE); + } + + if (flags.recursive && strchr(argv[0], '@') == 0) { (void) fprintf(stderr, gettext("source dataset for recursive " "rename must be a snapshot\n")); usage(B_FALSE); } - if ((zhp = zfs_open(g_zfs, argv[0], parents ? ZFS_TYPE_FILESYSTEM | - ZFS_TYPE_VOLUME : ZFS_TYPE_DATASET)) == NULL) + if (flags.nounmount) + types = ZFS_TYPE_FILESYSTEM; + else if (parents) + types = ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME; + else + types = ZFS_TYPE_DATASET; + + if ((zhp = zfs_open(g_zfs, argv[0], types)) == NULL) return (1); /* If we were asked and the name looks good, try to create ancestors. */ @@ -3684,7 +3701,7 @@ zfs_do_rename(int argc, char **argv) return (1); } - ret = (zfs_rename(zhp, argv[1], recurse, force_unmount) != 0); + ret = (zfs_rename(zhp, argv[1], flags) != 0); zfs_close(zhp); return (ret); diff --git a/config/kernel-global_page_state.m4 b/config/kernel-global_page_state.m4 index 75043f40beca..badb5e5d2e23 100644 --- a/config/kernel-global_page_state.m4 +++ b/config/kernel-global_page_state.m4 @@ -94,9 +94,6 @@ AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_ZONE_PAGE_STATE_SANITY], [ ZFS_AC_KERNEL_GLOBAL_PAGE_STATE_ENUM_CHECK([NR_FILE_PAGES]) ZFS_AC_KERNEL_GLOBAL_PAGE_STATE_ENUM_CHECK([NR_INACTIVE_ANON]) ZFS_AC_KERNEL_GLOBAL_PAGE_STATE_ENUM_CHECK([NR_INACTIVE_FILE]) - AS_IF([test -z "$ZFS_ENUM_NODE_STAT_ITEM_NR_SLAB_RECLAIMABLE_B"],[ - ZFS_AC_KERNEL_GLOBAL_PAGE_STATE_ENUM_CHECK([NR_SLAB_RECLAIMABLE]) - ]) AC_MSG_RESULT(yes) ]) @@ -119,10 +116,6 @@ AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_PAGE_STATE], [ [node_stat_item], [$LINUX/include/linux/mmzone.h]) ZFS_AC_KERNEL_ENUM_MEMBER([NR_INACTIVE_FILE], [node_stat_item], [$LINUX/include/linux/mmzone.h]) - ZFS_AC_KERNEL_ENUM_MEMBER([NR_SLAB_RECLAIMABLE], - [node_stat_item], [$LINUX/include/linux/mmzone.h]) - ZFS_AC_KERNEL_ENUM_MEMBER([NR_SLAB_RECLAIMABLE_B], - [node_stat_item], [$LINUX/include/linux/mmzone.h]) ZFS_AC_KERNEL_ENUM_MEMBER([NR_FILE_PAGES], [zone_stat_item], [$LINUX/include/linux/mmzone.h]) @@ -130,8 +123,6 @@ AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_PAGE_STATE], [ [zone_stat_item], [$LINUX/include/linux/mmzone.h]) ZFS_AC_KERNEL_ENUM_MEMBER([NR_INACTIVE_FILE], [zone_stat_item], [$LINUX/include/linux/mmzone.h]) - ZFS_AC_KERNEL_ENUM_MEMBER([NR_SLAB_RECLAIMABLE], - [zone_stat_item], [$LINUX/include/linux/mmzone.h]) ZFS_AC_KERNEL_GLOBAL_ZONE_PAGE_STATE_SANITY ]) diff --git a/config/zfs-build.m4 b/config/zfs-build.m4 index 54b61de090e7..2f0aca830598 100644 --- a/config/zfs-build.m4 +++ b/config/zfs-build.m4 @@ -418,33 +418,43 @@ dnl # package type for 'make pkg': (rpm | deb | tgz) dnl # AC_DEFUN([ZFS_AC_DEFAULT_PACKAGE], [ AC_MSG_CHECKING([os distribution]) - if test -f /etc/toss-release ; then - VENDOR=toss ; - elif test -f /etc/fedora-release ; then - VENDOR=fedora ; - elif test -f /etc/redhat-release ; then - VENDOR=redhat ; - elif test -f /etc/gentoo-release ; then - VENDOR=gentoo ; - elif test -f /etc/arch-release ; then - VENDOR=arch ; - elif test -f /etc/SuSE-release ; then - VENDOR=sles ; - elif test -f /etc/slackware-version ; then - VENDOR=slackware ; - elif test -f /etc/lunar.release ; then - VENDOR=lunar ; - elif test -f /etc/lsb-release ; then - VENDOR=ubuntu ; - elif test -f /etc/debian_version ; then - VENDOR=debian ; - elif test -f /etc/alpine-release ; then - VENDOR=alpine ; - elif test -f /bin/freebsd-version ; then - VENDOR=freebsd ; - else - VENDOR= ; - fi + AC_ARG_WITH([vendor], + [AS_HELP_STRING([--with-vendor], + [Distribution vendor @<:@default=check@:>@])], + [with_vendor=$withval], + [with_vendor=check]) + AS_IF([test "x$with_vendor" = "xcheck"],[ + if test -f /etc/toss-release ; then + VENDOR=toss ; + elif test -f /etc/fedora-release ; then + VENDOR=fedora ; + elif test -f /etc/redhat-release ; then + VENDOR=redhat ; + elif test -f /etc/gentoo-release ; then + VENDOR=gentoo ; + elif test -f /etc/arch-release ; then + VENDOR=arch ; + elif test -f /etc/SuSE-release ; then + VENDOR=sles ; + elif test -f /etc/slackware-version ; then + VENDOR=slackware ; + elif test -f /etc/lunar.release ; then + VENDOR=lunar ; + elif test -f /etc/lsb-release ; then + VENDOR=ubuntu ; + elif test -f /etc/debian_version ; then + VENDOR=debian ; + elif test -f /etc/alpine-release ; then + VENDOR=alpine ; + elif test -f /bin/freebsd-version ; then + VENDOR=freebsd ; + else + VENDOR= ; + fi], + [ test "x${with_vendor}" != x],[ + VENDOR="$with_vendor" ], + [ VENDOR= ; ] + ) AC_MSG_RESULT([$VENDOR]) AC_SUBST(VENDOR) diff --git a/etc/systemd/system-generators/zfs-mount-generator.in b/etc/systemd/system-generators/zfs-mount-generator.in index fdef13cfa95a..28439f424ad9 100755 --- a/etc/systemd/system-generators/zfs-mount-generator.in +++ b/etc/systemd/system-generators/zfs-mount-generator.in @@ -38,8 +38,6 @@ do_fail() { is_known() { query="$1" IFS=' ' - # protect against special characters - set -f for element in $2 ; do if [ "$query" = "$element" ] ; then return 0 @@ -54,8 +52,7 @@ is_known() { create_dependencies() { unitfile="$1" suffix="$2" - # protect against special characters - set -f + IFS=' ' for target in $3 ; do target_dir="${dest_norm}/${target}.${suffix}/" mkdir -p "${target_dir}" @@ -72,6 +69,7 @@ else do_fail "zero or three arguments required" fi +pools=$(zpool list -H -o name || true) # All needed information about each ZFS is available from # zfs list -H -t filesystem -o @@ -83,11 +81,11 @@ process_line() { # zfs list -H -o name,... # fields are tab separated IFS="$(printf '\t')" - # protect against special characters in, e.g., mountpoints - set -f # shellcheck disable=SC2086 set -- $1 + dataset="${1}" + pool="${dataset%%/*}" p_mountpoint="${2}" p_canmount="${3}" p_atime="${4}" @@ -120,6 +118,25 @@ process_line() { requiredby="" noauto="off" + # If the pool is already imported, zfs-import.target is not needed. This + # avoids a dependency loop on root-on-ZFS systems: + # systemd-random-seed.service After (via RequiresMountsFor) var-lib.mount + # After zfs-import.target After zfs-import-{cache,scan}.service After + # cryptsetup.service After systemd-random-seed.service. + # + # Pools are newline-separated and may contain spaces in their names. + # There is no better portable way to set IFS to just a newline. Using + # $(printf '\n') doesn't work because $(...) strips trailing newlines. + IFS=" +" + for p in $pools ; do + if [ "$p" = "$pool" ] ; then + after="" + wants="" + break + fi + done + if [ -n "${p_systemd_after}" ] && \ [ "${p_systemd_after}" != "-" ] ; then after="${p_systemd_after} ${after}" @@ -204,6 +221,10 @@ ${keymountdep} [Service] Type=oneshot RemainAfterExit=yes +# This avoids a dependency loop involving systemd-journald.socket if this +# dataset is a parent of the root filesystem. +StandardOutput=null +StandardError=null ExecStart=${keyloadcmd} ExecStop=${keyunloadcmd}" > "${dest_norm}/${keyloadunit}" fi @@ -438,6 +459,8 @@ Options=defaults${opts},zfsutil" > "${dest_norm}/${mountfile}" } for cachefile in "${FSLIST}/"* ; do + # Disable glob expansion to protect against special characters when parsing. + set -f # Sort cachefile's lines by canmount, "on" before "noauto" # and feed each line into process_line sort -t "$(printf '\t')" -k 3 -r "${cachefile}" | \ diff --git a/etc/systemd/system/zfs-mount.service.in b/etc/systemd/system/zfs-mount.service.in index 480f39a49769..3ab82fb033c1 100644 --- a/etc/systemd/system/zfs-mount.service.in +++ b/etc/systemd/system/zfs-mount.service.in @@ -6,7 +6,6 @@ After=systemd-udev-settle.service After=zfs-import.target After=systemd-remount-fs.service Before=local-fs.target -Before=systemd-random-seed.service ConditionPathIsDirectory=/sys/module/zfs [Service] diff --git a/include/libzfs.h b/include/libzfs.h index 4e6336180648..6b4f518a4a86 100644 --- a/include/libzfs.h +++ b/include/libzfs.h @@ -642,7 +642,19 @@ extern int zfs_snapshot(libzfs_handle_t *, const char *, boolean_t, nvlist_t *); extern int zfs_snapshot_nvl(libzfs_handle_t *hdl, nvlist_t *snaps, nvlist_t *props); extern int zfs_rollback(zfs_handle_t *, zfs_handle_t *, boolean_t); -extern int zfs_rename(zfs_handle_t *, const char *, boolean_t, boolean_t); + +typedef struct renameflags { + /* recursive rename */ + int recursive : 1; + + /* don't unmount file systems */ + int nounmount : 1; + + /* force unmount file systems */ + int forceunmount : 1; +} renameflags_t; + +extern int zfs_rename(zfs_handle_t *, const char *, renameflags_t); typedef struct sendflags { /* Amount of extra information to print. */ diff --git a/include/libzfs_impl.h b/include/libzfs_impl.h index 26e042964739..dfb63285c1fd 100644 --- a/include/libzfs_impl.h +++ b/include/libzfs_impl.h @@ -166,6 +166,10 @@ int zprop_expand_list(libzfs_handle_t *hdl, zprop_list_t **plp, * 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; diff --git a/include/os/freebsd/spl/sys/cred.h b/include/os/freebsd/spl/sys/cred.h index e32910e0efab..86f79011d6da 100644 --- a/include/os/freebsd/spl/sys/cred.h +++ b/include/os/freebsd/spl/sys/cred.h @@ -93,7 +93,7 @@ extern cred_t *zone_kcred(void); extern gid_t crgetrgid(const cred_t *); extern gid_t crgetsgid(const cred_t *); -#define crgetzoneid(x) (0) +#define crgetzoneid(cr) ((cr)->cr_prison->pr_id) extern projid_t crgetprojid(const cred_t *); extern cred_t *crgetmapped(const cred_t *); diff --git a/include/os/freebsd/spl/sys/zone.h b/include/os/freebsd/spl/sys/zone.h index 71a28adaf26e..dd088de836d3 100644 --- a/include/os/freebsd/spl/sys/zone.h +++ b/include/os/freebsd/spl/sys/zone.h @@ -29,6 +29,8 @@ #ifndef _OPENSOLARIS_SYS_ZONE_H_ #define _OPENSOLARIS_SYS_ZONE_H_ +#include + /* * Macros to help with zone visibility restrictions. */ @@ -36,12 +38,9 @@ #define GLOBAL_ZONEID 0 /* - * Is thread in the global zone? + * Is proc in the global zone? */ -#define INGLOBALZONE(p) in_globalzone((p)) - - -extern boolean_t in_globalzone(struct proc *); +#define INGLOBALZONE(proc) (!jailed((proc)->p_ucred)) /* * Attach the given dataset to the given jail. diff --git a/include/os/freebsd/zfs/sys/Makefile.am b/include/os/freebsd/zfs/sys/Makefile.am index a8cfa39f3543..6a65a7326066 100644 --- a/include/os/freebsd/zfs/sys/Makefile.am +++ b/include/os/freebsd/zfs/sys/Makefile.am @@ -6,7 +6,7 @@ KERNEL_H = \ zfs_ctldir.h \ zfs_dir.h \ zfs_ioctl_compat.h \ - zfs_vfsops.h \ + zfs_vfsops_os.h \ zfs_vnops.h \ zfs_znode_impl.h \ zpl.h diff --git a/include/os/freebsd/zfs/sys/zfs_vfsops.h b/include/os/freebsd/zfs/sys/zfs_vfsops.h index 70ada204a292..1b80ee7cb177 100644 --- a/include/os/freebsd/zfs/sys/zfs_vfsops.h +++ b/include/os/freebsd/zfs/sys/zfs_vfsops.h @@ -168,7 +168,6 @@ extern boolean_t zfs_is_readonly(zfsvfs_t *zfsvfs); extern int zfs_get_temporary_prop(struct dsl_dataset *ds, zfs_prop_t zfs_prop, uint64_t *val, char *setpoint); extern int zfs_busy(void); -extern void zfsvfs_update_fromname(const char *oldname, const char *newname); #ifdef __cplusplus } diff --git a/include/os/linux/kernel/linux/page_compat.h b/include/os/linux/kernel/linux/page_compat.h index 8ad04f9bbfc6..bd6cb398b0c0 100644 --- a/include/os/linux/kernel/linux/page_compat.h +++ b/include/os/linux/kernel/linux/page_compat.h @@ -35,16 +35,6 @@ #else #define nr_inactive_file_pages() global_zone_page_state(NR_INACTIVE_FILE) #endif -#if defined(ZFS_ENUM_NODE_STAT_ITEM_NR_SLAB_RECLAIMABLE_B) -#define nr_slab_reclaimable_pages() \ - global_node_page_state(NR_SLAB_RECLAIMABLE_B) -#else -#if defined(ZFS_ENUM_NODE_STAT_ITEM_NR_SLAB_RECLAIMABLE) -#define nr_slab_reclaimable_pages() global_node_page_state(NR_SLAB_RECLAIMABLE) -#else -#define nr_slab_reclaimable_pages() global_zone_page_state(NR_SLAB_RECLAIMABLE) -#endif -#endif #elif defined(ZFS_GLOBAL_NODE_PAGE_STATE) @@ -64,16 +54,6 @@ #else #define nr_inactive_file_pages() global_page_state(NR_INACTIVE_FILE) #endif -#if defined(ZFS_ENUM_NODE_STAT_ITEM_NR_SLAB_RECLAIMABLE_B) -#define nr_slab_reclaimable_pages() \ - global_node_page_state(NR_SLAB_RECLAIMABLE_B) -#else -#if defined(ZFS_ENUM_NODE_STAT_ITEM_NR_SLAB_RECLAIMABLE) -#define nr_slab_reclaimable_pages() global_node_page_state(NR_SLAB_RECLAIMABLE) -#else -#define nr_slab_reclaimable_pages() global_page_state(NR_SLAB_RECLAIMABLE) -#endif -#endif #else @@ -81,11 +61,6 @@ #define nr_file_pages() global_page_state(NR_FILE_PAGES) #define nr_inactive_anon_pages() global_page_state(NR_INACTIVE_ANON) #define nr_inactive_file_pages() global_page_state(NR_INACTIVE_FILE) -#ifdef ZFS_ENUM_NODE_STAT_ITEM_NR_SLAB_RECLAIMABLE_B -#define nr_slab_reclaimable_pages() global_page_state(NR_SLAB_RECLAIMABLE_B) -#else -#define nr_slab_reclaimable_pages() global_page_state(NR_SLAB_RECLAIMABLE) -#endif /* ZFS_ENUM_NODE_STAT_ITEM_NR_SLAB_RECLAIMABLE_B */ #endif /* ZFS_GLOBAL_ZONE_PAGE_STATE */ diff --git a/include/os/linux/spl/sys/vmsystm.h b/include/os/linux/spl/sys/vmsystm.h index 705339486bc8..8783231dcf2a 100644 --- a/include/os/linux/spl/sys/vmsystm.h +++ b/include/os/linux/spl/sys/vmsystm.h @@ -47,17 +47,6 @@ #define membar_producer() smp_wmb() #define physmem zfs_totalram_pages -#ifdef ZFS_ENUM_NODE_STAT_ITEM_NR_SLAB_RECLAIMABLE_B -#define freemem (nr_free_pages() + \ - global_page_state(NR_INACTIVE_FILE) + \ - global_page_state(NR_INACTIVE_ANON) + \ - global_page_state(NR_SLAB_RECLAIMABLE_B)) -#else -#define freemem (nr_free_pages() + \ - global_page_state(NR_INACTIVE_FILE) + \ - global_page_state(NR_INACTIVE_ANON) + \ - global_page_state(NR_SLAB_RECLAIMABLE)) -#endif /* ZFS_ENUM_NODE_STAT_ITEM_NR_SLAB_RECLAIMABLE_B */ #define xcopyin(from, to, size) copy_from_user(to, from, size) #define xcopyout(from, to, size) copy_to_user(to, from, size) diff --git a/include/os/linux/zfs/sys/Makefile.am b/include/os/linux/zfs/sys/Makefile.am index 732d94ee804e..b56e6771d28a 100644 --- a/include/os/linux/zfs/sys/Makefile.am +++ b/include/os/linux/zfs/sys/Makefile.am @@ -19,7 +19,7 @@ KERNEL_H = \ zfs_context_os.h \ zfs_ctldir.h \ zfs_dir.h \ - zfs_vfsops.h \ + zfs_vfsops_os.h \ zfs_vnops.h \ zfs_znode_impl.h \ zpl.h diff --git a/include/sys/Makefile.am b/include/sys/Makefile.am index c2bc3be03c9f..75727b93aacd 100644 --- a/include/sys/Makefile.am +++ b/include/sys/Makefile.am @@ -115,6 +115,7 @@ COMMON_H = \ zfs_sa.h \ zfs_stat.h \ zfs_sysfs.h \ + zfs_vfsops.h \ zfs_znode.h \ zil.h \ zil_impl.h \ diff --git a/include/sys/zfs_vfsops.h b/include/sys/zfs_vfsops.h new file mode 100644 index 000000000000..a438c86f0a0c --- /dev/null +++ b/include/sys/zfs_vfsops.h @@ -0,0 +1,35 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Portions Copyright 2020 iXsystems, Inc. + */ + +#ifndef _SYS_ZFS_VFSOPS_H +#define _SYS_ZFS_VFSOPS_H + +#ifdef _KERNEL +#include +#endif + +extern void zfsvfs_update_fromname(const char *, const char *); + +#endif /* _SYS_ZFS_VFSOPS_H */ diff --git a/lib/libspl/Makefile.am b/lib/libspl/Makefile.am index f576d69248fa..fc4f27c64e3e 100644 --- a/lib/libspl/Makefile.am +++ b/lib/libspl/Makefile.am @@ -27,7 +27,6 @@ USER_C = \ strlcat.c \ strlcpy.c \ timestamp.c \ - zone.c \ include/sys/list.h \ include/sys/list_impl.h @@ -35,7 +34,8 @@ if BUILD_LINUX USER_C += \ os/linux/getexecname.c \ os/linux/gethostid.c \ - os/linux/getmntany.c + os/linux/getmntany.c \ + os/linux/zone.c endif if BUILD_FREEBSD @@ -43,7 +43,8 @@ USER_C += \ os/freebsd/getexecname.c \ os/freebsd/gethostid.c \ os/freebsd/getmntany.c \ - os/freebsd/mnttab.c + os/freebsd/mnttab.c \ + os/freebsd/zone.c endif libspl_la_SOURCES = \ diff --git a/lib/libspl/include/limits.h b/lib/libspl/include/limits.h index 1a42cfec469c..5d996eb846d1 100644 --- a/lib/libspl/include/limits.h +++ b/lib/libspl/include/limits.h @@ -25,16 +25,21 @@ */ #include_next +#include #ifndef _LIBSPL_LIMITS_H #define _LIBSPL_LIMITS_H +#ifndef DBL_DIG #define DBL_DIG 15 #define DBL_MAX 1.7976931348623157081452E+308 #define DBL_MIN 2.2250738585072013830903E-308 +#endif +#ifndef FLT_DIG #define FLT_DIG 6 #define FLT_MAX 3.4028234663852885981170E+38F #define FLT_MIN 1.1754943508222875079688E-38F +#endif #endif /* _LIBSPL_LIMITS_H */ diff --git a/lib/libspl/include/zone.h b/lib/libspl/include/zone.h index b4a6deb40ce4..b0ac2d9bc610 100644 --- a/lib/libspl/include/zone.h +++ b/lib/libspl/include/zone.h @@ -26,25 +26,16 @@ #ifndef _LIBSPL_ZONE_H #define _LIBSPL_ZONE_H - - #include #include -#include #ifdef __cplusplus extern "C" { #endif #define GLOBAL_ZONEID 0 -#define GLOBAL_ZONEID_NAME "global" -/* - * Functions for mapping between id and name for active zones. - */ extern zoneid_t getzoneid(void); -extern zoneid_t getzoneidbyname(const char *); -extern ssize_t getzonenamebyid(zoneid_t, char *, size_t); #ifdef __cplusplus } diff --git a/lib/libspl/os/freebsd/zone.c b/lib/libspl/os/freebsd/zone.c new file mode 100644 index 000000000000..c07cb0532e16 --- /dev/null +++ b/lib/libspl/os/freebsd/zone.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2007 Pawel Jakub Dawidek + * 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. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include + +zoneid_t +getzoneid(void) +{ + size_t size; + int jailid; + + /* Information that we are in jail or not is enough for our needs. */ + size = sizeof (jailid); + if (sysctlbyname("security.jail.jailed", &jailid, &size, NULL, 0) == -1) + assert(!"No security.jail.jailed sysctl!"); + return ((zoneid_t)jailid); +} diff --git a/lib/libspl/zone.c b/lib/libspl/zone.c index 5ca93b224d9e..a71c4e0b275b 100644 --- a/lib/libspl/zone.c +++ b/lib/libspl/zone.c @@ -24,40 +24,9 @@ */ #include -#include -#include zoneid_t getzoneid() { return (GLOBAL_ZONEID); } - -zoneid_t -getzoneidbyname(const char *name) -{ - if (name == NULL) - return (GLOBAL_ZONEID); - - if (strcmp(name, GLOBAL_ZONEID_NAME) == 0) - return (GLOBAL_ZONEID); - - return (EINVAL); -} - -ssize_t -getzonenamebyid(zoneid_t id, char *buf, size_t buflen) -{ - if (id != GLOBAL_ZONEID) - return (EINVAL); - - ssize_t ret = strlen(GLOBAL_ZONEID_NAME) + 1; - - if (buf == NULL || buflen == 0) - return (ret); - - strncpy(buf, GLOBAL_ZONEID_NAME, buflen); - buf[buflen - 1] = '\0'; - - return (ret); -} diff --git a/lib/libzfs/libzfs_changelist.c b/lib/libzfs/libzfs_changelist.c index fec2fd5f2648..1592b75eb098 100644 --- a/lib/libzfs/libzfs_changelist.c +++ b/lib/libzfs/libzfs_changelist.c @@ -128,6 +128,8 @@ changelist_prefix(prop_changelist_t *clp) */ switch (clp->cl_prop) { case ZFS_PROP_MOUNTPOINT: + if (clp->cl_gflags & CL_GATHER_DONT_UNMOUNT) + break; if (zfs_unmount(cn->cn_handle, NULL, clp->cl_mflags) != 0) { ret = -1; @@ -184,7 +186,8 @@ changelist_postfix(prop_changelist_t *clp) if ((cn = uu_avl_last(clp->cl_tree)) == NULL) return (0); - if (clp->cl_prop == ZFS_PROP_MOUNTPOINT) + if (clp->cl_prop == ZFS_PROP_MOUNTPOINT && + !(clp->cl_gflags & CL_GATHER_DONT_UNMOUNT)) remove_mountpoint(cn->cn_handle); /* @@ -235,7 +238,8 @@ changelist_postfix(prop_changelist_t *clp) needs_key = (zfs_prop_get_int(cn->cn_handle, ZFS_PROP_KEYSTATUS) == ZFS_KEYSTATUS_UNAVAILABLE); - mounted = zfs_is_mounted(cn->cn_handle, NULL); + mounted = (clp->cl_gflags & CL_GATHER_DONT_UNMOUNT) || + zfs_is_mounted(cn->cn_handle, NULL); if (!mounted && !needs_key && (cn->cn_mounted || ((sharenfs || sharesmb || clp->cl_waslegacy) && diff --git a/lib/libzfs/libzfs_dataset.c b/lib/libzfs/libzfs_dataset.c index d548cc0ecabc..2c707f23f4b0 100644 --- a/lib/libzfs/libzfs_dataset.c +++ b/lib/libzfs/libzfs_dataset.c @@ -4370,14 +4370,14 @@ zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, boolean_t force) * Renames the given dataset. */ int -zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive, - boolean_t force_unmount) +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[1024]; @@ -4429,7 +4429,7 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive, if (!zfs_validate_name(hdl, target, zhp->zfs_type, B_TRUE)) return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); } else { - if (recursive) { + if (flags.recursive) { zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "recursive rename must be a snapshot")); return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); @@ -4470,8 +4470,19 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive, return (zfs_error(hdl, EZFS_ZONED, errbuf)); } - if (recursive) { - zfs_handle_t *zhrp; + /* + * 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); if (parentname == NULL) { ret = -1; @@ -4479,7 +4490,8 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive, } delim = strchr(parentname, '@'); *delim = '\0'; - zhrp = zfs_open(zhp->zfs_hdl, parentname, ZFS_TYPE_DATASET); + zfs_handle_t *zhrp = zfs_open(zhp->zfs_hdl, parentname, + ZFS_TYPE_DATASET); free(parentname); if (zhrp == NULL) { ret = -1; @@ -4488,8 +4500,9 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive, 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, - force_unmount ? MS_FORCE : 0)) == NULL) + flags.forceunmount ? MS_FORCE : 0)) == NULL) return (-1); if (changelist_haszonedchild(cl)) { @@ -4513,7 +4526,8 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive, (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 = recursive; + zc.zc_cookie = !!flags.recursive; + zc.zc_cookie |= (!!flags.nounmount) << 1; if ((ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_RENAME, &zc)) != 0) { /* @@ -4523,7 +4537,7 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive, (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, "cannot rename '%s'"), zc.zc_name); - if (recursive && errno == EEXIST) { + if (flags.recursive && errno == EEXIST) { zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "a child dataset already has a snapshot " "with the new name")); diff --git a/lib/libzpool/kernel.c b/lib/libzpool/kernel.c index cba1d242b843..145b21d40f99 100644 --- a/lib/libzpool/kernel.c +++ b/lib/libzpool/kernel.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -1408,3 +1409,8 @@ zfs_file_put(int fd) { abort(); } + +void +zfsvfs_update_fromname(const char *oldname, const char *newname) +{ +} diff --git a/man/man8/zfs-rename.8 b/man/man8/zfs-rename.8 index 9d650709a0ad..d8d9f49d7689 100644 --- a/man/man8/zfs-rename.8 +++ b/man/man8/zfs-rename.8 @@ -44,9 +44,16 @@ .Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot .Nm .Cm rename -.Op Fl fp +.Fl p +.Op Fl f .Ar filesystem Ns | Ns Ar volume .Ar filesystem Ns | Ns Ar volume +.Nm +.Cm rename +.Fl u +.Op Fl f +.Ar filesystem +.Ar filesystem .Sh DESCRIPTION .Bl -tag -width "" .It Xo @@ -59,10 +66,19 @@ .It Xo .Nm .Cm rename -.Op Fl fp +.Fl p +.Op Fl f .Ar filesystem Ns | Ns Ar volume .Ar filesystem Ns | Ns Ar volume .Xc +.It Xo +.Nm +.Cm rename +.Fl u +.Op Fl f +.Ar filesystem +.Ar filesystem +.Xc Renames the given dataset. The new target can be located anywhere in the ZFS hierarchy, with the exception of snapshots. @@ -73,12 +89,24 @@ Renamed file systems can inherit new mount points, in which case they are unmounted and remounted at the new mount point. .Bl -tag -width "-a" .It Fl f -Force unmount any filesystems that need to be unmounted in the process. +Force unmount any file systems that need to be unmounted in the process. +This flag has no effect if used together with the +.Fl u +flag. .It Fl p Creates all the nonexistent parent datasets. Datasets created in this manner are automatically mounted according to the .Sy mountpoint property inherited from their parent. +.It Fl u +Do not remount file systems during rename. +If a file system's +.Sy mountpoint +property is set to +.Sy legacy +or +.Sy none , +the file system is not unmounted even if this option is not given. .El .It Xo .Nm diff --git a/module/avl/avl.c b/module/avl/avl.c index 9cc8362399d9..48865365d8e3 100644 --- a/module/avl/avl.c +++ b/module/avl/avl.c @@ -96,6 +96,9 @@ * which each have their own compilation environments and subsequent * requirements. Each of these environments must be considered when adding * dependencies from avl.c. + * + * Link to Illumos.org for more information on avl function: + * [1] https://illumos.org/man/9f/avl */ #include diff --git a/module/nvpair/nvpair.c b/module/nvpair/nvpair.c index 20a58802f6b7..990a4482c993 100644 --- a/module/nvpair/nvpair.c +++ b/module/nvpair/nvpair.c @@ -25,6 +25,15 @@ * Copyright 2018 RackTop Systems. */ +/* + * Links to Illumos.org for more information on Interface Libraries: + * [1] https://illumos.org/man/3lib/libnvpair + * [2] https://illumos.org/man/3nvpair/nvlist_alloc + * [3] https://illumos.org/man/9f/nvlist_alloc + * [4] https://illumos.org/man/9f/nvlist_next_nvpair + * [5] https://illumos.org/man/9f/nvpair_value_byte + */ + #include #include #include diff --git a/module/os/freebsd/spl/spl_kstat.c b/module/os/freebsd/spl/spl_kstat.c index 756667045b17..df2da2d602b6 100644 --- a/module/os/freebsd/spl/spl_kstat.c +++ b/module/os/freebsd/spl/spl_kstat.c @@ -22,6 +22,10 @@ * 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. + * + * Links to Illumos.org for more information on kstat function: + * [1] https://illumos.org/man/1M/kstat + * [2] https://illumos.org/man/9f/kstat_create */ #include @@ -34,6 +38,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include static MALLOC_DEFINE(M_KSTAT, "kstat_data", "Kernel statistics"); @@ -61,6 +66,156 @@ kstat_default_update(kstat_t *ksp, int rw) return (0); } +static int +kstat_resize_raw(kstat_t *ksp) +{ + if (ksp->ks_raw_bufsize == KSTAT_RAW_MAX) + return (ENOMEM); + + free(ksp->ks_raw_buf, M_TEMP); + ksp->ks_raw_bufsize = MIN(ksp->ks_raw_bufsize * 2, KSTAT_RAW_MAX); + ksp->ks_raw_buf = malloc(ksp->ks_raw_bufsize, M_TEMP, M_WAITOK); + + return (0); +} + +static void * +kstat_raw_default_addr(kstat_t *ksp, loff_t n) +{ + if (n == 0) + return (ksp->ks_data); + return (NULL); +} + +static int +kstat_sysctl(SYSCTL_HANDLER_ARGS) +{ + kstat_t *ksp = arg1; + kstat_named_t *ksent; + uint64_t val; + + ksent = ksp->ks_data; + /* Select the correct element */ + ksent += arg2; + /* Update the aggsums before reading */ + (void) ksp->ks_update(ksp, KSTAT_READ); + val = ksent->value.ui64; + + return (sysctl_handle_64(oidp, &val, 0, req)); +} + +static int +kstat_sysctl_string(SYSCTL_HANDLER_ARGS) +{ + kstat_t *ksp = arg1; + kstat_named_t *ksent = ksp->ks_data; + char *val; + uint32_t len = 0; + + /* Select the correct element */ + ksent += arg2; + /* Update the aggsums before reading */ + (void) ksp->ks_update(ksp, KSTAT_READ); + val = KSTAT_NAMED_STR_PTR(ksent); + len = KSTAT_NAMED_STR_BUFLEN(ksent); + val[len-1] = '\0'; + + return (sysctl_handle_string(oidp, val, len, req)); +} + +static int +kstat_sysctl_io(SYSCTL_HANDLER_ARGS) +{ + struct sbuf *sb; + kstat_t *ksp = arg1; + kstat_io_t *kip = ksp->ks_data; + int rc; + + sb = sbuf_new_auto(); + if (sb == NULL) + return (ENOMEM); + /* Update the aggsums before reading */ + (void) ksp->ks_update(ksp, KSTAT_READ); + + /* though wlentime & friends are signed, they will never be negative */ + sbuf_printf(sb, + "%-8llu %-8llu %-8u %-8u %-8llu %-8llu " + "%-8llu %-8llu %-8llu %-8llu %-8u %-8u\n", + kip->nread, kip->nwritten, + kip->reads, kip->writes, + kip->wtime, kip->wlentime, kip->wlastupdate, + kip->rtime, kip->rlentime, kip->rlastupdate, + kip->wcnt, kip->rcnt); + rc = sbuf_finish(sb); + if (rc == 0) + rc = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb)); + sbuf_delete(sb); + return (rc); +} + +static int +kstat_sysctl_raw(SYSCTL_HANDLER_ARGS) +{ + struct sbuf *sb; + void *data; + kstat_t *ksp = arg1; + void *(*addr_op)(kstat_t *ksp, loff_t index); + int n, rc = 0; + + sb = sbuf_new_auto(); + if (sb == NULL) + return (ENOMEM); + + if (ksp->ks_raw_ops.addr) + addr_op = ksp->ks_raw_ops.addr; + else + addr_op = kstat_raw_default_addr; + + mutex_enter(ksp->ks_lock); + + /* Update the aggsums before reading */ + (void) ksp->ks_update(ksp, KSTAT_READ); + + ksp->ks_raw_bufsize = PAGE_SIZE; + ksp->ks_raw_buf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK); + + n = 0; +restart_headers: + if (ksp->ks_raw_ops.headers) { + rc = ksp->ks_raw_ops.headers( + ksp->ks_raw_buf, ksp->ks_raw_bufsize); + if (rc == ENOMEM && !kstat_resize_raw(ksp)) + goto restart_headers; + if (rc == 0) + sbuf_printf(sb, "%s", ksp->ks_raw_buf); + } + + while ((data = addr_op(ksp, n)) != NULL) { +restart: + if (ksp->ks_raw_ops.data) { + rc = ksp->ks_raw_ops.data(ksp->ks_raw_buf, + ksp->ks_raw_bufsize, data); + if (rc == ENOMEM && !kstat_resize_raw(ksp)) + goto restart; + if (rc == 0) + sbuf_printf(sb, "%s", ksp->ks_raw_buf); + + } else { + ASSERT(ksp->ks_ndata == 1); + sbuf_hexdump(sb, ksp->ks_data, + ksp->ks_data_size, NULL, 0); + } + n++; + } + free(ksp->ks_raw_buf, M_TEMP); + mutex_exit(ksp->ks_lock); + rc = sbuf_finish(sb); + if (rc == 0) + rc = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb)); + sbuf_delete(sb); + return (rc); +} + kstat_t * __kstat_create(const char *module, int instance, const char *name, const char *class, uchar_t ks_type, uint_t ks_ndata, uchar_t flags) @@ -88,6 +243,9 @@ __kstat_create(const char *module, int instance, const char *name, ksp->ks_flags = flags; ksp->ks_update = kstat_default_update; + mutex_init(&ksp->ks_private_lock, NULL, MUTEX_DEFAULT, NULL); + ksp->ks_lock = &ksp->ks_private_lock; + switch (ksp->ks_type) { case KSTAT_TYPE_RAW: ksp->ks_ndata = 1; @@ -146,75 +304,38 @@ __kstat_create(const char *module, int instance, const char *name, free(ksp, M_KSTAT); return (NULL); } - root = SYSCTL_ADD_NODE(&ksp->ks_sysctl_ctx, SYSCTL_CHILDREN(root), - OID_AUTO, name, CTLFLAG_RW, 0, ""); - if (root == NULL) { - printf("%s: Cannot create kstat.%s.%s.%s tree!\n", __func__, - module, class, name); - sysctl_ctx_free(&ksp->ks_sysctl_ctx); - free(ksp, M_KSTAT); - return (NULL); + if (ksp->ks_type == KSTAT_TYPE_NAMED) { + root = SYSCTL_ADD_NODE(&ksp->ks_sysctl_ctx, + SYSCTL_CHILDREN(root), + OID_AUTO, name, CTLFLAG_RW, 0, ""); + if (root == NULL) { + printf("%s: Cannot create kstat.%s.%s.%s tree!\n", + __func__, module, class, name); + sysctl_ctx_free(&ksp->ks_sysctl_ctx); + free(ksp, M_KSTAT); + return (NULL); + } + } ksp->ks_sysctl_root = root; return (ksp); } -static int -kstat_sysctl(SYSCTL_HANDLER_ARGS) -{ - kstat_t *ksp = arg1; - kstat_named_t *ksent = ksp->ks_data; - uint64_t val; - - /* Select the correct element */ - ksent += arg2; - /* Update the aggsums before reading */ - (void) ksp->ks_update(ksp, KSTAT_READ); - val = ksent->value.ui64; - - return (sysctl_handle_64(oidp, &val, 0, req)); -} - -static int -kstat_sysctl_string(SYSCTL_HANDLER_ARGS) -{ - kstat_t *ksp = arg1; - kstat_named_t *ksent = ksp->ks_data; - char *val; - uint32_t len = 0; - - /* Select the correct element */ - ksent += arg2; - /* Update the aggsums before reading */ - (void) ksp->ks_update(ksp, KSTAT_READ); - val = KSTAT_NAMED_STR_PTR(ksent); - len = KSTAT_NAMED_STR_BUFLEN(ksent); - val[len-1] = '\0'; - - return (sysctl_handle_string(oidp, val, len, req)); -} - -void -kstat_install(kstat_t *ksp) +static void +kstat_install_named(kstat_t *ksp) { kstat_named_t *ksent; char *namelast; int typelast; ksent = ksp->ks_data; - if (ksp->ks_ndata == UINT32_MAX) { -#ifdef INVARIANTS - printf("can't handle raw ops yet!!!\n"); -#endif - return; - } - if (ksent == NULL) { - printf("%s ksp->ks_data == NULL!!!!\n", __func__); - return; - } + + VERIFY((ksp->ks_flags & KSTAT_FLAG_VIRTUAL) || ksent != NULL); + typelast = 0; namelast = NULL; + for (int i = 0; i < ksp->ks_ndata; i++, ksent++) { if (ksent->data_type != 0) { typelast = ksent->data_type; @@ -278,6 +399,51 @@ kstat_install(kstat_t *ksp) } } + +} + +void +kstat_install(kstat_t *ksp) +{ + struct sysctl_oid *root; + + if (ksp->ks_ndata == UINT32_MAX) + VERIFY(ksp->ks_type == KSTAT_TYPE_RAW); + + switch (ksp->ks_type) { + case KSTAT_TYPE_NAMED: + return (kstat_install_named(ksp)); + break; + case KSTAT_TYPE_RAW: + if (ksp->ks_raw_ops.data) { + root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx, + SYSCTL_CHILDREN(ksp->ks_sysctl_root), + OID_AUTO, ksp->ks_name, + CTLTYPE_STRING | CTLFLAG_RD, ksp, 0, + kstat_sysctl_raw, "A", ksp->ks_name); + } else { + root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx, + SYSCTL_CHILDREN(ksp->ks_sysctl_root), + OID_AUTO, ksp->ks_name, + CTLTYPE_OPAQUE | CTLFLAG_RD, ksp, 0, + kstat_sysctl_raw, "", ksp->ks_name); + } + VERIFY(root != NULL); + break; + case KSTAT_TYPE_IO: + root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx, + SYSCTL_CHILDREN(ksp->ks_sysctl_root), + OID_AUTO, ksp->ks_name, + CTLTYPE_STRING | CTLFLAG_RD, ksp, 0, + kstat_sysctl_io, "A", ksp->ks_name); + break; + case KSTAT_TYPE_TIMER: + case KSTAT_TYPE_INTR: + default: + panic("unsupported kstat type %d\n", ksp->ks_type); + } + ksp->ks_sysctl_root = root; + } void @@ -285,6 +451,8 @@ kstat_delete(kstat_t *ksp) { sysctl_ctx_free(&ksp->ks_sysctl_ctx); + ksp->ks_lock = NULL; + mutex_destroy(&ksp->ks_private_lock); free(ksp, M_KSTAT); } diff --git a/module/os/freebsd/spl/spl_zone.c b/module/os/freebsd/spl/spl_zone.c index 0b3b04d2a73e..bd3f019b2fa6 100644 --- a/module/os/freebsd/spl/spl_zone.c +++ b/module/os/freebsd/spl/spl_zone.c @@ -242,12 +242,6 @@ zone_get_hostid(void *ptr) return ((uint32_t)curthread->td_ucred->cr_prison->pr_hostid); } -boolean_t -in_globalzone(struct proc *p) -{ - return (!jailed(FIRST_THREAD_IN_PROC((p))->td_ucred)); -} - static void zone_sysinit(void *arg __unused) { diff --git a/module/os/freebsd/zfs/spa_stats.c b/module/os/freebsd/zfs/spa_stats.c index 45c880ada24d..e69de29bb2d1 100644 --- a/module/os/freebsd/zfs/spa_stats.c +++ b/module/os/freebsd/zfs/spa_stats.c @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2020 iXsystems, Inc. - * 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. - * - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include - -void -spa_stats_init(spa_t *spa) -{ - -} - -void -spa_stats_destroy(spa_t *spa) -{ - -} - -void -spa_iostats_trim_add(spa_t *spa, trim_type_t type, - uint64_t extents_written, uint64_t bytes_written, - uint64_t extents_skipped, uint64_t bytes_skipped, - uint64_t extents_failed, uint64_t bytes_failed) -{ -} - -void -spa_read_history_add(spa_t *spa, const zbookmark_phys_t *zb, uint32_t aflags) -{ -} - -void -spa_txg_history_add(spa_t *spa, uint64_t txg, hrtime_t birth_time) -{ - -} -/* - * Set txg state completion time and increment current state. - */ -int -spa_txg_history_set(spa_t *spa, uint64_t txg, txg_state_t completed_state, - hrtime_t completed_time) -{ - return (0); -} - -txg_stat_t * -spa_txg_history_init_io(spa_t *spa, uint64_t txg, dsl_pool_t *dp) -{ - return (NULL); -} - -void -spa_txg_history_fini_io(spa_t *spa, txg_stat_t *ts) -{ - -} - -void -spa_tx_assign_add_nsecs(spa_t *spa, uint64_t nsecs) -{ - -} - -void -spa_mmp_history_add(spa_t *spa, uint64_t txg, uint64_t timestamp, - uint64_t mmp_delay, vdev_t *vd, int label, uint64_t mmp_node_id, - int error) -{ - -} - -int -spa_mmp_history_set(spa_t *spa, uint64_t mmp_node_id, int io_error, - hrtime_t duration) -{ - return (0); -} - -int -spa_mmp_history_set_skip(spa_t *spa, uint64_t mmp_node_id) -{ - return (0); -} diff --git a/module/os/freebsd/zfs/zfs_vfsops.c b/module/os/freebsd/zfs/zfs_vfsops.c index f94ea44335c6..b6cf0c92b70b 100644 --- a/module/os/freebsd/zfs/zfs_vfsops.c +++ b/module/os/freebsd/zfs/zfs_vfsops.c @@ -1267,193 +1267,6 @@ zfs_unregister_callbacks(zfsvfs_t *zfsvfs) dsl_prop_unregister_all(dmu_objset_ds(os), zfsvfs); } -#ifdef SECLABEL -/* - * Convert a decimal digit string to a uint64_t integer. - */ -static int -str_to_uint64(char *str, uint64_t *objnum) -{ - uint64_t num = 0; - - while (*str) { - if (*str < '0' || *str > '9') - return (SET_ERROR(EINVAL)); - - num = num*10 + *str++ - '0'; - } - - *objnum = num; - return (0); -} - -/* - * The boot path passed from the boot loader is in the form of - * "rootpool-name/root-filesystem-object-number'. Convert this - * string to a dataset name: "rootpool-name/root-filesystem-name". - */ -static int -zfs_parse_bootfs(char *bpath, char *outpath) -{ - char *slashp; - uint64_t objnum; - int error; - - if (*bpath == 0 || *bpath == '/') - return (SET_ERROR(EINVAL)); - - (void) strcpy(outpath, bpath); - - slashp = strchr(bpath, '/'); - - /* if no '/', just return the pool name */ - if (slashp == NULL) { - return (0); - } - - /* if not a number, just return the root dataset name */ - if (str_to_uint64(slashp+1, &objnum)) { - return (0); - } - - *slashp = '\0'; - error = dsl_dsobj_to_dsname(bpath, objnum, outpath); - *slashp = '/'; - - return (error); -} - -/* - * Check that the hex label string is appropriate for the dataset being - * mounted into the global_zone proper. - * - * Return an error if the hex label string is not default or - * admin_low/admin_high. For admin_low labels, the corresponding - * dataset must be readonly. - */ -int -zfs_check_global_label(const char *dsname, const char *hexsl) -{ - if (strcasecmp(hexsl, ZFS_MLSLABEL_DEFAULT) == 0) - return (0); - if (strcasecmp(hexsl, ADMIN_HIGH) == 0) - return (0); - if (strcasecmp(hexsl, ADMIN_LOW) == 0) { - /* must be readonly */ - uint64_t rdonly; - - if (dsl_prop_get_integer(dsname, - zfs_prop_to_name(ZFS_PROP_READONLY), &rdonly, NULL)) - return (SET_ERROR(EACCES)); - return (rdonly ? 0 : EACCES); - } - return (SET_ERROR(EACCES)); -} - -/* - * Determine whether the mount is allowed according to MAC check. - * by comparing (where appropriate) label of the dataset against - * the label of the zone being mounted into. If the dataset has - * no label, create one. - * - * Returns 0 if access allowed, error otherwise (e.g. EACCES) - */ -static int -zfs_mount_label_policy(vfs_t *vfsp, char *osname) -{ - int error, retv; - zone_t *mntzone = NULL; - ts_label_t *mnt_tsl; - bslabel_t *mnt_sl; - bslabel_t ds_sl; - char ds_hexsl[MAXNAMELEN]; - - retv = EACCES; /* assume the worst */ - - /* - * Start by getting the dataset label if it exists. - */ - error = dsl_prop_get(osname, zfs_prop_to_name(ZFS_PROP_MLSLABEL), - 1, sizeof (ds_hexsl), &ds_hexsl, NULL); - if (error) - return (SET_ERROR(EACCES)); - - /* - * If labeling is NOT enabled, then disallow the mount of datasets - * which have a non-default label already. No other label checks - * are needed. - */ - if (!is_system_labeled()) { - if (strcasecmp(ds_hexsl, ZFS_MLSLABEL_DEFAULT) == 0) - return (0); - return (SET_ERROR(EACCES)); - } - - /* - * Get the label of the mountpoint. If mounting into the global - * zone (i.e. mountpoint is not within an active zone and the - * zoned property is off), the label must be default or - * admin_low/admin_high only; no other checks are needed. - */ - mntzone = zone_find_by_any_path(vfsp->vfs_mntpt, B_FALSE); - if (mntzone->zone_id == GLOBAL_ZONEID) { - uint64_t zoned; - - zone_rele(mntzone); - - if (dsl_prop_get_integer(osname, - zfs_prop_to_name(ZFS_PROP_ZONED), &zoned, NULL)) - return (SET_ERROR(EACCES)); - if (!zoned) - return (zfs_check_global_label(osname, ds_hexsl)); - else - /* - * This is the case of a zone dataset being mounted - * initially, before the zone has been fully created; - * allow this mount into global zone. - */ - return (0); - } - - mnt_tsl = mntzone->zone_slabel; - ASSERT(mnt_tsl != NULL); - label_hold(mnt_tsl); - mnt_sl = label2bslabel(mnt_tsl); - - if (strcasecmp(ds_hexsl, ZFS_MLSLABEL_DEFAULT) == 0) { - /* - * The dataset doesn't have a real label, so fabricate one. - */ - char *str = NULL; - - if (l_to_str_internal(mnt_sl, &str) == 0 && - dsl_prop_set_string(osname, - zfs_prop_to_name(ZFS_PROP_MLSLABEL), - ZPROP_SRC_LOCAL, str) == 0) - retv = 0; - if (str != NULL) - kmem_free(str, strlen(str) + 1); - } else if (hexstr_to_label(ds_hexsl, &ds_sl) == 0) { - /* - * Now compare labels to complete the MAC check. If the - * labels are equal then allow access. If the mountpoint - * label dominates the dataset label, allow readonly access. - * Otherwise, access is denied. - */ - if (blequal(mnt_sl, &ds_sl)) - retv = 0; - else if (bldominates(mnt_sl, &ds_sl)) { - vfs_setmntopt(vfsp, MNTOPT_RO, NULL, 0); - retv = 0; - } - } - - label_rele(mnt_tsl); - zone_rele(mntzone); - return (retv); -} -#endif /* SECLABEL */ - static int getpoolname(const char *osname, char *poolname) { @@ -1544,12 +1357,6 @@ zfs_mount(vfs_t *vfsp) goto out; } -#ifdef SECLABEL - error = zfs_mount_label_policy(vfsp, osname); - if (error) - goto out; -#endif - vfsp->vfs_flag |= MNT_NFS4ACLS; /* diff --git a/module/os/freebsd/zfs/zvol_os.c b/module/os/freebsd/zfs/zvol_os.c index 113733a5c11a..ecef075f9e15 100644 --- a/module/os/freebsd/zfs/zvol_os.c +++ b/module/os/freebsd/zfs/zvol_os.c @@ -210,6 +210,7 @@ zvol_geom_open(struct g_provider *pp, int flag, int count) zvol_state_t *zv; int err = 0; boolean_t drop_suspend = B_TRUE; + boolean_t drop_namespace = B_FALSE; if (!zpool_on_zvol && tsd_get(zfs_geom_probe_vdev_key) != NULL) { /* @@ -223,13 +224,28 @@ zvol_geom_open(struct g_provider *pp, int flag, int count) return (SET_ERROR(EOPNOTSUPP)); } +retry: rw_enter(&zvol_state_lock, ZVOL_RW_READER); zv = pp->private; if (zv == NULL) { + if (drop_namespace) + mutex_exit(&spa_namespace_lock); rw_exit(&zvol_state_lock); return (SET_ERROR(ENXIO)); } + if (zv->zv_open_count == 0 && !mutex_owned(&spa_namespace_lock)) { + /* + * We need to guarantee that the namespace lock is held + * to avoid spurious failures in zvol_first_open + */ + drop_namespace = B_TRUE; + if (!mutex_tryenter(&spa_namespace_lock)) { + rw_exit(&zvol_state_lock); + mutex_enter(&spa_namespace_lock); + goto retry; + } + } mutex_enter(&zv->zv_state_lock); ASSERT(zv->zv_zso->zso_volmode == ZFS_VOLMODE_GEOM); @@ -291,6 +307,8 @@ zvol_geom_open(struct g_provider *pp, int flag, int count) #endif zv->zv_open_count += count; + if (drop_namespace) + mutex_exit(&spa_namespace_lock); mutex_exit(&zv->zv_state_lock); if (drop_suspend) rw_exit(&zv->zv_suspend_lock); @@ -300,6 +318,8 @@ zvol_geom_open(struct g_provider *pp, int flag, int count) if (zv->zv_open_count == 0) zvol_last_close(zv); out_mutex: + if (drop_namespace) + mutex_exit(&spa_namespace_lock); mutex_exit(&zv->zv_state_lock); if (drop_suspend) rw_exit(&zv->zv_suspend_lock); @@ -606,7 +626,7 @@ zvol_geom_bio_strategy(struct bio *bp) addr = bp->bio_data; resid = bp->bio_length; - if (resid > 0 && (off < 0 || off >= volsize)) { + if (resid > 0 && off >= volsize) { error = SET_ERROR(EIO); goto resume; } diff --git a/module/os/linux/spl/spl-kstat.c b/module/os/linux/spl/spl-kstat.c index b971b4498cc6..b9eeb332ee57 100644 --- a/module/os/linux/spl/spl-kstat.c +++ b/module/os/linux/spl/spl-kstat.c @@ -22,6 +22,10 @@ * with the SPL. If not, see . * * Solaris Porting Layer (SPL) Kstat Implementation. + * + * Links to Illumos.org for more information on kstat function: + * [1] https://illumos.org/man/1M/kstat + * [2] https://illumos.org/man/9f/kstat_create */ #include diff --git a/module/os/linux/zfs/Makefile.in b/module/os/linux/zfs/Makefile.in index 9f493ef16de5..87414d6eacc5 100644 --- a/module/os/linux/zfs/Makefile.in +++ b/module/os/linux/zfs/Makefile.in @@ -14,7 +14,6 @@ $(MODULE)-objs += ../os/linux/zfs/qat.o $(MODULE)-objs += ../os/linux/zfs/qat_compress.o $(MODULE)-objs += ../os/linux/zfs/qat_crypt.o $(MODULE)-objs += ../os/linux/zfs/spa_misc_os.o -$(MODULE)-objs += ../os/linux/zfs/spa_stats.o $(MODULE)-objs += ../os/linux/zfs/vdev_disk.o $(MODULE)-objs += ../os/linux/zfs/vdev_file.o $(MODULE)-objs += ../os/linux/zfs/zfs_acl.o diff --git a/module/os/linux/zfs/arc_os.c b/module/os/linux/zfs/arc_os.c index 92f9bae8ccd3..792c75d46ffe 100644 --- a/module/os/linux/zfs/arc_os.c +++ b/module/os/linux/zfs/arc_os.c @@ -113,8 +113,7 @@ arc_free_memory(void) return (ptob(si.freeram - si.freehigh)); #else return (ptob(nr_free_pages() + - nr_inactive_file_pages() + - nr_slab_reclaimable_pages())); + nr_inactive_file_pages())); #endif /* CONFIG_HIGHMEM */ } diff --git a/module/os/linux/zfs/spa_stats.c b/module/os/linux/zfs/spa_stats.c index 86cefa6dddab..cf0be3c45dc8 100644 --- a/module/os/linux/zfs/spa_stats.c +++ b/module/os/linux/zfs/spa_stats.c @@ -835,7 +835,9 @@ spa_mmp_history_add(spa_t *spa, uint64_t txg, uint64_t timestamp, static void * spa_state_addr(kstat_t *ksp, loff_t n) { - return (ksp->ks_private); /* return the spa_t */ + if (n == 0) + return (ksp->ks_private); /* return the spa_t */ + return (NULL); } static int @@ -1026,22 +1028,16 @@ spa_stats_destroy(spa_t *spa) spa_mmp_history_destroy(spa); } -#if defined(_KERNEL) -/* CSTYLED */ -module_param(zfs_read_history, int, 0644); -MODULE_PARM_DESC(zfs_read_history, - "Historical statistics for the last N reads"); +/* BEGIN CSTYLED */ +ZFS_MODULE_PARAM(zfs, zfs_, read_history, INT, ZMOD_RW, + "Historical statistics for the last N reads"); -module_param(zfs_read_history_hits, int, 0644); -MODULE_PARM_DESC(zfs_read_history_hits, - "Include cache hits in read history"); +ZFS_MODULE_PARAM(zfs, zfs_, read_history_hits, INT, ZMOD_RW, + "Include cache hits in read history"); -module_param(zfs_txg_history, int, 0644); -MODULE_PARM_DESC(zfs_txg_history, - "Historical statistics for the last N txgs"); +ZFS_MODULE_PARAM(zfs_txg, zfs_txg_, history, INT, ZMOD_RW, + "Historical statistics for the last N txgs"); -module_param(zfs_multihost_history, int, 0644); -MODULE_PARM_DESC(zfs_multihost_history, - "Historical statistics for last N multihost writes"); +ZFS_MODULE_PARAM(zfs_multihost, zfs_multihost_, history, INT, ZMOD_RW, + "Historical statistics for last N multihost writes"); /* END CSTYLED */ -#endif diff --git a/module/os/linux/zfs/zfs_vfsops.c b/module/os/linux/zfs/zfs_vfsops.c index db831bf54704..389200b52127 100644 --- a/module/os/linux/zfs/zfs_vfsops.c +++ b/module/os/linux/zfs/zfs_vfsops.c @@ -2126,6 +2126,16 @@ zfs_get_vfs_flag_unmounted(objset_t *os) return (unmounted); } +/*ARGSUSED*/ +void +zfsvfs_update_fromname(const char *oldname, const char *newname) +{ + /* + * We don't need to do anything here, the devname is always current by + * virtue of zfsvfs->z_sb->s_op->show_devname. + */ +} + void zfs_init(void) { diff --git a/module/os/linux/zfs/zpl_super.c b/module/os/linux/zfs/zpl_super.c index 75adff51782e..333c647466cc 100644 --- a/module/os/linux/zfs/zpl_super.c +++ b/module/os/linux/zfs/zpl_super.c @@ -182,6 +182,25 @@ zpl_remount_fs(struct super_block *sb, int *flags, char *data) return (error); } +static int +__zpl_show_devname(struct seq_file *seq, zfsvfs_t *zfsvfs) +{ + char *fsname; + + fsname = kmem_alloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP); + dmu_objset_name(zfsvfs->z_os, fsname); + seq_puts(seq, fsname); + kmem_free(fsname, ZFS_MAX_DATASET_NAME_LEN); + + return (0); +} + +static int +zpl_show_devname(struct seq_file *seq, struct dentry *root) +{ + return (__zpl_show_devname(seq, root->d_sb->s_fs_info)); +} + static int __zpl_show_options(struct seq_file *seq, zfsvfs_t *zfsvfs) { @@ -314,6 +333,7 @@ const struct super_operations zpl_super_operations = { .sync_fs = zpl_sync_fs, .statfs = zpl_statfs, .remount_fs = zpl_remount_fs, + .show_devname = zpl_show_devname, .show_options = zpl_show_options, .show_stats = NULL, }; diff --git a/module/zfs/Makefile.in b/module/zfs/Makefile.in index 9ddcd6c339d4..259ac4dc926c 100644 --- a/module/zfs/Makefile.in +++ b/module/zfs/Makefile.in @@ -76,6 +76,7 @@ $(MODULE)-objs += spa_errlog.o $(MODULE)-objs += spa_history.o $(MODULE)-objs += spa_log_spacemap.o $(MODULE)-objs += spa_misc.o +$(MODULE)-objs += spa_stats.o $(MODULE)-objs += space_map.o $(MODULE)-objs += space_reftree.o $(MODULE)-objs += txg.o diff --git a/module/zfs/arc.c b/module/zfs/arc.c index 70565cc25011..904c325f37a1 100644 --- a/module/zfs/arc.c +++ b/module/zfs/arc.c @@ -2187,7 +2187,7 @@ arc_untransform(arc_buf_t *buf, spa_t *spa, const zbookmark_phys_t *zb, */ ret = SET_ERROR(EIO); spa_log_error(spa, zb); - zfs_ereport_post(FM_EREPORT_ZFS_AUTHENTICATION, + (void) zfs_ereport_post(FM_EREPORT_ZFS_AUTHENTICATION, spa, NULL, zb, NULL, 0, 0); } @@ -5652,7 +5652,8 @@ arc_read_done(zio_t *zio) error = SET_ERROR(EIO); if ((zio->io_flags & ZIO_FLAG_SPECULATIVE) == 0) { spa_log_error(zio->io_spa, &acb->acb_zb); - zfs_ereport_post(FM_EREPORT_ZFS_AUTHENTICATION, + (void) zfs_ereport_post( + FM_EREPORT_ZFS_AUTHENTICATION, zio->io_spa, NULL, &acb->acb_zb, zio, 0, 0); } } @@ -5928,7 +5929,7 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, rc = SET_ERROR(EIO); if ((zio_flags & ZIO_FLAG_SPECULATIVE) == 0) { spa_log_error(spa, zb); - zfs_ereport_post( + (void) zfs_ereport_post( FM_EREPORT_ZFS_AUTHENTICATION, spa, NULL, zb, NULL, 0, 0); } diff --git a/module/zfs/dsl_dir.c b/module/zfs/dsl_dir.c index 29672e9a613e..90dd787023be 100644 --- a/module/zfs/dsl_dir.c +++ b/module/zfs/dsl_dir.c @@ -46,14 +46,12 @@ #include #include #include +#include #include #include #include #include "zfs_namecheck.h" #include "zfs_prop.h" -#ifdef _KERNEL -#include -#endif /* * Filesystem and Snapshot Limits @@ -2124,6 +2122,8 @@ dsl_dir_rename_sync(void *arg, dmu_tx_t *tx) VERIFY0(zap_add(mos, dsl_dir_phys(newparent)->dd_child_dir_zapobj, dd->dd_myname, 8, 1, &dd->dd_object, tx)); + /* TODO: A rename callback to avoid these layering violations. */ + zfsvfs_update_fromname(ddra->ddra_oldname, ddra->ddra_newname); zvol_rename_minors(dp->dp_spa, ddra->ddra_oldname, ddra->ddra_newname, B_TRUE); diff --git a/module/zfs/spa.c b/module/zfs/spa.c index 75ff398d17c7..aac469f44b59 100644 --- a/module/zfs/spa.c +++ b/module/zfs/spa.c @@ -2868,7 +2868,8 @@ spa_load(spa_t *spa, spa_load_state_t state, spa_import_type_t type) spa->spa_loaded_ts.tv_nsec = 0; } if (error != EBADF) { - zfs_ereport_post(ereport, spa, NULL, NULL, NULL, 0, 0); + (void) zfs_ereport_post(ereport, spa, + NULL, NULL, NULL, 0, 0); } } spa->spa_load_state = error ? SPA_LOAD_ERROR : SPA_LOAD_NONE; diff --git a/module/zfs/spa_config.c b/module/zfs/spa_config.c index cc65a00d9dec..b98b7badbae1 100644 --- a/module/zfs/spa_config.c +++ b/module/zfs/spa_config.c @@ -314,7 +314,8 @@ spa_write_cachefile(spa_t *target, boolean_t removing, boolean_t postsysevent) * resource issues are resolved. */ if (target->spa_ccw_fail_time == 0) { - zfs_ereport_post(FM_EREPORT_ZFS_CONFIG_CACHE_WRITE, + (void) zfs_ereport_post( + FM_EREPORT_ZFS_CONFIG_CACHE_WRITE, target, NULL, NULL, NULL, 0, 0); } target->spa_ccw_fail_time = gethrtime(); diff --git a/module/zfs/vdev.c b/module/zfs/vdev.c index 1844a5653f12..95a2f5947db1 100644 --- a/module/zfs/vdev.c +++ b/module/zfs/vdev.c @@ -1480,7 +1480,7 @@ vdev_probe_done(zio_t *zio) } else { ASSERT(zio->io_error != 0); vdev_dbgmsg(vd, "failed probe"); - zfs_ereport_post(FM_EREPORT_ZFS_PROBE_FAILURE, + (void) zfs_ereport_post(FM_EREPORT_ZFS_PROBE_FAILURE, spa, vd, NULL, NULL, 0, 0); zio->io_error = SET_ERROR(ENXIO); } @@ -1860,7 +1860,8 @@ vdev_open(vdev_t *vd) */ if (vd->vdev_ashift > vd->vdev_top->vdev_ashift && vd->vdev_ops->vdev_op_leaf) { - zfs_ereport_post(FM_EREPORT_ZFS_DEVICE_BAD_ASHIFT, + (void) zfs_ereport_post( + FM_EREPORT_ZFS_DEVICE_BAD_ASHIFT, spa, vd, NULL, NULL, 0, 0); vdev_set_state(vd, B_TRUE, VDEV_STATE_CANT_OPEN, VDEV_AUX_BAD_LABEL); @@ -4757,7 +4758,7 @@ vdev_set_state(vdev_t *vd, boolean_t isopen, vdev_state_t state, vdev_aux_t aux) class = FM_EREPORT_ZFS_DEVICE_UNKNOWN; } - zfs_ereport_post(class, spa, vd, NULL, NULL, + (void) zfs_ereport_post(class, spa, vd, NULL, NULL, save_state, 0); } diff --git a/module/zfs/vdev_indirect.c b/module/zfs/vdev_indirect.c index 6a944f4e88b6..6bc2d917d59c 100644 --- a/module/zfs/vdev_indirect.c +++ b/module/zfs/vdev_indirect.c @@ -1403,7 +1403,7 @@ vdev_indirect_checksum_error(zio_t *zio, zio_bad_cksum_t zbc = {{{ 0 }}}; abd_t *bad_abd = ic->ic_data; abd_t *good_abd = is->is_good_child->ic_data; - zfs_ereport_post_checksum(zio->io_spa, vd, NULL, zio, + (void) zfs_ereport_post_checksum(zio->io_spa, vd, NULL, zio, is->is_target_offset, is->is_size, good_abd, bad_abd, &zbc); } @@ -1478,8 +1478,8 @@ vdev_indirect_all_checksum_errors(zio_t *zio) vd->vdev_stat.vs_checksum_errors++; mutex_exit(&vd->vdev_stat_lock); - zfs_ereport_post_checksum(zio->io_spa, vd, NULL, zio, - is->is_target_offset, is->is_size, + (void) zfs_ereport_post_checksum(zio->io_spa, vd, + NULL, zio, is->is_target_offset, is->is_size, NULL, NULL, NULL); } } diff --git a/module/zfs/vdev_raidz.c b/module/zfs/vdev_raidz.c index 8d49628053dd..4320078b6f7c 100644 --- a/module/zfs/vdev_raidz.c +++ b/module/zfs/vdev_raidz.c @@ -1797,7 +1797,7 @@ raidz_checksum_error(zio_t *zio, raidz_col_t *rc, abd_t *bad_data) zbc.zbc_has_cksum = 0; zbc.zbc_injected = rm->rm_ecksuminjected; - zfs_ereport_post_checksum(zio->io_spa, vd, + (void) zfs_ereport_post_checksum(zio->io_spa, vd, &zio->io_bookmark, zio, rc->rc_offset, rc->rc_size, rc->rc_abd, bad_data, &zbc); } diff --git a/module/zfs/zfs_fm.c b/module/zfs/zfs_fm.c index 579aa0380411..ad13ccedfc06 100644 --- a/module/zfs/zfs_fm.c +++ b/module/zfs/zfs_fm.c @@ -846,7 +846,7 @@ zfs_ereport_start_checksum(spa_t *spa, vdev_t *vd, const zbookmark_phys_t *zb, report->zcr_length = length; #ifdef _KERNEL - zfs_ereport_start(&report->zcr_ereport, &report->zcr_detector, + (void) zfs_ereport_start(&report->zcr_ereport, &report->zcr_detector, FM_EREPORT_ZFS_CHECKSUM, spa, vd, zb, zio, offset, length); if (report->zcr_ereport == NULL) { diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c index 7f623bb046ea..495ff4707d77 100644 --- a/module/zfs/zfs_ioctl.c +++ b/module/zfs/zfs_ioctl.c @@ -4316,6 +4316,7 @@ zfs_ioc_rename(zfs_cmd_t *zc) objset_t *os; dmu_objset_type_t ost; boolean_t recursive = zc->zc_cookie & 1; + boolean_t nounmount = !!(zc->zc_cookie & 2); char *at; int err; @@ -4341,7 +4342,7 @@ zfs_ioc_rename(zfs_cmd_t *zc) if (strncmp(zc->zc_name, zc->zc_value, at - zc->zc_name + 1)) return (SET_ERROR(EXDEV)); *at = '\0'; - if (ost == DMU_OST_ZFS) { + if (ost == DMU_OST_ZFS && !nounmount) { error = dmu_objset_find(zc->zc_name, recursive_unmount, at + 1, recursive ? DS_FIND_CHILDREN : 0); diff --git a/module/zfs/zio.c b/module/zfs/zio.c index 2628cc029d49..f956a9ef7621 100644 --- a/module/zfs/zio.c +++ b/module/zfs/zio.c @@ -546,7 +546,7 @@ zio_decrypt(zio_t *zio, abd_t *data, uint64_t size) zio->io_error = SET_ERROR(EIO); if ((zio->io_flags & ZIO_FLAG_SPECULATIVE) == 0) { spa_log_error(spa, &zio->io_bookmark); - zfs_ereport_post(FM_EREPORT_ZFS_AUTHENTICATION, + (void) zfs_ereport_post(FM_EREPORT_ZFS_AUTHENTICATION, spa, NULL, &zio->io_bookmark, zio, 0, 0); } } else { @@ -2003,7 +2003,7 @@ zio_deadman_impl(zio_t *pio, int ziodepth) pio->io_stage, pio->io_pipeline, pio->io_pipeline_trace, zb->zb_objset, zb->zb_object, zb->zb_level, zb->zb_blkid, pio->io_offset, pio->io_size, pio->io_error); - zfs_ereport_post(FM_EREPORT_ZFS_DEADMAN, + (void) zfs_ereport_post(FM_EREPORT_ZFS_DEADMAN, pio->io_spa, vd, zb, pio, 0, 0); if (failmode == ZIO_FAILURE_MODE_CONTINUE && @@ -2330,7 +2330,7 @@ zio_suspend(spa_t *spa, zio_t *zio, zio_suspend_reason_t reason) cmn_err(CE_WARN, "Pool '%s' has encountered an uncorrectable I/O " "failure and has been suspended.\n", spa_name(spa)); - zfs_ereport_post(FM_EREPORT_ZFS_IO_FAILURE, spa, NULL, + (void) zfs_ereport_post(FM_EREPORT_ZFS_IO_FAILURE, spa, NULL, NULL, NULL, 0, 0); mutex_enter(&spa->spa_suspend_lock); @@ -4541,7 +4541,7 @@ zio_done(zio_t *zio) zio->io_vd->vdev_stat.vs_slow_ios++; mutex_exit(&zio->io_vd->vdev_stat_lock); - zfs_ereport_post(FM_EREPORT_ZFS_DELAY, + (void) zfs_ereport_post(FM_EREPORT_ZFS_DELAY, zio->io_spa, zio->io_vd, &zio->io_bookmark, zio, 0, 0); } @@ -4565,7 +4565,7 @@ zio_done(zio_t *zio) } mutex_exit(&zio->io_vd->vdev_stat_lock); - zfs_ereport_post(FM_EREPORT_ZFS_IO, zio->io_spa, + (void) zfs_ereport_post(FM_EREPORT_ZFS_IO, zio->io_spa, zio->io_vd, &zio->io_bookmark, zio, 0, 0); } @@ -4577,8 +4577,8 @@ zio_done(zio_t *zio) * error and generate a logical data ereport. */ spa_log_error(zio->io_spa, &zio->io_bookmark); - zfs_ereport_post(FM_EREPORT_ZFS_DATA, zio->io_spa, - NULL, &zio->io_bookmark, zio, 0, 0); + (void) zfs_ereport_post(FM_EREPORT_ZFS_DATA, + zio->io_spa, NULL, &zio->io_bookmark, zio, 0, 0); } } diff --git a/tests/runfiles/common.run b/tests/runfiles/common.run index 851488602f85..fcd9684603b4 100644 --- a/tests/runfiles/common.run +++ b/tests/runfiles/common.run @@ -225,7 +225,7 @@ tests = ['zfs_rename_001_pos', 'zfs_rename_002_pos', 'zfs_rename_003_pos', 'zfs_rename_007_pos', 'zfs_rename_008_pos', 'zfs_rename_009_neg', 'zfs_rename_010_neg', 'zfs_rename_011_pos', 'zfs_rename_012_neg', 'zfs_rename_013_pos', 'zfs_rename_014_neg', 'zfs_rename_encrypted_child', - 'zfs_rename_to_encrypted', 'zfs_rename_mountpoint'] + 'zfs_rename_to_encrypted', 'zfs_rename_mountpoint', 'zfs_rename_nounmount'] tags = ['functional', 'cli_root', 'zfs_rename'] [tests/functional/cli_root/zfs_reservation] diff --git a/tests/zfs-tests/include/tunables.cfg b/tests/zfs-tests/include/tunables.cfg index 67a32af1d9c8..ad2811395332 100644 --- a/tests/zfs-tests/include/tunables.cfg +++ b/tests/zfs-tests/include/tunables.cfg @@ -54,7 +54,7 @@ MAX_MISSING_TVDS max_missing_tvds zfs_max_missing_tvds METASLAB_DEBUG_LOAD metaslab.debug_load metaslab_debug_load METASLAB_FORCE_GANGING metaslab.force_ganging metaslab_force_ganging MULTIHOST_FAIL_INTERVALS multihost.fail_intervals zfs_multihost_fail_intervals -MULTIHOST_HISTORY UNSUPPORTED zfs_multihost_history +MULTIHOST_HISTORY multihost.history zfs_multihost_history MULTIHOST_IMPORT_INTERVALS multihost.import_intervals zfs_multihost_import_intervals MULTIHOST_INTERVAL multihost.interval zfs_multihost_interval OVERRIDE_ESTIMATE_RECORDSIZE send.override_estimate_recordsize zfs_override_estimate_recordsize @@ -73,7 +73,7 @@ SPA_LOAD_VERIFY_METADATA spa.load_verify_metadata spa_load_verify_metadata TRIM_EXTENT_BYTES_MIN trim.extent_bytes_min zfs_trim_extent_bytes_min TRIM_METASLAB_SKIP trim.metaslab_skip zfs_trim_metaslab_skip TRIM_TXG_BATCH trim.txg_batch zfs_trim_txg_batch -TXG_HISTORY UNSUPPORTED zfs_txg_history +TXG_HISTORY txg.history zfs_txg_history TXG_TIMEOUT txg.timeout zfs_txg_timeout UNLINK_SUSPEND_PROGRESS UNSUPPORTED zfs_unlink_suspend_progress VDEV_MIN_MS_COUNT vdev.min_ms_count zfs_vdev_min_ms_count diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/Makefile.am index 406e27881523..f8273d72c569 100644 --- a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/Makefile.am +++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/Makefile.am @@ -18,7 +18,8 @@ dist_pkgdata_SCRIPTS = \ zfs_rename_014_neg.ksh \ zfs_rename_encrypted_child.ksh \ zfs_rename_to_encrypted.ksh \ - zfs_rename_mountpoint.ksh + zfs_rename_mountpoint.ksh \ + zfs_rename_nounmount.ksh dist_pkgdata_DATA = \ zfs_rename.cfg \ diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_mountpoint.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_mountpoint.ksh index 4d2b94dc887f..7ec6b2aa490c 100755 --- a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_mountpoint.ksh +++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_mountpoint.ksh @@ -34,8 +34,8 @@ verify_runnable "both" function rename_cleanup { - log_note zfs destroy -fR $TESTPOOL/rename_test - log_note zfs destroy -fR $TESTPOOL/renamed + zfs destroy -fR $TESTPOOL/rename_test + zfs destroy -fR $TESTPOOL/renamed } log_onexit rename_cleanup diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_nounmount.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_nounmount.ksh new file mode 100644 index 000000000000..1c707762a72c --- /dev/null +++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_nounmount.ksh @@ -0,0 +1,93 @@ +#!/bin/ksh -p +# +# CDDL HEADER START +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy is of the CDDL is also available via the Internet +# at http://www.illumos.org/license/CDDL. +# +# CDDL HEADER END +# + +# +# Copyright (c) 2019 iXsystems, Inc. +# + +. $STF_SUITE/include/libtest.shlib + +# +# DESCRIPTION: +# zfs rename -u should rename datasets without unmounting them +# +# STRATEGY: +# 1. Create a set of nested datasets. +# 2. Verify datasets are mounted. +# 3. Rename with -u and verify all datasets stayed mounted. +# + +verify_runnable "both" + +function rename_cleanup +{ + cd $back + zfs destroy -fR $TESTPOOL/rename_test + zfs destroy -fR $TESTPOOL/renamed +} + +back=$(pwd) +log_onexit rename_cleanup + +log_must zfs create $TESTPOOL/rename_test +log_must zfs create $TESTPOOL/rename_test/child +log_must zfs create $TESTPOOL/rename_test/child/grandchild + +if ! ismounted $TESTPOOL/rename_test; then + log_fail "$TESTPOOL/rename_test is not mounted" +fi +if ! ismounted $TESTPOOL/rename_test/child; then + log_fail "$TESTPOOL/rename_test/child is not mounted" +fi +if ! ismounted $TESTPOOL/rename_test/child/grandchild; then + log_fail "$TESTPOOL/rename_test/child/grandchild is not mounted" +fi + +mntp_p=$(get_prop mountpoint $TESTPOOL/rename_test) +mntp_c=$(get_prop mountpoint $TESTPOOL/rename_test/child) +mntp_g=$(get_prop mountpoint $TESTPOOL/rename_test/child/grandchild) + +log_must cd $mntp_g +log_mustnot zfs rename $TESTPOOL/rename_test $TESTPOOL/renamed +log_must zfs rename -u $TESTPOOL/rename_test $TESTPOOL/renamed + +log_mustnot zfs list $TESTPOOL/rename_test +log_mustnot zfs list $TESTPOOL/rename_test/child +log_mustnot zfs list $TESTPOOL/rename_test/child/grandchild + +log_must zfs list $TESTPOOL/renamed +log_must zfs list $TESTPOOL/renamed/child +log_must zfs list $TESTPOOL/renamed/child/grandchild + +missing=$(zfs mount | awk -v pat=$TESTPOOL/renamed '$1 ~ pat' | awk \ + -v mntp_p=$mntp_p \ + -v mntp_c=$mntp_c \ + -v mntp_g=$mntp_g ' + BEGIN { p = c = g = 0 } + $2 == mntp_p { p = 1 } + $2 == mntp_c { c = 1 } + $2 == mntp_g { g = 1 } + END { + if (p != 1) + print mntp_p + if (c != 1) + print mntp_c + if (g != 1) + print mntp_g + }') +[[ -z "$missing" ]] || log_fail "Mountpoints no longer mounted: $missing" + +log_pass "Verified rename -u does not unmount datasets"