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 */
21f3861e1aSahl
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 */
34fa9e4066Sahrens
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 */
70fa9e4066Sahrens
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>
87fa9e4066Sahrens
88fa9e4066Sahrens #include <libzfs.h>
89fa9e4066Sahrens
90fa9e4066Sahrens #include "libzfs_impl.h"
91591e0e13SSebastien Roy #include "libzfs_taskq.h"
92fa9e4066Sahrens
9367331909Sdougm #include <libshare.h>
9467331909Sdougm #include <sys/systeminfo.h>
9567331909Sdougm #define MAXISALEN 257 /* based on sysinfo(2) man page */
9667331909Sdougm
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);
103da6c28aaSamw
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;
114da6c28aaSamw
115da6c28aaSamw proto_table_t proto_table[PROTO_END] = {
116da6c28aaSamw {ZFS_PROP_SHARENFS, "nfs", EZFS_SHARENFSFAILED, EZFS_UNSHARENFSFAILED},
117da6c28aaSamw {ZFS_PROP_SHARESMB, "smb", EZFS_SHARESMBFAILED, EZFS_UNSHARESMBFAILED},
118da6c28aaSamw };
119da6c28aaSamw
120da6c28aaSamw zfs_share_proto_t nfs_only[] = {
121da6c28aaSamw PROTO_NFS,
122da6c28aaSamw PROTO_END
123da6c28aaSamw };
124da6c28aaSamw
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 };
134da6c28aaSamw
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;
144fa9e4066Sahrens
14599653d4eSeschrock if (hdl->libzfs_sharetab == NULL)
146da6c28aaSamw return (SHARED_NOT_SHARED);
147fa9e4066Sahrens
14899653d4eSeschrock (void) fseek(hdl->libzfs_sharetab, 0, SEEK_SET);
149fa9e4066Sahrens
15099653d4eSeschrock while (fgets(buf, sizeof (buf), hdl->libzfs_sharetab) != NULL) {
151fa9e4066Sahrens
152fa9e4066Sahrens /* the mountpoint is the first entry on each line */
153da6c28aaSamw if ((tab = strchr(buf, '\t')) == NULL)
154da6c28aaSamw continue;
155da6c28aaSamw
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 }
182fa9e4066Sahrens
183da6c28aaSamw return (SHARED_NOT_SHARED);
184fa9e4066Sahrens }
185fa9e4066Sahrens
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;
216fa9e4066Sahrens
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 }
226fa9e4066Sahrens
227fa9e4066Sahrens while ((dp = readdir64(dirp)) != NULL) {
228fa9e4066Sahrens
229fa9e4066Sahrens if (strcmp(dp->d_name, ".") == 0 ||
230fa9e4066Sahrens strcmp(dp->d_name, "..") == 0)
231fa9e4066Sahrens continue;
232fa9e4066Sahrens
233fa9e4066Sahrens (void) closedir(dirp);
23499653d4eSeschrock return (B_FALSE);
235fa9e4066Sahrens }
236fa9e4066Sahrens
237fa9e4066Sahrens (void) closedir(dirp);
23899653d4eSeschrock return (B_TRUE);
239fa9e4066Sahrens }
240fa9e4066Sahrens
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;
286fa9e4066Sahrens
287ebedde84SEric Taylor if (libzfs_mnttab_find(zfs_hdl, special, &entry) != 0)
28899653d4eSeschrock return (B_FALSE);
289fa9e4066Sahrens
290fa9e4066Sahrens if (where != NULL)
29155434c77Sek *where = zfs_strdup(zfs_hdl, entry.mnt_mountp);
292fa9e4066Sahrens
29399653d4eSeschrock return (B_TRUE);
294fa9e4066Sahrens }
295fa9e4066Sahrens
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 }
30155434c77Sek
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;
312e9dbad6fSeschrock
313e9dbad6fSeschrock if (!zfs_prop_valid_for_type(ZFS_PROP_MOUNTPOINT, zhp->zfs_type))
314e9dbad6fSeschrock return (B_FALSE);
315e9dbad6fSeschrock
316e9dbad6fSeschrock verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, buf, buflen,
317e9dbad6fSeschrock &sourcetype, sourceloc, sizeof (sourceloc), B_FALSE) == 0);
318e9dbad6fSeschrock
319e9dbad6fSeschrock if (strcmp(buf, ZFS_MOUNTPOINT_NONE) == 0 ||
320e9dbad6fSeschrock strcmp(buf, ZFS_MOUNTPOINT_LEGACY) == 0)
321e9dbad6fSeschrock return (B_FALSE);
322e9dbad6fSeschrock
323a227b7f4Shs if (zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT) == ZFS_CANMOUNT_OFF)
324e9dbad6fSeschrock return (B_FALSE);
325e9dbad6fSeschrock
326e9dbad6fSeschrock if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED) &&
327e9dbad6fSeschrock getzoneid() == GLOBAL_ZONEID)
328e9dbad6fSeschrock return (B_FALSE);
329e9dbad6fSeschrock
330e9dbad6fSeschrock if (source)
331e9dbad6fSeschrock *source = sourcetype;
332e9dbad6fSeschrock
333e9dbad6fSeschrock return (B_TRUE);
334e9dbad6fSeschrock }
335e9dbad6fSeschrock
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;
348fa9e4066Sahrens
349fa9e4066Sahrens if (options == NULL)
350fa9e4066Sahrens mntopts[0] = '\0';
351fa9e4066Sahrens else
352fa9e4066Sahrens (void) strlcpy(mntopts, options, sizeof (mntopts));
353fa9e4066Sahrens
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);
362fa9e4066Sahrens
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) {
381