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