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