Home | History | Annotate | Download | only in common
      1    789    ahrens /*
      2    789    ahrens  * CDDL HEADER START
      3    789    ahrens  *
      4    789    ahrens  * The contents of this file are subject to the terms of the
      5   1544  eschrock  * Common Development and Distribution License (the "License").
      6   1544  eschrock  * You may not use this file except in compliance with the License.
      7    789    ahrens  *
      8    789    ahrens  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9    789    ahrens  * or http://www.opensolaris.org/os/licensing.
     10    789    ahrens  * See the License for the specific language governing permissions
     11    789    ahrens  * and limitations under the License.
     12    789    ahrens  *
     13    789    ahrens  * When distributing Covered Code, include this CDDL HEADER in each
     14    789    ahrens  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15    789    ahrens  * If applicable, add the following below this CDDL HEADER, with the
     16    789    ahrens  * fields enclosed by brackets "[]" replaced with your own identifying
     17    789    ahrens  * information: Portions Copyright [yyyy] [name of copyright owner]
     18    789    ahrens  *
     19    789    ahrens  * CDDL HEADER END
     20    789    ahrens  */
     21   3126       ahl 
     22    789    ahrens /*
     23   8536     David  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24    789    ahrens  * Use is subject to license terms.
     25    789    ahrens  */
     26    789    ahrens 
     27    789    ahrens /*
     28    789    ahrens  * Routines to manage ZFS mounts.  We separate all the nasty routines that have
     29   3126       ahl  * to deal with the OS.  The following functions are the main entry points --
     30   3126       ahl  * they are used by mount and unmount and when changing a filesystem's
     31   3126       ahl  * mountpoint.
     32    789    ahrens  *
     33    789    ahrens  * 	zfs_is_mounted()
     34    789    ahrens  * 	zfs_mount()
     35    789    ahrens  * 	zfs_unmount()
     36    789    ahrens  * 	zfs_unmountall()
     37    789    ahrens  *
     38   3126       ahl  * This file also contains the functions used to manage sharing filesystems via
     39   3126       ahl  * NFS and iSCSI:
     40    789    ahrens  *
     41    789    ahrens  * 	zfs_is_shared()
     42    789    ahrens  * 	zfs_share()
     43    789    ahrens  * 	zfs_unshare()
     44   3126       ahl  *
     45   3126       ahl  * 	zfs_is_shared_nfs()
     46   5331       amw  * 	zfs_is_shared_smb()
     47   5331       amw  * 	zfs_is_shared_iscsi()
     48   5331       amw  * 	zfs_share_proto()
     49   5331       amw  * 	zfs_shareall();
     50   5331       amw  * 	zfs_share_iscsi()
     51   3126       ahl  * 	zfs_unshare_nfs()
     52   5331       amw  * 	zfs_unshare_smb()
     53   3126       ahl  * 	zfs_unshareall_nfs()
     54   5331       amw  *	zfs_unshareall_smb()
     55   5331       amw  *	zfs_unshareall()
     56   5331       amw  *	zfs_unshareall_bypath()
     57   3126       ahl  * 	zfs_unshare_iscsi()
     58   2474  eschrock  *
     59   2474  eschrock  * The following functions are available for pool consumers, and will
     60   3126       ahl  * mount/unmount and share/unshare all datasets within pool:
     61   2474  eschrock  *
     62   3126       ahl  * 	zpool_enable_datasets()
     63   3126       ahl  * 	zpool_disable_datasets()
     64    789    ahrens  */
     65    789    ahrens 
     66    789    ahrens #include <dirent.h>
     67   3134       ahl #include <dlfcn.h>
     68    789    ahrens #include <errno.h>
     69    789    ahrens #include <libgen.h>
     70    789    ahrens #include <libintl.h>
     71    789    ahrens #include <stdio.h>
     72    789    ahrens #include <stdlib.h>
     73    789    ahrens #include <strings.h>
     74    789    ahrens #include <unistd.h>
     75    789    ahrens #include <zone.h>
     76    789    ahrens #include <sys/mntent.h>
     77    789    ahrens #include <sys/mount.h>
     78    789    ahrens #include <sys/stat.h>
     79    789    ahrens 
     80    789    ahrens #include <libzfs.h>
     81    789    ahrens 
     82    789    ahrens #include "libzfs_impl.h"
     83   4180     dougm 
     84   4180     dougm #include <libshare.h>
     85   4180     dougm #include <sys/systeminfo.h>
     86   4180     dougm #define	MAXISALEN	257	/* based on sysinfo(2) man page */
     87   3134       ahl 
     88   5331       amw static int zfs_share_proto(zfs_handle_t *, zfs_share_proto_t *);
     89   5331       amw zfs_share_type_t zfs_is_shared_proto(zfs_handle_t *, char **,
     90   5331       amw     zfs_share_proto_t);
     91   5331       amw 
     92   3134       ahl static int (*iscsitgt_zfs_share)(const char *);
     93   3134       ahl static int (*iscsitgt_zfs_unshare)(const char *);
     94   3134       ahl static int (*iscsitgt_zfs_is_shared)(const char *);
     95   4543     marks static int (*iscsitgt_svc_online)();
     96   5331       amw 
     97   5331       amw /*
     98   5331       amw  * The share protocols table must be in the same order as the zfs_share_prot_t
     99   5331       amw  * enum in libzfs_impl.h
    100   5331       amw  */
    101   5331       amw typedef struct {
    102   5331       amw 	zfs_prop_t p_prop;
    103   5331       amw 	char *p_name;
    104   5331       amw 	int p_share_err;
    105   5331       amw 	int p_unshare_err;
    106   5331       amw } proto_table_t;
    107   5331       amw 
    108   5331       amw proto_table_t proto_table[PROTO_END] = {
    109   5331       amw 	{ZFS_PROP_SHARENFS, "nfs", EZFS_SHARENFSFAILED, EZFS_UNSHARENFSFAILED},
    110   5331       amw 	{ZFS_PROP_SHARESMB, "smb", EZFS_SHARESMBFAILED, EZFS_UNSHARESMBFAILED},
    111   5331       amw };
    112   5331       amw 
    113   5331       amw zfs_share_proto_t nfs_only[] = {
    114   5331       amw 	PROTO_NFS,
    115   5331       amw 	PROTO_END
    116   5331       amw };
    117   5331       amw 
    118   5331       amw zfs_share_proto_t smb_only[] = {
    119   5331       amw 	PROTO_SMB,
    120   5331       amw 	PROTO_END
    121   5331       amw };
    122   5331       amw zfs_share_proto_t share_all_proto[] = {
    123   5331       amw 	PROTO_NFS,
    124   5331       amw 	PROTO_SMB,
    125   5331       amw 	PROTO_END
    126   5331       amw };
    127   3134       ahl 
    128   3134       ahl #pragma init(zfs_iscsi_init)
    129   3134       ahl static void
    130   3134       ahl zfs_iscsi_init(void)
    131   3134       ahl {
    132   3134       ahl 	void *libiscsitgt;
    133   3134       ahl 
    134   3134       ahl 	if ((libiscsitgt = dlopen("/lib/libiscsitgt.so.1",
    135   3134       ahl 	    RTLD_LAZY | RTLD_GLOBAL)) == NULL ||
    136   3134       ahl 	    (iscsitgt_zfs_share = (int (*)(const char *))dlsym(libiscsitgt,
    137   3134       ahl 	    "iscsitgt_zfs_share")) == NULL ||
    138   3134       ahl 	    (iscsitgt_zfs_unshare = (int (*)(const char *))dlsym(libiscsitgt,
    139   3134       ahl 	    "iscsitgt_zfs_unshare")) == NULL ||
    140   3134       ahl 	    (iscsitgt_zfs_is_shared = (int (*)(const char *))dlsym(libiscsitgt,
    141   4543     marks 	    "iscsitgt_zfs_is_shared")) == NULL ||
    142   4543     marks 	    (iscsitgt_svc_online = (int (*)(const char *))dlsym(libiscsitgt,
    143   4543     marks 	    "iscsitgt_svc_online")) == NULL) {
    144   3134       ahl 		iscsitgt_zfs_share = NULL;
    145   3134       ahl 		iscsitgt_zfs_unshare = NULL;
    146   3134       ahl 		iscsitgt_zfs_is_shared = NULL;
    147   4543     marks 		iscsitgt_svc_online = NULL;
    148   3134       ahl 	}
    149   3134       ahl }
    150    789    ahrens 
    151    789    ahrens /*
    152   5331       amw  * Search the sharetab for the given mountpoint and protocol, returning
    153   5331       amw  * a zfs_share_type_t value.
    154    789    ahrens  */
    155   5331       amw static zfs_share_type_t
    156   5331       amw is_shared(libzfs_handle_t *hdl, const char *mountpoint, zfs_share_proto_t proto)
    157    789    ahrens {
    158    789    ahrens 	char buf[MAXPATHLEN], *tab;
    159   5331       amw 	char *ptr;
    160    789    ahrens 
    161   2082  eschrock 	if (hdl->libzfs_sharetab == NULL)
    162   5331       amw 		return (SHARED_NOT_SHARED);
    163    789    ahrens 
    164   2082  eschrock 	(void) fseek(hdl->libzfs_sharetab, 0, SEEK_SET);
    165    789    ahrens 
    166   2082  eschrock 	while (fgets(buf, sizeof (buf), hdl->libzfs_sharetab) != NULL) {
    167    789    ahrens 
    168    789    ahrens 		/* the mountpoint is the first entry on each line */
    169   5331       amw 		if ((tab = strchr(buf, '\t')) == NULL)
    170   5331       amw 			continue;
    171   5331       amw 
    172   5331       amw 		*tab = '\0';
    173   5331       amw 		if (strcmp(buf, mountpoint) == 0) {
    174   5331       amw 			/*
    175   5331       amw 			 * the protocol field is the third field
    176   5331       amw 			 * skip over second field
    177   5331       amw 			 */
    178   5331       amw 			ptr = ++tab;
    179   5331       amw 			if ((tab = strchr(ptr, '\t')) == NULL)
    180   5331       amw 				continue;
    181   5331       amw 			ptr = ++tab;
    182   5331       amw 			if ((tab = strchr(ptr, '\t')) == NULL)
    183   5331       amw 				continue;
    184    789    ahrens 			*tab = '\0';
    185   5331       amw 			if (strcmp(ptr,
    186   5331       amw 			    proto_table[proto].p_name) == 0) {
    187   5331       amw 				switch (proto) {
    188   5331       amw 				case PROTO_NFS:
    189   5331       amw 					return (SHARED_NFS);
    190   5331       amw 				case PROTO_SMB:
    191   5331       amw 					return (SHARED_SMB);
    192   5331       amw 				default:
    193   5331       amw 					return (0);
    194   5331       amw 				}
    195   5331       amw 			}
    196    789    ahrens 		}
    197    789    ahrens 	}
    198    789    ahrens 
    199   5331       amw 	return (SHARED_NOT_SHARED);
    200    789    ahrens }
    201    789    ahrens 
    202    789    ahrens /*
    203   2082  eschrock  * Returns true if the specified directory is empty.  If we can't open the
    204   2082  eschrock  * directory at all, return true so that the mount can fail with a more
    205    789    ahrens  * informative error message.
    206    789    ahrens  */
    207   2082  eschrock static boolean_t
    208    789    ahrens dir_is_empty(const char *dirname)
    209    789    ahrens {
    210    789    ahrens 	DIR *dirp;
    211    789    ahrens 	struct dirent64 *dp;
    212    789    ahrens 
    213    789    ahrens 	if ((dirp = opendir(dirname)) == NULL)
    214   2082  eschrock 		return (B_TRUE);
    215    789    ahrens 
    216    789    ahrens 	while ((dp = readdir64(dirp)) != NULL) {
    217    789    ahrens 
    218    789    ahrens 		if (strcmp(dp->d_name, ".") == 0 ||
    219    789    ahrens 		    strcmp(dp->d_name, "..") == 0)
    220    789    ahrens 			continue;
    221    789    ahrens 
    222    789    ahrens 		(void) closedir(dirp);
    223   2082  eschrock 		return (B_FALSE);
    224    789    ahrens 	}
    225    789    ahrens 
    226    789    ahrens 	(void) closedir(dirp);
    227   2082  eschrock 	return (B_TRUE);
    228    789    ahrens }
    229    789    ahrens 
    230    789    ahrens /*
    231    789    ahrens  * Checks to see if the mount is active.  If the filesystem is mounted, we fill
    232    789    ahrens  * in 'where' with the current mountpoint, and return 1.  Otherwise, we return
    233    789    ahrens  * 0.
    234    789    ahrens  */
    235   2082  eschrock boolean_t
    236   3444  ek110237 is_mounted(libzfs_handle_t *zfs_hdl, const char *special, char **where)
    237    789    ahrens {
    238   8228      Eric 	struct mnttab entry;
    239    789    ahrens 
    240   8228      Eric 	if (libzfs_mnttab_find(zfs_hdl, special, &entry) != 0)
    241   2082  eschrock 		return (B_FALSE);
    242    789    ahrens 
    243    789    ahrens 	if (where != NULL)
    244   3444  ek110237 		*where = zfs_strdup(zfs_hdl, entry.mnt_mountp);
    245    789    ahrens 
    246   2082  eschrock 	return (B_TRUE);
    247   3444  ek110237 }
    248   3444  ek110237 
    249   3444  ek110237 boolean_t
    250   3444  ek110237 zfs_is_mounted(zfs_handle_t *zhp, char **where)
    251   3444  ek110237 {
    252   3444  ek110237 	return (is_mounted(zhp->zfs_hdl, zfs_get_name(zhp), where));
    253    789    ahrens }
    254    789    ahrens 
    255    789    ahrens /*
    256   2676  eschrock  * Returns true if the given dataset is mountable, false otherwise.  Returns the
    257   2676  eschrock  * mountpoint in 'buf'.
    258   2676  eschrock  */
    259   2676  eschrock static boolean_t
    260   2676  eschrock zfs_is_mountable(zfs_handle_t *zhp, char *buf, size_t buflen,
    261   5094     lling     zprop_source_t *source)
    262   2676  eschrock {
    263   2676  eschrock 	char sourceloc[ZFS_MAXNAMELEN];
    264   5094     lling 	zprop_source_t sourcetype;
    265   2676  eschrock 
    266   2676  eschrock 	if (!zfs_prop_valid_for_type(ZFS_PROP_MOUNTPOINT, zhp->zfs_type))
    267   2676  eschrock 		return (B_FALSE);
    268   2676  eschrock 
    269   2676  eschrock 	verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, buf, buflen,
    270   2676  eschrock 	    &sourcetype, sourceloc, sizeof (sourceloc), B_FALSE) == 0);
    271   2676  eschrock 
    272   2676  eschrock 	if (strcmp(buf, ZFS_MOUNTPOINT_NONE) == 0 ||
    273   2676  eschrock 	    strcmp(buf, ZFS_MOUNTPOINT_LEGACY) == 0)
    274   2676  eschrock 		return (B_FALSE);
    275   2676  eschrock 
    276   6168   hs24103 	if (zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT) == ZFS_CANMOUNT_OFF)
    277   2676  eschrock 		return (B_FALSE);
    278   2676  eschrock 
    279   2676  eschrock 	if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED) &&
    280   2676  eschrock 	    getzoneid() == GLOBAL_ZONEID)
    281   2676  eschrock 		return (B_FALSE);
    282   2676  eschrock 
    283   2676  eschrock 	if (source)
    284   2676  eschrock 		*source = sourcetype;
    285   2676  eschrock 
    286   2676  eschrock 	return (B_TRUE);
    287   2676  eschrock }
    288   2676  eschrock 
    289   2676  eschrock /*
    290    789    ahrens  * Mount the given filesystem.
    291    789    ahrens  */
    292    789    ahrens int
    293    789    ahrens zfs_mount(zfs_handle_t *zhp, const char *options, int flags)
    294    789    ahrens {
    295    789    ahrens 	struct stat buf;
    296    789    ahrens 	char mountpoint[ZFS_MAXPROPLEN];
    297    789    ahrens 	char mntopts[MNT_LINE_MAX];
    298   2082  eschrock 	libzfs_handle_t *hdl = zhp->zfs_hdl;
    299    789    ahrens 
    300    789    ahrens 	if (options == NULL)
    301    789    ahrens 		mntopts[0] = '\0';
    302    789    ahrens 	else
    303    789    ahrens 		(void) strlcpy(mntopts, options, sizeof (mntopts));
    304    789    ahrens 
    305   2676  eschrock 	if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL))
    306   2082  eschrock 		return (0);
    307    789    ahrens 
    308    789    ahrens 	/* Create the directory if it doesn't already exist */
    309    789    ahrens 	if (lstat(mountpoint, &buf) != 0) {
    310    789    ahrens 		if (mkdirp(mountpoint, 0755) != 0) {
    311   2082  eschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    312   2082  eschrock 			    "failed to create mountpoint"));
    313   3237     lling 			return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED,
    314   2082  eschrock 			    dgettext(TEXT_DOMAIN, "cannot mount '%s'"),
    315   2082  eschrock 			    mountpoint));
    316    789    ahrens 		}
    317    789    ahrens 	}
    318    789    ahrens 
    319    789    ahrens 	/*
    320    789    ahrens 	 * Determine if the mountpoint is empty.  If so, refuse to perform the
    321    789    ahrens 	 * mount.  We don't perform this check if MS_OVERLAY is specified, which
    322    789    ahrens 	 * would defeat the point.  We also avoid this check if 'remount' is
    323    789    ahrens 	 * specified.
    324    789    ahrens 	 */
    325    789    ahrens 	if ((flags & MS_OVERLAY) == 0 &&
    326    789    ahrens 	    strstr(mntopts, MNTOPT_REMOUNT) == NULL &&
    327    789    ahrens 	    !dir_is_empty(mountpoint)) {
    328   2082  eschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    329   2082  eschrock 		    "directory is not empty"));
    330   3237     lling 		return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED,
    331   2082  eschrock 		    dgettext(TEXT_DOMAIN, "cannot mount '%s'"), mountpoint));
    332    789    ahrens 	}
    333    789    ahrens 
    334    789    ahrens 	/* perform the mount */
    335    789    ahrens 	if (mount(zfs_get_name(zhp), mountpoint, MS_OPTIONSTR | flags,
    336    789    ahrens 	    MNTTYPE_ZFS, NULL, 0, mntopts, sizeof (mntopts)) != 0) {
    337    789    ahrens 		/*
    338    789    ahrens 		 * Generic errors are nasty, but there are just way too many
    339    789    ahrens 		 * from mount(), and they're well-understood.  We pick a few
    340    789    ahrens 		 * common ones to improve upon.
    341    789    ahrens 		 */
    342   4302     dougm 		if (errno == EBUSY) {
    343   2082  eschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    344   2082  eschrock 			    "mountpoint or dataset is busy"));
    345   4543     marks 		} else if (errno == EPERM) {
    346   4543     marks 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    347   4543     marks 			    "Insufficient privileges"));
    348   4302     dougm 		} else {
    349   2082  eschrock 			zfs_error_aux(hdl, strerror(errno));
    350   4302     dougm 		}
    351   3237     lling 		return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED,
    352   2082  eschrock 		    dgettext(TEXT_DOMAIN, "cannot mount '%s'"),
    353   2082  eschrock 		    zhp->zfs_name));
    354    789    ahrens 	}
    355    789    ahrens 
    356   8228      Eric 	/* add the mounted entry into our cache */
    357   8228      Eric 	libzfs_mnttab_add(hdl, zfs_get_name(zhp), mountpoint,
    358   8228      Eric 	    mntopts);
    359    789    ahrens 	return (0);
    360    789    ahrens }
    361    789    ahrens 
    362    789    ahrens /*
    363   2474  eschrock  * Unmount a single filesystem.
    364   2474  eschrock  */
    365   2474  eschrock static int
    366   2474  eschrock unmount_one(libzfs_handle_t *hdl, const char *mountpoint, int flags)
    367   2474  eschrock {
    368   2474  eschrock 	if (umount2(mountpoint, flags) != 0) {
    369   2474  eschrock 		zfs_error_aux(hdl, strerror(errno));
    370   3237     lling 		return (zfs_error_fmt(hdl, EZFS_UMOUNTFAILED,
    371   2474  eschrock 		    dgettext(TEXT_DOMAIN, "cannot unmount '%s'"),
    372   2474  eschrock 		    mountpoint));
    373   2474  eschrock 	}
    374   2474  eschrock 
    375   2474  eschrock 	return (0);
    376   2474  eschrock }
    377   2474  eschrock 
    378   2474  eschrock /*
    379    789    ahrens  * Unmount the given filesystem.
    380    789    ahrens  */
    381    789    ahrens int
    382    789    ahrens zfs_unmount(zfs_handle_t *zhp, const char *mountpoint, int flags)
    383    789    ahrens {
    384   8228      Eric 	libzfs_handle_t *hdl = zhp->zfs_hdl;
    385   8228      Eric 	struct mnttab entry;
    386   4180     dougm 	char *mntpt = NULL;
    387    789    ahrens 
    388   8228      Eric 	/* check to see if we need to unmount the filesystem */
    389    789    ahrens 	if (mountpoint != NULL || ((zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) &&
    390   8228      Eric 	    libzfs_mnttab_find(hdl, zhp->zfs_name, &entry) == 0)) {
    391   4180     dougm 		/*
    392   4180     dougm 		 * mountpoint may have come from a call to
    393   4180     dougm 		 * getmnt/getmntany if it isn't NULL. If it is NULL,
    394   8228      Eric 		 * we know it comes from libzfs_mnttab_find which can
    395   8228      Eric 		 * then get freed later. We strdup it to play it safe.
    396   4180     dougm 		 */
    397    789    ahrens 		if (mountpoint == NULL)
    398   8228      Eric 			mntpt = zfs_strdup(hdl, entry.mnt_mountp);
    399   4180     dougm 		else
    400   8228      Eric 			mntpt = zfs_strdup(hdl, mountpoint);
    401    789    ahrens 
    402    789    ahrens 		/*
    403   2474  eschrock 		 * Unshare and unmount the filesystem
    404    789    ahrens 		 */
    405   5331       amw 		if (zfs_unshare_proto(zhp, mntpt, share_all_proto) != 0)
    406   4331  th199096 			return (-1);
    407   4331  th199096 
    408   8228      Eric 		if (unmount_one(hdl, mntpt, flags) != 0) {
    409   4180     dougm 			free(mntpt);
    410   5331       amw 			(void) zfs_shareall(zhp);
    411    789    ahrens 			return (-1);
    412   4180     dougm 		}
    413   8228      Eric 		libzfs_mnttab_remove(hdl, zhp->zfs_name);
    414   4180     dougm 		free(mntpt);
    415    789    ahrens 	}
    416    789    ahrens 
    417    789    ahrens 	return (0);
    418    789    ahrens }
    419    789    ahrens 
    420    789    ahrens /*
    421    789    ahrens  * Unmount this filesystem and any children inheriting the mountpoint property.
    422    789    ahrens  * To do this, just act like we're changing the mountpoint property, but don't
    423    789    ahrens  * remount the filesystems afterwards.
    424    789    ahrens  */
    425    789    ahrens int
    426    789    ahrens zfs_unmountall(zfs_handle_t *zhp, int flags)
    427    789    ahrens {
    428    789    ahrens 	prop_changelist_t *clp;
    429    789    ahrens 	int ret;
    430    789    ahrens 
    431   7366       Tim 	clp = changelist_gather(zhp, ZFS_PROP_MOUNTPOINT, 0, flags);
    432    789    ahrens 	if (clp == NULL)
    433    789    ahrens 		return (-1);
    434    789    ahrens 
    435    789    ahrens 	ret = changelist_prefix(clp);
    436    789    ahrens 	changelist_free(clp);
    437    789    ahrens 
    438    789    ahrens 	return (ret);
    439    789    ahrens }
    440    789    ahrens 
    441   3126       ahl boolean_t
    442   3126       ahl zfs_is_shared(zfs_handle_t *zhp)
    443   3126       ahl {
    444   5331       amw 	zfs_share_type_t rc = 0;
    445   5331       amw 	zfs_share_proto_t *curr_proto;
    446   5331       amw 
    447   3126       ahl 	if (ZFS_IS_VOLUME(zhp))
    448   3126       ahl 		return (zfs_is_shared_iscsi(zhp));
    449   3126       ahl 
    450   5331       amw 	for (curr_proto = share_all_proto; *curr_proto != PROTO_END;
    451   5331       amw 	    curr_proto++)
    452   5331       amw 		rc |= zfs_is_shared_proto(zhp, NULL, *curr_proto);
    453   5331       amw 
    454   5331       amw 	return (rc ? B_TRUE : B_FALSE);
    455   3126       ahl }
    456   3126       ahl 
    457   3126       ahl int
    458   3126       ahl zfs_share(zfs_handle_t *zhp)
    459   3126       ahl {
    460   3126       ahl 	if (ZFS_IS_VOLUME(zhp))
    461   3126       ahl 		return (zfs_share_iscsi(zhp));
    462   3126       ahl 
    463   5331       amw 	return (zfs_share_proto(zhp, share_all_proto));
    464   3126       ahl }
    465   3126       ahl 
    466   3126       ahl int
    467   3126       ahl zfs_unshare(zfs_handle_t *zhp)
    468   3126       ahl {
    469   3126       ahl 	if (ZFS_IS_VOLUME(zhp))
    470   3126       ahl 		return (zfs_unshare_iscsi(zhp));
    471   3126       ahl 
    472   5331       amw 	return (zfs_unshareall(zhp));
    473   3126       ahl }
    474   3126       ahl 
    475    789    ahrens /*
    476    789    ahrens  * Check to see if the filesystem is currently shared.
    477    789    ahrens  */
    478   5331       amw zfs_share_type_t
    479   5331       amw zfs_is_shared_proto(zfs_handle_t *zhp, char **where, zfs_share_proto_t proto)
    480    789    ahrens {
    481    789    ahrens 	char *mountpoint;
    482   5331       amw 	zfs_share_type_t rc;
    483    789    ahrens 
    484    789    ahrens 	if (!zfs_is_mounted(zhp, &mountpoint))
    485   5331       amw 		return (SHARED_NOT_SHARED);
    486    789    ahrens 
    487   5331       amw 	if (rc = is_shared(zhp->zfs_hdl, mountpoint, proto)) {
    488    789    ahrens 		if (where != NULL)
    489    789    ahrens 			*where = mountpoint;
    490    789    ahrens 		else
    491    789    ahrens 			free(mountpoint);
    492   5331       amw 		return (rc);
    493    789    ahrens 	} else {
    494    789    ahrens 		free(mountpoint);
    495   5331       amw 		return (SHARED_NOT_SHARED);
    496    789    ahrens 	}
    497   5331       amw }
    498   5331       amw 
    499   5331       amw boolean_t
    500   5331       amw zfs_is_shared_nfs(zfs_handle_t *zhp, char **where)
    501   5331       amw {
    502   5331       amw 	return (zfs_is_shared_proto(zhp, where,
    503   5331       amw 	    PROTO_NFS) != SHARED_NOT_SHARED);
    504   5331       amw }
    505   5331       amw 
    506   5331       amw boolean_t
    507   5331       amw zfs_is_shared_smb(zfs_handle_t *zhp, char **where)
    508   5331       amw {
    509   5331       amw 	return (zfs_is_shared_proto(zhp, where,
    510   5331       amw 	    PROTO_SMB) != SHARED_NOT_SHARED);
    511    789    ahrens }
    512    789    ahrens 
    513    789    ahrens /*
    514   4180     dougm  * Make sure things will work if libshare isn't installed by using
    515   4180     dougm  * wrapper functions that check to see that the pointers to functions
    516   4180     dougm  * initialized in _zfs_init_libshare() are actually present.
    517   4180     dougm  */
    518   4180     dougm 
    519   4180     dougm static sa_handle_t (*_sa_init)(int);
    520   4180     dougm static void (*_sa_fini)(sa_handle_t);
    521   4180     dougm static sa_share_t (*_sa_find_share)(sa_handle_t, char *);
    522   4180     dougm static int (*_sa_enable_share)(sa_share_t, char *);
    523   4180     dougm static int (*_sa_disable_share)(sa_share_t, char *);
    524   4180     dougm static char *(*_sa_errorstr)(int);
    525   4180     dougm static int (*_sa_parse_legacy_options)(sa_group_t, char *, char *);
    526   5951     dougm static boolean_t (*_sa_needs_refresh)(sa_handle_t *);
    527   5951     dougm static libzfs_handle_t *(*_sa_get_zfs_handle)(sa_handle_t);
    528   5951     dougm static int (*_sa_zfs_process_share)(sa_handle_t, sa_group_t, sa_share_t,
    529   5951     dougm     char *, char *, zprop_source_t, char *, char *, char *);
    530   5951     dougm static void (*_sa_update_sharetab_ts)(sa_handle_t);
    531   4180     dougm 
    532   4180     dougm /*
    533   4180     dougm  * _zfs_init_libshare()
    534   4180     dougm  *
    535   4180     dougm  * Find the libshare.so.1 entry points that we use here and save the
    536   4180     dougm  * values to be used later. This is triggered by the runtime loader.
    537   4180     dougm  * Make sure the correct ISA version is loaded.
    538   4180     dougm  */
    539   5951     dougm 
    540   4180     dougm #pragma init(_zfs_init_libshare)
    541   4180     dougm static void
    542   4180     dougm _zfs_init_libshare(void)
    543   4180     dougm {
    544   4180     dougm 	void *libshare;
    545   4180     dougm 	char path[MAXPATHLEN];
    546   4180     dougm 	char isa[MAXISALEN];
    547   4180     dougm 
    548   4180     dougm #if defined(_LP64)
    549   4180     dougm 	if (sysinfo(SI_ARCHITECTURE_64, isa, MAXISALEN) == -1)
    550   4302     dougm 		isa[0] = '\0';
    551   4180     dougm #else
    552   4180     dougm 	isa[0] = '\0';
    553   4180     dougm #endif
    554   4180     dougm 	(void) snprintf(path, MAXPATHLEN,
    555   4302     dougm 	    "/usr/lib/%s/libshare.so.1", isa);
    556   4180     dougm 
    557   4180     dougm 	if ((libshare = dlopen(path, RTLD_LAZY | RTLD_GLOBAL)) != NULL) {
    558   4302     dougm 		_sa_init = (sa_handle_t (*)(int))dlsym(libshare, "sa_init");
    559   4302     dougm 		_sa_fini = (void (*)(sa_handle_t))dlsym(libshare, "sa_fini");
    560   4302     dougm 		_sa_find_share = (sa_share_t (*)(sa_handle_t, char *))
    561   4302     dougm 		    dlsym(libshare, "sa_find_share");
    562   4302     dougm 		_sa_enable_share = (int (*)(sa_share_t, char *))dlsym(libshare,
    563   4302     dougm 		    "sa_enable_share");
    564   4302     dougm 		_sa_disable_share = (int (*)(sa_share_t, char *))dlsym(libshare,
    565   4302     dougm 		    "sa_disable_share");
    566   4302     dougm 		_sa_errorstr = (char *(*)(int))dlsym(libshare, "sa_errorstr");
    567   4302     dougm 		_sa_parse_legacy_options = (int (*)(sa_group_t, char *, char *))
    568   4302     dougm 		    dlsym(libshare, "sa_parse_legacy_options");
    569   5951     dougm 		_sa_needs_refresh = (boolean_t (*)(sa_handle_t *))
    570   5951     dougm 		    dlsym(libshare, "sa_needs_refresh");
    571   5951     dougm 		_sa_get_zfs_handle = (libzfs_handle_t *(*)(sa_handle_t))
    572   5951     dougm 		    dlsym(libshare, "sa_get_zfs_handle");
    573   5951     dougm 		_sa_zfs_process_share = (int (*)(sa_handle_t, sa_group_t,
    574   5951     dougm 		    sa_share_t, char *, char *, zprop_source_t, char *,
    575   5951     dougm 		    char *, char *))dlsym(libshare, "sa_zfs_process_share");
    576   5951     dougm 		_sa_update_sharetab_ts = (void (*)(sa_handle_t))
    577   5951     dougm 		    dlsym(libshare, "sa_update_sharetab_ts");
    578   4327     dougm 		if (_sa_init == NULL || _sa_fini == NULL ||
    579   4327     dougm 		    _sa_find_share == NULL || _sa_enable_share == NULL ||
    580   4327     dougm 		    _sa_disable_share == NULL || _sa_errorstr == NULL ||
    581   5951     dougm 		    _sa_parse_legacy_options == NULL ||
    582   5951     dougm 		    _sa_needs_refresh == NULL || _sa_get_zfs_handle == NULL ||
    583   5951     dougm 		    _sa_zfs_process_share == NULL ||
    584   5951     dougm 		    _sa_update_sharetab_ts == NULL) {
    585   4327     dougm 			_sa_init = NULL;
    586   4327     dougm 			_sa_fini = NULL;
    587   4327     dougm 			_sa_disable_share = NULL;
    588   4327     dougm 			_sa_enable_share = NULL;
    589   4327     dougm 			_sa_errorstr = NULL;
    590   4327     dougm 			_sa_parse_legacy_options = NULL;
    591   4327     dougm 			(void) dlclose(libshare);
    592   5951     dougm 			_sa_needs_refresh = NULL;
    593   5951     dougm 			_sa_get_zfs_handle = NULL;
    594   5951     dougm 			_sa_zfs_process_share = NULL;
    595   5951     dougm 			_sa_update_sharetab_ts = NULL;
    596   4327     dougm 		}
    597   4180     dougm 	}
    598   4180     dougm }
    599   4180     dougm 
    600   4180     dougm /*
    601   4180     dougm  * zfs_init_libshare(zhandle, service)
    602   4180     dougm  *
    603   4180     dougm  * Initialize the libshare API if it hasn't already been initialized.
    604   4180     dougm  * In all cases it returns 0 if it succeeded and an error if not. The
    605   4180     dougm  * service value is which part(s) of the API to initialize and is a
    606   4180     dougm  * direct map to the libshare sa_init(service) interface.
    607   4180     dougm  */
    608   4180     dougm int
    609   4180     dougm zfs_init_libshare(libzfs_handle_t *zhandle, int service)
    610   4180     dougm {
    611   4180     dougm 	int ret = SA_OK;
    612   4180     dougm 
    613   4302     dougm 	if (_sa_init == NULL)
    614   4302     dougm 		ret = SA_CONFIG_ERR;
    615   5951     dougm 
    616   5951     dougm 	if (ret == SA_OK && zhandle->libzfs_shareflags & ZFSSHARE_MISS) {
    617   5951     dougm 		/*
    618   5951     dougm 		 * We had a cache miss. Most likely it is a new ZFS
    619   5951     dougm 		 * dataset that was just created. We want to make sure
    620   5951     dougm 		 * so check timestamps to see if a different process
    621   5951     dougm 		 * has updated any of the configuration. If there was
    622   5951     dougm 		 * some non-ZFS change, we need to re-initialize the
    623   5951     dougm 		 * internal cache.
    624   5951     dougm 		 */
    625   5951     dougm 		zhandle->libzfs_shareflags &= ~ZFSSHARE_MISS;
    626   5951     dougm 		if (_sa_needs_refresh != NULL &&
    627   5951     dougm 		    _sa_needs_refresh(zhandle->libzfs_sharehdl)) {
    628   5951     dougm 			zfs_uninit_libshare(zhandle);
    629   5951     dougm 			zhandle->libzfs_sharehdl = _sa_init(service);
    630   5951     dougm 		}
    631   5951     dougm 	}
    632   4302     dougm 
    633   4302     dougm 	if (ret == SA_OK && zhandle && zhandle->libzfs_sharehdl == NULL)
    634   4302     dougm 		zhandle->libzfs_sharehdl = _sa_init(service);
    635   4302     dougm 
    636   4302     dougm 	if (ret == SA_OK && zhandle->libzfs_sharehdl == NULL)
    637   4302     dougm 		ret = SA_NO_MEMORY;
    638   4302     dougm 
    639   4180     dougm 	return (ret);
    640   4180     dougm }
    641   4180     dougm 
    642   4180     dougm /*
    643   4180     dougm  * zfs_uninit_libshare(zhandle)
    644   4180     dougm  *
    645   4180     dougm  * Uninitialize the libshare API if it hasn't already been
    646   4180     dougm  * uninitialized. It is OK to call multiple times.
    647   4180     dougm  */
    648   4180     dougm void
    649   4180     dougm zfs_uninit_libshare(libzfs_handle_t *zhandle)
    650   4180     dougm {
    651   4180     dougm 	if (zhandle != NULL && zhandle->libzfs_sharehdl != NULL) {
    652   4302     dougm 		if (_sa_fini != NULL)
    653   4302     dougm 			_sa_fini(zhandle->libzfs_sharehdl);
    654   4302     dougm 		zhandle->libzfs_sharehdl = NULL;
    655   4180     dougm 	}
    656   4180     dougm }
    657   4180     dougm 
    658   4180     dougm /*
    659   4180     dougm  * zfs_parse_options(options, proto)
    660   4180     dougm  *
    661   4180     dougm  * Call the legacy parse interface to get the protocol specific
    662   4180     dougm  * options using the NULL arg to indicate that this is a "parse" only.
    663   4180     dougm  */
    664   4180     dougm int
    665   5331       amw zfs_parse_options(char *options, zfs_share_proto_t proto)
    666   4180     dougm {
    667   5367    ahrens 	if (_sa_parse_legacy_options != NULL) {
    668   5367    ahrens 		return (_sa_parse_legacy_options(NULL, options,
    669   5367    ahrens 		    proto_table[proto].p_name));
    670   5367    ahrens 	}
    671   5367    ahrens 	return (SA_CONFIG_ERR);
    672   4180     dougm }
    673   4180     dougm 
    674   4180     dougm /*
    675   4180     dougm  * zfs_sa_find_share(handle, path)
    676   4180     dougm  *
    677   4180     dougm  * wrapper around sa_find_share to find a share path in the
    678   4180     dougm  * configuration.
    679   4180     dougm  */
    680   4180     dougm static sa_share_t
    681   4180     dougm zfs_sa_find_share(sa_handle_t handle, char *path)
    682   4180     dougm {
    683   4180     dougm 	if (_sa_find_share != NULL)
    684   4302     dougm 		return (_sa_find_share(handle, path));
    685   4180     dougm 	return (NULL);
    686   4180     dougm }
    687   4180     dougm 
    688   4180     dougm /*
    689   4180     dougm  * zfs_sa_enable_share(share, proto)
    690   4180     dougm  *
    691   4180     dougm  * Wrapper for sa_enable_share which enables a share for a specified
    692   4180     dougm  * protocol.
    693   4180     dougm  */
    694   4180     dougm static int
    695   4180     dougm zfs_sa_enable_share(sa_share_t share, char *proto)
    696   4180     dougm {
    697   4180     dougm 	if (_sa_enable_share != NULL)
    698   4302     dougm 		return (_sa_enable_share(share, proto));
    699   4180     dougm 	return (SA_CONFIG_ERR);
    700   4180     dougm }
    701   4180     dougm 
    702   4180     dougm /*
    703   4180     dougm  * zfs_sa_disable_share(share, proto)
    704   4180     dougm  *
    705   4180     dougm  * Wrapper for sa_enable_share which disables a share for a specified
    706   4180     dougm  * protocol.
    707   4180     dougm  */
    708   4180     dougm static int
    709   4180     dougm zfs_sa_disable_share(sa_share_t share, char *proto)
    710   4180     dougm {
    711   4180     dougm 	if (_sa_disable_share != NULL)
    712   4302     dougm 		return (_sa_disable_share(share, proto));
    713   4180     dougm 	return (SA_CONFIG_ERR);
    714   4180     dougm }
    715   4180     dougm 
    716   4180     dougm /*
    717   5331       amw  * Share the given filesystem according to the options in the specified
    718   5331       amw  * protocol specific properties (sharenfs, sharesmb).  We rely
    719   4180     dougm  * on "libshare" to the dirty work for us.
    720    789    ahrens  */
    721   5331       amw static int
    722   5331       amw zfs_share_proto(zfs_handle_t *zhp, zfs_share_proto_t *proto)
    723    789    ahrens {
    724    789    ahrens 	char mountpoint[ZFS_MAXPROPLEN];
    725    789    ahrens 	char shareopts[ZFS_MAXPROPLEN];
    726   5951     dougm 	char sourcestr[ZFS_MAXPROPLEN];
    727   2082  eschrock 	libzfs_handle_t *hdl = zhp->zfs_hdl;
    728   4180     dougm 	sa_share_t share;
    729   5331       amw 	zfs_share_proto_t *curr_proto;
    730   5951     dougm 	zprop_source_t sourcetype;
    731   4180     dougm 	int ret;
    732    789    ahrens 
    733   2676  eschrock 	if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL))
    734    789    ahrens 		return (0);
    735    789    ahrens 
    736   4180     dougm 	if ((ret = zfs_init_libshare(hdl, SA_INIT_SHARE_API)) != SA_OK) {
    737   4302     dougm 		(void) zfs_error_fmt(hdl, EZFS_SHARENFSFAILED,
    738   4302     dougm 		    dgettext(TEXT_DOMAIN, "cannot share '%s': %s"),
    739   5951     dougm 		    zfs_get_name(zhp), _sa_errorstr != NULL ?
    740   5951     dougm 		    _sa_errorstr(ret) : "");
    741   4302     dougm 		return (-1);
    742   4180     dougm 	}
    743   5331       amw 
    744   5331       amw 	for (curr_proto = proto; *curr_proto != PROTO_END; curr_proto++) {
    745   5331       amw 		/*
    746   5331       amw 		 * Return success if there are no share options.
    747   5331       amw 		 */
    748   5331       amw 		if (zfs_prop_get(zhp, proto_table[*curr_proto].p_prop,
    749   5951     dougm 		    shareopts, sizeof (shareopts), &sourcetype, sourcestr,
    750   5951     dougm 		    ZFS_MAXPROPLEN, B_FALSE) != 0 ||
    751   5951     dougm 		    strcmp(shareopts, "off") == 0)
    752   5331       amw 			continue;
    753   5331       amw 
    754   5331       amw 		/*
    755   5331       amw 		 * If the 'zoned' property is set, then zfs_is_mountable()
    756   5331       amw 		 * will have already bailed out if we are in the global zone.
    757   5331       amw 		 * But local zones cannot be NFS servers, so we ignore it for
    758   5331       amw 		 * local zones as well.
    759   5331       amw 		 */
    760   5331       amw 		if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED))
    761   5331       amw 			continue;
    762   5331       amw 
    763   5331       amw 		share = zfs_sa_find_share(hdl->libzfs_sharehdl, mountpoint);
    764   5951     dougm 		if (share == NULL) {
    765   5951     dougm 			/*
    766   5951     dougm 			 * This may be a new file system that was just
    767   5951     dougm 			 * created so isn't in the internal cache
    768   5951     dougm 			 * (second time through). Rather than
    769   5951     dougm 			 * reloading the entire configuration, we can
    770   5951     dougm 			 * assume ZFS has done the checking and it is
    771   5951     dougm 			 * safe to add this to the internal
    772   5951     dougm 			 * configuration.
    773   5951     dougm 			 */
    774   5951     dougm 			if (_sa_zfs_process_share(hdl->libzfs_sharehdl,
    775   5951     dougm 			    NULL, NULL, mountpoint,
    776   5951     dougm 			    proto_table[*curr_proto].p_name, sourcetype,
    777   5951     dougm 			    shareopts, sourcestr, zhp->zfs_name) != SA_OK) {
    778   5951     dougm 				(void) zfs_error_fmt(hdl,
    779   5951     dougm 				    proto_table[*curr_proto].p_share_err,
    780   5951     dougm 				    dgettext(TEXT_DOMAIN, "cannot share '%s'"),
    781   5951     dougm 				    zfs_get_name(zhp));
    782   5951     dougm 				return (-1);
    783   5951     dougm 			}
    784   5951     dougm 			hdl->libzfs_shareflags |= ZFSSHARE_MISS;
    785   5951     dougm 			share = zfs_sa_find_share(hdl->libzfs_sharehdl,
    786   5951     dougm 			    mountpoint);
    787   5951     dougm 		}
    788   5331       amw 		if (share != NULL) {
    789   5331       amw 			int err;
    790   5331       amw 			err = zfs_sa_enable_share(share,
    791   5331       amw 			    proto_table[*curr_proto].p_name);
    792   5331       amw 			if (err != SA_OK) {
    793   5331       amw 				(void) zfs_error_fmt(hdl,
    794   5331       amw 				    proto_table[*curr_proto].p_share_err,
    795   5331       amw 				    dgettext(TEXT_DOMAIN, "cannot share '%s'"),
    796   5331       amw 				    zfs_get_name(zhp));
    797   5331       amw 				return (-1);
    798   5331       amw 			}
    799   5331       amw 		} else {
    800   5331       amw 			(void) zfs_error_fmt(hdl,
    801   5331       amw 			    proto_table[*curr_proto].p_share_err,
    802   4302     dougm 			    dgettext(TEXT_DOMAIN, "cannot share '%s'"),
    803   4302     dougm 			    zfs_get_name(zhp));
    804   4302     dougm 			return (-1);
    805   4302     dougm 		}
    806   5331       amw 
    807   2474  eschrock 	}
    808   5331       amw 	return (0);
    809   5331       amw }
    810   2474  eschrock 
    811   5331       amw 
    812   5331       amw int
    813   5331       amw zfs_share_nfs(zfs_handle_t *zhp)
    814   5331       amw {
    815   5331       amw 	return (zfs_share_proto(zhp, nfs_only));
    816   5331       amw }
    817   5331       amw 
    818   5331       amw int
    819   5331       amw zfs_share_smb(zfs_handle_t *zhp)
    820   5331       amw {
    821   5331       amw 	return (zfs_share_proto(zhp, smb_only));
    822   5331       amw }
    823   5331       amw 
    824   5331       amw int
    825   5331       amw zfs_shareall(zfs_handle_t *zhp)
    826   5331       amw {
    827   5331       amw 	return (zfs_share_proto(zhp, share_all_proto));
    828   2474  eschrock }
    829   2474  eschrock 
    830   2474  eschrock /*
    831   2474  eschrock  * Unshare a filesystem by mountpoint.
    832   2474  eschrock  */
    833   2474  eschrock static int
    834   5331       amw unshare_one(libzfs_handle_t *hdl, const char *name, const char *mountpoint,
    835   5331       amw     zfs_share_proto_t proto)
    836   2474  eschrock {
    837   4180     dougm 	sa_share_t share;
    838   4180     dougm 	int err;
    839   4180     dougm 	char *mntpt;
    840   2474  eschrock 	/*
    841   4180     dougm 	 * Mountpoint could get trashed if libshare calls getmntany
    842   8228      Eric 	 * which it does during API initialization, so strdup the
    843   4180     dougm 	 * value.
    844   2474  eschrock 	 */
    845   4180     dougm 	mntpt = zfs_strdup(hdl, mountpoint);
    846   2474  eschrock 
    847   4180     dougm 	/* make sure libshare initialized */
    848   4180     dougm 	if ((err = zfs_init_libshare(hdl, SA_INIT_SHARE_API)) != SA_OK) {
    849   4180     dougm 		free(mntpt);	/* don't need the copy anymore */
    850   4180     dougm 		return (zfs_error_fmt(hdl, EZFS_SHARENFSFAILED,
    851   4302     dougm 		    dgettext(TEXT_DOMAIN, "cannot unshare '%s': %s"),
    852   4302     dougm 		    name, _sa_errorstr(err)));
    853    789    ahrens 	}
    854    789    ahrens 
    855   4180     dougm 	share = zfs_sa_find_share(hdl->libzfs_sharehdl, mntpt);
    856   4180     dougm 	free(mntpt);	/* don't need the copy anymore */
    857    789    ahrens 
    858   4180     dougm 	if (share != NULL) {
    859   5331       amw 		err = zfs_sa_disable_share(share, proto_table[proto].p_name);
    860   4180     dougm 		if (err != SA_OK) {
    861   4302     dougm 			return (zfs_error_fmt(hdl, EZFS_UNSHARENFSFAILED,
    862   4302     dougm 			    dgettext(TEXT_DOMAIN, "cannot unshare '%s': %s"),
    863   4302     dougm 			    name, _sa_errorstr(err)));
    864   4180     dougm 		}
    865   4180     dougm 	} else {
    866   4180     dougm 		return (zfs_error_fmt(hdl, EZFS_UNSHARENFSFAILED,
    867   4302     dougm 		    dgettext(TEXT_DOMAIN, "cannot unshare '%s': not found"),
    868   4302     dougm 		    name));
    869   4180     dougm 	}
    870    789    ahrens 	return (0);
    871    789    ahrens }
    872    789    ahrens 
    873    789    ahrens /*
    874    789    ahrens  * Unshare the given filesystem.
    875    789    ahrens  */
    876    789    ahrens int
    877   5331       amw zfs_unshare_proto(zfs_handle_t *zhp, const char *mountpoint,
    878   5331       amw     zfs_share_proto_t *proto)
    879    789    ahrens {
    880   8228      Eric 	libzfs_handle_t *hdl = zhp->zfs_hdl;
    881   8228      Eric 	struct mnttab entry;
    882   4180     dougm 	char *mntpt = NULL;
    883    789    ahrens 
    884    789    ahrens 	/* check to see if need to unmount the filesystem */
    885   2082  eschrock 	rewind(zhp->zfs_hdl->libzfs_mnttab);
    886   4302     dougm 	if (mountpoint != NULL)
    887   8228      Eric 		mountpoint = mntpt = zfs_strdup(hdl, mountpoint);
    888   4302     dougm 
    889    789    ahrens 	if (mountpoint != NULL || ((zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) &&
    890   8228      Eric 	    libzfs_mnttab_find(hdl, zfs_get_name(zhp), &entry) == 0)) {
    891   5331       amw 		zfs_share_proto_t *curr_proto;
    892    789    ahrens 
    893    789    ahrens 		if (mountpoint == NULL)
    894   5331       amw 			mntpt = zfs_strdup(zhp->zfs_hdl, entry.mnt_mountp);
    895    789    ahrens 
    896   5331       amw 		for (curr_proto = proto; *curr_proto != PROTO_END;
    897   5331       amw 		    curr_proto++) {
    898   5331       amw 
    899   8228      Eric 			if (is_shared(hdl, mntpt, *curr_proto) &&
    900   8228      Eric 			    unshare_one(hdl, zhp->zfs_name,
    901   5331       amw 			    mntpt, *curr_proto) != 0) {
    902   5331       amw 				if (mntpt != NULL)
    903   5331       amw 					free(mntpt);
    904   5331       amw 				return (-1);
    905   5331       amw 			}
    906   4180     dougm 		}
    907    789    ahrens 	}
    908   4180     dougm 	if (mntpt != NULL)
    909   4302     dougm 		free(mntpt);
    910    789    ahrens 
    911    789    ahrens 	return (0);
    912    789    ahrens }
    913    789    ahrens 
    914   5331       amw int
    915   5331       amw zfs_unshare_nfs(zfs_handle_t *zhp, const char *mountpoint)
    916   5331       amw {
    917   5331       amw 	return (zfs_unshare_proto(zhp, mountpoint, nfs_only));
    918   5331       amw }
    919   5331       amw 
    920   5331       amw int
    921   5331       amw zfs_unshare_smb(zfs_handle_t *zhp, const char *mountpoint)
    922   5331       amw {
    923   5331       amw 	return (zfs_unshare_proto(zhp, mountpoint, smb_only));
    924   5331       amw }
    925   5331       amw 
    926    789    ahrens /*
    927   5331       amw  * Same as zfs_unmountall(), but for NFS and SMB unshares.
    928    789    ahrens  */
    929    789    ahrens int
    930   5331       amw zfs_unshareall_proto(zfs_handle_t *zhp, zfs_share_proto_t *proto)
    931    789    ahrens {
    932    789    ahrens 	prop_changelist_t *clp;
    933    789    ahrens 	int ret;
    934    789    ahrens 
    935   7366       Tim 	clp = changelist_gather(zhp, ZFS_PROP_SHARENFS, 0, 0);
    936    789    ahrens 	if (clp == NULL)
    937    789    ahrens 		return (-1);
    938    789    ahrens 
    939   5331       amw 	ret = changelist_unshare(clp, proto);
    940    789    ahrens 	changelist_free(clp);
    941    789    ahrens 
    942    789    ahrens 	return (ret);
    943   5331       amw }
    944   5331       amw 
    945   5331       amw int
    946   5331       amw zfs_unshareall_nfs(zfs_handle_t *zhp)
    947   5331       amw {
    948   5331       amw 	return (zfs_unshareall_proto(zhp, nfs_only));
    949   5331       amw }
    950   5331       amw 
    951   5331       amw int
    952   5331       amw zfs_unshareall_smb(zfs_handle_t *zhp)
    953   5331       amw {
    954   5331       amw 	return (zfs_unshareall_proto(zhp, smb_only));
    955   5331       amw }
    956   5331       amw 
    957   5331       amw int
    958   5331       amw zfs_unshareall(zfs_handle_t *zhp)
    959   5331       amw {
    960   5331       amw 	return (zfs_unshareall_proto(zhp, share_all_proto));
    961   5331       amw }
    962   5331       amw 
    963   5331       amw int
    964   5331       amw zfs_unshareall_bypath(zfs_handle_t *zhp, const char *mountpoint)
    965   5331       amw {
    966   5331       amw 	return (zfs_unshare_proto(zhp, mountpoint, share_all_proto));
    967    789    ahrens }
    968    789    ahrens 
    969    789    ahrens /*
    970    789    ahrens  * Remove the mountpoint associated with the current dataset, if necessary.
    971    789    ahrens  * We only remove the underlying directory if:
    972    789    ahrens  *
    973    789    ahrens  *	- The mountpoint is not 'none' or 'legacy'
    974    789    ahrens  *	- The mountpoint is non-empty
    975    789    ahrens  *	- The mountpoint is the default or inherited
    976    789    ahrens  *	- The 'zoned' property is set, or we're in a local zone
    977    789    ahrens  *
    978    789    ahrens  * Any other directories we leave alone.
    979    789    ahrens  */
    980    789    ahrens void
    981    789    ahrens remove_mountpoint(zfs_handle_t *zhp)
    982    789    ahrens {
    983    789    ahrens 	char mountpoint[ZFS_MAXPROPLEN];
    984   5094     lling 	zprop_source_t source;
    985    789    ahrens 
    986   2676  eschrock 	if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint),
    987   2676  eschrock 	    &source))
    988    789    ahrens 		return;
    989    789    ahrens 
    990   5094     lling 	if (source == ZPROP_SRC_DEFAULT ||
    991   5094     lling 	    source == ZPROP_SRC_INHERITED) {
    992    789    ahrens 		/*
    993    789    ahrens 		 * Try to remove the directory, silently ignoring any errors.
    994    789    ahrens 		 * The filesystem may have since been removed or moved around,
    995   2676  eschrock 		 * and this error isn't really useful to the administrator in
    996   2676  eschrock 		 * any way.
    997    789    ahrens 		 */
    998    789    ahrens 		(void) rmdir(mountpoint);
    999    789    ahrens 	}
   1000    789    ahrens }
   1001   2474  eschrock 
   1002   3126       ahl boolean_t
   1003   3126       ahl zfs_is_shared_iscsi(zfs_handle_t *zhp)
   1004   3126       ahl {
   1005   4543     marks 
   1006   4543     marks 	/*
   1007   4543     marks 	 * If iscsi deamon isn't running then we aren't shared
   1008   4543     marks 	 */
   1009   4543     marks 	if (iscsitgt_svc_online && iscsitgt_svc_online() == 1)
   1010   5331       amw 		return (B_FALSE);
   1011   4543     marks 	else
   1012   4543     marks 		return (iscsitgt_zfs_is_shared != NULL &&
   1013   4543     marks 		    iscsitgt_zfs_is_shared(zhp->zfs_name) != 0);
   1014   3126       ahl }
   1015   3126       ahl 
   1016   3126       ahl int
   1017   3126       ahl zfs_share_iscsi(zfs_handle_t *zhp)
   1018   3126       ahl {
   1019   3126       ahl 	char shareopts[ZFS_MAXPROPLEN];
   1020   3126       ahl 	const char *dataset = zhp->zfs_name;
   1021   3126       ahl 	libzfs_handle_t *hdl = zhp->zfs_hdl;
   1022   3126       ahl 
   1023   3126       ahl 	/*
   1024   3126       ahl 	 * Return success if there are no share options.
   1025   3126       ahl 	 */
   1026   3126       ahl 	if (zfs_prop_get(zhp, ZFS_PROP_SHAREISCSI, shareopts,
   1027   3126       ahl 	    sizeof (shareopts), NULL, NULL, 0, B_FALSE) != 0 ||
   1028   3126       ahl 	    strcmp(shareopts, "off") == 0)
   1029   3126       ahl 		return (0);
   1030   3126       ahl 
   1031   4543     marks 	if (iscsitgt_zfs_share == NULL || iscsitgt_zfs_share(dataset) != 0) {
   1032   4543     marks 		int error = EZFS_SHAREISCSIFAILED;
   1033   4543     marks 
   1034   4543     marks 		/*
   1035   4543     marks 		 * If service isn't availabele and EPERM was
   1036   4543     marks 		 * returned then use special error.
   1037   4543     marks 		 */
   1038   4543     marks 		if (iscsitgt_svc_online && errno == EPERM &&
   1039   4543     marks 		    (iscsitgt_svc_online() != 0))
   1040   4543     marks 			error = EZFS_ISCSISVCUNAVAIL;
   1041   4543     marks 
   1042   4543     marks 		return (zfs_error_fmt(hdl, error,
   1043   3126       ahl 		    dgettext(TEXT_DOMAIN, "cannot share '%s'"), dataset));
   1044   4543     marks 	}
   1045   3126       ahl 
   1046   3126       ahl 	return (0);
   1047   3126       ahl }
   1048   3126       ahl 
   1049   3126       ahl int
   1050   3126       ahl zfs_unshare_iscsi(zfs_handle_t *zhp)
   1051   3126       ahl {
   1052   3126       ahl 	const char *dataset = zfs_get_name(zhp);
   1053   3126       ahl 	libzfs_handle_t *hdl = zhp->zfs_hdl;
   1054   3126       ahl 
   1055   3126       ahl 	/*
   1056   3380   gw25295 	 * Return if the volume is not shared
   1057   3380   gw25295 	 */
   1058   5331       amw 	if (zfs_is_shared_iscsi(zhp) != SHARED_ISCSI)
   1059   3380   gw25295 		return (0);
   1060   3380   gw25295 
   1061   3380   gw25295 	/*
   1062   3126       ahl 	 * If this fails with ENODEV it indicates that zvol wasn't shared so
   1063   3126       ahl 	 * we should return success in that case.
   1064   3126       ahl 	 */
   1065   3134       ahl 	if (iscsitgt_zfs_unshare == NULL ||
   1066   4543     marks 	    (iscsitgt_zfs_unshare(dataset) != 0 && errno != ENODEV)) {
   1067   4543     marks 		if (errno == EPERM)
   1068   4543     marks 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
   1069   4543     marks 			    "Insufficient privileges to unshare iscsi"));
   1070   3237     lling 		return (zfs_error_fmt(hdl, EZFS_UNSHAREISCSIFAILED,
   1071   3126       ahl 		    dgettext(TEXT_DOMAIN, "cannot unshare '%s'"), dataset));
   1072   4543     marks 	}
   1073   3126       ahl 
   1074   3126       ahl 	return (0);
   1075   3126       ahl }
   1076   3126       ahl 
   1077   2474  eschrock typedef struct mount_cbdata {
   1078   2474  eschrock 	zfs_handle_t	**cb_datasets;
   1079   2474  eschrock 	int 		cb_used;
   1080   2474  eschrock 	int		cb_alloc;
   1081   2474  eschrock } mount_cbdata_t;
   1082   2474  eschrock 
   1083   2474  eschrock static int
   1084   2474  eschrock mount_cb(zfs_handle_t *zhp, void *data)
   1085   2474  eschrock {
   1086   2474  eschrock 	mount_cbdata_t *cbp = data;
   1087   2474  eschrock 
   1088   3126       ahl 	if (!(zfs_get_type(zhp) & (ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME))) {
   1089   2474  eschrock 		zfs_close(zhp);
   1090   2474  eschrock 		return (0);
   1091   2474  eschrock 	}
   1092   2474  eschrock 
   1093   6168   hs24103 	if (zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT) == ZFS_CANMOUNT_NOAUTO) {
   1094   6168   hs24103 		zfs_close(zhp);
   1095   6168   hs24103 		return (0);
   1096   6168   hs24103 	}
   1097   6168   hs24103 
   1098   2474  eschrock 	if (cbp->cb_alloc == cbp->cb_used) {
   1099   2676  eschrock 		void *ptr;
   1100   2474  eschrock 
   1101   2676  eschrock 		if ((ptr = zfs_realloc(zhp->zfs_hdl,
   1102   2676  eschrock 		    cbp->cb_datasets, cbp->cb_alloc * sizeof (void *),
   1103   2676  eschrock 		    cbp->cb_alloc * 2 * sizeof (void *))) == NULL)
   1104   2474  eschrock 			return (-1);
   1105   2676  eschrock 		cbp->cb_datasets = ptr;
   1106   2474  eschrock 
   1107   2676  eschrock 		cbp->cb_alloc *= 2;
   1108   2474  eschrock 	}
   1109   2474  eschrock 
   1110   2474  eschrock 	cbp->cb_datasets[cbp->cb_used++] = zhp;
   1111   3126       ahl 
   1112   6027  rm160521 	return (zfs_iter_filesystems(zhp, mount_cb, cbp));
   1113   2474  eschrock }
   1114   2474  eschrock 
   1115   2474  eschrock static int
   1116   3126       ahl dataset_cmp(const void *a, const void *b)
   1117   2474  eschrock {
   1118   2474  eschrock 	zfs_handle_t **za = (zfs_handle_t **)a;
   1119   2474  eschrock 	zfs_handle_t **zb = (zfs_handle_t **)b;
   1120   2474  eschrock 	char mounta[MAXPATHLEN];
   1121   2474  eschrock 	char mountb[MAXPATHLEN];
   1122   3126       ahl 	boolean_t gota, gotb;
   1123   2474  eschrock 
   1124   3126       ahl 	if ((gota = (zfs_get_type(*za) == ZFS_TYPE_FILESYSTEM)) != 0)
   1125   3126       ahl 		verify(zfs_prop_get(*za, ZFS_PROP_MOUNTPOINT, mounta,
   1126   3126       ahl 		    sizeof (mounta), NULL, NULL, 0, B_FALSE) == 0);
   1127   3126       ahl 	if ((gotb = (zfs_get_type(*zb) == ZFS_TYPE_FILESYSTEM)) != 0)
   1128   3126       ahl 		verify(zfs_prop_get(*zb, ZFS_PROP_MOUNTPOINT, mountb,
   1129   3126       ahl 		    sizeof (mountb), NULL, NULL, 0, B_FALSE) == 0);
   1130   2474  eschrock 
   1131   3126       ahl 	if (gota && gotb)
   1132   3126       ahl 		return (strcmp(mounta, mountb));
   1133   3126       ahl 
   1134   3126       ahl 	if (gota)
   1135   3126       ahl 		return (-1);
   1136   3126       ahl 	if (gotb)
   1137   3126       ahl 		return (1);
   1138   3126       ahl 
   1139   3126       ahl 	return (strcmp(zfs_get_name(a), zfs_get_name(b)));
   1140   2474  eschrock }
   1141   2474  eschrock 
   1142   3126       ahl /*
   1143   3126       ahl  * Mount and share all datasets within the given pool.  This assumes that no
   1144   3126       ahl  * datasets within the pool are currently mounted.  Because users can create
   1145   3126       ahl  * complicated nested hierarchies of mountpoints, we first gather all the
   1146   3126       ahl  * datasets and mountpoints within the pool, and sort them by mountpoint.  Once
   1147   3126       ahl  * we have the list of all filesystems, we iterate over them in order and mount
   1148   3126       ahl  * and/or share each one.
   1149   3126       ahl  */
   1150   3126       ahl #pragma weak zpool_mount_datasets = zpool_enable_datasets
   1151   2474  eschrock int
   1152   3126       ahl zpool_enable_datasets(zpool_handle_t *zhp, const char *mntopts, int flags)
   1153   2474  eschrock {
   1154   2474  eschrock 	mount_cbdata_t cb = { 0 };
   1155   2474  eschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
   1156   2474  eschrock 	zfs_handle_t *zfsp;
   1157   2474  eschrock 	int i, ret = -1;
   1158   4180     dougm 	int *good;
   1159   2474  eschrock 
   1160   2474  eschrock 	/*
   1161   6027  rm160521 	 * Gather all non-snap datasets within the pool.
   1162   2474  eschrock 	 */
   1163   2474  eschrock 	if ((cb.cb_datasets = zfs_alloc(hdl, 4 * sizeof (void *))) == NULL)
   1164   2474  eschrock 		return (-1);
   1165   2474  eschrock 	cb.cb_alloc = 4;
   1166   2474  eschrock 
   1167   5094     lling 	if ((zfsp = zfs_open(hdl, zhp->zpool_name, ZFS_TYPE_DATASET)) == NULL)
   1168   2474  eschrock 		goto out;
   1169   2474  eschrock 
   1170   2474  eschrock 	cb.cb_datasets[0] = zfsp;
   1171   2474  eschrock 	cb.cb_used = 1;
   1172   2474  eschrock 
   1173   6027  rm160521 	if (zfs_iter_filesystems(zfsp, mount_cb, &cb) != 0)
   1174   2474  eschrock 		goto out;
   1175   2474  eschrock 
   1176   2474  eschrock 	/*
   1177   2474  eschrock 	 * Sort the datasets by mountpoint.
   1178   2474  eschrock 	 */
   1179   3126       ahl 	qsort(cb.cb_datasets, cb.cb_used, sizeof (void *), dataset_cmp);
   1180   2474  eschrock 
   1181   2474  eschrock 	/*
   1182   4180     dougm 	 * And mount all the datasets, keeping track of which ones
   1183   8536     David 	 * succeeded or failed.
   1184   2474  eschrock 	 */
   1185   8536     David 	if ((good = zfs_alloc(zhp->zpool_hdl,
   1186   8536     David 	    cb.cb_used * sizeof (int))) == NULL)
   1187   8536     David 		goto out;
   1188   8536     David 
   1189   2474  eschrock 	ret = 0;
   1190   2474  eschrock 	for (i = 0; i < cb.cb_used; i++) {
   1191   4302     dougm 		if (zfs_mount(cb.cb_datasets[i], mntopts, flags) != 0)
   1192   4180     dougm 			ret = -1;
   1193   4302     dougm 		else
   1194   4180     dougm 			good[i] = 1;
   1195   4180     dougm 	}
   1196   5951     dougm 
   1197   4180     dougm 	/*
   1198   4180     dougm 	 * Then share all the ones that need to be shared. This needs
   1199   4180     dougm 	 * to be a separate pass in order to avoid excessive reloading
   1200   4180     dougm 	 * of the configuration. Good should never be NULL since
   1201   4180     dougm 	 * zfs_alloc is supposed to exit if memory isn't available.
   1202   4180     dougm 	 */
   1203   4180     dougm 	for (i = 0; i < cb.cb_used; i++) {
   1204   4180     dougm 		if (good[i] && zfs_share(cb.cb_datasets[i]) != 0)
   1205   2474  eschrock 			ret = -1;
   1206   2474  eschrock 	}
   1207   4180     dougm 
   1208   4180     dougm 	free(good);
   1209   2474  eschrock 
   1210   2474  eschrock out:
   1211   2474  eschrock 	for (i = 0; i < cb.cb_used; i++)
   1212   2474  eschrock 		zfs_close(cb.cb_datasets[i]);
   1213   2474  eschrock 	free(cb.cb_datasets);
   1214   2474  eschrock 
   1215   2474  eschrock 	return (ret);
   1216   2474  eschrock }
   1217   2474  eschrock 
   1218  10588      Eric /*ARGSUSED1*/
   1219  10588      Eric static int
   1220  10588      Eric zvol_cb(zfs_handle_t *zhp, void *unused)
   1221  10588      Eric {
   1222  10588      Eric 	int error = 0;
   1223   3126       ahl 
   1224  10588      Eric 	if (zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM)
   1225  10588      Eric 		(void) zfs_iter_children(zhp, zvol_cb, NULL);
   1226  10588      Eric 	if (zfs_get_type(zhp) == ZFS_TYPE_VOLUME)
   1227  10588      Eric 		error = zfs_unshare_iscsi(zhp);
   1228   3126       ahl 	zfs_close(zhp);
   1229   3126       ahl 
   1230  10588      Eric 	return (error);
   1231   3126       ahl }
   1232   3126       ahl 
   1233   2474  eschrock static int
   1234   2474  eschrock mountpoint_compare(const void *a, const void *b)
   1235   2474  eschrock {
   1236   2474  eschrock 	const char *mounta = *((char **)a);
   1237   2474  eschrock 	const char *mountb = *((char **)b);
   1238   2474  eschrock 
   1239   2474  eschrock 	return (strcmp(mountb, mounta));
   1240   2474  eschrock }
   1241   2474  eschrock 
   1242  10588      Eric /* alias for 2002/240 */
   1243  10588      Eric #pragma weak zpool_unmount_datasets = zpool_disable_datasets
   1244   3126       ahl /*
   1245   3126       ahl  * Unshare and unmount all datasets within the given pool.  We don't want to
   1246   3126       ahl  * rely on traversing the DSL to discover the filesystems within the pool,
   1247   3126       ahl  * because this may be expensive (if not all of them are mounted), and can fail
   1248   3126       ahl  * arbitrarily (on I/O error, for example).  Instead, we walk /etc/mnttab and
   1249   3126       ahl  * gather all the filesystems that are currently mounted.
   1250   3126       ahl  */
   1251   2474  eschrock int
   1252   3126       ahl zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force)
   1253   2474  eschrock {
   1254   2474  eschrock 	int used, alloc;
   1255   2474  eschrock 	struct mnttab entry;
   1256   2474  eschrock 	size_t namelen;
   1257   2474  eschrock 	char **mountpoints = NULL;
   1258  10588      Eric 	zfs_handle_t *zfp;
   1259   2474  eschrock 	zfs_handle_t **datasets = NULL;
   1260   2474  eschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
   1261   2474  eschrock 	int i;
   1262   2474  eschrock 	int ret = -1;
   1263   2474  eschrock 	int flags = (force ? MS_FORCE : 0);
   1264   3126       ahl 
   1265   3126       ahl 	/*
   1266   3126       ahl 	 * First unshare all zvols.
   1267   3126       ahl 	 */
   1268  10588      Eric 	zfp = zfs_open(zhp->zpool_hdl, zhp->zpool_name,
   1269  10588      Eric 	    ZFS_TYPE_FILESYSTEM);
   1270  10588      Eric 	if (zfp != NULL) {
   1271  10588      Eric 		(void) zfs_iter_children(zfp, zvol_cb, NULL);
   1272  10588      Eric 		zfs_close(zfp);
   1273  10588      Eric 	}
   1274   2474  eschrock 
   1275   2474  eschrock 	namelen = strlen(zhp->zpool_name);
   1276   2474  eschrock 
   1277   2474  eschrock 	rewind(hdl->libzfs_mnttab);
   1278   2474  eschrock 	used = alloc = 0;
   1279   2474  eschrock 	while (getmntent(hdl->libzfs_mnttab, &entry) == 0) {
   1280   2474  eschrock 		/*
   1281   2474  eschrock 		 * Ignore non-ZFS entries.
   1282   2474  eschrock 		 */
   1283   2474  eschrock 		if (entry.mnt_fstype == NULL ||
   1284   2474  eschrock 		    strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0)
   1285   2474  eschrock 			continue;
   1286   2474  eschrock 
   1287   2474  eschrock 		/*
   1288   2474  eschrock 		 * Ignore filesystems not within this pool.
   1289   2474  eschrock 		 */
   1290   2474  eschrock 		if (entry.mnt_mountp == NULL ||
   1291   2474  eschrock 		    strncmp(entry.mnt_special, zhp->zpool_name, namelen) != 0 ||
   1292   2474  eschrock 		    (entry.mnt_special[namelen] != '/' &&
   1293   2474  eschrock 		    entry.mnt_special[namelen] != '\0'))
   1294   2474  eschrock 			continue;
   1295   2474  eschrock 
   1296   2474  eschrock 		/*
   1297   2474  eschrock 		 * At this point we've found a filesystem within our pool.  Add
   1298   2474  eschrock 		 * it to our growing list.
   1299   2474  eschrock 		 */
   1300   2474  eschrock 		if (used == alloc) {
   1301   2474  eschrock 			if (alloc == 0) {
   1302   2474  eschrock 				if ((mountpoints = zfs_alloc(hdl,
   1303   2474  eschrock 				    8 * sizeof (void *))) == NULL)
   1304   2474  eschrock 					goto out;
   1305   2474  eschrock 
   1306   2474  eschrock 				if ((datasets = zfs_alloc(hdl,
   1307   2474  eschrock 				    8 * sizeof (void *))) == NULL)
   1308   2474  eschrock 					goto out;
   1309   2474  eschrock 
   1310   2474  eschrock 				alloc = 8;
   1311   2474  eschrock 			} else {
   1312   2676  eschrock 				void *ptr;
   1313   2474  eschrock 
   1314   2676  eschrock 				if ((ptr = zfs_realloc(hdl, mountpoints,
   1315   2676  eschrock 				    alloc * sizeof (void *),
   1316   2474  eschrock 				    alloc * 2 * sizeof (void *))) == NULL)
   1317   2474  eschrock 					goto out;
   1318   2676  eschrock 				mountpoints = ptr;
   1319   2474  eschrock 
   1320   2676  eschrock 				if ((ptr = zfs_realloc(hdl, datasets,
   1321   2676  eschrock 				    alloc * sizeof (void *),
   1322   2474  eschrock 				    alloc * 2 * sizeof (void *))) == NULL)
   1323   2474  eschrock 					goto out;
   1324   2676  eschrock 				datasets = ptr;
   1325   2474  eschrock 
   1326   2474  eschrock 				alloc *= 2;
   1327   2474  eschrock 			}
   1328   2474  eschrock 		}
   1329   2474  eschrock 
   1330   2474  eschrock 		if ((mountpoints[used] = zfs_strdup(hdl,
   1331   2474  eschrock 		    entry.mnt_mountp)) == NULL)
   1332   2474  eschrock 			goto out;
   1333   2474  eschrock 
   1334   2474  eschrock 		/*
   1335   2474  eschrock 		 * This is allowed to fail, in case there is some I/O error.  It
   1336   2474  eschrock 		 * is only used to determine if we need to remove the underlying
   1337   2474  eschrock 		 * mountpoint, so failure is not fatal.
   1338   2474  eschrock 		 */
   1339   2474  eschrock 		datasets[used] = make_dataset_handle(hdl, entry.mnt_special);
   1340   2474  eschrock 
   1341   2474  eschrock 		used++;
   1342   2474  eschrock 	}
   1343   2474  eschrock 
   1344   2474  eschrock 	/*
   1345   2474  eschrock 	 * At this point, we have the entire list of filesystems, so sort it by
   1346   2474  eschrock 	 * mountpoint.
   1347   2474  eschrock 	 */
   1348   2474  eschrock 	qsort(mountpoints, used, sizeof (char *), mountpoint_compare);
   1349   2474  eschrock 
   1350   2474  eschrock 	/*
   1351   2474  eschrock 	 * Walk through and first unshare everything.
   1352   2474  eschrock 	 */
   1353   2474  eschrock 	for (i = 0; i < used; i++) {
   1354   5331       amw 		zfs_share_proto_t *curr_proto;
   1355   5331       amw 		for (curr_proto = share_all_proto; *curr_proto != PROTO_END;
   1356   5331       amw 		    curr_proto++) {
   1357   5331       amw 			if (is_shared(hdl, mountpoints[i], *curr_proto) &&
   1358   5331       amw 			    unshare_one(hdl, mountpoints[i],
   1359   5331       amw 			    mountpoints[i], *curr_proto) != 0)
   1360   5331       amw 				goto out;
   1361   5331       amw 		}
   1362   2474  eschrock 	}
   1363   2474  eschrock 
   1364   2474  eschrock 	/*
   1365   2474  eschrock 	 * Now unmount everything, removing the underlying directories as
   1366   2474  eschrock 	 * appropriate.
   1367   2474  eschrock 	 */
   1368   2474  eschrock 	for (i = 0; i < used; i++) {
   1369   2474  eschrock 		if (unmount_one(hdl, mountpoints[i], flags) != 0)
   1370   2474  eschrock 			goto out;
   1371   2676  eschrock 	}
   1372   2474  eschrock 
   1373   2676  eschrock 	for (i = 0; i < used; i++) {
   1374   2474  eschrock 		if (datasets[i])
   1375   2474  eschrock 			remove_mountpoint(datasets[i]);
   1376   2474  eschrock 	}
   1377   2474  eschrock 
   1378   2474  eschrock 	ret = 0;
   1379   2474  eschrock out:
   1380   2474  eschrock 	for (i = 0; i < used; i++) {
   1381   2474  eschrock 		if (datasets[i])
   1382   2474  eschrock 			zfs_close(datasets[i]);
   1383   2474  eschrock 		free(mountpoints[i]);
   1384   2474  eschrock 	}
   1385   2474  eschrock 	free(datasets);
   1386   2474  eschrock 	free(mountpoints);
   1387   2474  eschrock 
   1388   2474  eschrock 	return (ret);
   1389   2474  eschrock }
   1390