1 // SPDX-License-Identifier: CDDL-1.0
2 /*
3 * CDDL HEADER START
4 *
5 * The contents of this file are subject to the terms of the
6 * Common Development and Distribution License (the "License").
7 * You may not use this file except in compliance with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or https://opensource.org/licenses/CDDL-1.0.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22
23 /*
24 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
25 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
26 * Copyright (c) 2014, 2022 by Delphix. All rights reserved.
27 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
28 * Copyright 2017 RackTop Systems.
29 * Copyright (c) 2018 Datto Inc.
30 * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
31 */
32
33 /*
34 * Routines to manage ZFS mounts. We separate all the nasty routines that have
35 * to deal with the OS. The following functions are the main entry points --
36 * they are used by mount and unmount and when changing a filesystem's
37 * mountpoint.
38 *
39 * zfs_is_mounted()
40 * zfs_mount()
41 * zfs_mount_at()
42 * zfs_unmount()
43 * zfs_unmountall()
44 *
45 * This file also contains the functions used to manage sharing filesystems:
46 *
47 * zfs_is_shared()
48 * zfs_share()
49 * zfs_unshare()
50 * zfs_unshareall()
51 * zfs_commit_shares()
52 *
53 * The following functions are available for pool consumers, and will
54 * mount/unmount and share/unshare all datasets within pool:
55 *
56 * zpool_enable_datasets()
57 * zpool_disable_datasets()
58 */
59
60 #include <dirent.h>
61 #include <dlfcn.h>
62 #include <errno.h>
63 #include <fcntl.h>
64 #include <libgen.h>
65 #include <libintl.h>
66 #include <stdio.h>
67 #include <stdlib.h>
68 #include <string.h>
69 #include <unistd.h>
70 #include <zone.h>
71 #include <sys/mntent.h>
72 #include <sys/mount.h>
73 #include <sys/stat.h>
74 #include <sys/vfs.h>
75 #include <sys/dsl_crypt.h>
76
77 #include <libzfs.h>
78 #include <libzutil.h>
79
80 #include "libzfs_impl.h"
81
82 #include <sys/systeminfo.h>
83 #define MAXISALEN 257 /* based on sysinfo(2) man page */
84
85 static void zfs_mount_task(void *);
86
87 static const proto_table_t proto_table[SA_PROTOCOL_COUNT] = {
88 [SA_PROTOCOL_NFS] =
89 {ZFS_PROP_SHARENFS, EZFS_SHARENFSFAILED, EZFS_UNSHARENFSFAILED},
90 [SA_PROTOCOL_SMB] =
91 {ZFS_PROP_SHARESMB, EZFS_SHARESMBFAILED, EZFS_UNSHARESMBFAILED},
92 };
93
94 static const enum sa_protocol share_all_proto[SA_PROTOCOL_COUNT + 1] = {
95 SA_PROTOCOL_NFS,
96 SA_PROTOCOL_SMB,
97 SA_NO_PROTOCOL
98 };
99
100 const char *
zfs_share_protocol_name(enum sa_protocol protocol)101 zfs_share_protocol_name(enum sa_protocol protocol)
102 {
103 return (sa_protocol_names[protocol]);
104 }
105
106 static boolean_t
dir_is_empty_stat(const char * dirname)107 dir_is_empty_stat(const char *dirname)
108 {
109 struct stat st;
110
111 /*
112 * We only want to return false if the given path is a non empty
113 * directory, all other errors are handled elsewhere.
114 */
115 if (stat(dirname, &st) < 0 || !S_ISDIR(st.st_mode)) {
116 return (B_TRUE);
117 }
118
119 /*
120 * An empty directory will still have two entries in it, one
121 * entry for each of "." and "..".
122 */
123 if (st.st_size > 2) {
124 return (B_FALSE);
125 }
126
127 return (B_TRUE);
128 }
129
130 static boolean_t
dir_is_empty_readdir(const char * dirname)131 dir_is_empty_readdir(const char *dirname)
132 {
133 DIR *dirp;
134 struct dirent64 *dp;
135 int dirfd;
136
137 if ((dirfd = openat(AT_FDCWD, dirname,
138 O_RDONLY | O_NDELAY | O_LARGEFILE | O_CLOEXEC, 0)) < 0) {
139 return (B_TRUE);
140 }
141
142 if ((dirp = fdopendir(dirfd)) == NULL) {
143 (void) close(dirfd);
144 return (B_TRUE);
145 }
146
147 while ((dp = readdir64(dirp)) != NULL) {
148
149 if (strcmp(dp->d_name, ".") == 0 ||
150 strcmp(dp->d_name, "..") == 0)
151 continue;
152
153 (void) closedir(dirp);
154 return (B_FALSE);
155 }
156
157 (void) closedir(dirp);
158 return (B_TRUE);
159 }
160
161 /*
162 * Returns true if the specified directory is empty. If we can't open the
163 * directory at all, return true so that the mount can fail with a more
164 * informative error message.
165 */
166 static boolean_t
dir_is_empty(const char * dirname)167 dir_is_empty(const char *dirname)
168 {
169 struct statfs64 st;
170
171 /*
172 * If the statvfs call fails or the filesystem is not a ZFS
173 * filesystem, fall back to the slow path which uses readdir.
174 */
175 if ((statfs64(dirname, &st) != 0) ||
176 (st.f_type != ZFS_SUPER_MAGIC)) {
177 return (dir_is_empty_readdir(dirname));
178 }
179
180 /*
181 * At this point, we know the provided path is on a ZFS
182 * filesystem, so we can use stat instead of readdir to
183 * determine if the directory is empty or not. We try to avoid
184 * using readdir because that requires opening "dirname"; this
185 * open file descriptor can potentially end up in a child
186 * process if there's a concurrent fork, thus preventing the
187 * zfs_mount() from otherwise succeeding (the open file
188 * descriptor inherited by the child process will cause the
189 * parent's mount to fail with EBUSY). The performance
190 * implications of replacing the open, read, and close with a
191 * single stat is nice; but is not the main motivation for the
192 * added complexity.
193 */
194 return (dir_is_empty_stat(dirname));
195 }
196
197 /*
198 * Checks to see if the mount is active. If the filesystem is mounted, we fill
199 * in 'where' with the current mountpoint, and return 1. Otherwise, we return
200 * 0.
201 */
202 boolean_t
is_mounted(libzfs_handle_t * zfs_hdl,const char * special,char ** where)203 is_mounted(libzfs_handle_t *zfs_hdl, const char *special, char **where)
204 {
205 struct mnttab entry;
206
207 if (libzfs_mnttab_find(zfs_hdl, special, &entry) != 0)
208 return (B_FALSE);
209
210 if (where != NULL)
211 *where = zfs_strdup(zfs_hdl, entry.mnt_mountp);
212
213 return (B_TRUE);
214 }
215
216 boolean_t
zfs_is_mounted(zfs_handle_t * zhp,char ** where)217 zfs_is_mounted(zfs_handle_t *zhp, char **where)
218 {
219 return (is_mounted(zhp->zfs_hdl, zfs_get_name(zhp), where));
220 }
221
222 /*
223 * Checks any higher order concerns about whether the given dataset is
224 * mountable, false otherwise. zfs_is_mountable_internal specifically assumes
225 * that the caller has verified the sanity of mounting the dataset at
226 * its mountpoint to the extent the caller wants.
227 */
228 static boolean_t
zfs_is_mountable_internal(zfs_handle_t * zhp)229 zfs_is_mountable_internal(zfs_handle_t *zhp)
230 {
231 if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED) &&
232 getzoneid() == GLOBAL_ZONEID)
233 return (B_FALSE);
234
235 return (B_TRUE);
236 }
237
238 /*
239 * Returns true if the given dataset is mountable, false otherwise. Returns the
240 * mountpoint in 'buf'.
241 */
242 static boolean_t
zfs_is_mountable(zfs_handle_t * zhp,char * buf,size_t buflen,zprop_source_t * source,int flags)243 zfs_is_mountable(zfs_handle_t *zhp, char *buf, size_t buflen,
244 zprop_source_t *source, int flags)
245 {
246 char sourceloc[MAXNAMELEN];
247 zprop_source_t sourcetype;
248
249 if (!zfs_prop_valid_for_type(ZFS_PROP_MOUNTPOINT, zhp->zfs_type,
250 B_FALSE))
251 return (B_FALSE);
252
253 verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, buf, buflen,
254 &sourcetype, sourceloc, sizeof (sourceloc), B_FALSE) == 0);
255
256 if (strcmp(buf, ZFS_MOUNTPOINT_NONE) == 0 ||
257 strcmp(buf, ZFS_MOUNTPOINT_LEGACY) == 0)
258 return (B_FALSE);
259
260 if (zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT) == ZFS_CANMOUNT_OFF)
261 return (B_FALSE);
262
263 if (!zfs_is_mountable_internal(zhp))
264 return (B_FALSE);
265
266 if (zfs_prop_get_int(zhp, ZFS_PROP_REDACTED) && !(flags & MS_FORCE))
267 return (B_FALSE);
268
269 if (source)
270 *source = sourcetype;
271
272 return (B_TRUE);
273 }
274
275 /*
276 * The filesystem is mounted by invoking the system mount utility rather
277 * than by the system call mount(2). This ensures that the /etc/mtab
278 * file is correctly locked for the update. Performing our own locking
279 * and /etc/mtab update requires making an unsafe assumption about how
280 * the mount utility performs its locking. Unfortunately, this also means
281 * in the case of a mount failure we do not have the exact errno. We must
282 * make due with return value from the mount process.
283 *
284 * In the long term a shared library called libmount is under development
285 * which provides a common API to address the locking and errno issues.
286 * Once the standard mount utility has been updated to use this library
287 * we can add an autoconf check to conditionally use it.
288 *
289 * http://www.kernel.org/pub/linux/utils/util-linux/libmount-docs/index.html
290 */
291
292 static int
zfs_add_option(zfs_handle_t * zhp,char * options,int len,zfs_prop_t prop,const char * on,const char * off)293 zfs_add_option(zfs_handle_t *zhp, char *options, int len,
294 zfs_prop_t prop, const char *on, const char *off)
295 {
296 const char *source;
297 uint64_t value;
298
299 /* Skip adding duplicate default options */
300 if ((strstr(options, on) != NULL) || (strstr(options, off) != NULL))
301 return (0);
302
303 /*
304 * zfs_prop_get_int() is not used to ensure our mount options
305 * are not influenced by the current /proc/self/mounts contents.
306 */
307 value = getprop_uint64(zhp, prop, &source);
308
309 (void) strlcat(options, ",", len);
310 (void) strlcat(options, value ? on : off, len);
311
312 return (0);
313 }
314
315 static int
zfs_add_options(zfs_handle_t * zhp,char * options,int len)316 zfs_add_options(zfs_handle_t *zhp, char *options, int len)
317 {
318 int error = 0;
319
320 error = zfs_add_option(zhp, options, len,
321 ZFS_PROP_ATIME, MNTOPT_ATIME, MNTOPT_NOATIME);
322 /*
323 * don't add relatime/strictatime when atime=off, otherwise strictatime
324 * will force atime=on
325 */
326 if (strstr(options, MNTOPT_NOATIME) == NULL) {
327 error = zfs_add_option(zhp, options, len,
328 ZFS_PROP_RELATIME, MNTOPT_RELATIME, MNTOPT_STRICTATIME);
329 }
330 error = error ? error : zfs_add_option(zhp, options, len,
331 ZFS_PROP_DEVICES, MNTOPT_DEVICES, MNTOPT_NODEVICES);
332 error = error ? error : zfs_add_option(zhp, options, len,
333 ZFS_PROP_EXEC, MNTOPT_EXEC, MNTOPT_NOEXEC);
334 error = error ? error : zfs_add_option(zhp, options, len,
335 ZFS_PROP_READONLY, MNTOPT_RO, MNTOPT_RW);
336 error = error ? error : zfs_add_option(zhp, options, len,
337 ZFS_PROP_SETUID, MNTOPT_SETUID, MNTOPT_NOSETUID);
338 error = error ? error : zfs_add_option(zhp, options, len,
339 ZFS_PROP_NBMAND, MNTOPT_NBMAND, MNTOPT_NONBMAND);
340
341 return (error);
342 }
343
344 int
zfs_mount(zfs_handle_t * zhp,const char * options,int flags)345 zfs_mount(zfs_handle_t *zhp, const char *options, int flags)
346 {
347 char mountpoint[ZFS_MAXPROPLEN];
348
349 if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL,
350 flags))
351 return (0);
352
353 return (zfs_mount_at(zhp, options, flags, mountpoint));
354 }
355
356 /*
357 * Mount the given filesystem.
358 */
359 int
zfs_mount_at(zfs_handle_t * zhp,const char * options,int flags,const char * mountpoint)360 zfs_mount_at(zfs_handle_t *zhp, const char *options, int flags,
361 const char *mountpoint)
362 {
363 struct stat buf;
364 char mntopts[MNT_LINE_MAX];
365 char overlay[ZFS_MAXPROPLEN];
366 char prop_encroot[MAXNAMELEN];
367 boolean_t is_encroot;
368 zfs_handle_t *encroot_hp = zhp;
369 libzfs_handle_t *hdl = zhp->zfs_hdl;
370 uint64_t keystatus;
371 int remount = 0, rc;
372
373 if (options == NULL) {
374 (void) strlcpy(mntopts, MNTOPT_DEFAULTS, sizeof (mntopts));
375 } else {
376 (void) strlcpy(mntopts, options, sizeof (mntopts));
377 }
378
379 if (strstr(mntopts, MNTOPT_REMOUNT) != NULL)
380 remount = 1;
381
382 /* Potentially duplicates some checks if invoked by zfs_mount(). */
383 if (!zfs_is_mountable_internal(zhp))
384 return (0);
385
386 /*
387 * If the pool is imported read-only then all mounts must be read-only
388 */
389 if (zpool_get_prop_int(zhp->zpool_hdl, ZPOOL_PROP_READONLY, NULL))
390 (void) strlcat(mntopts, "," MNTOPT_RO, sizeof (mntopts));
391
392 /*
393 * Append default mount options which apply to the mount point.
394 * This is done because under Linux (unlike Solaris) multiple mount
395 * points may reference a single super block. This means that just
396 * given a super block there is no back reference to update the per
397 * mount point options.
398 */
399 rc = zfs_add_options(zhp, mntopts, sizeof (mntopts));
400 if (rc) {
401 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
402 "default options unavailable"));
403 return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED,
404 dgettext(TEXT_DOMAIN, "cannot mount '%s'"),
405 mountpoint));
406 }
407
408 /*
409 * If the filesystem is encrypted the key must be loaded in order to
410 * mount. If the key isn't loaded, the MS_CRYPT flag decides whether
411 * or not we attempt to load the keys. Note: we must call
412 * zfs_refresh_properties() here since some callers of this function
413 * (most notably zpool_enable_datasets()) may implicitly load our key
414 * by loading the parent's key first.
415 */
416 if (zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION) != ZIO_CRYPT_OFF) {
417 zfs_refresh_properties(zhp);
418 keystatus = zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS);
419
420 /*
421 * If the key is unavailable and MS_CRYPT is set give the
422 * user a chance to enter the key. Otherwise just fail
423 * immediately.
424 */
425 if (keystatus == ZFS_KEYSTATUS_UNAVAILABLE) {
426 if (flags & MS_CRYPT) {
427 rc = zfs_crypto_get_encryption_root(zhp,
428 &is_encroot, prop_encroot);
429 if (rc) {
430 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
431 "Failed to get encryption root for "
432 "'%s'."), zfs_get_name(zhp));
433 return (rc);
434 }
435
436 if (!is_encroot) {
437 encroot_hp = zfs_open(hdl, prop_encroot,
438 ZFS_TYPE_DATASET);
439 if (encroot_hp == NULL)
440 return (hdl->libzfs_error);
441 }
442
443 rc = zfs_crypto_load_key(encroot_hp,
444 B_FALSE, NULL);
445
446 if (!is_encroot)
447 zfs_close(encroot_hp);
448 if (rc)
449 return (rc);
450 } else {
451 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
452 "encryption key not loaded"));
453 return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED,
454 dgettext(TEXT_DOMAIN, "cannot mount '%s'"),
455 mountpoint));
456 }
457 }
458
459 }
460
461 /*
462 * Append zfsutil option so the mount helper allow the mount
463 */
464 strlcat(mntopts, "," MNTOPT_ZFSUTIL, sizeof (mntopts));
465
466 /* Create the directory if it doesn't already exist */
467 if (lstat(mountpoint, &buf) != 0) {
468 if (mkdirp(mountpoint, 0755) != 0) {
469 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
470 "failed to create mountpoint: %s"),
471 zfs_strerror(errno));
472 return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED,
473 dgettext(TEXT_DOMAIN, "cannot mount '%s'"),
474 mountpoint));
475 }
476 }
477
478 /*
479 * Overlay mounts are enabled by default but may be disabled
480 * via the 'overlay' property. The -O flag remains for compatibility.
481 */
482 if (!(flags & MS_OVERLAY)) {
483 if (zfs_prop_get(zhp, ZFS_PROP_OVERLAY, overlay,
484 sizeof (overlay), NULL, NULL, 0, B_FALSE) == 0) {
485 if (strcmp(overlay, "on") == 0) {
486 flags |= MS_OVERLAY;
487 }
488 }
489 }
490
491 /*
492 * Determine if the mountpoint is empty. If so, refuse to perform the
493 * mount. We don't perform this check if 'remount' is
494 * specified or if overlay option (-O) is given
495 */
496 if ((flags & MS_OVERLAY) == 0 && !remount &&
497 !dir_is_empty(mountpoint)) {
498 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
499 "directory is not empty"));
500 return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED,
501 dgettext(TEXT_DOMAIN, "cannot mount '%s'"), mountpoint));
502 }
503
504 /* perform the mount */
505 rc = do_mount(zhp, mountpoint, mntopts, flags);
506 if (rc) {
507 /*
508 * Generic errors are nasty, but there are just way too many
509 * from mount(), and they're well-understood. We pick a few
510 * common ones to improve upon.
511 */
512 if (rc == EBUSY) {
513 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
514 "mountpoint or dataset is busy"));
515 } else if (rc == EPERM) {
516 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
517 "Insufficient privileges"));
518 } else if (rc == ENOTSUP) {
519 int spa_version;
520
521 VERIFY0(zfs_spa_version(zhp, &spa_version));
522 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
523 "Can't mount a version %llu "
524 "file system on a version %d pool. Pool must be"
525 " upgraded to mount this file system."),
526 (u_longlong_t)zfs_prop_get_int(zhp,
527 ZFS_PROP_VERSION), spa_version);
528 } else {
529 zfs_error_aux(hdl, "%s", zfs_strerror(rc));
530 }
531 return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED,
532 dgettext(TEXT_DOMAIN, "cannot mount '%s'"),
533 zhp->zfs_name));
534 }
535
536 /* remove the mounted entry before re-adding on remount */
537 if (remount)
538 libzfs_mnttab_remove(hdl, zhp->zfs_name);
539
540 /* add the mounted entry into our cache */
541 libzfs_mnttab_add(hdl, zfs_get_name(zhp), mountpoint, mntopts);
542 return (0);
543 }
544
545 /*
546 * Unmount a single filesystem.
547 */
548 static int
unmount_one(zfs_handle_t * zhp,const char * mountpoint,int flags)549 unmount_one(zfs_handle_t *zhp, const char *mountpoint, int flags)
550 {
551 int error;
552
553 error = do_unmount(zhp, mountpoint, flags);
554 if (error != 0) {
555 int libzfs_err;
556
557 switch (error) {
558 case EBUSY:
559 libzfs_err = EZFS_BUSY;
560 break;
561 case EIO:
562 libzfs_err = EZFS_IO;
563 break;
564 case ENOENT:
565 libzfs_err = EZFS_NOENT;
566 break;
567 case ENOMEM:
568 libzfs_err = EZFS_NOMEM;
569 break;
570 case EPERM:
571 libzfs_err = EZFS_PERM;
572 break;
573 default:
574 libzfs_err = EZFS_UMOUNTFAILED;
575 }
576 if (zhp) {
577 return (zfs_error_fmt(zhp->zfs_hdl, libzfs_err,
578 dgettext(TEXT_DOMAIN, "cannot unmount '%s'"),
579 mountpoint));
580 } else {
581 return (-1);
582 }
583 }
584
585 return (0);
586 }
587
588 /*
589 * Unmount the given filesystem.
590 */
591 int
zfs_unmount(zfs_handle_t * zhp,const char * mountpoint,int flags)592 zfs_unmount(zfs_handle_t *zhp, const char *mountpoint, int flags)
593 {
594 libzfs_handle_t *hdl = zhp->zfs_hdl;
595 struct mnttab entry;
596 char *mntpt = NULL;
597 boolean_t encroot, unmounted = B_FALSE;
598
599 /* check to see if we need to unmount the filesystem */
600 if (mountpoint != NULL || ((zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) &&
601 libzfs_mnttab_find(hdl, zhp->zfs_name, &entry) == 0)) {
602 /*
603 * mountpoint may have come from a call to
604 * getmnt/getmntany if it isn't NULL. If it is NULL,
605 * we know it comes from libzfs_mnttab_find which can
606 * then get freed later. We strdup it to play it safe.
607 */
608 if (mountpoint == NULL)
609 mntpt = zfs_strdup(hdl, entry.mnt_mountp);
610 else
611 mntpt = zfs_strdup(hdl, mountpoint);
612
613 /*
614 * Unshare and unmount the filesystem
615 */
616 if (zfs_unshare(zhp, mntpt, share_all_proto) != 0) {
617 free(mntpt);
618 return (-1);
619 }
620 zfs_commit_shares(NULL);
621
622 if (unmount_one(zhp, mntpt, flags) != 0) {
623 free(mntpt);
624 (void) zfs_share(zhp, NULL);
625 zfs_commit_shares(NULL);
626 return (-1);
627 }
628
629 libzfs_mnttab_remove(hdl, zhp->zfs_name);
630 free(mntpt);
631 unmounted = B_TRUE;
632 }
633
634 /*
635 * If the MS_CRYPT flag is provided we must ensure we attempt to
636 * unload the dataset's key regardless of whether we did any work
637 * to unmount it. We only do this for encryption roots.
638 */
639 if ((flags & MS_CRYPT) != 0 &&
640 zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION) != ZIO_CRYPT_OFF) {
641 zfs_refresh_properties(zhp);
642
643 if (zfs_crypto_get_encryption_root(zhp, &encroot, NULL) != 0 &&
644 unmounted) {
645 (void) zfs_mount(zhp, NULL, 0);
646 return (-1);
647 }
648
649 if (encroot && zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS) ==
650 ZFS_KEYSTATUS_AVAILABLE &&
651 zfs_crypto_unload_key(zhp) != 0) {
652 (void) zfs_mount(zhp, NULL, 0);
653 return (-1);
654 }
655 }
656
657 zpool_disable_volume_os(zhp->zfs_name);
658
659 return (0);
660 }
661
662 /*
663 * Unmount this filesystem and any children inheriting the mountpoint property.
664 * To do this, just act like we're changing the mountpoint property, but don't
665 * remount the filesystems afterwards.
666 */
667 int
zfs_unmountall(zfs_handle_t * zhp,int flags)668 zfs_unmountall(zfs_handle_t *zhp, int flags)
669 {
670 prop_changelist_t *clp;
671 int ret;
672
673 clp = changelist_gather(zhp, ZFS_PROP_MOUNTPOINT,
674 CL_GATHER_ITER_MOUNTED, flags);
675 if (clp == NULL)
676 return (-1);
677
678 ret = changelist_prefix(clp);
679 changelist_free(clp);
680
681 return (ret);
682 }
683
684 /*
685 * Unshare a filesystem by mountpoint.
686 */
687 static int
unshare_one(libzfs_handle_t * hdl,const char * name,const char * mountpoint,enum sa_protocol proto)688 unshare_one(libzfs_handle_t *hdl, const char *name, const char *mountpoint,
689 enum sa_protocol proto)
690 {
691 int err = sa_disable_share(mountpoint, proto);
692 if (err != SA_OK)
693 return (zfs_error_fmt(hdl, proto_table[proto].p_unshare_err,
694 dgettext(TEXT_DOMAIN, "cannot unshare '%s': %s"),
695 name, sa_errorstr(err)));
696
697 return (0);
698 }
699
700 /*
701 * Share the given filesystem according to the options in the specified
702 * protocol specific properties (sharenfs, sharesmb). We rely
703 * on "libshare" to do the dirty work for us.
704 */
705 int
zfs_share(zfs_handle_t * zhp,const enum sa_protocol * proto)706 zfs_share(zfs_handle_t *zhp, const enum sa_protocol *proto)
707 {
708 char mountpoint[ZFS_MAXPROPLEN];
709 char shareopts[ZFS_MAXPROPLEN];
710 char sourcestr[ZFS_MAXPROPLEN];
711 const enum sa_protocol *curr_proto;
712 zprop_source_t sourcetype;
713 int err = 0;
714
715 if (proto == NULL)
716 proto = share_all_proto;
717
718 if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL, 0))
719 return (0);
720
721 for (curr_proto = proto; *curr_proto != SA_NO_PROTOCOL; curr_proto++) {
722 /*
723 * Return success if there are no share options.
724 */
725 if (zfs_prop_get(zhp, proto_table[*curr_proto].p_prop,
726 shareopts, sizeof (shareopts), &sourcetype, sourcestr,
727 ZFS_MAXPROPLEN, B_FALSE) != 0 ||
728 strcmp(shareopts, "off") == 0)
729 continue;
730
731 /*
732 * If the 'zoned' property is set, then zfs_is_mountable()
733 * will have already bailed out if we are in the global zone.
734 * But local zones cannot be NFS servers, so we ignore it for
735 * local zones as well.
736 */
737 if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED))
738 continue;
739
740 err = sa_enable_share(zfs_get_name(zhp), mountpoint, shareopts,
741 *curr_proto);
742 if (err != SA_OK) {
743 return (zfs_error_fmt(zhp->zfs_hdl,
744 proto_table[*curr_proto].p_share_err,
745 dgettext(TEXT_DOMAIN, "cannot share '%s: %s'"),
746 zfs_get_name(zhp), sa_errorstr(err)));
747 }
748
749 }
750 return (0);
751 }
752
753 /*
754 * Check to see if the filesystem is currently shared.
755 */
756 boolean_t
zfs_is_shared(zfs_handle_t * zhp,char ** where,const enum sa_protocol * proto)757 zfs_is_shared(zfs_handle_t *zhp, char **where,
758 const enum sa_protocol *proto)
759 {
760 char *mountpoint;
761 if (proto == NULL)
762 proto = share_all_proto;
763
764 if (ZFS_IS_VOLUME(zhp))
765 return (B_FALSE);
766
767 if (!zfs_is_mounted(zhp, &mountpoint))
768 return (B_FALSE);
769
770 for (const enum sa_protocol *p = proto; *p != SA_NO_PROTOCOL; ++p)
771 if (sa_is_shared(mountpoint, *p)) {
772 if (where != NULL)
773 *where = mountpoint;
774 else
775 free(mountpoint);
776 return (B_TRUE);
777 }
778
779 free(mountpoint);
780 return (B_FALSE);
781 }
782
783 void
zfs_commit_shares(const enum sa_protocol * proto)784 zfs_commit_shares(const enum sa_protocol *proto)
785 {
786 if (proto == NULL)
787 proto = share_all_proto;
788
789 for (const enum sa_protocol *p = proto; *p != SA_NO_PROTOCOL; ++p)
790 sa_commit_shares(*p);
791 }
792
793 void
zfs_truncate_shares(const enum sa_protocol * proto)794 zfs_truncate_shares(const enum sa_protocol *proto)
795 {
796 if (proto == NULL)
797 proto = share_all_proto;
798
799 for (const enum sa_protocol *p = proto; *p != SA_NO_PROTOCOL; ++p)
800 sa_truncate_shares(*p);
801 }
802
803 /*
804 * Unshare the given filesystem.
805 */
806 int
zfs_unshare(zfs_handle_t * zhp,const char * mountpoint,const enum sa_protocol * proto)807 zfs_unshare(zfs_handle_t *zhp, const char *mountpoint,
808 const enum sa_protocol *proto)
809 {
810 libzfs_handle_t *hdl = zhp->zfs_hdl;
811 struct mnttab entry;
812
813 if (proto == NULL)
814 proto = share_all_proto;
815
816 if (mountpoint != NULL || ((zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) &&
817 libzfs_mnttab_find(hdl, zfs_get_name(zhp), &entry) == 0)) {
818
819 /* check to see if need to unmount the filesystem */
820 const char *mntpt = mountpoint ?: entry.mnt_mountp;
821
822 for (const enum sa_protocol *curr_proto = proto;
823 *curr_proto != SA_NO_PROTOCOL; curr_proto++)
824 if (sa_is_shared(mntpt, *curr_proto) &&
825 unshare_one(hdl, zhp->zfs_name,
826 mntpt, *curr_proto) != 0)
827 return (-1);
828 }
829
830 return (0);
831 }
832
833 /*
834 * Same as zfs_unmountall(), but for NFS and SMB unshares.
835 */
836 int
zfs_unshareall(zfs_handle_t * zhp,const enum sa_protocol * proto)837 zfs_unshareall(zfs_handle_t *zhp, const enum sa_protocol *proto)
838 {
839 prop_changelist_t *clp;
840 int ret;
841
842 if (proto == NULL)
843 proto = share_all_proto;
844
845 clp = changelist_gather(zhp, ZFS_PROP_SHARENFS, 0, 0);
846 if (clp == NULL)
847 return (-1);
848
849 ret = changelist_unshare(clp, proto);
850 changelist_free(clp);
851
852 return (ret);
853 }
854
855 /*
856 * Remove the mountpoint associated with the current dataset, if necessary.
857 * We only remove the underlying directory if:
858 *
859 * - The mountpoint is not 'none' or 'legacy'
860 * - The mountpoint is non-empty
861 * - The mountpoint is the default or inherited
862 * - The 'zoned' property is set, or we're in a local zone
863 *
864 * Any other directories we leave alone.
865 */
866 void
remove_mountpoint(zfs_handle_t * zhp)867 remove_mountpoint(zfs_handle_t *zhp)
868 {
869 char mountpoint[ZFS_MAXPROPLEN];
870 zprop_source_t source;
871
872 if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint),
873 &source, 0))
874 return;
875
876 if (source == ZPROP_SRC_DEFAULT ||
877 source == ZPROP_SRC_INHERITED) {
878 /*
879 * Try to remove the directory, silently ignoring any errors.
880 * The filesystem may have since been removed or moved around,
881 * and this error isn't really useful to the administrator in
882 * any way.
883 */
884 (void) rmdir(mountpoint);
885 }
886 }
887
888 /*
889 * Add the given zfs handle to the cb_handles array, dynamically reallocating
890 * the array if it is out of space.
891 */
892 void
libzfs_add_handle(get_all_cb_t * cbp,zfs_handle_t * zhp)893 libzfs_add_handle(get_all_cb_t *cbp, zfs_handle_t *zhp)
894 {
895 if (cbp->cb_alloc == cbp->cb_used) {
896 size_t newsz;
897 zfs_handle_t **newhandles;
898
899 newsz = cbp->cb_alloc != 0 ? cbp->cb_alloc * 2 : 64;
900 newhandles = zfs_realloc(zhp->zfs_hdl,
901 cbp->cb_handles, cbp->cb_alloc * sizeof (zfs_handle_t *),
902 newsz * sizeof (zfs_handle_t *));
903 cbp->cb_handles = newhandles;
904 cbp->cb_alloc = newsz;
905 }
906 cbp->cb_handles[cbp->cb_used++] = zhp;
907 }
908
909 /*
910 * Recursive helper function used during file system enumeration
911 */
912 static int
zfs_iter_cb(zfs_handle_t * zhp,void * data)913 zfs_iter_cb(zfs_handle_t *zhp, void *data)
914 {
915 get_all_cb_t *cbp = data;
916
917 if (!(zfs_get_type(zhp) & ZFS_TYPE_FILESYSTEM)) {
918 zfs_close(zhp);
919 return (0);
920 }
921
922 if (zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT) == ZFS_CANMOUNT_NOAUTO) {
923 zfs_close(zhp);
924 return (0);
925 }
926
927 if (zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS) ==
928 ZFS_KEYSTATUS_UNAVAILABLE) {
929 zfs_close(zhp);
930 return (0);
931 }
932
933 /*
934 * If this filesystem is inconsistent and has a receive resume
935 * token, we can not mount it.
936 */
937 if (zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT) &&
938 zfs_prop_get(zhp, ZFS_PROP_RECEIVE_RESUME_TOKEN,
939 NULL, 0, NULL, NULL, 0, B_TRUE) == 0) {
940 zfs_close(zhp);
941 return (0);
942 }
943
944 libzfs_add_handle(cbp, zhp);
945 if (zfs_iter_filesystems_v2(zhp, 0, zfs_iter_cb, cbp) != 0) {
946 zfs_close(zhp);
947 return (-1);
948 }
949 return (0);
950 }
951
952 /*
953 * Sort comparator that compares two mountpoint paths. We sort these paths so
954 * that subdirectories immediately follow their parents. This means that we
955 * effectively treat the '/' character as the lowest value non-nul char.
956 * Since filesystems from non-global zones can have the same mountpoint
957 * as other filesystems, the comparator sorts global zone filesystems to
958 * the top of the list. This means that the global zone will traverse the
959 * filesystem list in the correct order and can stop when it sees the
960 * first zoned filesystem. In a non-global zone, only the delegated
961 * filesystems are seen.
962 *
963 * An example sorted list using this comparator would look like:
964 *
965 * /foo
966 * /foo/bar
967 * /foo/bar/baz
968 * /foo/baz
969 * /foo.bar
970 * /foo (NGZ1)
971 * /foo (NGZ2)
972 *
973 * The mounting code depends on this ordering to deterministically iterate
974 * over filesystems in order to spawn parallel mount tasks.
975 */
976 static int
mountpoint_cmp(const void * arga,const void * argb)977 mountpoint_cmp(const void *arga, const void *argb)
978 {
979 zfs_handle_t *const *zap = arga;
980 zfs_handle_t *za = *zap;
981 zfs_handle_t *const *zbp = argb;
982 zfs_handle_t *zb = *zbp;
983 char mounta[MAXPATHLEN];
984 char mountb[MAXPATHLEN];
985 const char *a = mounta;
986 const char *b = mountb;
987 boolean_t gota, gotb;
988 uint64_t zoneda, zonedb;
989
990 zoneda = zfs_prop_get_int(za, ZFS_PROP_ZONED);
991 zonedb = zfs_prop_get_int(zb, ZFS_PROP_ZONED);
992 if (zoneda && !zonedb)
993 return (1);
994 if (!zoneda && zonedb)
995 return (-1);
996
997 gota = (zfs_get_type(za) == ZFS_TYPE_FILESYSTEM);
998 if (gota) {
999 verify(zfs_prop_get(za, ZFS_PROP_MOUNTPOINT, mounta,
1000 sizeof (mounta), NULL, NULL, 0, B_FALSE) == 0);
1001 }
1002 gotb = (zfs_get_type(zb) == ZFS_TYPE_FILESYSTEM);
1003 if (gotb) {
1004 verify(zfs_prop_get(zb, ZFS_PROP_MOUNTPOINT, mountb,
1005 sizeof (mountb), NULL, NULL, 0, B_FALSE) == 0);
1006 }
1007
1008 if (gota && gotb) {
1009 while (*a != '\0' && (*a == *b)) {
1010 a++;
1011 b++;
1012 }
1013 if (*a == *b)
1014 return (0);
1015 if (*a == '\0')
1016 return (-1);
1017 if (*b == '\0')
1018 return (1);
1019 if (*a == '/')
1020 return (-1);
1021 if (*b == '/')
1022 return (1);
1023 return (*a < *b ? -1 : *a > *b);
1024 }
1025
1026 if (gota)
1027 return (-1);
1028 if (gotb)
1029 return (1);
1030
1031 /*
1032 * If neither filesystem has a mountpoint, revert to sorting by
1033 * dataset name.
1034 */
1035 return (strcmp(zfs_get_name(za), zfs_get_name(zb)));
1036 }
1037
1038 /*
1039 * Return true if path2 is a child of path1 or path2 equals path1 or
1040 * path1 is "/" (path2 is always a child of "/").
1041 */
1042 static boolean_t
libzfs_path_contains(const char * path1,const char * path2)1043 libzfs_path_contains(const char *path1, const char *path2)
1044 {
1045 return (strcmp(path1, path2) == 0 || strcmp(path1, "/") == 0 ||
1046 (strstr(path2, path1) == path2 && path2[strlen(path1)] == '/'));
1047 }
1048
1049 /*
1050 * Given a mountpoint specified by idx in the handles array, find the first
1051 * non-descendent of that mountpoint and return its index. Descendant paths
1052 * start with the parent's path. This function relies on the ordering
1053 * enforced by mountpoint_cmp().
1054 */
1055 static int
non_descendant_idx(zfs_handle_t ** handles,size_t num_handles,int idx)1056 non_descendant_idx(zfs_handle_t **handles, size_t num_handles, int idx)
1057 {
1058 char parent[ZFS_MAXPROPLEN];
1059 char child[ZFS_MAXPROPLEN];
1060 int i;
1061
1062 verify(zfs_prop_get(handles[idx], ZFS_PROP_MOUNTPOINT, parent,
1063 sizeof (parent), NULL, NULL, 0, B_FALSE) == 0);
1064
1065 for (i = idx + 1; i < num_handles; i++) {
1066 verify(zfs_prop_get(handles[i], ZFS_PROP_MOUNTPOINT, child,
1067 sizeof (child), NULL, NULL, 0, B_FALSE) == 0);
1068 if (!libzfs_path_contains(parent, child))
1069 break;
1070 }
1071 return (i);
1072 }
1073
1074 typedef struct mnt_param {
1075 libzfs_handle_t *mnt_hdl;
1076 taskq_t *mnt_tq;
1077 zfs_handle_t **mnt_zhps; /* filesystems to mount */
1078 size_t mnt_num_handles;
1079 int mnt_idx; /* Index of selected entry to mount */
1080 zfs_iter_f mnt_func;
1081 void *mnt_data;
1082 } mnt_param_t;
1083
1084 /*
1085 * Allocate and populate the parameter struct for mount function, and
1086 * schedule mounting of the entry selected by idx.
1087 */
1088 static void
zfs_dispatch_mount(libzfs_handle_t * hdl,zfs_handle_t ** handles,size_t num_handles,int idx,zfs_iter_f func,void * data,taskq_t * tq)1089 zfs_dispatch_mount(libzfs_handle_t *hdl, zfs_handle_t **handles,
1090 size_t num_handles, int idx, zfs_iter_f func, void *data, taskq_t *tq)
1091 {
1092 mnt_param_t *mnt_param = zfs_alloc(hdl, sizeof (mnt_param_t));
1093
1094 mnt_param->mnt_hdl = hdl;
1095 mnt_param->mnt_tq = tq;
1096 mnt_param->mnt_zhps = handles;
1097 mnt_param->mnt_num_handles = num_handles;
1098 mnt_param->mnt_idx = idx;
1099 mnt_param->mnt_func = func;
1100 mnt_param->mnt_data = data;
1101
1102 if (taskq_dispatch(tq, zfs_mount_task, (void*)mnt_param,
1103 TQ_SLEEP) == TASKQID_INVALID) {
1104 /* Could not dispatch to thread pool; execute directly */
1105 zfs_mount_task((void*)mnt_param);
1106 }
1107 }
1108
1109 /*
1110 * This is the structure used to keep state of mounting or sharing operations
1111 * during a call to zpool_enable_datasets().
1112 */
1113 typedef struct mount_state {
1114 /*
1115 * ms_mntstatus is set to -1 if any mount fails. While multiple threads
1116 * could update this variable concurrently, no synchronization is
1117 * needed as it's only ever set to -1.
1118 */
1119 int ms_mntstatus;
1120 int ms_mntflags;
1121 const char *ms_mntopts;
1122 } mount_state_t;
1123
1124 static int
zfs_mount_one(zfs_handle_t * zhp,void * arg)1125 zfs_mount_one(zfs_handle_t *zhp, void *arg)
1126 {
1127 mount_state_t *ms = arg;
1128 int ret = 0;
1129
1130 /*
1131 * don't attempt to mount encrypted datasets with
1132 * unloaded keys
1133 */
1134 if (zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS) ==
1135 ZFS_KEYSTATUS_UNAVAILABLE)
1136 return (0);
1137
1138 if (zfs_mount(zhp, ms->ms_mntopts, ms->ms_mntflags) != 0)
1139 ret = ms->ms_mntstatus = -1;
1140 return (ret);
1141 }
1142
1143 static int
zfs_share_one(zfs_handle_t * zhp,void * arg)1144 zfs_share_one(zfs_handle_t *zhp, void *arg)
1145 {
1146 mount_state_t *ms = arg;
1147 int ret = 0;
1148
1149 if (zfs_share(zhp, NULL) != 0)
1150 ret = ms->ms_mntstatus = -1;
1151 return (ret);
1152 }
1153
1154 /*
1155 * Thread pool function to mount one file system. On completion, it finds and
1156 * schedules its children to be mounted. This depends on the sorting done in
1157 * zfs_foreach_mountpoint(). Note that the degenerate case (chain of entries
1158 * each descending from the previous) will have no parallelism since we always
1159 * have to wait for the parent to finish mounting before we can schedule
1160 * its children.
1161 */
1162 static void
zfs_mount_task(void * arg)1163 zfs_mount_task(void *arg)
1164 {
1165 mnt_param_t *mp = arg;
1166 int idx = mp->mnt_idx;
1167 zfs_handle_t **handles = mp->mnt_zhps;
1168 size_t num_handles = mp->mnt_num_handles;
1169 char mountpoint[ZFS_MAXPROPLEN];
1170
1171 verify(zfs_prop_get(handles[idx], ZFS_PROP_MOUNTPOINT, mountpoint,
1172 sizeof (mountpoint), NULL, NULL, 0, B_FALSE) == 0);
1173
1174 if (mp->mnt_func(handles[idx], mp->mnt_data) != 0)
1175 goto out;
1176
1177 /*
1178 * We dispatch tasks to mount filesystems with mountpoints underneath
1179 * this one. We do this by dispatching the next filesystem with a
1180 * descendant mountpoint of the one we just mounted, then skip all of
1181 * its descendants, dispatch the next descendant mountpoint, and so on.
1182 * The non_descendant_idx() function skips over filesystems that are
1183 * descendants of the filesystem we just dispatched.
1184 */
1185 for (int i = idx + 1; i < num_handles;
1186 i = non_descendant_idx(handles, num_handles, i)) {
1187 char child[ZFS_MAXPROPLEN];
1188 verify(zfs_prop_get(handles[i], ZFS_PROP_MOUNTPOINT,
1189 child, sizeof (child), NULL, NULL, 0, B_FALSE) == 0);
1190
1191 if (!libzfs_path_contains(mountpoint, child))
1192 break; /* not a descendant, return */
1193 zfs_dispatch_mount(mp->mnt_hdl, handles, num_handles, i,
1194 mp->mnt_func, mp->mnt_data, mp->mnt_tq);
1195 }
1196
1197 out:
1198 free(mp);
1199 }
1200
1201 /*
1202 * Issue the func callback for each ZFS handle contained in the handles
1203 * array. This function is used to mount all datasets, and so this function
1204 * guarantees that filesystems for parent mountpoints are called before their
1205 * children. As such, before issuing any callbacks, we first sort the array
1206 * of handles by mountpoint.
1207 *
1208 * Callbacks are issued in one of two ways:
1209 *
1210 * 1. Sequentially: If the nthr argument is <= 1 or the ZFS_SERIAL_MOUNT
1211 * environment variable is set, then we issue callbacks sequentially.
1212 *
1213 * 2. In parallel: If the nthr argument is > 1 and the ZFS_SERIAL_MOUNT
1214 * environment variable is not set, then we use a tpool to dispatch threads
1215 * to mount filesystems in parallel. This function dispatches tasks to mount
1216 * the filesystems at the top-level mountpoints, and these tasks in turn
1217 * are responsible for recursively mounting filesystems in their children
1218 * mountpoints. The value of the nthr argument will be the number of worker
1219 * threads for the thread pool.
1220 */
1221 void
zfs_foreach_mountpoint(libzfs_handle_t * hdl,zfs_handle_t ** handles,size_t num_handles,zfs_iter_f func,void * data,uint_t nthr)1222 zfs_foreach_mountpoint(libzfs_handle_t *hdl, zfs_handle_t **handles,
1223 size_t num_handles, zfs_iter_f func, void *data, uint_t nthr)
1224 {
1225 zoneid_t zoneid = getzoneid();
1226
1227 /*
1228 * The ZFS_SERIAL_MOUNT environment variable is an undocumented
1229 * variable that can be used as a convenience to do a/b comparison
1230 * of serial vs. parallel mounting.
1231 */
1232 boolean_t serial_mount = nthr <= 1 ||
1233 (getenv("ZFS_SERIAL_MOUNT") != NULL);
1234
1235 /*
1236 * Sort the datasets by mountpoint. See mountpoint_cmp for details
1237 * of how these are sorted.
1238 */
1239 qsort(handles, num_handles, sizeof (zfs_handle_t *), mountpoint_cmp);
1240
1241 if (serial_mount) {
1242 for (int i = 0; i < num_handles; i++) {
1243 func(handles[i], data);
1244 }
1245 return;
1246 }
1247
1248 /*
1249 * Issue the callback function for each dataset using a parallel
1250 * algorithm that uses a thread pool to manage threads.
1251 */
1252 taskq_t *tq = taskq_create("zfs_foreach_mountpoint", nthr, minclsyspri,
1253 1, INT_MAX, TASKQ_DYNAMIC);
1254
1255 /*
1256 * There may be multiple "top level" mountpoints outside of the pool's
1257 * root mountpoint, e.g.: /foo /bar. Dispatch a mount task for each of
1258 * these.
1259 */
1260 for (int i = 0; i < num_handles;
1261 i = non_descendant_idx(handles, num_handles, i)) {
1262 /*
1263 * Since the mountpoints have been sorted so that the zoned
1264 * filesystems are at the end, a zoned filesystem seen from
1265 * the global zone means that we're done.
1266 */
1267 if (zoneid == GLOBAL_ZONEID &&
1268 zfs_prop_get_int(handles[i], ZFS_PROP_ZONED))
1269 break;
1270 zfs_dispatch_mount(hdl, handles, num_handles, i, func, data,
1271 tq);
1272 }
1273
1274 taskq_wait(tq); /* wait for all scheduled mounts to complete */
1275 taskq_destroy(tq);
1276 }
1277
1278 /*
1279 * Mount and share all datasets within the given pool. This assumes that no
1280 * datasets within the pool are currently mounted. nthr will be number of
1281 * worker threads to use while mounting datasets.
1282 */
1283 int
zpool_enable_datasets(zpool_handle_t * zhp,const char * mntopts,int flags,uint_t nthr)1284 zpool_enable_datasets(zpool_handle_t *zhp, const char *mntopts, int flags,
1285 uint_t nthr)
1286 {
1287 get_all_cb_t cb = { 0 };
1288 mount_state_t ms = { 0 };
1289 zfs_handle_t *zfsp;
1290 int ret = 0;
1291
1292 if ((zfsp = zfs_open(zhp->zpool_hdl, zhp->zpool_name,
1293 ZFS_TYPE_DATASET)) == NULL)
1294 goto out;
1295
1296 /*
1297 * Gather all non-snapshot datasets within the pool. Start by adding
1298 * the root filesystem for this pool to the list, and then iterate
1299 * over all child filesystems.
1300 */
1301 libzfs_add_handle(&cb, zfsp);
1302 if (zfs_iter_filesystems_v2(zfsp, 0, zfs_iter_cb, &cb) != 0)
1303 goto out;
1304
1305 /*
1306 * Mount all filesystems
1307 */
1308 ms.ms_mntopts = mntopts;
1309 ms.ms_mntflags = flags;
1310 zfs_foreach_mountpoint(zhp->zpool_hdl, cb.cb_handles, cb.cb_used,
1311 zfs_mount_one, &ms, nthr);
1312 if (ms.ms_mntstatus != 0)
1313 ret = EZFS_MOUNTFAILED;
1314
1315 /*
1316 * Share all filesystems that need to be shared. This needs to be
1317 * a separate pass because libshare is not mt-safe, and so we need
1318 * to share serially.
1319 */
1320 ms.ms_mntstatus = 0;
1321 zfs_foreach_mountpoint(zhp->zpool_hdl, cb.cb_handles, cb.cb_used,
1322 zfs_share_one, &ms, 1);
1323 if (ms.ms_mntstatus != 0)
1324 ret = EZFS_SHAREFAILED;
1325 else
1326 zfs_commit_shares(NULL);
1327
1328 out:
1329 for (int i = 0; i < cb.cb_used; i++)
1330 zfs_close(cb.cb_handles[i]);
1331 free(cb.cb_handles);
1332
1333 return (ret);
1334 }
1335
1336 struct sets_s {
1337 char *mountpoint;
1338 zfs_handle_t *dataset;
1339 };
1340
1341 static int
mountpoint_compare(const void * a,const void * b)1342 mountpoint_compare(const void *a, const void *b)
1343 {
1344 const struct sets_s *mounta = (struct sets_s *)a;
1345 const struct sets_s *mountb = (struct sets_s *)b;
1346
1347 return (strcmp(mountb->mountpoint, mounta->mountpoint));
1348 }
1349
1350 /*
1351 * Unshare and unmount all datasets within the given pool. We don't want to
1352 * rely on traversing the DSL to discover the filesystems within the pool,
1353 * because this may be expensive (if not all of them are mounted), and can fail
1354 * arbitrarily (on I/O error, for example). Instead, we walk /proc/self/mounts
1355 * and gather all the filesystems that are currently mounted.
1356 */
1357 int
zpool_disable_datasets(zpool_handle_t * zhp,boolean_t force)1358 zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force)
1359 {
1360 int used, alloc;
1361 FILE *mnttab;
1362 struct mnttab entry;
1363 size_t namelen;
1364 struct sets_s *sets = NULL;
1365 libzfs_handle_t *hdl = zhp->zpool_hdl;
1366 int i;
1367 int ret = -1;
1368 int flags = (force ? MS_FORCE : 0);
1369
1370 namelen = strlen(zhp->zpool_name);
1371
1372 if ((mnttab = fopen(MNTTAB, "re")) == NULL)
1373 return (ENOENT);
1374
1375 used = alloc = 0;
1376 while (getmntent(mnttab, &entry) == 0) {
1377 /*
1378 * Ignore non-ZFS entries.
1379 */
1380 if (entry.mnt_fstype == NULL ||
1381 strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0)
1382 continue;
1383
1384 /*
1385 * Ignore filesystems not within this pool.
1386 */
1387 if (entry.mnt_mountp == NULL ||
1388 strncmp(entry.mnt_special, zhp->zpool_name, namelen) != 0 ||
1389 (entry.mnt_special[namelen] != '/' &&
1390 entry.mnt_special[namelen] != '\0'))
1391 continue;
1392
1393 /*
1394 * At this point we've found a filesystem within our pool. Add
1395 * it to our growing list.
1396 */
1397 if (used == alloc) {
1398 if (alloc == 0) {
1399 sets = zfs_alloc(hdl,
1400 8 * sizeof (struct sets_s));
1401 alloc = 8;
1402 } else {
1403 sets = zfs_realloc(hdl, sets,
1404 alloc * sizeof (struct sets_s),
1405 alloc * 2 * sizeof (struct sets_s));
1406
1407 alloc *= 2;
1408 }
1409 }
1410
1411 sets[used].mountpoint = zfs_strdup(hdl, entry.mnt_mountp);
1412
1413 /*
1414 * This is allowed to fail, in case there is some I/O error. It
1415 * is only used to determine if we need to remove the underlying
1416 * mountpoint, so failure is not fatal.
1417 */
1418 sets[used].dataset = make_dataset_handle(hdl,
1419 entry.mnt_special);
1420
1421 used++;
1422 }
1423
1424 /*
1425 * At this point, we have the entire list of filesystems, so sort it by
1426 * mountpoint.
1427 */
1428 if (used != 0)
1429 qsort(sets, used, sizeof (struct sets_s), mountpoint_compare);
1430
1431 /*
1432 * Walk through and first unshare everything.
1433 */
1434 for (i = 0; i < used; i++) {
1435 for (enum sa_protocol p = 0; p < SA_PROTOCOL_COUNT; ++p) {
1436 if (sa_is_shared(sets[i].mountpoint, p) &&
1437 unshare_one(hdl, sets[i].mountpoint,
1438 sets[i].mountpoint, p) != 0)
1439 goto out;
1440 }
1441 }
1442 zfs_commit_shares(NULL);
1443
1444 /*
1445 * Now unmount everything, removing the underlying directories as
1446 * appropriate.
1447 */
1448 for (i = 0; i < used; i++) {
1449 if (unmount_one(sets[i].dataset, sets[i].mountpoint,
1450 flags) != 0)
1451 goto out;
1452 }
1453
1454 for (i = 0; i < used; i++) {
1455 if (sets[i].dataset)
1456 remove_mountpoint(sets[i].dataset);
1457 }
1458
1459 zpool_disable_datasets_os(zhp, force);
1460
1461 ret = 0;
1462 out:
1463 (void) fclose(mnttab);
1464 for (i = 0; i < used; i++) {
1465 if (sets[i].dataset)
1466 zfs_close(sets[i].dataset);
1467 free(sets[i].mountpoint);
1468 }
1469 free(sets);
1470
1471 return (ret);
1472 }
1473