diff --git a/include/Makefile.am b/include/Makefile.am
index 17286ecbb7fd..4da43afd850d 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -1,34 +1,33 @@
 SUBDIRS = sys os
 
 COMMON_H = \
 	cityhash.h \
 	zfeature_common.h \
 	zfs_comutil.h \
 	zfs_deleg.h \
 	zfs_fletcher.h \
 	zfs_namecheck.h \
 	zfs_prop.h
 
 USER_H = \
 	libnvpair.h \
 	libuutil_common.h \
 	libuutil.h \
 	libuutil_impl.h \
 	libzfs.h \
 	libzfsbootenv.h \
 	libzfs_core.h \
-	libzfs_impl.h \
 	libzutil.h \
 	thread_pool.h
 
 if CONFIG_USER
 libzfsdir = $(includedir)/libzfs
 libzfs_HEADERS = $(COMMON_H) $(USER_H)
 endif
 
 if CONFIG_KERNEL
 if BUILD_LINUX
 kerneldir = @prefix@/src/zfs-$(VERSION)/include
 kernel_HEADERS = $(COMMON_H)
 endif
 endif
diff --git a/lib/libshare/libshare.c b/lib/libshare/libshare.c
index d32a282a36e3..a228645fbf8f 100644
--- a/lib/libshare/libshare.c
+++ b/lib/libshare/libshare.c
@@ -1,366 +1,365 @@
 /*
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
  * Common Development and Distribution License (the "License").
  * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
  * See the License for the specific language governing permissions
  * and limitations under the License.
  *
  * When distributing Covered Code, include this CDDL HEADER in each
  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  * If applicable, add the following below this CDDL HEADER, with the
  * fields enclosed by brackets "[]" replaced with your own identifying
  * information: Portions Copyright [yyyy] [name of copyright owner]
  *
  * CDDL HEADER END
  */
 
 /*
  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2011 Gunnar Beutner
  * Copyright (c) 2018, 2020 by Delphix. All rights reserved.
  */
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <strings.h>
 #include <libintl.h>
 #include <sys/file.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
 #include <libzfs.h>
 #include <libshare.h>
-#include "libzfs_impl.h"
 #include "libshare_impl.h"
 #include "nfs.h"
 #include "smb.h"
 
 static sa_share_impl_t alloc_share(const char *zfsname, const char *path);
 static void free_share(sa_share_impl_t share);
 
 static int fstypes_count;
 static sa_fstype_t *fstypes;
 
 sa_fstype_t *
 register_fstype(const char *name, const sa_share_ops_t *ops)
 {
 	sa_fstype_t *fstype;
 
 	fstype = calloc(1, sizeof (sa_fstype_t));
 
 	if (fstype == NULL)
 		return (NULL);
 
 	fstype->name = name;
 	fstype->ops = ops;
 	fstype->fsinfo_index = fstypes_count;
 
 	fstypes_count++;
 
 	fstype->next = fstypes;
 	fstypes = fstype;
 
 	return (fstype);
 }
 
 __attribute__((constructor)) static void
 libshare_init(void)
 {
 	libshare_nfs_init();
 	libshare_smb_init();
 }
 
 int
 sa_enable_share(const char *zfsname, const char *mountpoint,
     const char *shareopts, char *protocol)
 {
 	int rc, ret = SA_OK;
 	boolean_t found_protocol = B_FALSE;
 	sa_fstype_t *fstype;
 
 	sa_share_impl_t impl_share = alloc_share(zfsname, mountpoint);
 	if (impl_share == NULL)
 		return (SA_NO_MEMORY);
 
 	fstype = fstypes;
 	while (fstype != NULL) {
 		if (strcmp(fstype->name, protocol) == 0) {
 
 			rc = fstype->ops->update_shareopts(impl_share,
 			    shareopts);
 			if (rc != SA_OK)
 				break;
 
 			rc = fstype->ops->enable_share(impl_share);
 			if (rc != SA_OK)
 				ret = rc;
 
 			found_protocol = B_TRUE;
 		}
 
 		fstype = fstype->next;
 	}
 	free_share(impl_share);
 
 	return (found_protocol ? ret : SA_INVALID_PROTOCOL);
 }
 
 int
 sa_disable_share(const char *mountpoint, char *protocol)
 {
 	int rc, ret = SA_OK;
 	boolean_t found_protocol = B_FALSE;
 	sa_fstype_t *fstype;
 
 	sa_share_impl_t impl_share = alloc_share(NULL, mountpoint);
 	if (impl_share == NULL)
 		return (SA_NO_MEMORY);
 
 	fstype = fstypes;
 	while (fstype != NULL) {
 		if (strcmp(fstype->name, protocol) == 0) {
 
 			rc = fstype->ops->disable_share(impl_share);
 			if (rc != SA_OK)
 				ret = rc;
 
 			found_protocol = B_TRUE;
 		}
 
 		fstype = fstype->next;
 	}
 	free_share(impl_share);
 
 	return (found_protocol ? ret : SA_INVALID_PROTOCOL);
 }
 
 boolean_t
 sa_is_shared(const char *mountpoint, char *protocol)
 {
 	sa_fstype_t *fstype;
 	boolean_t ret = B_FALSE;
 
 	/* guid value is not used */
 	sa_share_impl_t impl_share = alloc_share(NULL, mountpoint);
 	if (impl_share == NULL)
 		return (B_FALSE);
 
 	fstype = fstypes;
 	while (fstype != NULL) {
 		if (strcmp(fstype->name, protocol) == 0) {
 			ret = fstype->ops->is_shared(impl_share);
 		}
 		fstype = fstype->next;
 	}
 	free_share(impl_share);
 	return (ret);
 }
 
 void
 sa_commit_shares(const char *protocol)
 {
 	sa_fstype_t *fstype = fstypes;
 	while (fstype != NULL) {
 		if (strcmp(fstype->name, protocol) == 0)
 			fstype->ops->commit_shares();
 		fstype = fstype->next;
 	}
 }
 
 /*
  * sa_errorstr(err)
  *
  * convert an error value to an error string
  */
 char *
 sa_errorstr(int err)
 {
 	static char errstr[32];
 	char *ret = NULL;
 
 	switch (err) {
 	case SA_OK:
 		ret = dgettext(TEXT_DOMAIN, "ok");
 		break;
 	case SA_NO_SUCH_PATH:
 		ret = dgettext(TEXT_DOMAIN, "path doesn't exist");
 		break;
 	case SA_NO_MEMORY:
 		ret = dgettext(TEXT_DOMAIN, "no memory");
 		break;
 	case SA_DUPLICATE_NAME:
 		ret = dgettext(TEXT_DOMAIN, "name in use");
 		break;
 	case SA_BAD_PATH:
 		ret = dgettext(TEXT_DOMAIN, "bad path");
 		break;
 	case SA_NO_SUCH_GROUP:
 		ret = dgettext(TEXT_DOMAIN, "no such group");
 		break;
 	case SA_CONFIG_ERR:
 		ret = dgettext(TEXT_DOMAIN, "configuration error");
 		break;
 	case SA_SYSTEM_ERR:
 		ret = dgettext(TEXT_DOMAIN, "system error");
 		break;
 	case SA_SYNTAX_ERR:
 		ret = dgettext(TEXT_DOMAIN, "syntax error");
 		break;
 	case SA_NO_PERMISSION:
 		ret = dgettext(TEXT_DOMAIN, "no permission");
 		break;
 	case SA_BUSY:
 		ret = dgettext(TEXT_DOMAIN, "busy");
 		break;
 	case SA_NO_SUCH_PROP:
 		ret = dgettext(TEXT_DOMAIN, "no such property");
 		break;
 	case SA_INVALID_NAME:
 		ret = dgettext(TEXT_DOMAIN, "invalid name");
 		break;
 	case SA_INVALID_PROTOCOL:
 		ret = dgettext(TEXT_DOMAIN, "invalid protocol");
 		break;
 	case SA_NOT_ALLOWED:
 		ret = dgettext(TEXT_DOMAIN, "operation not allowed");
 		break;
 	case SA_BAD_VALUE:
 		ret = dgettext(TEXT_DOMAIN, "bad property value");
 		break;
 	case SA_INVALID_SECURITY:
 		ret = dgettext(TEXT_DOMAIN, "invalid security type");
 		break;
 	case SA_NO_SUCH_SECURITY:
 		ret = dgettext(TEXT_DOMAIN, "security type not found");
 		break;
 	case SA_VALUE_CONFLICT:
 		ret = dgettext(TEXT_DOMAIN, "property value conflict");
 		break;
 	case SA_NOT_IMPLEMENTED:
 		ret = dgettext(TEXT_DOMAIN, "not implemented");
 		break;
 	case SA_INVALID_PATH:
 		ret = dgettext(TEXT_DOMAIN, "invalid path");
 		break;
 	case SA_NOT_SUPPORTED:
 		ret = dgettext(TEXT_DOMAIN, "operation not supported");
 		break;
 	case SA_PROP_SHARE_ONLY:
 		ret = dgettext(TEXT_DOMAIN, "property not valid for group");
 		break;
 	case SA_NOT_SHARED:
 		ret = dgettext(TEXT_DOMAIN, "not shared");
 		break;
 	case SA_NO_SUCH_RESOURCE:
 		ret = dgettext(TEXT_DOMAIN, "no such resource");
 		break;
 	case SA_RESOURCE_REQUIRED:
 		ret = dgettext(TEXT_DOMAIN, "resource name required");
 		break;
 	case SA_MULTIPLE_ERROR:
 		ret = dgettext(TEXT_DOMAIN, "errors from multiple protocols");
 		break;
 	case SA_PATH_IS_SUBDIR:
 		ret = dgettext(TEXT_DOMAIN, "path is a subpath of share");
 		break;
 	case SA_PATH_IS_PARENTDIR:
 		ret = dgettext(TEXT_DOMAIN, "path is parent of a share");
 		break;
 	case SA_NO_SECTION:
 		ret = dgettext(TEXT_DOMAIN, "protocol requires a section");
 		break;
 	case SA_NO_PROPERTIES:
 		ret = dgettext(TEXT_DOMAIN, "properties not found");
 		break;
 	case SA_NO_SUCH_SECTION:
 		ret = dgettext(TEXT_DOMAIN, "section not found");
 		break;
 	case SA_PASSWORD_ENC:
 		ret = dgettext(TEXT_DOMAIN, "passwords must be encrypted");
 		break;
 	case SA_SHARE_EXISTS:
 		ret = dgettext(TEXT_DOMAIN, "path or file is already shared");
 		break;
 	default:
 		(void) snprintf(errstr, sizeof (errstr),
 		    dgettext(TEXT_DOMAIN, "unknown %d"), err);
 		ret = errstr;
 	}
 	return (ret);
 }
 
 int
 sa_validate_shareopts(char *options, char *proto)
 {
 	sa_fstype_t *fstype;
 
 	fstype = fstypes;
 	while (fstype != NULL) {
 		if (strcmp(fstype->name, proto) != 0) {
 			fstype = fstype->next;
 			continue;
 		}
 
 		return (fstype->ops->validate_shareopts(options));
 	}
 
 	return (SA_INVALID_PROTOCOL);
 }
 
 static sa_share_impl_t
 alloc_share(const char *zfsname, const char *mountpoint)
 {
 	sa_share_impl_t impl_share;
 
 	impl_share = calloc(1, sizeof (struct sa_share_impl));
 
 	if (impl_share == NULL)
 		return (NULL);
 
 	if (mountpoint != NULL &&
 	    ((impl_share->sa_mountpoint = strdup(mountpoint)) == NULL)) {
 		free(impl_share);
 		return (NULL);
 	}
 
 	if (zfsname != NULL &&
 	    ((impl_share->sa_zfsname = strdup(zfsname)) == NULL)) {
 		free(impl_share->sa_mountpoint);
 		free(impl_share);
 		return (NULL);
 	}
 
 	impl_share->sa_fsinfo = calloc(fstypes_count,
 	    sizeof (sa_share_fsinfo_t));
 	if (impl_share->sa_fsinfo == NULL) {
 		free(impl_share->sa_mountpoint);
 		free(impl_share->sa_zfsname);
 		free(impl_share);
 		return (NULL);
 	}
 
 	return (impl_share);
 }
 
 static void
 free_share(sa_share_impl_t impl_share)
 {
 	sa_fstype_t *fstype;
 
 	fstype = fstypes;
 	while (fstype != NULL) {
 		fstype->ops->clear_shareopts(impl_share);
 		fstype = fstype->next;
 	}
 
 	free(impl_share->sa_mountpoint);
 	free(impl_share->sa_zfsname);
 	free(impl_share->sa_fsinfo);
 	free(impl_share);
 }
diff --git a/lib/libshare/os/freebsd/nfs.c b/lib/libshare/os/freebsd/nfs.c
index 323c9269f188..b82491f2ebe8 100644
--- a/lib/libshare/os/freebsd/nfs.c
+++ b/lib/libshare/os/freebsd/nfs.c
@@ -1,342 +1,342 @@
 /*
  * Copyright (c) 2007 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.
  *
  * Copyright (c) 2020 by Delphix. All rights reserved.
  */
 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/vfs.h>
 
 #include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <libutil.h>
 #include <signal.h>
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 #include <libintl.h>
 
-#include "libzfs_impl.h"
+#include <libshare.h>
 #include "libshare_impl.h"
 #include "nfs.h"
 
 #define	_PATH_MOUNTDPID	"/var/run/mountd.pid"
 #define	OPTSSIZE	1024
 #define	MAXLINESIZE	(PATH_MAX + OPTSSIZE)
 #define	ZFS_EXPORTS_FILE	"/etc/zfs/exports"
 #define	ZFS_EXPORTS_LOCK	ZFS_EXPORTS_FILE".lock"
 
 static sa_fstype_t *nfs_fstype;
 
 /*
  * Read one line from a file. Skip comments, empty lines and a line with a
  * mountpoint specified in the 'skip' argument.
  *
  * NOTE: This function returns a static buffer and thus is not thread-safe.
  */
 static char *
 zgetline(FILE *fd, const char *skip)
 {
 	static char line[MAXLINESIZE];
 	size_t len, skiplen = 0;
 	char *s, last;
 
 	if (skip != NULL)
 		skiplen = strlen(skip);
 	for (;;) {
 		s = fgets(line, sizeof (line), fd);
 		if (s == NULL)
 			return (NULL);
 		/* Skip empty lines and comments. */
 		if (line[0] == '\n' || line[0] == '#')
 			continue;
 		len = strlen(line);
 		if (line[len - 1] == '\n')
 			line[len - 1] = '\0';
 		last = line[skiplen];
 		/* Skip the given mountpoint. */
 		if (skip != NULL && strncmp(skip, line, skiplen) == 0 &&
 		    (last == '\t' || last == ' ' || last == '\0')) {
 			continue;
 		}
 		break;
 	}
 	return (line);
 }
 
 /*
  * This function translate options to a format acceptable by exports(5), eg.
  *
  *	-ro -network=192.168.0.0 -mask=255.255.255.0 -maproot=0 \
  *	zfs.freebsd.org 69.147.83.54
  *
  * Accepted input formats:
  *
  *	ro,network=192.168.0.0,mask=255.255.255.0,maproot=0,zfs.freebsd.org
  *	ro network=192.168.0.0 mask=255.255.255.0 maproot=0 zfs.freebsd.org
  *	-ro,-network=192.168.0.0,-mask=255.255.255.0,-maproot=0,zfs.freebsd.org
  *	-ro -network=192.168.0.0 -mask=255.255.255.0 -maproot=0 \
  *	zfs.freebsd.org
  *
  * Recognized keywords:
  *
  *	ro, maproot, mapall, mask, network, sec, alldirs, public, webnfs,
  *	index, quiet
  *
  * NOTE: This function returns a static buffer and thus is not thread-safe.
  */
 static char *
 translate_opts(const char *shareopts)
 {
 	static const char *known_opts[] = { "ro", "maproot", "mapall", "mask",
 	    "network", "sec", "alldirs", "public", "webnfs", "index", "quiet",
 	    NULL };
 	static char newopts[OPTSSIZE];
 	char oldopts[OPTSSIZE];
 	char *o, *s = NULL;
 	unsigned int i;
 	size_t len;
 
 	strlcpy(oldopts, shareopts, sizeof (oldopts));
 	newopts[0] = '\0';
 	s = oldopts;
 	while ((o = strsep(&s, "-, ")) != NULL) {
 		if (o[0] == '\0')
 			continue;
 		for (i = 0; known_opts[i] != NULL; i++) {
 			len = strlen(known_opts[i]);
 			if (strncmp(known_opts[i], o, len) == 0 &&
 			    (o[len] == '\0' || o[len] == '=')) {
 				strlcat(newopts, "-", sizeof (newopts));
 				break;
 			}
 		}
 		strlcat(newopts, o, sizeof (newopts));
 		strlcat(newopts, " ", sizeof (newopts));
 	}
 	return (newopts);
 }
 
 /*
  * This function copies all entries from the exports file to "filename",
  * omitting any entries for the specified mountpoint.
  */
 __attribute__((visibility("hidden"))) int
 nfs_copy_entries(char *filename, const char *mountpoint)
 {
 	int error = SA_OK;
 	char *line;
 
 	FILE *oldfp = fopen(ZFS_EXPORTS_FILE, "re");
 	FILE *newfp = fopen(filename, "w+e");
 	if (newfp == NULL) {
 		fprintf(stderr, "failed to open %s file: %s", filename,
 		    strerror(errno));
 		fclose(oldfp);
 		return (SA_SYSTEM_ERR);
 	}
 	fputs(FILE_HEADER, newfp);
 
 	/*
 	 * The ZFS_EXPORTS_FILE may not exist yet. If that's the
 	 * case then just write out the new file.
 	 */
 	if (oldfp != NULL) {
 		while ((line = zgetline(oldfp, mountpoint)) != NULL)
 			fprintf(newfp, "%s\n", line);
 		if (ferror(oldfp) != 0) {
 			error = ferror(oldfp);
 		}
 		if (fclose(oldfp) != 0) {
 			fprintf(stderr, "Unable to close file %s: %s\n",
 			    filename, strerror(errno));
 			error = error != 0 ? error : SA_SYSTEM_ERR;
 		}
 	}
 
 	if (error == 0 && ferror(newfp) != 0) {
 		error = ferror(newfp);
 	}
 
 	if (fclose(newfp) != 0) {
 		fprintf(stderr, "Unable to close file %s: %s\n",
 		    filename, strerror(errno));
 		error = error != 0 ? error : SA_SYSTEM_ERR;
 	}
 	return (error);
 }
 
 static int
 nfs_enable_share_impl(sa_share_impl_t impl_share, char *filename)
 {
 	FILE *fp = fopen(filename, "a+e");
 	if (fp == NULL) {
 		fprintf(stderr, "failed to open %s file: %s", filename,
 		    strerror(errno));
 		return (SA_SYSTEM_ERR);
 	}
 
 	char *shareopts = FSINFO(impl_share, nfs_fstype)->shareopts;
 	if (strcmp(shareopts, "on") == 0)
 		shareopts = "";
 
 	if (fprintf(fp, "%s\t%s\n", impl_share->sa_mountpoint,
 	    translate_opts(shareopts)) < 0) {
 		fprintf(stderr, "failed to write to %s\n", filename);
 		fclose(fp);
 		return (SA_SYSTEM_ERR);
 	}
 
 	if (fclose(fp) != 0) {
 		fprintf(stderr, "Unable to close file %s: %s\n",
 		    filename, strerror(errno));
 		return (SA_SYSTEM_ERR);
 	}
 
 	return (SA_OK);
 }
 
 static int
 nfs_enable_share(sa_share_impl_t impl_share)
 {
 	return (nfs_toggle_share(
 	    ZFS_EXPORTS_LOCK, ZFS_EXPORTS_FILE, NULL, impl_share,
 	    nfs_enable_share_impl));
 }
 
 static int
 nfs_disable_share_impl(sa_share_impl_t impl_share, char *filename)
 {
 	return (SA_OK);
 }
 
 static int
 nfs_disable_share(sa_share_impl_t impl_share)
 {
 	return (nfs_toggle_share(
 	    ZFS_EXPORTS_LOCK, ZFS_EXPORTS_FILE, NULL, impl_share,
 	    nfs_disable_share_impl));
 }
 
 static boolean_t
 nfs_is_shared(sa_share_impl_t impl_share)
 {
 	char *s, last, line[MAXLINESIZE];
 	size_t len;
 	char *mntpoint = impl_share->sa_mountpoint;
 	size_t mntlen = strlen(mntpoint);
 
 	FILE *fp = fopen(ZFS_EXPORTS_FILE, "re");
 	if (fp == NULL)
 		return (B_FALSE);
 
 	for (;;) {
 		s = fgets(line, sizeof (line), fp);
 		if (s == NULL)
 			return (B_FALSE);
 		/* Skip empty lines and comments. */
 		if (line[0] == '\n' || line[0] == '#')
 			continue;
 		len = strlen(line);
 		if (line[len - 1] == '\n')
 			line[len - 1] = '\0';
 		last = line[mntlen];
 		/* Skip the given mountpoint. */
 		if (strncmp(mntpoint, line, mntlen) == 0 &&
 		    (last == '\t' || last == ' ' || last == '\0')) {
 			fclose(fp);
 			return (B_TRUE);
 		}
 	}
 	fclose(fp);
 	return (B_FALSE);
 }
 
 static int
 nfs_validate_shareopts(const char *shareopts)
 {
 	return (SA_OK);
 }
 
 static int
 nfs_update_shareopts(sa_share_impl_t impl_share, const char *shareopts)
 {
 	FSINFO(impl_share, nfs_fstype)->shareopts = (char *)shareopts;
 	return (SA_OK);
 }
 
 static void
 nfs_clear_shareopts(sa_share_impl_t impl_share)
 {
 	FSINFO(impl_share, nfs_fstype)->shareopts = NULL;
 }
 
 /*
  * Commit the shares by restarting mountd.
  */
 static int
 nfs_commit_shares(void)
 {
 	struct pidfh *pfh;
 	pid_t mountdpid;
 
 	pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &mountdpid);
 	if (pfh != NULL) {
 		/* Mountd is not running. */
 		pidfile_remove(pfh);
 		return (SA_OK);
 	}
 	if (errno != EEXIST) {
 		/* Cannot open pidfile for some reason. */
 		return (SA_SYSTEM_ERR);
 	}
 	/* We have mountd(8) PID in mountdpid variable. */
 	kill(mountdpid, SIGHUP);
 	return (SA_OK);
 }
 
 static const sa_share_ops_t nfs_shareops = {
 	.enable_share = nfs_enable_share,
 	.disable_share = nfs_disable_share,
 	.is_shared = nfs_is_shared,
 
 	.validate_shareopts = nfs_validate_shareopts,
 	.update_shareopts = nfs_update_shareopts,
 	.clear_shareopts = nfs_clear_shareopts,
 	.commit_shares = nfs_commit_shares,
 };
 
 /*
  * Initializes the NFS functionality of libshare.
  */
 void
 libshare_nfs_init(void)
 {
 	nfs_fstype = register_fstype("nfs", &nfs_shareops);
 }
diff --git a/lib/libzfs/Makefile.am b/lib/libzfs/Makefile.am
index 31267fd9a5e9..9385eb1aadbb 100644
--- a/lib/libzfs/Makefile.am
+++ b/lib/libzfs/Makefile.am
@@ -1,98 +1,99 @@
 include $(top_srcdir)/config/Rules.am
 
 VPATH = \
 	$(top_srcdir)/module/icp \
 	$(top_srcdir)/module/zcommon \
 	$(top_srcdir)/lib/libzfs
 
 # Suppress unused but set variable warnings often due to ASSERTs
 AM_CFLAGS += $(NO_UNUSED_BUT_SET_VARIABLE)
 AM_CFLAGS += $(LIBCRYPTO_CFLAGS) $(ZLIB_CFLAGS)
 
 pkgconfig_DATA = libzfs.pc
 
 lib_LTLIBRARIES = libzfs.la
 
 include $(top_srcdir)/config/Abigail.am
 
 USER_C = \
+	libzfs_impl.h \
 	libzfs_changelist.c \
 	libzfs_config.c \
 	libzfs_crypto.c \
 	libzfs_dataset.c \
 	libzfs_diff.c \
 	libzfs_import.c \
 	libzfs_iter.c \
 	libzfs_mount.c \
 	libzfs_pool.c \
 	libzfs_sendrecv.c \
 	libzfs_status.c \
 	libzfs_util.c
 
 
 if BUILD_FREEBSD
 USER_C += \
 	os/freebsd/libzfs_compat.c \
 	os/freebsd/libzfs_ioctl_compat.c \
 	os/freebsd/libzfs_zmount.c
 endif
 
 if BUILD_LINUX
 USER_C += \
 	os/linux/libzfs_mount_os.c \
 	os/linux/libzfs_pool_os.c \
 	os/linux/libzfs_sendrecv_os.c \
 	os/linux/libzfs_util_os.c
 endif
 
 KERNEL_C = \
 	algs/sha2/sha2.c \
 	cityhash.c \
 	zfeature_common.c \
 	zfs_comutil.c \
 	zfs_deleg.c \
 	zfs_fletcher.c \
 	zfs_fletcher_aarch64_neon.c \
 	zfs_fletcher_avx512.c \
 	zfs_fletcher_intel.c \
 	zfs_fletcher_sse.c \
 	zfs_fletcher_superscalar.c \
 	zfs_fletcher_superscalar4.c \
 	zfs_namecheck.c \
 	zfs_prop.c \
 	zpool_prop.c \
 	zprop_common.c
 
 dist_libzfs_la_SOURCES = \
 	$(USER_C)
 
 nodist_libzfs_la_SOURCES = \
 	$(KERNEL_C)
 
 libzfs_la_LIBADD = \
 	$(abs_top_builddir)/lib/libshare/libshare.la \
 	$(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \
 	$(abs_top_builddir)/lib/libnvpair/libnvpair.la \
 	$(abs_top_builddir)/lib/libuutil/libuutil.la
 
 libzfs_la_LIBADD += -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 5:0:1
 
 include $(top_srcdir)/config/CppCheck.am
 
 # Library ABI
 EXTRA_DIST = libzfs.abi libzfs.suppr
 
 # Licensing data
 EXTRA_DIST += THIRDPARTYLICENSE.openssl THIRDPARTYLICENSE.openssl.descrip
diff --git a/include/libzfs_impl.h b/lib/libzfs/libzfs_impl.h
similarity index 100%
rename from include/libzfs_impl.h
rename to lib/libzfs/libzfs_impl.h
diff --git a/lib/libzfs/libzfs_import.c b/lib/libzfs/libzfs_import.c
index 64fa31c67d0f..0d375b355166 100644
--- a/lib/libzfs/libzfs_import.c
+++ b/lib/libzfs/libzfs_import.c
@@ -1,471 +1,471 @@
 /*
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
  * Common Development and Distribution License (the "License").
  * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
  * See the License for the specific language governing permissions
  * and limitations under the License.
  *
  * When distributing Covered Code, include this CDDL HEADER in each
  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  * If applicable, add the following below this CDDL HEADER, with the
  * fields enclosed by brackets "[]" replaced with your own identifying
  * information: Portions Copyright [yyyy] [name of copyright owner]
  *
  * CDDL HEADER END
  */
 /*
  * Copyright 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 "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;
 	uint64_t theguid;
 
 	if (zpool_open_silent(hdl, name, &zhp) != 0)
 		return (-1);
 
 	if (zhp == NULL) {
 		*isactive = B_FALSE;
 		return (0);
 	}
 
 	verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_POOL_GUID,
 	    &theguid) == 0);
 
 	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;
 
 	if (zcmd_write_conf_nvlist(hdl, &zc, config) != 0)
 		return (NULL);
 
 	dstbuf_size = MAX(CONFIG_BUF_MINSIZE, zc.zc_nvlist_conf_size * 32);
 
 	if (zcmd_alloc_dst_nvlist(hdl, &zc, dstbuf_size) != 0) {
 		zcmd_free_nvlists(&zc);
 		return (NULL);
 	}
 
 	while ((err = zfs_ioctl(hdl, ZFS_IOC_POOL_TRYIMPORT,
 	    &zc)) != 0 && errno == ENOMEM) {
 		if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) {
 			zcmd_free_nvlists(&zc);
 			return (NULL);
 		}
 	}
 
 	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)
 {
 	ASSERT(P2PHASE_TYPED(size, sizeof (vdev_label_t), uint64_t) == 0);
 	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;
 	l2arc_dev_hdr_phys_t *l2dhdr;
 	uint64_t size;
 	int labels_cleared = 0, header_cleared = 0;
 	boolean_t clear_l2arc_header = 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);
 
 	if ((l2dhdr = calloc(1, sizeof (l2arc_dev_hdr_phys_t))) == NULL) {
 		free(label);
 		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++;
 		}
 	}
 
 	/* Clear the L2ARC header. */
 	if (clear_l2arc_header) {
 		memset(l2dhdr, 0, sizeof (l2arc_dev_hdr_phys_t));
 		if (pwrite64(fd, l2dhdr, sizeof (l2arc_dev_hdr_phys_t),
 		    VDEV_LABEL_START_SIZE) == sizeof (l2arc_dev_hdr_phys_t)) {
 			header_cleared++;
 		}
 	}
 
 	free(label);
 	free(l2dhdr);
 
 	if (labels_cleared == 0)
 		return (-1);
 
 	return (0);
 }
 
 static boolean_t
 find_guid(nvlist_t *nv, uint64_t guid)
 {
 	uint64_t tmp;
 	nvlist_t **child;
 	uint_t c, children;
 
 	verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &tmp) == 0);
 	if (tmp == 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 i, count;
 	uint64_t guid;
 	nvlist_t *nvroot;
 
 	verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
 	    &nvroot) == 0);
 
 	if (nvlist_lookup_nvlist_array(nvroot, cbp->cb_type,
 	    &list, &count) == 0) {
 		for (i = 0; i < count; i++) {
 			verify(nvlist_lookup_uint64(list[i],
 			    ZPOOL_CONFIG_GUID, &guid) == 0);
 			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;
 	char *name;
 	boolean_t ret;
 	uint64_t guid, 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) {
 		(void) no_memory(hdl);
 		return (-1);
 	}
 
 	if (config == NULL)
 		return (0);
 
 	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
 	    &stateval) == 0);
 	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_GUID,
 	    &vdev_guid) == 0);
 
 	if (stateval != POOL_STATE_SPARE && stateval != POOL_STATE_L2CACHE) {
 		verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
 		    &name) == 0);
 		verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
 		    &guid) == 0);
 	}
 
 	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;
 
 				verify(nvlist_lookup_nvlist(pool_config,
 				    ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
 				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) {
 		if ((*namestr = zfs_strdup(hdl, name)) == NULL) {
 			if (cb.cb_zhp)
 				zpool_close(cb.cb_zhp);
 			nvlist_free(config);
 			return (-1);
 		}
 		*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/os/freebsd/libzfs_compat.c b/lib/libzfs/os/freebsd/libzfs_compat.c
index 3c5f684c6889..4d7421df8d3b 100644
--- a/lib/libzfs/os/freebsd/libzfs_compat.c
+++ b/lib/libzfs/os/freebsd/libzfs_compat.c
@@ -1,355 +1,355 @@
 /*
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
  * Common Development and Distribution License (the "License").
  * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
  * See the License for the specific language governing permissions
  * and limitations under the License.
  *
  * When distributing Covered Code, include this CDDL HEADER in each
  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  * If applicable, add the following below this CDDL HEADER, with the
  * fields enclosed by brackets "[]" replaced with your own identifying
  * information: Portions Copyright [yyyy] [name of copyright owner]
  *
  * CDDL HEADER END
  */
 
 /*
  * Copyright (c) 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
  */
 #include <os/freebsd/zfs/sys/zfs_ioctl_compat.h>
-#include <libzfs_impl.h>
+#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
 
 void
 libzfs_set_pipe_max(int infd)
 {
 	/* FreeBSD automatically resizes */
 }
 
 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;
 		}
 		bcopy(p, buf, lp);
 		buf[lp] = '/';
 		bcopy(name, buf + lp + 1, 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;
 				bcopy(argv + 1, memp + 2,
 				    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));
 }
 
 #define	ERRBUFLEN 256
 
 static __thread char errbuf[ERRBUFLEN];
 
 const char *
 libzfs_error_init(int error)
 {
 	char *msg = errbuf;
 	size_t len, msglen = ERRBUFLEN;
 
 	if (modfind("zfs") < 0) {
 		len = snprintf(msg, msglen, dgettext(TEXT_DOMAIN,
 		    "Failed to load %s module: "), ZFS_KMOD);
 		msg += len;
 		msglen -= len;
 	}
 
 	(void) snprintf(msg, msglen, "%s", strerror(error));
 
 	return (errbuf);
 }
 
 int
 zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc)
 {
 	return (zfs_ioctl_fd(hdl->libzfs_fd, request, zc));
 }
 
 /*
  * 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)
 {
 	return (0);
 }
 
 int
 zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, const char *name)
 {
 	return (0);
 }
 
 int
 find_shares_object(differ_info_t *di)
 {
 	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"};
 	char errbuf[1024];
 	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_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;
 	int error;
 
 	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);
 	error = zcmd_write_src_nvlist(hdl, &zc, args);
 	if (error == 0)
 		error = zfs_ioctl(hdl, ZFS_IOC_NEXTBOOT, &zc);
 	zcmd_free_nvlists(&zc);
 	nvlist_free(args);
 	return (error);
 }
 
 /*
  * Fill given version buffer with zfs kernel version.
  * Returns 0 on success, and -1 on error (with errno set)
  */
 int
 zfs_version_kernel(char *version, int len)
 {
 	size_t l = len;
 
 	return (sysctlbyname("vfs.zfs.version.module",
 	    version, &l, NULL, 0));
 }
diff --git a/lib/libzfs/os/freebsd/libzfs_zmount.c b/lib/libzfs/os/freebsd/libzfs_zmount.c
index 699d330ebdb4..e1febe6a2d91 100644
--- a/lib/libzfs/os/freebsd/libzfs_zmount.c
+++ b/lib/libzfs/os/freebsd/libzfs_zmount.c
@@ -1,135 +1,135 @@
 /*
  * 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/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #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"
+#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;
 }
 
 static int
 do_mount_(const char *spec, const char *dir, int mflag, char *fstype,
     char *dataptr, int datalen, char *optptr, int optlen)
 {
 	struct iovec *iov;
 	char *optstr, *p, *tofree;
 	int iovlen, rv;
 
 	assert(spec != NULL);
 	assert(dir != NULL);
 	assert(fstype != NULL);
 	assert(strcmp(fstype, MNTTYPE_ZFS) == 0);
 	assert(dataptr == NULL);
 	assert(datalen == 0);
 	assert(optptr != NULL);
 	assert(optlen > 0);
 
 	tofree = optstr = strdup(optptr);
 	assert(optstr != NULL);
 
 	iov = NULL;
 	iovlen = 0;
 	if (strstr(optstr, MNTOPT_REMOUNT) != NULL)
 		build_iovec(&iov, &iovlen, "update", NULL, 0);
 	if (mflag & MS_RDONLY)
 		build_iovec(&iov, &iovlen, "ro", NULL, 0);
 	build_iovec(&iov, &iovlen, "fstype", fstype, (size_t)-1);
 	build_iovec(&iov, &iovlen, "fspath", __DECONST(char *, dir),
 	    (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_mount(zfs_handle_t *zhp, const char *mntpt, char *opts, int flags)
 {
 
 	return (do_mount_(zfs_get_name(zhp), mntpt, flags, MNTTYPE_ZFS, NULL, 0,
 	    opts, sizeof (mntpt)));
 }
 
 int
 do_unmount(const char *mntpt, int flags)
 {
 	if (unmount(mntpt, flags) < 0)
 		return (errno);
 	return (0);
 }
 
 int
 zfs_mount_delegation_check(void)
 {
 	return (0);
 }
diff --git a/lib/libzfs/os/linux/libzfs_mount_os.c b/lib/libzfs/os/linux/libzfs_mount_os.c
index 21d64053862e..547895d7e370 100644
--- a/lib/libzfs/os/linux/libzfs_mount_os.c
+++ b/lib/libzfs/os/linux/libzfs_mount_os.c
@@ -1,413 +1,413 @@
 /*
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
  * Common Development and Distribution License (the "License").
  * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
  * See the License for the specific language governing permissions
  * and limitations under the License.
  *
  * When distributing Covered Code, include this CDDL HEADER in each
  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  * If applicable, add the following below this CDDL HEADER, with the
  * fields enclosed by brackets "[]" replaced with your own identifying
  * information: Portions Copyright [yyyy] [name of copyright owner]
  *
  * CDDL HEADER END
  */
 
 /*
  * Copyright 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 <strings.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 "../../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	},
 #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(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, 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;
 		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] = {
 		    "/bin/mount",
 		    "--no-canonicalize",
 		    "-t", MNTTYPE_ZFS,
 		    "-o", 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(const char *mntpt, int flags)
 {
 	if (!libzfs_envvar_is_set("ZFS_MOUNT_HELPER")) {
 		int rv = umount2(mntpt, flags);
 
 		return (rv < 0 ? errno : 0);
 	}
 
 	char force_opt[] = "-f";
 	char lazy_opt[] = "-l";
 	char *argv[7] = {
 	    "/bin/umount",
 	    "-t", MNTTYPE_ZFS,
 	    NULL, NULL, NULL, NULL };
 	int rc, count = 3;
 
 	if (flags & MS_FORCE) {
 		argv[count] = force_opt;
 		count++;
 	}
 
 	if (flags & MS_DETACH) {
 		argv[count] = lazy_opt;
 		count++;
 	}
 
 	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);
 }
diff --git a/lib/libzfs/os/linux/libzfs_pool_os.c b/lib/libzfs/os/linux/libzfs_pool_os.c
index 747b5652f7c0..90eb8db50790 100644
--- a/lib/libzfs/os/linux/libzfs_pool_os.c
+++ b/lib/libzfs/os/linux/libzfs_pool_os.c
@@ -1,342 +1,342 @@
 /*
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
  * Common Development and Distribution License (the "License").
  * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
  * See the License for the specific language governing permissions
  * and limitations under the License.
  *
  * When distributing Covered Code, include this CDDL HEADER in each
  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  * If applicable, add the following below this CDDL HEADER, with the
  * fields enclosed by brackets "[]" replaced with your own identifying
  * information: Portions Copyright [yyyy] [name of copyright owner]
  *
  * CDDL HEADER END
  */
 
 /*
  * Copyright 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 <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/vtoc.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 "../../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)
 {
 	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[1024];
 
 	/* prepare an error message just in case */
 	(void) snprintf(errbuf, sizeof (errbuf),
 	    dgettext(TEXT_DOMAIN, "cannot label '%s'"), name);
 
 	if (zhp) {
 		nvlist_t *nvroot;
 
 		verify(nvlist_lookup_nvlist(zhp->zpool_config,
 		    ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
 
 		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(slice_size, PARTITION_END_ALIGNMENT);
 
 	vtoc->efi_parts[0].p_start = start_block;
 	vtoc->efi_parts[0].p_size = slice_size;
 
 	/*
 	 * 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.  V_ROOT, V_BOOT,
 	 * etc. 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_sendrecv_os.c b/lib/libzfs/os/linux/libzfs_sendrecv_os.c
index ac7ab95a39b6..593c38ec62df 100644
--- a/lib/libzfs/os/linux/libzfs_sendrecv_os.c
+++ b/lib/libzfs/os/linux/libzfs_sendrecv_os.c
@@ -1,52 +1,52 @@
 /*
  * 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
  */
 
 
 #include <libzfs.h>
 
-#include "libzfs_impl.h"
+#include "../../libzfs_impl.h"
 
 #ifndef F_SETPIPE_SZ
 #define	F_SETPIPE_SZ (F_SETLEASE + 7)
 #endif /* F_SETPIPE_SZ */
 
 #ifndef F_GETPIPE_SZ
 #define	F_GETPIPE_SZ (F_GETLEASE + 7)
 #endif /* F_GETPIPE_SZ */
 
 void
 libzfs_set_pipe_max(int infd)
 {
 	FILE *procf = fopen("/proc/sys/fs/pipe-max-size", "re");
 
 	if (procf != NULL) {
 		unsigned long max_psize;
 		long cur_psize;
 		if (fscanf(procf, "%lu", &max_psize) > 0) {
 			cur_psize = fcntl(infd, F_GETPIPE_SZ);
 			if (cur_psize > 0 &&
 			    max_psize > (unsigned long) cur_psize)
 				fcntl(infd, F_SETPIPE_SZ,
 				    max_psize);
 		}
 		fclose(procf);
 	}
 }
diff --git a/lib/libzfs/os/linux/libzfs_util_os.c b/lib/libzfs/os/linux/libzfs_util_os.c
index e2482c57135a..b116f92d97af 100644
--- a/lib/libzfs/os/linux/libzfs_util_os.c
+++ b/lib/libzfs/os/linux/libzfs_util_os.c
@@ -1,215 +1,215 @@
 /*
  * 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
  */
 
 
 #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>
 #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 "../../libzfs_impl.h"
 #include "zfs_prop.h"
 #include <libzutil.h>
 #include <sys/zfs_sysfs.h>
 
 #define	ZDIFF_SHARESDIR		"/.zfs/shares/"
 
 int
 zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc)
 {
 	return (ioctl(hdl->libzfs_fd, request, zc));
 }
 
 const char *
 libzfs_error_init(int error)
 {
 	switch (error) {
 	case ENXIO:
 		return (dgettext(TEXT_DOMAIN, "The ZFS modules are not "
 		    "loaded.\nTry running '/sbin/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 '/sbin/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."));
 	}
 }
 
 static int
 libzfs_module_loaded(const char *module)
 {
 	const char path_prefix[] = "/sys/module/";
 	char path[256];
 
 	memcpy(path, path_prefix, sizeof (path_prefix) - 1);
 	strcpy(path + sizeof (path_prefix) - 1, module);
 
 	return (access(path, F_OK) == 0);
 }
 
 /*
  * 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.
  *
  * Environment variables:
  * - ZFS_MODULE_LOADING="YES|yes|ON|on" - Attempt to load modules.
  * - ZFS_MODULE_TIMEOUT="<seconds>"     - Seconds to wait for ZFS_DEV
  */
 static int
 libzfs_load_module_impl(const char *module)
 {
 	char *argv[4] = {"/sbin/modprobe", "-q", (char *)module, (char *)0};
 	char *load_str, *timeout_str;
 	long timeout = 10; /* seconds */
 	long busy_timeout = 10; /* milliseconds */
 	int load = 0, fd;
 	hrtime_t start;
 
 	/* Optionally request module loading */
 	if (!libzfs_module_loaded(module)) {
 		load_str = getenv("ZFS_MODULE_LOADING");
 		if (load_str) {
 			if (!strncasecmp(load_str, "YES", strlen("YES")) ||
 			    !strncasecmp(load_str, "ON", strlen("ON")))
 				load = 1;
 			else
 				load = 0;
 		}
 
 		if (load) {
 			if (libzfs_run_process("/sbin/modprobe", argv, 0))
 				return (ENOEXEC);
 		}
 
 		if (!libzfs_module_loaded(module))
 			return (ENXIO);
 	}
 
 	/*
 	 * Device creation by udev is asynchronous and waiting may be
 	 * required.  Busy wait for 10ms and then fall back to polling every
 	 * 10ms for the allowed timeout (default 10s, max 10m).  This is
 	 * done to optimize for the common case where the device is
 	 * immediately available and to avoid penalizing the possible
 	 * case where udev is slow or unable to create the device.
 	 */
 	timeout_str = getenv("ZFS_MODULE_TIMEOUT");
 	if (timeout_str) {
 		timeout = strtol(timeout_str, NULL, 0);
 		timeout = MAX(MIN(timeout, (10 * 60)), 0); /* 0 <= N <= 600 */
 	}
 
 	start = gethrtime();
 	do {
 		fd = open(ZFS_DEV, O_RDWR | O_CLOEXEC);
 		if (fd >= 0) {
 			(void) close(fd);
 			return (0);
 		} else if (errno != ENOENT) {
 			return (errno);
 		} else if (NSEC2MSEC(gethrtime() - start) < busy_timeout) {
 			sched_yield();
 		} else {
 			usleep(10 * MILLISEC);
 		}
 	} while (NSEC2MSEC(gethrtime() - start) < (timeout * MILLISEC));
 
 	return (ENOENT);
 }
 
 int
 libzfs_load_module(void)
 {
 	return (libzfs_load_module_impl(ZFS_DRIVER));
 }
 
 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);
 }
 
 /*
  * Fill given version buffer with zfs kernel version read from ZFS_SYSFS_DIR
  * Returns 0 on success, and -1 on error (with errno set)
  */
 int
 zfs_version_kernel(char *version, int len)
 {
 	int _errno;
 	int fd;
 	int rlen;
 
 	if ((fd = open(ZFS_SYSFS_DIR "/version", O_RDONLY | O_CLOEXEC)) == -1)
 		return (-1);
 
 	if ((rlen = read(fd, version, len)) == -1) {
 		version[0] = '\0';
 		_errno = errno;
 		(void) close(fd);
 		errno = _errno;
 		return (-1);
 	}
 
 	version[rlen-1] = '\0';  /* discard '\n' */
 
 	if (close(fd) == -1)
 		return (-1);
 
 	return (0);
 }