summaryrefslogtreecommitdiff
path: root/usr/src/lib/libshare/common/libshare_zfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libshare/common/libshare_zfs.c')
-rw-r--r--usr/src/lib/libshare/common/libshare_zfs.c124
1 files changed, 120 insertions, 4 deletions
diff --git a/usr/src/lib/libshare/common/libshare_zfs.c b/usr/src/lib/libshare/common/libshare_zfs.c
index 0a8f327edd..26bf9a8f9a 100644
--- a/usr/src/lib/libshare/common/libshare_zfs.c
+++ b/usr/src/lib/libshare/common/libshare_zfs.c
@@ -152,8 +152,8 @@ sa_zfs_is_shared(char *path)
* group. If the group doesn't exist, create it first, making sure it
* is marked as a ZFS group.
*
- * Not that all ZFS shares are in a subgroup of the top level group
- * "zfs".
+ * Note that all ZFS shares are in a subgroup of the top level group
+ * called "zfs".
*/
static sa_group_t
@@ -172,6 +172,8 @@ find_or_create_group(char *groupname, char *proto, int *err)
group = sa_get_group(groupname);
if (group == NULL) {
group = sa_create_group(groupname, &ret);
+
+ /* make sure this is flagged as a ZFS group */
if (group != NULL)
ret = sa_set_group_attr(group, "zfs", "true");
}
@@ -198,6 +200,64 @@ find_or_create_group(char *groupname, char *proto, int *err)
}
/*
+ * find_or_create_zfs_subgroup(groupname, optstring, *err)
+ *
+ * ZFS shares will be in a subgroup of the "zfs" master group. This
+ * function looks to see if the groupname exists and returns it if it
+ * does or else creates a new one with the specified name and returns
+ * that. The "zfs" group will exist before we get here, but we make
+ * sure just in case.
+ *
+ * err must be a valid pointer.
+ */
+
+static sa_group_t
+find_or_create_zfs_subgroup(char *groupname, char *optstring, int *err)
+{
+ sa_group_t group = NULL;
+ sa_group_t zfs;
+ char *name;
+ char *options;
+
+ /* start with the top-level "zfs" group */
+ zfs = sa_get_group("zfs");
+ *err = SA_OK;
+ if (zfs != NULL) {
+ for (group = sa_get_sub_group(zfs); group != NULL;
+ group = sa_get_next_group(group)) {
+ name = sa_get_group_attr(group, "name");
+ if (name != NULL && strcmp(name, groupname) == 0) {
+ /* have the group so break out of here */
+ sa_free_attr_string(name);
+ break;
+ }
+ if (name != NULL)
+ sa_free_attr_string(name);
+ }
+
+ if (group == NULL) {
+ /* need to create the sub-group since it doesn't exist */
+ group = _sa_create_zfs_group(zfs, groupname);
+ if (group != NULL) {
+ set_node_attr(group, "zfs", "true");
+ }
+ if (strcmp(optstring, "on") == 0)
+ optstring = "rw";
+ if (group != NULL) {
+ options = strdup(optstring);
+ if (options != NULL) {
+ *err = sa_parse_legacy_options(group, options, "nfs");
+ free(options);
+ } else {
+ *err = SA_NO_MEMORY;
+ }
+ }
+ }
+ }
+ return (group);
+}
+
+/*
* sa_get_zfs_shares(groupname)
*
* Walk the mnttab for all zfs mounts and determine which are
@@ -223,6 +283,7 @@ sa_get_zfs_shares(char *groupname)
zfs_source_t source;
char sourcestr[ZFS_MAXPROPLEN];
libzfs_handle_t *libhandle;
+ char *options;
/*
* if we can't access libzfs, don't bother doing anything.
@@ -269,10 +330,46 @@ sa_get_zfs_shares(char *groupname)
}
if (err == SA_OK) {
if (source & ZFS_SRC_INHERITED) {
- share = _sa_add_share(group, cur->mountp,
+ int doshopt = 0;
+ /*
+ * Need to find the "real" parent
+ * sub-group. It may not be mounted,
+ * but it was identified in the
+ * "sourcestr" variable. The real
+ * parent not mounted can occur if
+ * "canmount=off and sharenfs=on".
+ */
+ group = find_or_create_zfs_subgroup(sourcestr,
+ shareopts,
+ &doshopt);
+ if (group != NULL) {
+ share = _sa_add_share(group, cur->mountp,
SA_SHARE_TRANSIENT,
&err);
+ /*
+ * some options may only be on
+ * shares. If the opt string
+ * contains one of those, we
+ * put it just on the share.
+ */
+ if (share != NULL &&
+ doshopt == SA_PROP_SHARE_ONLY) {
+ options = strdup(shareopts);
+ if (options != NULL) {
+ err = sa_parse_legacy_options(share,
+ options, "nfs");
+ free(options);
+ }
+ }
+ } else {
+ err = SA_NO_MEMORY;
+ }
} else {
+ /*
+ * this is a sub-group that actually
+ * contains the sharenfs property as
+ * opposed to a share that inherited.
+ */
group = _sa_create_zfs_group(zfsgroup,
cur->resource);
set_node_attr(group, "zfs", "true");
@@ -280,7 +377,6 @@ sa_get_zfs_shares(char *groupname)
SA_SHARE_TRANSIENT,
&err);
if (err == SA_OK) {
- char *options;
if (strcmp(shareopts, "on") != 0) {
options = strdup(shareopts);
if (options != NULL) {
@@ -289,6 +385,26 @@ sa_get_zfs_shares(char *groupname)
"nfs");
free(options);
}
+ if (err == SA_PROP_SHARE_ONLY) {
+ /*
+ * Same as above, some
+ * properties may only be on
+ * shares, but due to the ZFS
+ * sub-groups being
+ * artificial, we sometimes
+ * get this and have to deal
+ * with it. We do it by
+ * attempting to put it on the
+ * share.
+ */
+ options = strdup(shareopts);
+ if (options != NULL)
+ err = sa_parse_legacy_options(
+ share,
+ options,
+ "nfs");
+ free(options);
+ }
/* unmark the share's changed state */
set_node_attr(share, "changed", NULL);
}