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