libzfs_mount.c revision 209962
11556Srgrimes/*
21556Srgrimes * CDDL HEADER START
31556Srgrimes *
41556Srgrimes * The contents of this file are subject to the terms of the
51556Srgrimes * Common Development and Distribution License (the "License").
61556Srgrimes * You may not use this file except in compliance with the License.
71556Srgrimes *
81556Srgrimes * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91556Srgrimes * or http://www.opensolaris.org/os/licensing.
101556Srgrimes * See the License for the specific language governing permissions
111556Srgrimes * and limitations under the License.
121556Srgrimes *
131556Srgrimes * When distributing Covered Code, include this CDDL HEADER in each
141556Srgrimes * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151556Srgrimes * If applicable, add the following below this CDDL HEADER, with the
161556Srgrimes * fields enclosed by brackets "[]" replaced with your own identifying
171556Srgrimes * information: Portions Copyright [yyyy] [name of copyright owner]
181556Srgrimes *
191556Srgrimes * CDDL HEADER END
201556Srgrimes */
211556Srgrimes
221556Srgrimes/*
231556Srgrimes * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
241556Srgrimes * Use is subject to license terms.
251556Srgrimes */
261556Srgrimes
271556Srgrimes/*
281556Srgrimes * Routines to manage ZFS mounts.  We separate all the nasty routines that have
291556Srgrimes * to deal with the OS.  The following functions are the main entry points --
301556Srgrimes * they are used by mount and unmount and when changing a filesystem's
311556Srgrimes * mountpoint.
321556Srgrimes *
331556Srgrimes * 	zfs_is_mounted()
341556Srgrimes * 	zfs_mount()
351556Srgrimes * 	zfs_unmount()
361556Srgrimes * 	zfs_unmountall()
371556Srgrimes *
3820420Ssteve * This file also contains the functions used to manage sharing filesystems via
391556Srgrimes * NFS and iSCSI:
401556Srgrimes *
411556Srgrimes * 	zfs_is_shared()
421556Srgrimes * 	zfs_share()
431556Srgrimes * 	zfs_unshare()
4436049Scharnier *
4536049Scharnier * 	zfs_is_shared_nfs()
4636049Scharnier * 	zfs_is_shared_smb()
4736049Scharnier * 	zfs_is_shared_iscsi()
4850471Speter * 	zfs_share_proto()
491556Srgrimes * 	zfs_shareall();
501556Srgrimes * 	zfs_share_iscsi()
511556Srgrimes * 	zfs_unshare_nfs()
521556Srgrimes * 	zfs_unshare_smb()
531556Srgrimes * 	zfs_unshareall_nfs()
541556Srgrimes *	zfs_unshareall_smb()
5531664Seivind *	zfs_unshareall()
561556Srgrimes *	zfs_unshareall_bypath()
571556Srgrimes * 	zfs_unshare_iscsi()
581556Srgrimes *
591556Srgrimes * The following functions are available for pool consumers, and will
6077409Simp * mount/unmount and share/unshare all datasets within pool:
611556Srgrimes *
621556Srgrimes * 	zpool_enable_datasets()
631556Srgrimes * 	zpool_disable_datasets()
6450544Smharo */
651556Srgrimes
661556Srgrimes#include <dirent.h>
671556Srgrimes#include <dlfcn.h>
681556Srgrimes#include <errno.h>
6950544Smharo#include <libgen.h>
701556Srgrimes#include <libintl.h>
7190110Simp#include <stdio.h>
7290110Simp#include <stdlib.h>
7390110Simp#include <strings.h>
7490110Simp#include <unistd.h>
751556Srgrimes#include <zone.h>
761556Srgrimes#include <sys/mntent.h>
7790110Simp#include <sys/mount.h>
781556Srgrimes#include <sys/stat.h>
791556Srgrimes
801556Srgrimes#include <libzfs.h>
811556Srgrimes
821556Srgrimes#include "libzfs_impl.h"
8377409Simp
841556Srgrimes#include <libshare.h>
8550544Smharo
861556Srgrimes#define	MAXISALEN	257	/* based on sysinfo(2) man page */
871556Srgrimes
8814154Swoschstatic int zfs_share_proto(zfs_handle_t *, zfs_share_proto_t *);
8914166Swoschzfs_share_type_t zfs_is_shared_proto(zfs_handle_t *, char **,
901556Srgrimes    zfs_share_proto_t);
911556Srgrimes
921556Srgrimesstatic int (*iscsitgt_zfs_share)(const char *);
9314166Swoschstatic int (*iscsitgt_zfs_unshare)(const char *);
941556Srgrimesstatic int (*iscsitgt_zfs_is_shared)(const char *);
9550544Smharostatic int (*iscsitgt_svc_online)();
9650544Smharo
9750544Smharo/*
981556Srgrimes * The share protocols table must be in the same order as the zfs_share_prot_t
991556Srgrimes * enum in libzfs_impl.h
1001556Srgrimes */
10114305Swoschtypedef struct {
1021556Srgrimes	zfs_prop_t p_prop;
1031556Srgrimes	char *p_name;
1041556Srgrimes	int p_share_err;
1051556Srgrimes	int p_unshare_err;
1061556Srgrimes} proto_table_t;
1071556Srgrimes
1081556Srgrimesproto_table_t proto_table[PROTO_END] = {
1091556Srgrimes	{ZFS_PROP_SHARENFS, "nfs", EZFS_SHARENFSFAILED, EZFS_UNSHARENFSFAILED},
1101556Srgrimes	{ZFS_PROP_SHARESMB, "smb", EZFS_SHARESMBFAILED, EZFS_UNSHARESMBFAILED},
1111556Srgrimes};
1121556Srgrimes
1131556Srgrimeszfs_share_proto_t nfs_only[] = {
1141556Srgrimes	PROTO_NFS,
1151556Srgrimes	PROTO_END
1161556Srgrimes};
1171556Srgrimes
11836785Simpzfs_share_proto_t smb_only[] = {
11936785Simp	PROTO_SMB,
1201556Srgrimes	PROTO_END
1211556Srgrimes};
1221556Srgrimeszfs_share_proto_t share_all_proto[] = {
12336383Ssteve	PROTO_NFS,
12436383Ssteve	PROTO_SMB,
12536383Ssteve	PROTO_END
12636383Ssteve};
1271556Srgrimes
12811298Sbde#pragma init(zfs_iscsi_init)
12911298Sbdestatic void
13011298Sbdezfs_iscsi_init(void)
13111298Sbde{
13211298Sbde	void *libiscsitgt;
13311298Sbde
13411298Sbde	if ((libiscsitgt = dlopen("/lib/libiscsitgt.so.1",
13511298Sbde	    RTLD_LAZY | RTLD_GLOBAL)) == NULL ||
13611298Sbde	    (iscsitgt_zfs_share = (int (*)(const char *))dlsym(libiscsitgt,
13711298Sbde	    "iscsitgt_zfs_share")) == NULL ||
13877409Simp	    (iscsitgt_zfs_unshare = (int (*)(const char *))dlsym(libiscsitgt,
1391556Srgrimes	    "iscsitgt_zfs_unshare")) == NULL ||
1401556Srgrimes	    (iscsitgt_zfs_is_shared = (int (*)(const char *))dlsym(libiscsitgt,
1411556Srgrimes	    "iscsitgt_zfs_is_shared")) == NULL ||
14276878Skris	    (iscsitgt_svc_online = (int (*)(const char *))dlsym(libiscsitgt,
1431556Srgrimes	    "iscsitgt_svc_online")) == NULL) {
1441556Srgrimes		iscsitgt_zfs_share = NULL;
1451556Srgrimes		iscsitgt_zfs_unshare = NULL;
1461556Srgrimes		iscsitgt_zfs_is_shared = NULL;
1471556Srgrimes		iscsitgt_svc_online = NULL;
1481556Srgrimes	}
1491556Srgrimes}
1501556Srgrimes
15190110Simp/*
1521556Srgrimes * Search the sharetab for the given mountpoint and protocol, returning
1531556Srgrimes * a zfs_share_type_t value.
15429933Swosch */
1551556Srgrimesstatic zfs_share_type_t
1561556Srgrimesis_shared(libzfs_handle_t *hdl, const char *mountpoint, zfs_share_proto_t proto)
1571556Srgrimes{
1581556Srgrimes	char buf[MAXPATHLEN], *tab;
1591556Srgrimes	char *ptr;
1601556Srgrimes
1611556Srgrimes	if (hdl->libzfs_sharetab == NULL)
1621556Srgrimes		return (SHARED_NOT_SHARED);
16314166Swosch
16414166Swosch	(void) fseek(hdl->libzfs_sharetab, 0, SEEK_SET);
16514166Swosch
16614305Swosch	while (fgets(buf, sizeof (buf), hdl->libzfs_sharetab) != NULL) {
16714305Swosch
16814166Swosch		/* the mountpoint is the first entry on each line */
16930106Swosch		if ((tab = strchr(buf, '\t')) == NULL)
17030106Swosch			continue;
1711556Srgrimes
1721556Srgrimes		*tab = '\0';
17330106Swosch		if (strcmp(buf, mountpoint) == 0) {
1741556Srgrimes#if defined(sun)
1751556Srgrimes			/*
1761556Srgrimes			 * the protocol field is the third field
17730106Swosch			 * skip over second field
1781556Srgrimes			 */
17976878Skris			ptr = ++tab;
18076878Skris			if ((tab = strchr(ptr, '\t')) == NULL)
1811556Srgrimes				continue;
1821556Srgrimes			ptr = ++tab;
1831556Srgrimes			if ((tab = strchr(ptr, '\t')) == NULL)
18429933Swosch				continue;
18529933Swosch			*tab = '\0';
18629933Swosch			if (strcmp(ptr,
18730106Swosch			    proto_table[proto].p_name) == 0) {
18830106Swosch				switch (proto) {
1891556Srgrimes				case PROTO_NFS:
19030106Swosch					return (SHARED_NFS);
1911556Srgrimes				case PROTO_SMB:
1921556Srgrimes					return (SHARED_SMB);
19350544Smharo				default:
19450544Smharo					return (0);
19550544Smharo				}
1961556Srgrimes			}
19750544Smharo#else
1981556Srgrimes			if (proto == PROTO_NFS)
19931664Seivind				return (SHARED_NFS);
20031664Seivind#endif
20177409Simp		}
20231664Seivind	}
20331664Seivind
20431664Seivind	return (SHARED_NOT_SHARED);
20531664Seivind}
20631664Seivind
20731664Seivind#if 0
20831664Seivind/*
20931664Seivind * Returns true if the specified directory is empty.  If we can't open the
21031664Seivind * directory at all, return true so that the mount can fail with a more
21131664Seivind * informative error message.
21231664Seivind */
2131556Srgrimesstatic boolean_t
2141556Srgrimesdir_is_empty(const char *dirname)
2151556Srgrimes{
2161556Srgrimes	DIR *dirp;
2171556Srgrimes	struct dirent64 *dp;
2181556Srgrimes
2191556Srgrimes	if ((dirp = opendir(dirname)) == NULL)
2201556Srgrimes		return (B_TRUE);
2211556Srgrimes
22262963Sdwmalone	while ((dp = readdir64(dirp)) != NULL) {
2231556Srgrimes
2241556Srgrimes		if (strcmp(dp->d_name, ".") == 0 ||
2251556Srgrimes		    strcmp(dp->d_name, "..") == 0)
2261556Srgrimes			continue;
2271556Srgrimes
2281556Srgrimes		(void) closedir(dirp);
2291556Srgrimes		return (B_FALSE);
2301556Srgrimes	}
23190110Simp
2321556Srgrimes	(void) closedir(dirp);
2331556Srgrimes	return (B_TRUE);
2341556Srgrimes}
2351556Srgrimes#endif
23623525Sguido
2371556Srgrimes/*
2381556Srgrimes * Checks to see if the mount is active.  If the filesystem is mounted, we fill
2391556Srgrimes * in 'where' with the current mountpoint, and return 1.  Otherwise, we return
2401556Srgrimes * 0.
2411556Srgrimes */
2421556Srgrimesboolean_t
24323525Sguidois_mounted(libzfs_handle_t *zfs_hdl, const char *special, char **where)
24423525Sguido{
24523525Sguido	struct mnttab entry;
24676878Skris
24723525Sguido	if (libzfs_mnttab_find(zfs_hdl, special, &entry) != 0)
24823525Sguido		return (B_FALSE);
24923525Sguido
25023525Sguido	if (where != NULL)
25123525Sguido		*where = zfs_strdup(zfs_hdl, entry.mnt_mountp);
25223525Sguido
25323525Sguido	return (B_TRUE);
25423525Sguido}
25523525Sguido
25623525Sguidoboolean_t
2571556Srgrimeszfs_is_mounted(zfs_handle_t *zhp, char **where)
2581556Srgrimes{
2591556Srgrimes	return (is_mounted(zhp->zfs_hdl, zfs_get_name(zhp), where));
2601556Srgrimes}
26176878Skris
26276878Skris/*
2631556Srgrimes * Returns true if the given dataset is mountable, false otherwise.  Returns the
2641556Srgrimes * mountpoint in 'buf'.
2651556Srgrimes */
2661556Srgrimesstatic boolean_t
2671556Srgrimeszfs_is_mountable(zfs_handle_t *zhp, char *buf, size_t buflen,
2681556Srgrimes    zprop_source_t *source)
2691556Srgrimes{
2701556Srgrimes	char sourceloc[ZFS_MAXNAMELEN];
2711556Srgrimes	zprop_source_t sourcetype;
2721556Srgrimes
2731556Srgrimes	if (!zfs_prop_valid_for_type(ZFS_PROP_MOUNTPOINT, zhp->zfs_type))
2741556Srgrimes		return (B_FALSE);
2751556Srgrimes
27623525Sguido	verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, buf, buflen,
27723525Sguido	    &sourcetype, sourceloc, sizeof (sourceloc), B_FALSE) == 0);
27837245Sbde
27937245Sbde	if (strcmp(buf, ZFS_MOUNTPOINT_NONE) == 0 ||
28023525Sguido	    strcmp(buf, ZFS_MOUNTPOINT_LEGACY) == 0)
28123525Sguido		return (B_FALSE);
28223525Sguido
28323525Sguido	if (zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT) == ZFS_CANMOUNT_OFF)
28423525Sguido		return (B_FALSE);
28523525Sguido
28623525Sguido	if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED) &&
2871556Srgrimes	    getzoneid() == GLOBAL_ZONEID)
28823525Sguido		return (B_FALSE);
28963680Ssada
29063680Ssada	if (source)
29163680Ssada		*source = sourcetype;
29263680Ssada
29363680Ssada	return (B_TRUE);
29463680Ssada}
29563680Ssada
29663680Ssada/*
29776878Skris * Mount the given filesystem.
29863680Ssada */
29963680Ssadaint
3001556Srgrimeszfs_mount(zfs_handle_t *zhp, const char *options, int flags)
3011556Srgrimes{
3021556Srgrimes	struct stat buf;
3031556Srgrimes	char mountpoint[ZFS_MAXPROPLEN];
3041556Srgrimes	char mntopts[MNT_LINE_MAX];
3051556Srgrimes	libzfs_handle_t *hdl = zhp->zfs_hdl;
3061556Srgrimes
3071556Srgrimes	if (options == NULL)
3081556Srgrimes		mntopts[0] = '\0';
3091556Srgrimes	else
3101556Srgrimes		(void) strlcpy(mntopts, options, sizeof (mntopts));
3111556Srgrimes
3121556Srgrimes	if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL))
3131556Srgrimes		return (0);
3141556Srgrimes
3151556Srgrimes	/* Create the directory if it doesn't already exist */
31650544Smharo	if (lstat(mountpoint, &buf) != 0) {
31750544Smharo		if (mkdirp(mountpoint, 0755) != 0) {
3181556Srgrimes			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3191556Srgrimes			    "failed to create mountpoint"));
3201556Srgrimes			return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED,
3211556Srgrimes			    dgettext(TEXT_DOMAIN, "cannot mount '%s'"),
32290110Simp			    mountpoint));
3231556Srgrimes		}
3241556Srgrimes	}
3251556Srgrimes
32640301Sdes#if 0	/* FreeBSD: overlay mounts are not checked. */
32779452Sbrian	/*
32879452Sbrian	 * Determine if the mountpoint is empty.  If so, refuse to perform the
3291556Srgrimes	 * mount.  We don't perform this check if MS_OVERLAY is specified, which
3301556Srgrimes	 * would defeat the point.  We also avoid this check if 'remount' is
3311556Srgrimes	 * specified.
3321556Srgrimes	 */
3331556Srgrimes	if ((flags & MS_OVERLAY) == 0 &&
3341556Srgrimes	    strstr(mntopts, MNTOPT_REMOUNT) == NULL &&
3351556Srgrimes	    !dir_is_empty(mountpoint)) {
3361556Srgrimes		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3371556Srgrimes		    "directory is not empty"));
3381556Srgrimes		return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED,
3391556Srgrimes		    dgettext(TEXT_DOMAIN, "cannot mount '%s'"), mountpoint));
3401556Srgrimes	}
3411556Srgrimes#endif
3421556Srgrimes
3431556Srgrimes	/* perform the mount */
3441556Srgrimes	if (zmount(zfs_get_name(zhp), mountpoint, flags,
3451556Srgrimes	    MNTTYPE_ZFS, NULL, 0, mntopts, sizeof (mntopts)) != 0) {
34679452Sbrian		/*
3471556Srgrimes		 * Generic errors are nasty, but there are just way too many
3481556Srgrimes		 * from mount(), and they're well-understood.  We pick a few
3491556Srgrimes		 * common ones to improve upon.
3501556Srgrimes		 */
3511556Srgrimes		if (errno == EBUSY) {
3521556Srgrimes			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3531556Srgrimes			    "mountpoint or dataset is busy"));
3541556Srgrimes		} else if (errno == EPERM) {
3551556Srgrimes			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3561556Srgrimes			    "Insufficient privileges"));
3571556Srgrimes		} else {
3581556Srgrimes			zfs_error_aux(hdl, strerror(errno));
3591556Srgrimes		}
3601556Srgrimes		return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED,
3611556Srgrimes		    dgettext(TEXT_DOMAIN, "cannot mount '%s'"),
3621556Srgrimes		    zhp->zfs_name));
3631556Srgrimes	}
3641556Srgrimes
3651556Srgrimes	/* add the mounted entry into our cache */
3661556Srgrimes	libzfs_mnttab_add(hdl, zfs_get_name(zhp), mountpoint,
36790110Simp	    mntopts);
3681556Srgrimes	return (0);
36950544Smharo}
37014305Swosch
37150544Smharo/*
37250544Smharo * Unmount a single filesystem.
37350544Smharo */
3741556Srgrimesstatic int
375unmount_one(libzfs_handle_t *hdl, const char *mountpoint, int flags)
376{
377	if (unmount(mountpoint, flags) != 0) {
378		zfs_error_aux(hdl, strerror(errno));
379		return (zfs_error_fmt(hdl, EZFS_UMOUNTFAILED,
380		    dgettext(TEXT_DOMAIN, "cannot unmount '%s'"),
381		    mountpoint));
382	}
383
384	return (0);
385}
386
387/*
388 * Unmount the given filesystem.
389 */
390int
391zfs_unmount(zfs_handle_t *zhp, const char *mountpoint, int flags)
392{
393	libzfs_handle_t *hdl = zhp->zfs_hdl;
394	struct mnttab entry;
395	char *mntpt = NULL;
396
397	/* check to see if we need to unmount the filesystem */
398	if (mountpoint != NULL || ((zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) &&
399	    libzfs_mnttab_find(hdl, zhp->zfs_name, &entry) == 0)) {
400		/*
401		 * mountpoint may have come from a call to
402		 * getmnt/getmntany if it isn't NULL. If it is NULL,
403		 * we know it comes from libzfs_mnttab_find which can
404		 * then get freed later. We strdup it to play it safe.
405		 */
406		if (mountpoint == NULL)
407			mntpt = zfs_strdup(hdl, entry.mnt_mountp);
408		else
409			mntpt = zfs_strdup(hdl, mountpoint);
410
411		/*
412		 * Unshare and unmount the filesystem
413		 */
414		if (zfs_unshare_proto(zhp, mntpt, share_all_proto) != 0)
415			return (-1);
416
417		if (unmount_one(hdl, mntpt, flags) != 0) {
418			free(mntpt);
419			(void) zfs_shareall(zhp);
420			return (-1);
421		}
422		libzfs_mnttab_remove(hdl, zhp->zfs_name);
423		free(mntpt);
424	}
425
426	return (0);
427}
428
429/*
430 * Unmount this filesystem and any children inheriting the mountpoint property.
431 * To do this, just act like we're changing the mountpoint property, but don't
432 * remount the filesystems afterwards.
433 */
434int
435zfs_unmountall(zfs_handle_t *zhp, int flags)
436{
437	prop_changelist_t *clp;
438	int ret;
439
440	clp = changelist_gather(zhp, ZFS_PROP_MOUNTPOINT, 0, flags);
441	if (clp == NULL)
442		return (-1);
443
444	ret = changelist_prefix(clp);
445	changelist_free(clp);
446
447	return (ret);
448}
449
450boolean_t
451zfs_is_shared(zfs_handle_t *zhp)
452{
453	zfs_share_type_t rc = 0;
454	zfs_share_proto_t *curr_proto;
455
456	if (ZFS_IS_VOLUME(zhp))
457		return (zfs_is_shared_iscsi(zhp));
458
459	for (curr_proto = share_all_proto; *curr_proto != PROTO_END;
460	    curr_proto++)
461		rc |= zfs_is_shared_proto(zhp, NULL, *curr_proto);
462
463	return (rc ? B_TRUE : B_FALSE);
464}
465
466int
467zfs_share(zfs_handle_t *zhp)
468{
469	if (ZFS_IS_VOLUME(zhp))
470		return (zfs_share_iscsi(zhp));
471
472	return (zfs_share_proto(zhp, share_all_proto));
473}
474
475int
476zfs_unshare(zfs_handle_t *zhp)
477{
478	if (ZFS_IS_VOLUME(zhp))
479		return (zfs_unshare_iscsi(zhp));
480
481	return (zfs_unshareall(zhp));
482}
483
484/*
485 * Check to see if the filesystem is currently shared.
486 */
487zfs_share_type_t
488zfs_is_shared_proto(zfs_handle_t *zhp, char **where, zfs_share_proto_t proto)
489{
490	char *mountpoint;
491	zfs_share_type_t rc;
492
493	if (!zfs_is_mounted(zhp, &mountpoint))
494		return (SHARED_NOT_SHARED);
495
496	if (rc = is_shared(zhp->zfs_hdl, mountpoint, proto)) {
497		if (where != NULL)
498			*where = mountpoint;
499		else
500			free(mountpoint);
501		return (rc);
502	} else {
503		free(mountpoint);
504		return (SHARED_NOT_SHARED);
505	}
506}
507
508boolean_t
509zfs_is_shared_nfs(zfs_handle_t *zhp, char **where)
510{
511	return (zfs_is_shared_proto(zhp, where,
512	    PROTO_NFS) != SHARED_NOT_SHARED);
513}
514
515boolean_t
516zfs_is_shared_smb(zfs_handle_t *zhp, char **where)
517{
518	return (zfs_is_shared_proto(zhp, where,
519	    PROTO_SMB) != SHARED_NOT_SHARED);
520}
521
522/*
523 * Make sure things will work if libshare isn't installed by using
524 * wrapper functions that check to see that the pointers to functions
525 * initialized in _zfs_init_libshare() are actually present.
526 */
527
528#if 0
529static sa_handle_t (*_sa_init)(int);
530static void (*_sa_fini)(sa_handle_t);
531static sa_share_t (*_sa_find_share)(sa_handle_t, char *);
532static int (*_sa_enable_share)(sa_share_t, char *);
533static int (*_sa_disable_share)(sa_share_t, char *);
534static char *(*_sa_errorstr)(int);
535static int (*_sa_parse_legacy_options)(sa_group_t, char *, char *);
536static boolean_t (*_sa_needs_refresh)(sa_handle_t *);
537static libzfs_handle_t *(*_sa_get_zfs_handle)(sa_handle_t);
538static int (*_sa_zfs_process_share)(sa_handle_t, sa_group_t, sa_share_t,
539    char *, char *, zprop_source_t, char *, char *, char *);
540static void (*_sa_update_sharetab_ts)(sa_handle_t);
541#endif
542
543/*
544 * _zfs_init_libshare()
545 *
546 * Find the libshare.so.1 entry points that we use here and save the
547 * values to be used later. This is triggered by the runtime loader.
548 * Make sure the correct ISA version is loaded.
549 */
550
551#pragma init(_zfs_init_libshare)
552static void
553_zfs_init_libshare(void)
554{
555#if 0
556	void *libshare;
557	char path[MAXPATHLEN];
558	char isa[MAXISALEN];
559
560#if defined(_LP64)
561	if (sysinfo(SI_ARCHITECTURE_64, isa, MAXISALEN) == -1)
562		isa[0] = '\0';
563#else
564	isa[0] = '\0';
565#endif
566	(void) snprintf(path, MAXPATHLEN,
567	    "/usr/lib/%s/libshare.so.1", isa);
568
569	if ((libshare = dlopen(path, RTLD_LAZY | RTLD_GLOBAL)) != NULL) {
570		_sa_init = (sa_handle_t (*)(int))dlsym(libshare, "sa_init");
571		_sa_fini = (void (*)(sa_handle_t))dlsym(libshare, "sa_fini");
572		_sa_find_share = (sa_share_t (*)(sa_handle_t, char *))
573		    dlsym(libshare, "sa_find_share");
574		_sa_enable_share = (int (*)(sa_share_t, char *))dlsym(libshare,
575		    "sa_enable_share");
576		_sa_disable_share = (int (*)(sa_share_t, char *))dlsym(libshare,
577		    "sa_disable_share");
578		_sa_errorstr = (char *(*)(int))dlsym(libshare, "sa_errorstr");
579		_sa_parse_legacy_options = (int (*)(sa_group_t, char *, char *))
580		    dlsym(libshare, "sa_parse_legacy_options");
581		_sa_needs_refresh = (boolean_t (*)(sa_handle_t *))
582		    dlsym(libshare, "sa_needs_refresh");
583		_sa_get_zfs_handle = (libzfs_handle_t *(*)(sa_handle_t))
584		    dlsym(libshare, "sa_get_zfs_handle");
585		_sa_zfs_process_share = (int (*)(sa_handle_t, sa_group_t,
586		    sa_share_t, char *, char *, zprop_source_t, char *,
587		    char *, char *))dlsym(libshare, "sa_zfs_process_share");
588		_sa_update_sharetab_ts = (void (*)(sa_handle_t))
589		    dlsym(libshare, "sa_update_sharetab_ts");
590		if (_sa_init == NULL || _sa_fini == NULL ||
591		    _sa_find_share == NULL || _sa_enable_share == NULL ||
592		    _sa_disable_share == NULL || _sa_errorstr == NULL ||
593		    _sa_parse_legacy_options == NULL ||
594		    _sa_needs_refresh == NULL || _sa_get_zfs_handle == NULL ||
595		    _sa_zfs_process_share == NULL ||
596		    _sa_update_sharetab_ts == NULL) {
597			_sa_init = NULL;
598			_sa_fini = NULL;
599			_sa_disable_share = NULL;
600			_sa_enable_share = NULL;
601			_sa_errorstr = NULL;
602			_sa_parse_legacy_options = NULL;
603			(void) dlclose(libshare);
604			_sa_needs_refresh = NULL;
605			_sa_get_zfs_handle = NULL;
606			_sa_zfs_process_share = NULL;
607			_sa_update_sharetab_ts = NULL;
608		}
609	}
610#endif
611}
612
613/*
614 * zfs_init_libshare(zhandle, service)
615 *
616 * Initialize the libshare API if it hasn't already been initialized.
617 * In all cases it returns 0 if it succeeded and an error if not. The
618 * service value is which part(s) of the API to initialize and is a
619 * direct map to the libshare sa_init(service) interface.
620 */
621int
622zfs_init_libshare(libzfs_handle_t *zhandle, int service)
623{
624	int ret = SA_OK;
625
626#if 0
627	if (_sa_init == NULL)
628		ret = SA_CONFIG_ERR;
629
630	if (ret == SA_OK && zhandle->libzfs_shareflags & ZFSSHARE_MISS) {
631		/*
632		 * We had a cache miss. Most likely it is a new ZFS
633		 * dataset that was just created. We want to make sure
634		 * so check timestamps to see if a different process
635		 * has updated any of the configuration. If there was
636		 * some non-ZFS change, we need to re-initialize the
637		 * internal cache.
638		 */
639		zhandle->libzfs_shareflags &= ~ZFSSHARE_MISS;
640		if (_sa_needs_refresh != NULL &&
641		    _sa_needs_refresh(zhandle->libzfs_sharehdl)) {
642			zfs_uninit_libshare(zhandle);
643			zhandle->libzfs_sharehdl = _sa_init(service);
644		}
645	}
646
647	if (ret == SA_OK && zhandle && zhandle->libzfs_sharehdl == NULL)
648		zhandle->libzfs_sharehdl = _sa_init(service);
649
650	if (ret == SA_OK && zhandle->libzfs_sharehdl == NULL)
651		ret = SA_NO_MEMORY;
652#endif
653
654	return (ret);
655}
656
657/*
658 * zfs_uninit_libshare(zhandle)
659 *
660 * Uninitialize the libshare API if it hasn't already been
661 * uninitialized. It is OK to call multiple times.
662 */
663void
664zfs_uninit_libshare(libzfs_handle_t *zhandle)
665{
666	if (zhandle != NULL && zhandle->libzfs_sharehdl != NULL) {
667#if 0
668		if (_sa_fini != NULL)
669			_sa_fini(zhandle->libzfs_sharehdl);
670#endif
671		zhandle->libzfs_sharehdl = NULL;
672	}
673}
674
675/*
676 * zfs_parse_options(options, proto)
677 *
678 * Call the legacy parse interface to get the protocol specific
679 * options using the NULL arg to indicate that this is a "parse" only.
680 */
681int
682zfs_parse_options(char *options, zfs_share_proto_t proto)
683{
684#if 0
685	if (_sa_parse_legacy_options != NULL) {
686		return (_sa_parse_legacy_options(NULL, options,
687		    proto_table[proto].p_name));
688	}
689	return (SA_CONFIG_ERR);
690#else
691	return (SA_OK);
692#endif
693}
694
695#if 0
696/*
697 * zfs_sa_find_share(handle, path)
698 *
699 * wrapper around sa_find_share to find a share path in the
700 * configuration.
701 */
702static sa_share_t
703zfs_sa_find_share(sa_handle_t handle, char *path)
704{
705	if (_sa_find_share != NULL)
706		return (_sa_find_share(handle, path));
707	return (NULL);
708}
709
710/*
711 * zfs_sa_enable_share(share, proto)
712 *
713 * Wrapper for sa_enable_share which enables a share for a specified
714 * protocol.
715 */
716static int
717zfs_sa_enable_share(sa_share_t share, char *proto)
718{
719	if (_sa_enable_share != NULL)
720		return (_sa_enable_share(share, proto));
721	return (SA_CONFIG_ERR);
722}
723
724/*
725 * zfs_sa_disable_share(share, proto)
726 *
727 * Wrapper for sa_enable_share which disables a share for a specified
728 * protocol.
729 */
730static int
731zfs_sa_disable_share(sa_share_t share, char *proto)
732{
733	if (_sa_disable_share != NULL)
734		return (_sa_disable_share(share, proto));
735	return (SA_CONFIG_ERR);
736}
737#endif
738
739/*
740 * Share the given filesystem according to the options in the specified
741 * protocol specific properties (sharenfs, sharesmb).  We rely
742 * on "libshare" to the dirty work for us.
743 */
744static int
745zfs_share_proto(zfs_handle_t *zhp, zfs_share_proto_t *proto)
746{
747	char mountpoint[ZFS_MAXPROPLEN];
748	char shareopts[ZFS_MAXPROPLEN];
749	char sourcestr[ZFS_MAXPROPLEN];
750	libzfs_handle_t *hdl = zhp->zfs_hdl;
751	zfs_share_proto_t *curr_proto;
752	zprop_source_t sourcetype;
753	int error, ret;
754
755	if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL))
756		return (0);
757
758	for (curr_proto = proto; *curr_proto != PROTO_END; curr_proto++) {
759		/*
760		 * Return success if there are no share options.
761		 */
762		if (zfs_prop_get(zhp, proto_table[*curr_proto].p_prop,
763		    shareopts, sizeof (shareopts), &sourcetype, sourcestr,
764		    ZFS_MAXPROPLEN, B_FALSE) != 0 ||
765		    strcmp(shareopts, "off") == 0)
766			continue;
767
768		/*
769		 * If the 'zoned' property is set, then zfs_is_mountable()
770		 * will have already bailed out if we are in the global zone.
771		 * But local zones cannot be NFS servers, so we ignore it for
772		 * local zones as well.
773		 */
774		if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED))
775			continue;
776
777		if (*curr_proto != PROTO_NFS) {
778			fprintf(stderr, "Unsupported share protocol: %d.\n",
779			    *curr_proto);
780			continue;
781		}
782
783#if 0
784		share = zfs_sa_find_share(hdl->libzfs_sharehdl, mountpoint);
785		if (share == NULL) {
786			/*
787			 * This may be a new file system that was just
788			 * created so isn't in the internal cache
789			 * (second time through). Rather than
790			 * reloading the entire configuration, we can
791			 * assume ZFS has done the checking and it is
792			 * safe to add this to the internal
793			 * configuration.
794			 */
795			if (_sa_zfs_process_share(hdl->libzfs_sharehdl,
796			    NULL, NULL, mountpoint,
797			    proto_table[*curr_proto].p_name, sourcetype,
798			    shareopts, sourcestr, zhp->zfs_name) != SA_OK) {
799				(void) zfs_error_fmt(hdl,
800				    proto_table[*curr_proto].p_share_err,
801				    dgettext(TEXT_DOMAIN, "cannot share '%s'"),
802				    zfs_get_name(zhp));
803				return (-1);
804			}
805			hdl->libzfs_shareflags |= ZFSSHARE_MISS;
806			share = zfs_sa_find_share(hdl->libzfs_sharehdl,
807			    mountpoint);
808		}
809		if (share != NULL) {
810			int err;
811			err = zfs_sa_enable_share(share,
812			    proto_table[*curr_proto].p_name);
813			if (err != SA_OK) {
814				(void) zfs_error_fmt(hdl,
815				    proto_table[*curr_proto].p_share_err,
816				    dgettext(TEXT_DOMAIN, "cannot share '%s'"),
817				    zfs_get_name(zhp));
818				return (-1);
819			}
820		} else
821#else
822		if (strcmp(shareopts, "on") == 0)
823			error = fsshare(ZFS_EXPORTS_PATH, mountpoint, "");
824		else
825			error = fsshare(ZFS_EXPORTS_PATH, mountpoint, shareopts);
826		if (error != 0)
827#endif
828		{
829			(void) zfs_error_fmt(hdl,
830			    proto_table[*curr_proto].p_share_err,
831			    dgettext(TEXT_DOMAIN, "cannot share '%s'"),
832			    zfs_get_name(zhp));
833			return (-1);
834		}
835	}
836	return (0);
837}
838
839
840int
841zfs_share_nfs(zfs_handle_t *zhp)
842{
843	return (zfs_share_proto(zhp, nfs_only));
844}
845
846int
847zfs_share_smb(zfs_handle_t *zhp)
848{
849	return (zfs_share_proto(zhp, smb_only));
850}
851
852int
853zfs_shareall(zfs_handle_t *zhp)
854{
855	return (zfs_share_proto(zhp, share_all_proto));
856}
857
858/*
859 * Unshare a filesystem by mountpoint.
860 */
861static int
862unshare_one(libzfs_handle_t *hdl, const char *name, const char *mountpoint,
863    zfs_share_proto_t proto)
864{
865	char buf[MAXPATHLEN];
866	FILE *fp;
867	int error;
868
869	if (proto != PROTO_NFS) {
870		fprintf(stderr, "No SMB support in FreeBSD yet.\n");
871		return (EOPNOTSUPP);
872	}
873
874	error = fsunshare(ZFS_EXPORTS_PATH, mountpoint);
875	if (error != 0) {
876		zfs_error_aux(hdl, "%s", strerror(error));
877		return (zfs_error_fmt(hdl, EZFS_UNSHARENFSFAILED,
878		    dgettext(TEXT_DOMAIN,
879		    "cannot unshare '%s'"), name));
880	}
881
882	return (0);
883}
884
885/*
886 * Unshare the given filesystem.
887 */
888int
889zfs_unshare_proto(zfs_handle_t *zhp, const char *mountpoint,
890    zfs_share_proto_t *proto)
891{
892	libzfs_handle_t *hdl = zhp->zfs_hdl;
893	struct mnttab entry;
894	char *mntpt = NULL;
895
896	/* check to see if need to unmount the filesystem */
897	rewind(zhp->zfs_hdl->libzfs_mnttab);
898	if (mountpoint != NULL)
899		mountpoint = mntpt = zfs_strdup(hdl, mountpoint);
900
901	if (mountpoint != NULL || ((zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) &&
902	    libzfs_mnttab_find(hdl, zfs_get_name(zhp), &entry) == 0)) {
903		zfs_share_proto_t *curr_proto;
904
905		if (mountpoint == NULL)
906			mntpt = zfs_strdup(zhp->zfs_hdl, entry.mnt_mountp);
907
908		for (curr_proto = proto; *curr_proto != PROTO_END;
909		    curr_proto++) {
910
911			if (is_shared(hdl, mntpt, *curr_proto) &&
912			    unshare_one(hdl, zhp->zfs_name,
913			    mntpt, *curr_proto) != 0) {
914				if (mntpt != NULL)
915					free(mntpt);
916				return (-1);
917			}
918		}
919	}
920	if (mntpt != NULL)
921		free(mntpt);
922
923	return (0);
924}
925
926int
927zfs_unshare_nfs(zfs_handle_t *zhp, const char *mountpoint)
928{
929	return (zfs_unshare_proto(zhp, mountpoint, nfs_only));
930}
931
932int
933zfs_unshare_smb(zfs_handle_t *zhp, const char *mountpoint)
934{
935	return (zfs_unshare_proto(zhp, mountpoint, smb_only));
936}
937
938/*
939 * Same as zfs_unmountall(), but for NFS and SMB unshares.
940 */
941int
942zfs_unshareall_proto(zfs_handle_t *zhp, zfs_share_proto_t *proto)
943{
944	prop_changelist_t *clp;
945	int ret;
946
947	clp = changelist_gather(zhp, ZFS_PROP_SHARENFS, 0, 0);
948	if (clp == NULL)
949		return (-1);
950
951	ret = changelist_unshare(clp, proto);
952	changelist_free(clp);
953
954	return (ret);
955}
956
957int
958zfs_unshareall_nfs(zfs_handle_t *zhp)
959{
960	return (zfs_unshareall_proto(zhp, nfs_only));
961}
962
963int
964zfs_unshareall_smb(zfs_handle_t *zhp)
965{
966	return (zfs_unshareall_proto(zhp, smb_only));
967}
968
969int
970zfs_unshareall(zfs_handle_t *zhp)
971{
972	return (zfs_unshareall_proto(zhp, share_all_proto));
973}
974
975int
976zfs_unshareall_bypath(zfs_handle_t *zhp, const char *mountpoint)
977{
978	return (zfs_unshare_proto(zhp, mountpoint, share_all_proto));
979}
980
981/*
982 * Remove the mountpoint associated with the current dataset, if necessary.
983 * We only remove the underlying directory if:
984 *
985 *	- The mountpoint is not 'none' or 'legacy'
986 *	- The mountpoint is non-empty
987 *	- The mountpoint is the default or inherited
988 *	- The 'zoned' property is set, or we're in a local zone
989 *
990 * Any other directories we leave alone.
991 */
992void
993remove_mountpoint(zfs_handle_t *zhp)
994{
995	char mountpoint[ZFS_MAXPROPLEN];
996	zprop_source_t source;
997
998	if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint),
999	    &source))
1000		return;
1001
1002	if (source == ZPROP_SRC_DEFAULT ||
1003	    source == ZPROP_SRC_INHERITED) {
1004		/*
1005		 * Try to remove the directory, silently ignoring any errors.
1006		 * The filesystem may have since been removed or moved around,
1007		 * and this error isn't really useful to the administrator in
1008		 * any way.
1009		 */
1010		(void) rmdir(mountpoint);
1011	}
1012}
1013
1014boolean_t
1015zfs_is_shared_iscsi(zfs_handle_t *zhp)
1016{
1017
1018	/*
1019	 * If iscsi deamon isn't running then we aren't shared
1020	 */
1021	if (iscsitgt_svc_online && iscsitgt_svc_online() == 1)
1022		return (B_FALSE);
1023	else
1024		return (iscsitgt_zfs_is_shared != NULL &&
1025		    iscsitgt_zfs_is_shared(zhp->zfs_name) != 0);
1026}
1027
1028int
1029zfs_share_iscsi(zfs_handle_t *zhp)
1030{
1031	char shareopts[ZFS_MAXPROPLEN];
1032	const char *dataset = zhp->zfs_name;
1033	libzfs_handle_t *hdl = zhp->zfs_hdl;
1034
1035	/*
1036	 * Return success if there are no share options.
1037	 */
1038	if (zfs_prop_get(zhp, ZFS_PROP_SHAREISCSI, shareopts,
1039	    sizeof (shareopts), NULL, NULL, 0, B_FALSE) != 0 ||
1040	    strcmp(shareopts, "off") == 0)
1041		return (0);
1042
1043/* We don't support iSCSI on FreeBSD yet. */
1044#ifdef TODO
1045	if (iscsitgt_zfs_share == NULL || iscsitgt_zfs_share(dataset) != 0) {
1046		int error = EZFS_SHAREISCSIFAILED;
1047
1048		/*
1049		 * If service isn't availabele and EPERM was
1050		 * returned then use special error.
1051		 */
1052		if (iscsitgt_svc_online && errno == EPERM &&
1053		    (iscsitgt_svc_online() != 0))
1054			error = EZFS_ISCSISVCUNAVAIL;
1055
1056		return (zfs_error_fmt(hdl, error,
1057		    dgettext(TEXT_DOMAIN, "cannot share '%s'"), dataset));
1058	}
1059#endif
1060
1061	return (0);
1062}
1063
1064int
1065zfs_unshare_iscsi(zfs_handle_t *zhp)
1066{
1067	const char *dataset = zfs_get_name(zhp);
1068	libzfs_handle_t *hdl = zhp->zfs_hdl;
1069
1070/* We don't support iSCSI on FreeBSD yet. */
1071#ifdef TODO
1072	/*
1073	 * Return if the volume is not shared
1074	 */
1075	if (zfs_is_shared_iscsi(zhp) != SHARED_ISCSI)
1076		return (0);
1077
1078	/*
1079	 * If this fails with ENODEV it indicates that zvol wasn't shared so
1080	 * we should return success in that case.
1081	 */
1082	if (iscsitgt_zfs_unshare == NULL ||
1083	    (iscsitgt_zfs_unshare(dataset) != 0 && errno != ENODEV)) {
1084		if (errno == EPERM)
1085			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1086			    "Insufficient privileges to unshare iscsi"));
1087		return (zfs_error_fmt(hdl, EZFS_UNSHAREISCSIFAILED,
1088		    dgettext(TEXT_DOMAIN, "cannot unshare '%s'"), dataset));
1089	}
1090#endif
1091
1092	return (0);
1093}
1094
1095typedef struct mount_cbdata {
1096	zfs_handle_t	**cb_datasets;
1097	int 		cb_used;
1098	int		cb_alloc;
1099} mount_cbdata_t;
1100
1101static int
1102mount_cb(zfs_handle_t *zhp, void *data)
1103{
1104	mount_cbdata_t *cbp = data;
1105
1106	if (!(zfs_get_type(zhp) & (ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME))) {
1107		zfs_close(zhp);
1108		return (0);
1109	}
1110
1111	if (zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT) == ZFS_CANMOUNT_NOAUTO) {
1112		zfs_close(zhp);
1113		return (0);
1114	}
1115
1116	if (cbp->cb_alloc == cbp->cb_used) {
1117		void *ptr;
1118
1119		if ((ptr = zfs_realloc(zhp->zfs_hdl,
1120		    cbp->cb_datasets, cbp->cb_alloc * sizeof (void *),
1121		    cbp->cb_alloc * 2 * sizeof (void *))) == NULL)
1122			return (-1);
1123		cbp->cb_datasets = ptr;
1124
1125		cbp->cb_alloc *= 2;
1126	}
1127
1128	cbp->cb_datasets[cbp->cb_used++] = zhp;
1129
1130	return (zfs_iter_filesystems(zhp, mount_cb, cbp));
1131}
1132
1133static int
1134dataset_cmp(const void *a, const void *b)
1135{
1136	zfs_handle_t **za = (zfs_handle_t **)a;
1137	zfs_handle_t **zb = (zfs_handle_t **)b;
1138	char mounta[MAXPATHLEN];
1139	char mountb[MAXPATHLEN];
1140	boolean_t gota, gotb;
1141
1142	if ((gota = (zfs_get_type(*za) == ZFS_TYPE_FILESYSTEM)) != 0)
1143		verify(zfs_prop_get(*za, ZFS_PROP_MOUNTPOINT, mounta,
1144		    sizeof (mounta), NULL, NULL, 0, B_FALSE) == 0);
1145	if ((gotb = (zfs_get_type(*zb) == ZFS_TYPE_FILESYSTEM)) != 0)
1146		verify(zfs_prop_get(*zb, ZFS_PROP_MOUNTPOINT, mountb,
1147		    sizeof (mountb), NULL, NULL, 0, B_FALSE) == 0);
1148
1149	if (gota && gotb)
1150		return (strcmp(mounta, mountb));
1151
1152	if (gota)
1153		return (-1);
1154	if (gotb)
1155		return (1);
1156
1157	return (strcmp(zfs_get_name(a), zfs_get_name(b)));
1158}
1159
1160/*
1161 * Mount and share all datasets within the given pool.  This assumes that no
1162 * datasets within the pool are currently mounted.  Because users can create
1163 * complicated nested hierarchies of mountpoints, we first gather all the
1164 * datasets and mountpoints within the pool, and sort them by mountpoint.  Once
1165 * we have the list of all filesystems, we iterate over them in order and mount
1166 * and/or share each one.
1167 */
1168#pragma weak zpool_mount_datasets = zpool_enable_datasets
1169int
1170zpool_enable_datasets(zpool_handle_t *zhp, const char *mntopts, int flags)
1171{
1172	mount_cbdata_t cb = { 0 };
1173	libzfs_handle_t *hdl = zhp->zpool_hdl;
1174	zfs_handle_t *zfsp;
1175	int i, ret = -1;
1176	int *good;
1177
1178	/*
1179	 * Gather all non-snap datasets within the pool.
1180	 */
1181	if ((cb.cb_datasets = zfs_alloc(hdl, 4 * sizeof (void *))) == NULL)
1182		return (-1);
1183	cb.cb_alloc = 4;
1184
1185	if ((zfsp = zfs_open(hdl, zhp->zpool_name, ZFS_TYPE_DATASET)) == NULL)
1186		goto out;
1187
1188	cb.cb_datasets[0] = zfsp;
1189	cb.cb_used = 1;
1190
1191	if (zfs_iter_filesystems(zfsp, mount_cb, &cb) != 0)
1192		goto out;
1193
1194	/*
1195	 * Sort the datasets by mountpoint.
1196	 */
1197	qsort(cb.cb_datasets, cb.cb_used, sizeof (void *), dataset_cmp);
1198
1199	/*
1200	 * And mount all the datasets, keeping track of which ones
1201	 * succeeded or failed.
1202	 */
1203	if ((good = zfs_alloc(zhp->zpool_hdl,
1204	    cb.cb_used * sizeof (int))) == NULL)
1205		goto out;
1206
1207	ret = 0;
1208	for (i = 0; i < cb.cb_used; i++) {
1209		if (zfs_mount(cb.cb_datasets[i], mntopts, flags) != 0)
1210			ret = -1;
1211		else
1212			good[i] = 1;
1213	}
1214
1215	/*
1216	 * Then share all the ones that need to be shared. This needs
1217	 * to be a separate pass in order to avoid excessive reloading
1218	 * of the configuration. Good should never be NULL since
1219	 * zfs_alloc is supposed to exit if memory isn't available.
1220	 */
1221	for (i = 0; i < cb.cb_used; i++) {
1222		if (good[i] && zfs_share(cb.cb_datasets[i]) != 0)
1223			ret = -1;
1224	}
1225
1226	free(good);
1227
1228out:
1229	for (i = 0; i < cb.cb_used; i++)
1230		zfs_close(cb.cb_datasets[i]);
1231	free(cb.cb_datasets);
1232
1233	return (ret);
1234}
1235
1236
1237static int
1238zvol_cb(const char *dataset, void *data)
1239{
1240	libzfs_handle_t *hdl = data;
1241	zfs_handle_t *zhp;
1242
1243	/*
1244	 * Ignore snapshots and ignore failures from non-existant datasets.
1245	 */
1246	if (strchr(dataset, '@') != NULL ||
1247	    (zhp = zfs_open(hdl, dataset, ZFS_TYPE_VOLUME)) == NULL)
1248		return (0);
1249
1250	if (zfs_unshare_iscsi(zhp) != 0)
1251		return (-1);
1252
1253	zfs_close(zhp);
1254
1255	return (0);
1256}
1257
1258static int
1259mountpoint_compare(const void *a, const void *b)
1260{
1261	const char *mounta = *((char **)a);
1262	const char *mountb = *((char **)b);
1263
1264	return (strcmp(mountb, mounta));
1265}
1266
1267/*
1268 * Unshare and unmount all datasets within the given pool.  We don't want to
1269 * rely on traversing the DSL to discover the filesystems within the pool,
1270 * because this may be expensive (if not all of them are mounted), and can fail
1271 * arbitrarily (on I/O error, for example).  Instead, we walk /etc/mnttab and
1272 * gather all the filesystems that are currently mounted.
1273 */
1274#pragma weak zpool_unmount_datasets = zpool_disable_datasets
1275int
1276zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force)
1277{
1278	int used, alloc;
1279	struct statfs *sfs;
1280	size_t namelen;
1281	char **mountpoints = NULL;
1282	zfs_handle_t **datasets = NULL;
1283	libzfs_handle_t *hdl = zhp->zpool_hdl;
1284	int i, j, n;
1285	int ret = -1;
1286	int flags = (force ? MS_FORCE : 0);
1287
1288	/*
1289	 * First unshare all zvols.
1290	 */
1291	if (zpool_iter_zvol(zhp, zvol_cb, hdl) != 0)
1292		return (-1);
1293
1294	namelen = strlen(zhp->zpool_name);
1295
1296	used = alloc = 0;
1297	if ((n = getmntinfo(&sfs, MNT_WAIT)) == 0) {
1298		fprintf(stderr, "getmntinfo(): %s\n", strerror(errno));
1299		return (-1);
1300	}
1301	for (j = 0; j < n; j++) {
1302		/*
1303		 * Ignore non-ZFS entries.
1304		 */
1305		if (strcmp(sfs[j].f_fstypename, MNTTYPE_ZFS) != 0)
1306			continue;
1307
1308		/*
1309		 * Ignore filesystems not within this pool.
1310		 */
1311		if (strncmp(sfs[j].f_mntfromname, zhp->zpool_name, namelen) != 0 ||
1312		    (sfs[j].f_mntfromname[namelen] != '/' &&
1313		    sfs[j].f_mntfromname[namelen] != '\0'))
1314			continue;
1315
1316		/*
1317		 * At this point we've found a filesystem within our pool.  Add
1318		 * it to our growing list.
1319		 */
1320		if (used == alloc) {
1321			if (alloc == 0) {
1322				if ((mountpoints = zfs_alloc(hdl,
1323				    8 * sizeof (void *))) == NULL)
1324					goto out;
1325
1326				if ((datasets = zfs_alloc(hdl,
1327				    8 * sizeof (void *))) == NULL)
1328					goto out;
1329
1330				alloc = 8;
1331			} else {
1332				void *ptr;
1333
1334				if ((ptr = zfs_realloc(hdl, mountpoints,
1335				    alloc * sizeof (void *),
1336				    alloc * 2 * sizeof (void *))) == NULL)
1337					goto out;
1338				mountpoints = ptr;
1339
1340				if ((ptr = zfs_realloc(hdl, datasets,
1341				    alloc * sizeof (void *),
1342				    alloc * 2 * sizeof (void *))) == NULL)
1343					goto out;
1344				datasets = ptr;
1345
1346				alloc *= 2;
1347			}
1348		}
1349
1350		if ((mountpoints[used] = zfs_strdup(hdl,
1351		    sfs[j].f_mntonname)) == NULL)
1352			goto out;
1353
1354		/*
1355		 * This is allowed to fail, in case there is some I/O error.  It
1356		 * is only used to determine if we need to remove the underlying
1357		 * mountpoint, so failure is not fatal.
1358		 */
1359		datasets[used] = make_dataset_handle(hdl, sfs[j].f_mntfromname);
1360
1361		used++;
1362	}
1363
1364	/*
1365	 * At this point, we have the entire list of filesystems, so sort it by
1366	 * mountpoint.
1367	 */
1368	qsort(mountpoints, used, sizeof (char *), mountpoint_compare);
1369
1370	/*
1371	 * Walk through and first unshare everything.
1372	 */
1373	for (i = 0; i < used; i++) {
1374		zfs_share_proto_t *curr_proto;
1375		for (curr_proto = share_all_proto; *curr_proto != PROTO_END;
1376		    curr_proto++) {
1377			if (is_shared(hdl, mountpoints[i], *curr_proto) &&
1378			    unshare_one(hdl, mountpoints[i],
1379			    mountpoints[i], *curr_proto) != 0)
1380				goto out;
1381		}
1382	}
1383
1384	/*
1385	 * Now unmount everything, removing the underlying directories as
1386	 * appropriate.
1387	 */
1388	for (i = 0; i < used; i++) {
1389		if (unmount_one(hdl, mountpoints[i], flags) != 0)
1390			goto out;
1391	}
1392
1393	for (i = 0; i < used; i++) {
1394		if (datasets[i])
1395			remove_mountpoint(datasets[i]);
1396	}
1397
1398	ret = 0;
1399out:
1400	for (i = 0; i < used; i++) {
1401		if (datasets[i])
1402			zfs_close(datasets[i]);
1403		free(mountpoints[i]);
1404	}
1405	free(datasets);
1406	free(mountpoints);
1407
1408	return (ret);
1409}
1410