1fa9e4066Sahrens /*
2fa9e4066Sahrens  * CDDL HEADER START
3fa9e4066Sahrens  *
4fa9e4066Sahrens  * The contents of this file are subject to the terms of the
5ea8dc4b6Seschrock  * Common Development and Distribution License (the "License").
6ea8dc4b6Seschrock  * You may not use this file except in compliance with the License.
7fa9e4066Sahrens  *
8fa9e4066Sahrens  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fa9e4066Sahrens  * or http://www.opensolaris.org/os/licensing.
10fa9e4066Sahrens  * See the License for the specific language governing permissions
11fa9e4066Sahrens  * and limitations under the License.
12fa9e4066Sahrens  *
13fa9e4066Sahrens  * When distributing Covered Code, include this CDDL HEADER in each
14fa9e4066Sahrens  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fa9e4066Sahrens  * If applicable, add the following below this CDDL HEADER, with the
16fa9e4066Sahrens  * fields enclosed by brackets "[]" replaced with your own identifying
17fa9e4066Sahrens  * information: Portions Copyright [yyyy] [name of copyright owner]
18fa9e4066Sahrens  *
19fa9e4066Sahrens  * CDDL HEADER END
20fa9e4066Sahrens  */
22fa9e4066Sahrens /*
23dc7cd546SMark Shellenbaum  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24*0dfe541eSEvan Layton  */
25*0dfe541eSEvan Layton 
26*0dfe541eSEvan Layton /*
27*0dfe541eSEvan Layton  * Copyright 2019 Nexenta Systems, Inc.
28*0dfe541eSEvan Layton  * Copyright (c) 2014, 2016 by Delphix. All rights reserved.
2988f61deeSIgor Kozhukhov  * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
301c18e8fbSJerry Jelinek  * Copyright 2017 Joyent, Inc.
314f4378ccSAndrew Stormont  * Copyright 2017 RackTop Systems.
32bc4c0ff1SAndy Fiddaman  * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
33fa9e4066Sahrens  */
35fa9e4066Sahrens /*
36fa9e4066Sahrens  * Routines to manage ZFS mounts.  We separate all the nasty routines that have
37f3861e1aSahl  * to deal with the OS.  The following functions are the main entry points --
38f3861e1aSahl  * they are used by mount and unmount and when changing a filesystem's
39f3861e1aSahl  * mountpoint.
40fa9e4066Sahrens  *
41591e0e13SSebastien Roy  *	zfs_is_mounted()
42591e0e13SSebastien Roy  *	zfs_mount()
43591e0e13SSebastien Roy  *	zfs_unmount()
44591e0e13SSebastien Roy  *	zfs_unmountall()
45fa9e4066Sahrens  *
46f3861e1aSahl  * This file also contains the functions used to manage sharing filesystems via
47f3861e1aSahl  * NFS and iSCSI:
48fa9e4066Sahrens  *
49591e0e13SSebastien Roy  *	zfs_is_shared()
50591e0e13SSebastien Roy  *	zfs_share()
51591e0e13SSebastien Roy  *	zfs_unshare()
52f3861e1aSahl  *
53591e0e13SSebastien Roy  *	zfs_is_shared_nfs()
54591e0e13SSebastien Roy  *	zfs_is_shared_smb()
55591e0e13SSebastien Roy  *	zfs_share_proto()
56591e0e13SSebastien Roy  *	zfs_shareall();
57591e0e13SSebastien Roy  *	zfs_unshare_nfs()
58591e0e13SSebastien Roy  *	zfs_unshare_smb()
59591e0e13SSebastien Roy  *	zfs_unshareall_nfs()
60da6c28aaSamw  *	zfs_unshareall_smb()
61da6c28aaSamw  *	zfs_unshareall()
62da6c28aaSamw  *	zfs_unshareall_bypath()
633bb79becSeschrock  *
643bb79becSeschrock  * The following functions are available for pool consumers, and will
65f3861e1aSahl  * mount/unmount and share/unshare all datasets within pool:
663bb79becSeschrock  *
67591e0e13SSebastien Roy  *	zpool_enable_datasets()
68591e0e13SSebastien Roy  *	zpool_disable_datasets()
69fa9e4066Sahrens  */
71fa9e4066Sahrens #include <dirent.h>
72d8d59944Sahl #include <dlfcn.h>
73fa9e4066Sahrens #include <errno.h>
74d420209dSAlex Reece #include <fcntl.h>
75fa9e4066Sahrens #include <libgen.h>
76fa9e4066Sahrens #include <libintl.h>
77fa9e4066Sahrens #include <stdio.h>
78fa9e4066Sahrens #include <stdlib.h>
79fa9e4066Sahrens #include <strings.h>
80fa9e4066Sahrens #include <unistd.h>
81fa9e4066Sahrens #include <zone.h>
82fa9e4066Sahrens #include <sys/mntent.h>
83fa9e4066Sahrens #include <sys/mount.h>
84fa9e4066Sahrens #include <sys/stat.h>
85873c4903SPrakash Surya #include <sys/statvfs.h>
86eb633035STom Caputi #include <sys/dsl_crypt.h>
88fa9e4066Sahrens #include <libzfs.h>
90fa9e4066Sahrens #include "libzfs_impl.h"
91591e0e13SSebastien Roy #include "libzfs_taskq.h"
9367331909Sdougm #include <libshare.h>
9467331909Sdougm #include <sys/systeminfo.h>
9567331909Sdougm #define	MAXISALEN	257	/* based on sysinfo(2) man page */
97591e0e13SSebastien Roy static int mount_tq_nthr = 512;	/* taskq threads for multi-threaded mounting */
98591e0e13SSebastien Roy 
99591e0e13SSebastien Roy static void zfs_mount_task(void *);
100da6c28aaSamw static int zfs_share_proto(zfs_handle_t *, zfs_share_proto_t *);
101da6c28aaSamw zfs_share_type_t zfs_is_shared_proto(zfs_handle_t *, char **,
102da6c28aaSamw     zfs_share_proto_t);
104da6c28aaSamw /*
1054f4378ccSAndrew Stormont  * The share protocols table must be in the same order as the zfs_share_proto_t
106da6c28aaSamw  * enum in libzfs_impl.h
107da6c28aaSamw  */
108da6c28aaSamw typedef struct {
109da6c28aaSamw 	zfs_prop_t p_prop;
110da6c28aaSamw 	char *p_name;
111da6c28aaSamw 	int p_share_err;
112da6c28aaSamw 	int p_unshare_err;
113da6c28aaSamw } proto_table_t;
115da6c28aaSamw proto_table_t proto_table[PROTO_END] = {
118da6c28aaSamw };
120da6c28aaSamw zfs_share_proto_t nfs_only[] = {
121da6c28aaSamw 	PROTO_NFS,
122da6c28aaSamw 	PROTO_END
123da6c28aaSamw };
125da6c28aaSamw zfs_share_proto_t smb_only[] = {
126da6c28aaSamw 	PROTO_SMB,
127da6c28aaSamw 	PROTO_END
128da6c28aaSamw };
129da6c28aaSamw zfs_share_proto_t share_all_proto[] = {
130da6c28aaSamw 	PROTO_NFS,
131da6c28aaSamw 	PROTO_SMB,
132da6c28aaSamw 	PROTO_END
133da6c28aaSamw };
135fa9e4066Sahrens /*
136da6c28aaSamw  * Search the sharetab for the given mountpoint and protocol, returning
137da6c28aaSamw  * a zfs_share_type_t value.
138fa9e4066Sahrens  */
139da6c28aaSamw static zfs_share_type_t
is_shared(libzfs_handle_t * hdl,const char * mountpoint,zfs_share_proto_t proto)140da6c28aaSamw is_shared(libzfs_handle_t *hdl, const char *mountpoint, zfs_share_proto_t proto)
141fa9e4066Sahrens {
142fa9e4066Sahrens 	char buf[MAXPATHLEN], *tab;
143da6c28aaSamw 	char *ptr;
14599653d4eSeschrock 	if (hdl->libzfs_sharetab == NULL)
146da6c28aaSamw 		return (SHARED_NOT_SHARED);
14899653d4eSeschrock 	(void) fseek(hdl->libzfs_sharetab, 0, SEEK_SET);
15099653d4eSeschrock 	while (fgets(buf, sizeof (buf), hdl->libzfs_sharetab) != NULL) {
152fa9e4066Sahrens 		/* the mountpoint is the first entry on each line */
153da6c28aaSamw 		if ((tab = strchr(buf, '\t')) == NULL)
154da6c28aaSamw 			continue;
156da6c28aaSamw 		*tab = '\0';
157da6c28aaSamw 		if (strcmp(buf, mountpoint) == 0) {
158da6c28aaSamw 			/*
159da6c28aaSamw 			 * the protocol field is the third field
160da6c28aaSamw 			 * skip over second field
161da6c28aaSamw 			 */
162da6c28aaSamw 			ptr = ++tab;
163da6c28aaSamw 			if ((tab = strchr(ptr, '\t')) == NULL)
164da6c28aaSamw 				continue;
165da6c28aaSamw 			ptr = ++tab;
166da6c28aaSamw 			if ((tab = strchr(ptr, '\t')) == NULL)
167da6c28aaSamw 				continue;
168fa9e4066Sahrens 			*tab = '\0';
169da6c28aaSamw 			if (strcmp(ptr,
170da6c28aaSamw 			    proto_table[proto].p_name) == 0) {
171da6c28aaSamw 				switch (proto) {
172da6c28aaSamw 				case PROTO_NFS:
173da6c28aaSamw 					return (SHARED_NFS);
174da6c28aaSamw 				case PROTO_SMB:
175da6c28aaSamw 					return (SHARED_SMB);
176da6c28aaSamw 				default:
177da6c28aaSamw 					return (0);
178da6c28aaSamw 				}
179da6c28aaSamw 			}
180fa9e4066Sahrens 		}
181fa9e4066Sahrens 	}
183da6c28aaSamw 	return (SHARED_NOT_SHARED);
184fa9e4066Sahrens }
18699653d4eSeschrock static boolean_t
dir_is_empty_stat(const char * dirname)187873c4903SPrakash Surya dir_is_empty_stat(const char *dirname)
188873c4903SPrakash Surya {
189873c4903SPrakash Surya 	struct stat st;
190873c4903SPrakash Surya 
191873c4903SPrakash Surya 	/*
192873c4903SPrakash Surya 	 * We only want to return false if the given path is a non empty
193873c4903SPrakash Surya 	 * directory, all other errors are handled elsewhere.
194873c4903SPrakash Surya 	 */
195873c4903SPrakash Surya 	if (stat(dirname, &st) < 0 || !S_ISDIR(st.st_mode)) {
196873c4903SPrakash Surya 		return (B_TRUE);
197873c4903SPrakash Surya 	}
198873c4903SPrakash Surya 
199873c4903SPrakash Surya 	/*
200873c4903SPrakash Surya 	 * An empty directory will still have two entries in it, one
201873c4903SPrakash Surya 	 * entry for each of "." and "..".
202873c4903SPrakash Surya 	 */
203873c4903SPrakash Surya 	if (st.st_size > 2) {
204873c4903SPrakash Surya 		return (B_FALSE);
205873c4903SPrakash Surya 	}
206873c4903SPrakash Surya 
207873c4903SPrakash Surya 	return (B_TRUE);
208873c4903SPrakash Surya }
209873c4903SPrakash Surya 
210873c4903SPrakash Surya static boolean_t
dir_is_empty_readdir(const char * dirname)211873c4903SPrakash Surya dir_is_empty_readdir(const char *dirname)
212fa9e4066Sahrens {
213fa9e4066Sahrens 	DIR *dirp;
214fa9e4066Sahrens 	struct dirent64 *dp;
215d420209dSAlex Reece 	int dirfd;
217d420209dSAlex Reece 	if ((dirfd = openat(AT_FDCWD, dirname,
218d420209dSAlex Reece 	    O_RDONLY | O_NDELAY | O_LARGEFILE | O_CLOEXEC, 0)) < 0) {
21999653d4eSeschrock 		return (B_TRUE);
220d420209dSAlex Reece 	}
221d420209dSAlex Reece 
222d420209dSAlex Reece 	if ((dirp = fdopendir(dirfd)) == NULL) {
223ba6e7e65SSowrabha Gopal 		(void) close(dirfd);
224d420209dSAlex Reece 		return (B_TRUE);
225d420209dSAlex Reece 	}
227fa9e4066Sahrens 	while ((dp = readdir64(dirp)) != NULL) {
229fa9e4066Sahrens 		if (strcmp(dp->d_name, ".") == 0 ||
230fa9e4066Sahrens 		    strcmp(dp->d_name, "..") == 0)
231fa9e4066Sahrens 			continue;
233fa9e4066Sahrens 		(void) closedir(dirp);
23499653d4eSeschrock 		return (B_FALSE);
235fa9e4066Sahrens 	}
237fa9e4066Sahrens 	(void) closedir(dirp);
23899653d4eSeschrock 	return (B_TRUE);
239fa9e4066Sahrens }
241873c4903SPrakash Surya /*
242873c4903SPrakash Surya  * Returns true if the specified directory is empty.  If we can't open the
243873c4903SPrakash Surya  * directory at all, return true so that the mount can fail with a more
244873c4903SPrakash Surya  * informative error message.
245873c4903SPrakash Surya  */
246873c4903SPrakash Surya static boolean_t
dir_is_empty(const char * dirname)247873c4903SPrakash Surya dir_is_empty(const char *dirname)
248873c4903SPrakash Surya {
249873c4903SPrakash Surya 	struct statvfs64 st;
250873c4903SPrakash Surya 
251873c4903SPrakash Surya 	/*
252873c4903SPrakash Surya 	 * If the statvfs call fails or the filesystem is not a ZFS
253873c4903SPrakash Surya 	 * filesystem, fall back to the slow path which uses readdir.
254873c4903SPrakash Surya 	 */
255873c4903SPrakash Surya 	if ((statvfs64(dirname, &st) != 0) ||
256873c4903SPrakash Surya 	    (strcmp(st.f_basetype, "zfs") != 0)) {
257873c4903SPrakash Surya 		return (dir_is_empty_readdir(dirname));
258873c4903SPrakash Surya 	}
259873c4903SPrakash Surya 
260873c4903SPrakash Surya 	/*
261873c4903SPrakash Surya 	 * At this point, we know the provided path is on a ZFS
262873c4903SPrakash Surya 	 * filesystem, so we can use stat instead of readdir to
263873c4903SPrakash Surya 	 * determine if the directory is empty or not. We try to avoid
264873c4903SPrakash Surya 	 * using readdir because that requires opening "dirname"; this
265873c4903SPrakash Surya 	 * open file descriptor can potentially end up in a child
266873c4903SPrakash Surya 	 * process if there's a concurrent fork, thus preventing the
267873c4903SPrakash Surya 	 * zfs_mount() from otherwise succeeding (the open file
268873c4903SPrakash Surya 	 * descriptor inherited by the child process will cause the
269873c4903SPrakash Surya 	 * parent's mount to fail with EBUSY). The performance
270873c4903SPrakash Surya 	 * implications of replacing the open, read, and close with a
271873c4903SPrakash Surya 	 * single stat is nice; but is not the main motivation for the
272873c4903SPrakash Surya 	 * added complexity.
273873c4903SPrakash Surya 	 */
274873c4903SPrakash Surya 	return (dir_is_empty_stat(dirname));
275873c4903SPrakash Surya }
276873c4903SPrakash Surya 
277fa9e4066Sahrens /*
278fa9e4066Sahrens  * Checks to see if the mount is active.  If the filesystem is mounted, we fill
279fa9e4066Sahrens  * in 'where' with the current mountpoint, and return 1.  Otherwise, we return
280fa9e4066Sahrens  * 0.
281fa9e4066Sahrens  */
28299653d4eSeschrock boolean_t
is_mounted(libzfs_handle_t * zfs_hdl,const char * special,char ** where)28355434c77Sek is_mounted(libzfs_handle_t *zfs_hdl, const char *special, char **where)
284fa9e4066Sahrens {
285ebedde84SEric Taylor 	struct mnttab entry;
287ebedde84SEric Taylor 	if (libzfs_mnttab_find(zfs_hdl, special, &entry) != 0)
28899653d4eSeschrock 		return (B_FALSE);
290fa9e4066Sahrens 	if (where != NULL)
29155434c77Sek 		*where = zfs_strdup(zfs_hdl, entry.mnt_mountp);
29399653d4eSeschrock 	return (B_TRUE);
294fa9e4066Sahrens }
29655434c77Sek boolean_t
zfs_is_mounted(zfs_handle_t * zhp,char ** where)29755434c77Sek zfs_is_mounted(zfs_handle_t *zhp, char **where)
29855434c77Sek {
29955434c77Sek 	return (is_mounted(zhp->zfs_hdl, zfs_get_name(zhp), where));
30055434c77Sek }
302e9dbad6fSeschrock /*
303e9dbad6fSeschrock  * Returns true if the given dataset is mountable, false otherwise.  Returns the
304e9dbad6fSeschrock  * mountpoint in 'buf'.
305e9dbad6fSeschrock  */
306e9dbad6fSeschrock static boolean_t
zfs_is_mountable(zfs_handle_t * zhp,char * buf,size_t buflen,zprop_source_t * source)307e9dbad6fSeschrock zfs_is_mountable(zfs_handle_t *zhp, char *buf, size_t buflen,
308990b4856Slling     zprop_source_t *source)
309e9dbad6fSeschrock {
3109adfa60dSMatthew Ahrens 	char sourceloc[MAXNAMELEN];
311990b4856Slling 	zprop_source_t sourcetype;
313e9dbad6fSeschrock 	if (!zfs_prop_valid_for_type(ZFS_PROP_MOUNTPOINT, zhp->zfs_type))
314e9dbad6fSeschrock 		return (B_FALSE);
316e9dbad6fSeschrock 	verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, buf, buflen,
317e9dbad6fSeschrock 	    &sourcetype, sourceloc, sizeof (sourceloc), B_FALSE) == 0);
319e9dbad6fSeschrock 	if (strcmp(buf, ZFS_MOUNTPOINT_NONE) == 0 ||
320e9dbad6fSeschrock 	    strcmp(buf, ZFS_MOUNTPOINT_LEGACY) == 0)
321e9dbad6fSeschrock 		return (B_FALSE);
323a227b7f4Shs 	if (zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT) == ZFS_CANMOUNT_OFF)
324e9dbad6fSeschrock 		return (B_FALSE);
326e9dbad6fSeschrock 	if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED) &&
327e9dbad6fSeschrock 	    getzoneid() == GLOBAL_ZONEID)
328e9dbad6fSeschrock 		return (B_FALSE);
330e9dbad6fSeschrock 	if (source)
331e9dbad6fSeschrock 		*source = sourcetype;
333e9dbad6fSeschrock 	return (B_TRUE);
334e9dbad6fSeschrock }
336fa9e4066Sahrens /*
337fa9e4066Sahrens  * Mount the given filesystem.
338fa9e4066Sahrens  */
339fa9e4066Sahrens int
zfs_mount(zfs_handle_t * zhp,const char * options,int flags)340fa9e4066Sahrens zfs_mount(zfs_handle_t *zhp, const char *options, int flags)
341fa9e4066Sahrens {
342fa9e4066Sahrens 	struct stat buf;
343fa9e4066Sahrens 	char mountpoint[ZFS_MAXPROPLEN];
344fa9e4066Sahrens 	char mntopts[MNT_LINE_MAX];
34599653d4eSeschrock 	libzfs_handle_t *hdl = zhp->zfs_hdl;
346eb633035STom Caputi 	uint64_t keystatus;
347eb633035STom Caputi 	int rc;
349fa9e4066Sahrens 	if (options == NULL)
350fa9e4066Sahrens 		mntopts[0] = '\0';
351fa9e4066Sahrens 	else
352fa9e4066Sahrens 		(void) strlcpy(mntopts, options, sizeof (mntopts));
354f9af39baSGeorge Wilson 	/*
355f9af39baSGeorge Wilson 	 * If the pool is imported read-only then all mounts must be read-only
356f9af39baSGeorge Wilson 	 */
357f9af39baSGeorge Wilson 	if (zpool_get_prop_int(zhp->zpool_hdl, ZPOOL_PROP_READONLY, NULL))
358f9af39baSGeorge Wilson 		flags |= MS_RDONLY;
359f9af39baSGeorge Wilson 
360e9dbad6fSeschrock 	if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL))
36199653d4eSeschrock 		return (0);
363eb633035STom Caputi 	/*
364eb633035STom Caputi 	 * If the filesystem is encrypted the key must be loaded  in order to
365eb633035STom Caputi 	 * mount. If the key isn't loaded, the MS_CRYPT flag decides whether
366eb633035STom Caputi 	 * or not we attempt to load the keys. Note: we must call
367eb633035STom Caputi 	 * zfs_refresh_properties() here since some callers of this function
368eb633035STom Caputi 	 * (most notably zpool_enable_datasets()) may implicitly load our key
369eb633035STom Caputi 	 * by loading the parent's key first.
370eb633035STom Caputi 	 */
371eb633035STom Caputi 	if (zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION) != ZIO_CRYPT_OFF) {
372eb633035STom Caputi 		zfs_refresh_properties(zhp);
373eb633035STom Caputi 		keystatus = zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS);
374eb633035STom Caputi 
375eb633035STom Caputi 		/*
376eb633035STom Caputi 		 * If the key is unavailable and MS_CRYPT is set give the
377eb633035STom Caputi 		 * user a chance to enter the key. Otherwise just fail
378eb633035STom Caputi 		 * immediately.
379eb633035STom Caputi 		 */
380eb633035STom Caputi 		if (keystatus == ZFS_KEYSTATUS_UNAVAILABLE) {