]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Publish libshare protocols, use enum-based API
authorнаб <nabijaczleweli@nabijaczleweli.xyz>
Mon, 28 Feb 2022 14:46:25 +0000 (15:46 +0100)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 12 May 2022 16:26:38 +0000 (09:26 -0700)
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #13165

lib/libshare/libshare.c
lib/libshare/libshare_impl.h
lib/libshare/os/freebsd/nfs.c
lib/libshare/os/freebsd/smb.c
lib/libshare/os/linux/nfs.c
lib/libshare/os/linux/smb.c
lib/libspl/include/libshare.h
lib/libzfs/libzfs_changelist.c
lib/libzfs/libzfs_dataset.c
lib/libzfs/libzfs_impl.h
lib/libzfs/libzfs_mount.c

index 4a8e32d773c64552a9a4441a818dd365015d130e..09529e5b410655a20d220b8015acc8d149f75bdd 100644 (file)
                .sa_mountpoint = path, \
                .sa_shareopts = shareopts, \
        }
-#define        find_proto(pcol) \
-       /* CSTYLED */ \
-       ({ \
-               sa_fstype_t prot = { \
-                       .protocol = pcol, \
-               }; \
-               avl_find(&fstypes, &prot, NULL); \
-       })
-
-static avl_tree_t fstypes;
-
-static int
-fstypes_compar(const void *lhs, const void *rhs)
-{
-       const sa_fstype_t *l = lhs, *r = rhs;
-       int cmp = strcmp(l->protocol, r->protocol);
-       return ((0 < cmp) - (cmp < 0));
-}
 
-__attribute__((constructor)) static void
-libshare_init(void)
-{
-       avl_create(&fstypes, fstypes_compar,
-           sizeof (sa_fstype_t), offsetof(sa_fstype_t, node));
-       avl_add(&fstypes, &libshare_nfs_type);
-       avl_add(&fstypes, &libshare_smb_type);
-}
+#define        VALIDATE_PROTOCOL(proto, ...) \
+       if ((proto) < 0 || (proto) >= SA_PROTOCOL_COUNT) \
+               return __VA_ARGS__
+
+const char *const sa_protocol_names[SA_PROTOCOL_COUNT] = {
+       [SA_PROTOCOL_NFS] = "nfs",
+       [SA_PROTOCOL_SMB] = "smb",
+};
+
+static const sa_fstype_t *fstypes[SA_PROTOCOL_COUNT] =
+       {&libshare_nfs_type, &libshare_smb_type};
 
 int
 sa_enable_share(const char *zfsname, const char *mountpoint,
-    const char *shareopts, const char *protocol)
+    const char *shareopts, enum sa_protocol protocol)
 {
-       sa_fstype_t *fstype = find_proto(protocol);
-       if (!fstype)
-               return (SA_INVALID_PROTOCOL);
+       VALIDATE_PROTOCOL(protocol, SA_INVALID_PROTOCOL);
 
        const struct sa_share_impl args =
            init_share(zfsname, mountpoint, shareopts);
-       return (fstype->enable_share(&args));
+       return (fstypes[protocol]->enable_share(&args));
 }
 
 int
-sa_disable_share(const char *mountpoint, const char *protocol)
+sa_disable_share(const char *mountpoint, enum sa_protocol protocol)
 {
-       sa_fstype_t *fstype = find_proto(protocol);
-       if (!fstype)
-               return (SA_INVALID_PROTOCOL);
+       VALIDATE_PROTOCOL(protocol, SA_INVALID_PROTOCOL);
 
        const struct sa_share_impl args = init_share(NULL, mountpoint, NULL);
-       return (fstype->disable_share(&args));
+       return (fstypes[protocol]->disable_share(&args));
 }
 
 boolean_t
-sa_is_shared(const char *mountpoint, const char *protocol)
+sa_is_shared(const char *mountpoint, enum sa_protocol protocol)
 {
-       sa_fstype_t *fstype = find_proto(protocol);
-       if (!fstype)
-               return (B_FALSE);
+       VALIDATE_PROTOCOL(protocol, B_FALSE);
 
        const struct sa_share_impl args = init_share(NULL, mountpoint, NULL);
-       return (fstype->is_shared(&args));
+       return (fstypes[protocol]->is_shared(&args));
 }
 
 void
-sa_commit_shares(const char *protocol)
+sa_commit_shares(enum sa_protocol protocol)
+{
+       /* CSTYLED */
+       VALIDATE_PROTOCOL(protocol, );
+
+       fstypes[protocol]->commit_shares();
+}
+
+int
+sa_validate_shareopts(const char *options, enum sa_protocol protocol)
 {
-       sa_fstype_t *fstype = find_proto(protocol);
-       if (!fstype)
-               return;
+       VALIDATE_PROTOCOL(protocol, SA_INVALID_PROTOCOL);
 
-       fstype->commit_shares();
+       return (fstypes[protocol]->validate_shareopts(options));
 }
 
 /*
@@ -205,13 +191,3 @@ sa_errorstr(int err)
                return (errstr);
        }
 }
-
-int
-sa_validate_shareopts(const char *options, const char *protocol)
-{
-       sa_fstype_t *fstype = find_proto(protocol);
-       if (!fstype)
-               return (SA_INVALID_PROTOCOL);
-
-       return (fstype->validate_shareopts(options));
-}
index c79b4f532a4f1fb24724621bdcdba411b249b901..110fe93d250f77fb195897fc10637083b60e41dc 100644 (file)
@@ -27,8 +27,6 @@
 #ifndef _LIBSPL_LIBSHARE_IMPL_H
 #define        _LIBSPL_LIBSHARE_IMPL_H
 
-#include <sys/avl.h>
-
 typedef const struct sa_share_impl {
        const char *sa_zfsname;
        const char *sa_mountpoint;
@@ -36,17 +34,13 @@ typedef const struct sa_share_impl {
 } *sa_share_impl_t;
 
 typedef struct {
-       const char *protocol;
-
        int (*const enable_share)(sa_share_impl_t share);
        int (*const disable_share)(sa_share_impl_t share);
        boolean_t (*const is_shared)(sa_share_impl_t share);
        int (*const validate_shareopts)(const char *shareopts);
        int (*const commit_shares)(void);
-
-       avl_node_t node;
 } sa_fstype_t;
 
-extern sa_fstype_t libshare_nfs_type, libshare_smb_type;
+extern const sa_fstype_t libshare_nfs_type, libshare_smb_type;
 
 #endif /* _LIBSPL_LIBSHARE_IMPL_H */
index 388bafc2836be0d996dcbdfee302636f41618d8d..338d25fcd0f84110bba785564b24c2c97c453d15 100644 (file)
@@ -186,9 +186,7 @@ start:
        return (SA_OK);
 }
 
-sa_fstype_t libshare_nfs_type = {
-       .protocol = "nfs",
-
+const sa_fstype_t libshare_nfs_type = {
        .enable_share = nfs_enable_share,
        .disable_share = nfs_disable_share,
        .is_shared = nfs_is_shared,
index fd61d473d5c6654771d8a9a2ef1858de469d8d09..0f546dc5543ef256febedc1a7d682801f6890995 100644 (file)
@@ -76,9 +76,7 @@ smb_update_shares(void)
        return (0);
 }
 
-sa_fstype_t libshare_smb_type = {
-       .protocol = "smb",
-
+const sa_fstype_t libshare_smb_type = {
        .enable_share = smb_enable_share,
        .disable_share = smb_disable_share,
        .is_shared = smb_is_share_active,
index f8a34924c1eb4a05b08b3fac9421e5adaf6a37de..09c7395c660c2d605f19c0300f3daa3d2490dcaf 100644 (file)
@@ -481,9 +481,7 @@ nfs_commit_shares(void)
        return (libzfs_run_process(argv[0], argv, 0));
 }
 
-sa_fstype_t libshare_nfs_type = {
-       .protocol = "nfs",
-
+const sa_fstype_t libshare_nfs_type = {
        .enable_share = nfs_enable_share,
        .disable_share = nfs_disable_share,
        .is_shared = nfs_is_shared,
index 91dffc9bb8a707a47c96cfd9cbbf9b2afb25e9d0..1f32d0e1096a5df3ebc6ad63734fd9f7b334dc74 100644 (file)
@@ -363,9 +363,7 @@ smb_update_shares(void)
        return (0);
 }
 
-sa_fstype_t libshare_smb_type = {
-       .protocol = "smb",
-
+const sa_fstype_t libshare_smb_type = {
        .enable_share = smb_enable_share,
        .disable_share = smb_disable_share,
        .is_shared = smb_is_share_active,
index b8aa02095c29e986adbd0b12352d0d143c16d42b..ae0e2c39dc6dc2c550dcfed90988744b98e22ab9 100644 (file)
 /* initialization */
 _LIBSPL_LIBSHARE_H const char *sa_errorstr(int);
 
+/* available protocols */
+enum sa_protocol {
+       SA_PROTOCOL_NFS,
+       SA_PROTOCOL_SMB, /* ABI: add before _COUNT */
+       SA_PROTOCOL_COUNT,
+};
+
+/* lower-case */
+_LIBSPL_LIBSHARE_H const char *const sa_protocol_names[SA_PROTOCOL_COUNT];
+
 /* share control */
 _LIBSPL_LIBSHARE_H int sa_enable_share(const char *, const char *, const char *,
-    const char *);
-_LIBSPL_LIBSHARE_H int sa_disable_share(const char *, const char *);
-_LIBSPL_LIBSHARE_H boolean_t sa_is_shared(const char *, const char *);
-_LIBSPL_LIBSHARE_H void sa_commit_shares(const char *);
+    enum sa_protocol);
+_LIBSPL_LIBSHARE_H int sa_disable_share(const char *, enum sa_protocol);
+_LIBSPL_LIBSHARE_H boolean_t sa_is_shared(const char *, enum sa_protocol);
+_LIBSPL_LIBSHARE_H void sa_commit_shares(enum sa_protocol);
 
 /* protocol specific interfaces */
-_LIBSPL_LIBSHARE_H int sa_validate_shareopts(const char *, const char *);
+_LIBSPL_LIBSHARE_H int sa_validate_shareopts(const char *, enum sa_protocol);
 
 #endif /* _LIBSPL_LIBSHARE_H */
index 5441864c5cf6caa6594799d8a60c58e68f699ccb..a70c7424b997a10682d6796e24fde038dec088b3 100644 (file)
@@ -345,7 +345,7 @@ changelist_rename(prop_changelist_t *clp, const char *src, const char *dst)
  * unshare all the datasets in the list.
  */
 int
-changelist_unshare(prop_changelist_t *clp, const zfs_share_proto_t *proto)
+changelist_unshare(prop_changelist_t *clp, const enum sa_protocol *proto)
 {
        prop_changenode_t *cn;
        uu_avl_walk_t *walk;
@@ -363,7 +363,8 @@ changelist_unshare(prop_changelist_t *clp, const zfs_share_proto_t *proto)
                        ret = -1;
        }
 
-       zfs_commit_proto(proto);
+       for (const enum sa_protocol *p = proto; *p != SA_NO_PROTOCOL; ++p)
+               sa_commit_shares(*p);
        uu_avl_walk_end(walk);
 
        return (ret);
index 3469d380652e6a2c992d2295c5dd37a50a89c1fc..e5c1bd62d5d1861b1e712aa32440fcff865ea722 100644 (file)
@@ -1418,14 +1418,15 @@ badlabel:
                            prop == ZFS_PROP_SHARESMB) &&
                            strcmp(strval, "on") != 0 &&
                            strcmp(strval, "off") != 0) {
-                               zfs_share_proto_t proto;
+                               enum sa_protocol proto;
 
                                if (prop == ZFS_PROP_SHARESMB)
-                                       proto = PROTO_SMB;
+                                       proto = SA_PROTOCOL_SMB;
                                else
-                                       proto = PROTO_NFS;
+                                       proto = SA_PROTOCOL_NFS;
 
-                               if (zfs_parse_options(strval, proto) != SA_OK) {
+                               if (sa_validate_shareopts(strval, proto) !=
+                                   SA_OK) {
                                        zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
                                            "'%s' cannot be set to invalid "
                                            "options"), propname);
index 4b18ad66854f125126e7f3ef4712b80548c2ea97..bf1a8359cef2800e39d0e7e0815b854281e267b6 100644 (file)
@@ -105,21 +105,14 @@ struct zpool_handle {
        diskaddr_t zpool_start_block;
 };
 
-typedef enum {
-       PROTO_NFS = 0,
-       PROTO_SMB = 1,
-       PROTO_END = 2
-} zfs_share_proto_t;
-
 /*
- * The following can be used as a bitmask and any new values
- * added must preserve that capability.
+ * Bitmask of shared types:
+ * 0 means none, otherwise | (1 << (enum sa_protocol + 1)).
  */
-typedef enum {
-       SHARED_NOT_SHARED = 0x0,
-       SHARED_NFS = 0x2,
-       SHARED_SMB = 0x4
-} zfs_share_type_t;
+typedef unsigned zfs_share_type_t;
+#define        SHARED_NOT_SHARED 0
+
+#define        SA_NO_PROTOCOL -1
 
 typedef int (*zfs_uri_handler_fn_t)(struct libzfs_handle *, const char *,
     const char *, zfs_keyformat_t, boolean_t, uint8_t **, size_t *);
@@ -189,7 +182,7 @@ extern void changelist_remove(prop_changelist_t *, const char *);
 extern void changelist_free(prop_changelist_t *);
 extern prop_changelist_t *changelist_gather(zfs_handle_t *, zfs_prop_t, int,
     int);
-extern int changelist_unshare(prop_changelist_t *, const zfs_share_proto_t *);
+extern int changelist_unshare(prop_changelist_t *, const enum sa_protocol *);
 extern int changelist_haszonedchild(prop_changelist_t *);
 
 extern void remove_mountpoint(zfs_handle_t *);
@@ -209,11 +202,8 @@ extern int zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type,
 
 extern void namespace_clear(libzfs_handle_t *);
 
-extern int zfs_parse_options(char *, zfs_share_proto_t);
-
 typedef struct {
        zfs_prop_t p_prop;
-       char *p_name;
        int p_share_err;
        int p_unshare_err;
 } proto_table_t;
@@ -244,20 +234,19 @@ extern int do_mount(zfs_handle_t *zhp, const char *mntpt, char *opts,
     int flags);
 extern int do_unmount(zfs_handle_t *zhp, const char *mntpt, int flags);
 extern int zfs_mount_delegation_check(void);
-extern int zfs_share_proto(zfs_handle_t *zhp, const zfs_share_proto_t *proto);
+extern int zfs_share_proto(zfs_handle_t *zhp, const enum sa_protocol *proto);
 extern int zfs_unshare_proto(zfs_handle_t *, const char *,
-    const zfs_share_proto_t *);
+    const enum sa_protocol *);
 extern int unshare_one(libzfs_handle_t *hdl, const char *name,
-    const char *mountpoint, zfs_share_proto_t proto);
+    const char *mountpoint, enum sa_protocol proto);
 extern boolean_t zfs_is_mountable(zfs_handle_t *zhp, char *buf, size_t buflen,
     zprop_source_t *source, int flags);
 extern zfs_share_type_t is_shared(const char *mountpoint,
-    zfs_share_proto_t proto);
+    enum sa_protocol proto);
 extern int libzfs_load_module(void);
 extern int zpool_relabel_disk(libzfs_handle_t *hdl, const char *path,
     const char *msg);
 extern int find_shares_object(differ_info_t *di);
-extern void zfs_commit_proto(const zfs_share_proto_t *);
 
 #ifdef __cplusplus
 }
index 59cfa22d34cc2e58b94d7fc868646de8dc17557e..ea7e97c2932f9c808a69acafe303403324b1c938 100644 (file)
@@ -96,30 +96,19 @@ static int mount_tp_nthr = 512;     /* tpool threads for multi-threaded mounting */
 
 static void zfs_mount_task(void *);
 static zfs_share_type_t zfs_is_shared_proto(zfs_handle_t *, char **,
-    zfs_share_proto_t);
+    enum sa_protocol);
 
-/*
- * The share protocols table must be in the same order as the zfs_share_proto_t
- * enum in libzfs_impl.h
- */
-static const proto_table_t proto_table[PROTO_END] = {
-       {ZFS_PROP_SHARENFS, "nfs", EZFS_SHARENFSFAILED, EZFS_UNSHARENFSFAILED},
-       {ZFS_PROP_SHARESMB, "smb", EZFS_SHARESMBFAILED, EZFS_UNSHARESMBFAILED},
+static const proto_table_t proto_table[SA_PROTOCOL_COUNT] = {
+       [SA_PROTOCOL_NFS] =
+           {ZFS_PROP_SHARENFS, EZFS_SHARENFSFAILED, EZFS_UNSHARENFSFAILED},
+       [SA_PROTOCOL_SMB] =
+           {ZFS_PROP_SHARESMB, EZFS_SHARESMBFAILED, EZFS_UNSHARESMBFAILED},
 };
 
-static const zfs_share_proto_t nfs_only[] = {
-       PROTO_NFS,
-       PROTO_END
-};
-
-static const zfs_share_proto_t smb_only[] = {
-       PROTO_SMB,
-       PROTO_END
-};
-static const zfs_share_proto_t share_all_proto[] = {
-       PROTO_NFS,
-       PROTO_SMB,
-       PROTO_END
+static const enum sa_protocol share_all_proto[SA_PROTOCOL_COUNT + 1] = {
+       SA_PROTOCOL_NFS,
+       SA_PROTOCOL_SMB,
+       SA_NO_PROTOCOL
 };
 
 
@@ -705,17 +694,14 @@ zfs_unmountall(zfs_handle_t *zhp, int flags)
 boolean_t
 zfs_is_shared(zfs_handle_t *zhp)
 {
-       zfs_share_type_t rc = 0;
-       const zfs_share_proto_t *curr_proto;
-
        if (ZFS_IS_VOLUME(zhp))
                return (B_FALSE);
 
-       for (curr_proto = share_all_proto; *curr_proto != PROTO_END;
-           curr_proto++)
-               rc |= zfs_is_shared_proto(zhp, NULL, *curr_proto);
+       for (enum sa_protocol i = 0; i < SA_PROTOCOL_COUNT; ++i)
+               if (zfs_is_shared_proto(zhp, NULL, i))
+                       return (B_TRUE);
 
-       return (rc ? B_TRUE : B_FALSE);
+       return (B_FALSE);
 }
 
 /*
@@ -723,16 +709,14 @@ zfs_is_shared(zfs_handle_t *zhp)
  */
 int
 unshare_one(libzfs_handle_t *hdl, const char *name, const char *mountpoint,
-    zfs_share_proto_t proto)
+    enum sa_protocol proto)
 {
-       int err;
-
-       err = sa_disable_share(mountpoint, proto_table[proto].p_name);
-       if (err != SA_OK) {
+       int err = sa_disable_share(mountpoint, proto);
+       if (err != SA_OK)
                return (zfs_error_fmt(hdl, proto_table[proto].p_unshare_err,
                    dgettext(TEXT_DOMAIN, "cannot unshare '%s': %s"),
                    name, sa_errorstr(err)));
-       }
+
        return (0);
 }
 
@@ -741,19 +725,12 @@ unshare_one(libzfs_handle_t *hdl, const char *name, const char *mountpoint,
  * a zfs_share_type_t value.
  */
 zfs_share_type_t
-is_shared(const char *mountpoint, zfs_share_proto_t proto)
+is_shared(const char *mountpoint, enum sa_protocol proto)
 {
-       if (sa_is_shared(mountpoint, proto_table[proto].p_name)) {
-               switch (proto) {
-               case PROTO_NFS:
-                       return (SHARED_NFS);
-               case PROTO_SMB:
-                       return (SHARED_SMB);
-               default:
-                       return (SHARED_NOT_SHARED);
-               }
-       }
-       return (SHARED_NOT_SHARED);
+       if (sa_is_shared(mountpoint, proto))
+               return (1 << (proto + 1));
+       else
+               return (SHARED_NOT_SHARED);
 }
 
 /*
@@ -762,19 +739,19 @@ is_shared(const char *mountpoint, zfs_share_proto_t proto)
  * on "libshare" to do the dirty work for us.
  */
 int
-zfs_share_proto(zfs_handle_t *zhp, const zfs_share_proto_t *proto)
+zfs_share_proto(zfs_handle_t *zhp, const enum sa_protocol *proto)
 {
        char mountpoint[ZFS_MAXPROPLEN];
        char shareopts[ZFS_MAXPROPLEN];
        char sourcestr[ZFS_MAXPROPLEN];
-       const zfs_share_proto_t *curr_proto;
+       const enum sa_protocol *curr_proto;
        zprop_source_t sourcetype;
        int err = 0;
 
        if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL, 0))
                return (0);
 
-       for (curr_proto = proto; *curr_proto != PROTO_END; curr_proto++) {
+       for (curr_proto = proto; *curr_proto != SA_NO_PROTOCOL; curr_proto++) {
                /*
                 * Return success if there are no share options.
                 */
@@ -794,7 +771,7 @@ zfs_share_proto(zfs_handle_t *zhp, const zfs_share_proto_t *proto)
                        continue;
 
                err = sa_enable_share(zfs_get_name(zhp), mountpoint, shareopts,
-                   proto_table[*curr_proto].p_name);
+                   *curr_proto);
                if (err != SA_OK) {
                        return (zfs_error_fmt(zhp->zfs_hdl,
                            proto_table[*curr_proto].p_share_err,
@@ -824,7 +801,7 @@ zfs_unshare(zfs_handle_t *zhp)
  * Check to see if the filesystem is currently shared.
  */
 static zfs_share_type_t
-zfs_is_shared_proto(zfs_handle_t *zhp, char **where, zfs_share_proto_t proto)
+zfs_is_shared_proto(zfs_handle_t *zhp, char **where, enum sa_protocol proto)
 {
        char *mountpoint;
        zfs_share_type_t rc;
@@ -849,74 +826,60 @@ boolean_t
 zfs_is_shared_nfs(zfs_handle_t *zhp, char **where)
 {
        return (zfs_is_shared_proto(zhp, where,
-           PROTO_NFS) != SHARED_NOT_SHARED);
+           SA_PROTOCOL_NFS) != SHARED_NOT_SHARED);
 }
 
 boolean_t
 zfs_is_shared_smb(zfs_handle_t *zhp, char **where)
 {
        return (zfs_is_shared_proto(zhp, where,
-           PROTO_SMB) != SHARED_NOT_SHARED);
-}
-
-/*
- * zfs_parse_options(options, proto)
- *
- * Call the legacy parse interface to get the protocol specific
- * options using the NULL arg to indicate that this is a "parse" only.
- */
-int
-zfs_parse_options(char *options, zfs_share_proto_t proto)
-{
-       return (sa_validate_shareopts(options, proto_table[proto].p_name));
-}
-
-void
-zfs_commit_proto(const zfs_share_proto_t *proto)
-{
-       const zfs_share_proto_t *curr_proto;
-       for (curr_proto = proto; *curr_proto != PROTO_END; curr_proto++)
-               sa_commit_shares(proto_table[*curr_proto].p_name);
+           SA_PROTOCOL_SMB) != SHARED_NOT_SHARED);
 }
 
 void
 zfs_commit_nfs_shares(void)
 {
-       zfs_commit_proto(nfs_only);
+       sa_commit_shares(SA_PROTOCOL_NFS);
 }
 
 void
 zfs_commit_smb_shares(void)
 {
-       zfs_commit_proto(smb_only);
+       sa_commit_shares(SA_PROTOCOL_SMB);
 }
 
 void
 zfs_commit_all_shares(void)
 {
-       zfs_commit_proto(share_all_proto);
+       for (enum sa_protocol i = 0; i < SA_PROTOCOL_COUNT; ++i)
+               sa_commit_shares(i);
 }
 
 void
 zfs_commit_shares(const char *proto)
 {
        if (proto == NULL)
-               zfs_commit_proto(share_all_proto);
-       else if (strcmp(proto, "nfs") == 0)
-               zfs_commit_proto(nfs_only);
-       else if (strcmp(proto, "smb") == 0)
-               zfs_commit_proto(smb_only);
+               zfs_commit_all_shares();
+       else
+               for (enum sa_protocol i = 0; i < ARRAY_SIZE(sa_protocol_names);
+                   ++i)
+                       if (strcmp(proto, sa_protocol_names[i]) == 0) {
+                               sa_commit_shares(i);
+                               return;
+                       }
 }
 
 int
 zfs_share_nfs(zfs_handle_t *zhp)
 {
+       const enum sa_protocol nfs_only[] = {SA_PROTOCOL_NFS, SA_NO_PROTOCOL};
        return (zfs_share_proto(zhp, nfs_only));
 }
 
 int
 zfs_share_smb(zfs_handle_t *zhp)
 {
+       const enum sa_protocol smb_only[] = {SA_PROTOCOL_SMB, SA_NO_PROTOCOL};
        return (zfs_share_proto(zhp, smb_only));
 }
 
@@ -931,7 +894,7 @@ zfs_shareall(zfs_handle_t *zhp)
  */
 int
 zfs_unshare_proto(zfs_handle_t *zhp, const char *mountpoint,
-    const zfs_share_proto_t *proto)
+    const enum sa_protocol *proto)
 {
        libzfs_handle_t *hdl = zhp->zfs_hdl;
        struct mnttab entry;
@@ -943,12 +906,12 @@ zfs_unshare_proto(zfs_handle_t *zhp, const char *mountpoint,
 
        if (mountpoint != NULL || ((zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) &&
            libzfs_mnttab_find(hdl, zfs_get_name(zhp), &entry) == 0)) {
-               const zfs_share_proto_t *curr_proto;
+               const enum sa_protocol *curr_proto;
 
                if (mountpoint == NULL)
                        mntpt = zfs_strdup(zhp->zfs_hdl, entry.mnt_mountp);
 
-               for (curr_proto = proto; *curr_proto != PROTO_END;
+               for (curr_proto = proto; *curr_proto != SA_NO_PROTOCOL;
                    curr_proto++) {
 
                        if (is_shared(mntpt, *curr_proto)) {
@@ -970,12 +933,14 @@ zfs_unshare_proto(zfs_handle_t *zhp, const char *mountpoint,
 int
 zfs_unshare_nfs(zfs_handle_t *zhp, const char *mountpoint)
 {
+       const enum sa_protocol nfs_only[] = {SA_PROTOCOL_NFS, SA_NO_PROTOCOL};
        return (zfs_unshare_proto(zhp, mountpoint, nfs_only));
 }
 
 int
 zfs_unshare_smb(zfs_handle_t *zhp, const char *mountpoint)
 {
+       const enum sa_protocol smb_only[] = {SA_PROTOCOL_SMB, SA_NO_PROTOCOL};
        return (zfs_unshare_proto(zhp, mountpoint, smb_only));
 }
 
@@ -983,7 +948,7 @@ zfs_unshare_smb(zfs_handle_t *zhp, const char *mountpoint)
  * Same as zfs_unmountall(), but for NFS and SMB unshares.
  */
 static int
-zfs_unshareall_proto(zfs_handle_t *zhp, const zfs_share_proto_t *proto)
+zfs_unshareall_proto(zfs_handle_t *zhp, const enum sa_protocol *proto)
 {
        prop_changelist_t *clp;
        int ret;
@@ -1001,12 +966,14 @@ zfs_unshareall_proto(zfs_handle_t *zhp, const zfs_share_proto_t *proto)
 int
 zfs_unshareall_nfs(zfs_handle_t *zhp)
 {
+       const enum sa_protocol nfs_only[] = {SA_PROTOCOL_NFS, SA_NO_PROTOCOL};
        return (zfs_unshareall_proto(zhp, nfs_only));
 }
 
 int
 zfs_unshareall_smb(zfs_handle_t *zhp)
 {
+       const enum sa_protocol smb_only[] = {SA_PROTOCOL_SMB, SA_NO_PROTOCOL};
        return (zfs_unshareall_proto(zhp, smb_only));
 }
 
@@ -1028,12 +995,14 @@ zfs_unshareall_bytype(zfs_handle_t *zhp, const char *mountpoint,
 {
        if (proto == NULL)
                return (zfs_unshare_proto(zhp, mountpoint, share_all_proto));
-       if (strcmp(proto, "nfs") == 0)
-               return (zfs_unshare_proto(zhp, mountpoint, nfs_only));
-       else if (strcmp(proto, "smb") == 0)
-               return (zfs_unshare_proto(zhp, mountpoint, smb_only));
-       else
-               return (1);
+
+       for (enum sa_protocol i = 0; i < ARRAY_SIZE(sa_protocol_names); ++i)
+               if (strcmp(proto, sa_protocol_names[i]) == 0) {
+                       enum sa_protocol protocols[] = {i, SA_NO_PROTOCOL};
+                       return (zfs_unshare_proto(zhp, mountpoint, protocols));
+               }
+
+       return (1);
 }
 
 /*
@@ -1608,12 +1577,10 @@ zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force)
         * Walk through and first unshare everything.
         */
        for (i = 0; i < used; i++) {
-               const zfs_share_proto_t *curr_proto;
-               for (curr_proto = share_all_proto; *curr_proto != PROTO_END;
-                   curr_proto++) {
-                       if (is_shared(sets[i].mountpoint, *curr_proto) &&
+               for (enum sa_protocol i = 0; i < SA_PROTOCOL_COUNT; ++i) {
+                       if (is_shared(sets[i].mountpoint, i) &&
                            unshare_one(hdl, sets[i].mountpoint,
-                           sets[i].mountpoint, *curr_proto) != 0)
+                           sets[i].mountpoint, i) != 0)
                                goto out;
                }
        }