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