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