summaryrefslogtreecommitdiff
path: root/usr/src/lib/libshare
diff options
context:
space:
mode:
authordougm <none@none>2007-05-07 16:12:42 -0700
committerdougm <none@none>2007-05-07 16:12:42 -0700
commit6733190958bbcc0bd6d1d601e7ae0a6994dafb45 (patch)
tree10f31ce7e31ce61f8bdc6b0b454cf9865af6792e /usr/src/lib/libshare
parentafc7d54587eb70585fcc35b5f933cc1ed713d87a (diff)
downloadillumos-joyent-6733190958bbcc0bd6d1d601e7ae0a6994dafb45.tar.gz
6491973 sharemgr: zfs set sharenfs=on is slow with lots of zfs filesystems
Diffstat (limited to 'usr/src/lib/libshare')
-rw-r--r--usr/src/lib/libshare/common/libshare.h4
-rw-r--r--usr/src/lib/libshare/common/libshare_zfs.c7
-rw-r--r--usr/src/lib/libshare/common/libsharecore.c93
3 files changed, 101 insertions, 3 deletions
diff --git a/usr/src/lib/libshare/common/libshare.h b/usr/src/lib/libshare/common/libshare.h
index 81de25f910..754ef61c69 100644
--- a/usr/src/lib/libshare/common/libshare.h
+++ b/usr/src/lib/libshare/common/libshare.h
@@ -170,8 +170,8 @@ extern sa_optionset_t sa_get_derived_optionset(void *, char *, int);
extern void sa_free_derived_optionset(sa_optionset_t);
/* property functions */
-extern sa_optionset_t sa_get_property(sa_optionset_t, char *);
-extern sa_optionset_t sa_get_next_property(sa_group_t);
+extern sa_property_t sa_get_property(sa_optionset_t, char *);
+extern sa_property_t sa_get_next_property(sa_group_t);
extern char *sa_get_property_attr(sa_property_t, char *);
extern sa_property_t sa_create_property(char *, char *);
extern int sa_add_property(void *, sa_property_t);
diff --git a/usr/src/lib/libshare/common/libshare_zfs.c b/usr/src/lib/libshare/common/libshare_zfs.c
index ff4a0ff744..494a516a7f 100644
--- a/usr/src/lib/libshare/common/libshare_zfs.c
+++ b/usr/src/lib/libshare/common/libshare_zfs.c
@@ -204,6 +204,7 @@ get_zfs_dataset(sa_handle_impl_t impl_handle, char *path)
char *dataset = NULL;
zfs_handle_t **zlist;
char mountpoint[ZFS_MAXPROPLEN];
+ char canmount[ZFS_MAXPROPLEN];
get_all_filesystems(impl_handle, &zlist, &count);
qsort(zlist, count, sizeof (void *), mountpoint_compare);
@@ -221,7 +222,10 @@ get_zfs_dataset(sa_handle_impl_t impl_handle, char *path)
continue;
/* canmount must be set */
- if (!zfs_prop_get_int(zlist[i], ZFS_PROP_CANMOUNT))
+ canmount[0] = '\0';
+ if (!zfs_prop_get(zlist[i], ZFS_PROP_CANMOUNT, canmount,
+ sizeof (canmount), NULL, NULL, 0, B_FALSE) != 0 ||
+ strcmp(canmount, "off") == 0)
continue;
/*
@@ -651,6 +655,7 @@ sa_zfs_set_sharenfs(sa_group_t group, char *path, int on)
}
impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
+ assert(impl_handle != NULL);
if (impl_handle != NULL)
dataset = get_zfs_dataset(impl_handle, path);
else
diff --git a/usr/src/lib/libshare/common/libsharecore.c b/usr/src/lib/libshare/common/libsharecore.c
index 84a9c9f2ef..8c28d2b54b 100644
--- a/usr/src/lib/libshare/common/libsharecore.c
+++ b/usr/src/lib/libshare/common/libsharecore.c
@@ -760,6 +760,81 @@ _sa_remove_property(sa_property_t property)
}
/*
+ * _sa_create_dummy_share()
+ *
+ * Create a share entry suitable for parsing but not tied to any real
+ * config tree. Need to have a parent as well as the node to parse
+ * on. Free using _sa_free_dummy_share(share);
+ */
+
+static sa_group_t
+_sa_create_dummy_share()
+{
+ xmlNodePtr parent_node = NULL;
+ xmlNodePtr child_node = NULL;
+
+ parent_node = xmlNewNode(NULL, (xmlChar *)"group");
+ if (parent_node != NULL) {
+ child_node = xmlNewChild(parent_node, NULL, (xmlChar *)"share",
+ NULL);
+ if (child_node != NULL) {
+ /*
+ * Use a "zfs" tag since that will make sure nothing
+ * really attempts to put values into the
+ * repository. Also ZFS is currently the only user of
+ * this interface.
+ */
+ set_node_attr(parent_node, "type", "transient");
+ set_node_attr(parent_node, "zfs", "true");
+ set_node_attr(child_node, "type", "transient");
+ set_node_attr(child_node, "zfs", "true");
+ } else {
+ xmlFreeNode(parent_node);
+ }
+ }
+ return (child_node);
+}
+
+/*
+ * _sa_free_dummy_share(share)
+ *
+ * Free the dummy share and its parent. It is an error to try and
+ * free something that isn't a dummy.
+ */
+
+static int
+_sa_free_dummy_share(sa_share_t share)
+{
+ xmlNodePtr node = (xmlNodePtr)share;
+ xmlNodePtr parent;
+ int ret = SA_OK;
+ char *name;
+
+ if (node != NULL) {
+ parent = node->parent;
+ name = (char *)xmlGetProp(node, (xmlChar *)"path");
+ if (name != NULL) {
+ /* Real shares always have a path but a dummy doesn't */
+ ret = SA_NOT_ALLOWED;
+ sa_free_attr_string(name);
+ } else {
+ /*
+ * If there is a parent, do the free on that since
+ * xmlFreeNode is a recursive function and free's an
+ * child nodes.
+ */
+ if (parent != NULL) {
+ node = parent;
+ }
+ xmlUnlinkNode(node);
+ xmlFreeNode(node);
+ }
+ }
+ return (ret);
+}
+
+
+/*
* sa_parse_legacy_options(group, options, proto)
*
* In order to support legacy configurations, we allow the protocol
@@ -778,10 +853,28 @@ sa_parse_legacy_options(sa_group_t group, char *options, char *proto)
{
int ret = SA_INVALID_PROTOCOL;
sa_group_t parent;
+ int using_dummy = B_FALSE;
+
+ /*
+ * if "group" is NULL, this is just a parse without saving
+ * anything in either SMF or ZFS. Create a dummy group to
+ * handle this case.
+ */
+ if (group == NULL) {
+ group = (sa_group_t)_sa_create_dummy_share();
+ using_dummy = B_TRUE;
+ }
+
parent = sa_get_parent_group(group);
if (proto != NULL)
ret = sa_proto_legacy_opts(proto, group, options);
+
+ if (using_dummy) {
+ /* Since this is a dummy parse, cleanup and quit here */
+ (void) _sa_free_dummy_share(group);
+ return (ret);
+ }
/*
* if in a group, remove the inherited options and security
*/