.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));
}
/*
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));
-}
#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;
} *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 */
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,
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,
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,
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,
/* 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 */
* 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;
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);
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);
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 *);
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 *);
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;
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
}
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
};
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);
}
/*
*/
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);
}
* 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);
}
/*
* 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.
*/
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,
* 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;
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));
}
*/
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;
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)) {
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));
}
* 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;
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));
}
{
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);
}
/*
* 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;
}
}