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