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  * Copyright (c) 2018, 2019 by Delphix. All rights reserved.
23  */
24 
25 #include <sys/types.h>
26 #include <sys/param.h>
27 #include <sys/zfeature.h>
28 #include <sys/zfs_ioctl.h>
29 #include <sys/zfs_sysfs.h>
30 #include <sys/kmem.h>
31 #include <sys/fs/zfs.h>
32 #include <linux/kobject.h>
33 
34 #include "zfs_prop.h"
35 
36 #if !defined(_KERNEL)
37 #error kernel builds only
38 #endif
39 
40 /*
41  * ZFS Module sysfs support
42  *
43  * This extends our sysfs '/sys/module/zfs' entry to include feature
44  * and property attributes. The primary consumer of this information
45  * is user processes, like the zfs CLI, that need to know what the
46  * current loaded ZFS module supports. The libzfs binary will consult
47  * this information when instantiating the zfs|zpool property tables
48  * and the pool features table.
49  *
50  * The added top-level directories are:
51  * /sys/module/zfs
52  *		├── features.kernel
53  *		├── features.pool
54  *		├── properties.dataset
55  *		└── properties.pool
56  *
57  * The local interface for the zfs kobjects includes:
58  *	zfs_kobj_init()
59  *	zfs_kobj_add()
60  *	zfs_kobj_release()
61  *	zfs_kobj_add_attr()
62  *	zfs_kobj_fini()
63  */
64 
65 /*
66  * A zfs_mod_kobj_t represents a zfs kobject under '/sys/module/zfs'
67  */
68 struct zfs_mod_kobj;
69 typedef struct zfs_mod_kobj zfs_mod_kobj_t;
70 
71 struct zfs_mod_kobj {
72 	struct kobject		zko_kobj;
73 	struct kobj_type	zko_kobj_type;
74 	struct sysfs_ops	zko_sysfs_ops;
75 	size_t			zko_attr_count;
76 	struct attribute	*zko_attr_list;		/* allocated */
77 	struct attribute	**zko_default_attrs;	/* allocated */
78 	size_t			zko_child_count;
79 	zfs_mod_kobj_t		*zko_children;		/* allocated */
80 };
81 
82 #define	ATTR_TABLE_SIZE(cnt)	(sizeof (struct attribute) * (cnt))
83 /* Note +1 for NULL terminator slot */
84 #define	DEFAULT_ATTR_SIZE(cnt)	(sizeof (struct attribute *) * (cnt + 1))
85 #define	CHILD_TABLE_SIZE(cnt)	(sizeof (zfs_mod_kobj_t) * (cnt))
86 
87 /*
88  * These are the top-level kobjects under '/sys/module/zfs/'
89  */
90 static zfs_mod_kobj_t kernel_features_kobj;
91 static zfs_mod_kobj_t pool_features_kobj;
92 static zfs_mod_kobj_t dataset_props_kobj;
93 static zfs_mod_kobj_t vdev_props_kobj;
94 static zfs_mod_kobj_t pool_props_kobj;
95 
96 /*
97  * The show function is used to provide the content
98  * of an attribute into a PAGE_SIZE buffer.
99  */
100 typedef ssize_t	(*sysfs_show_func)(struct kobject *, struct attribute *,
101     char *);
102 
103 static void
104 zfs_kobj_fini(zfs_mod_kobj_t *zkobj)
105 {
106 	/* finalize any child kobjects */
107 	if (zkobj->zko_child_count != 0) {
108 		ASSERT(zkobj->zko_children);
109 		for (int i = 0; i < zkobj->zko_child_count; i++)
110 			zfs_kobj_fini(&zkobj->zko_children[i]);
111 	}
112 
113 	/* kobject_put() will call zfs_kobj_release() to release memory */
114 	kobject_del(&zkobj->zko_kobj);
115 	kobject_put(&zkobj->zko_kobj);
116 }
117 
118 static void
119 zfs_kobj_release(struct kobject *kobj)
120 {
121 	zfs_mod_kobj_t *zkobj = container_of(kobj, zfs_mod_kobj_t, zko_kobj);
122 
123 	if (zkobj->zko_attr_list != NULL) {
124 		ASSERT3S(zkobj->zko_attr_count, !=, 0);
125 		kmem_free(zkobj->zko_attr_list,
126 		    ATTR_TABLE_SIZE(zkobj->zko_attr_count));
127 		zkobj->zko_attr_list = NULL;
128 	}
129 
130 	if (zkobj->zko_default_attrs != NULL) {
131 		kmem_free(zkobj->zko_default_attrs,
132 		    DEFAULT_ATTR_SIZE(zkobj->zko_attr_count));
133 		zkobj->zko_default_attrs = NULL;
134 	}
135 
136 	if (zkobj->zko_child_count != 0) {
137 		ASSERT(zkobj->zko_children);
138 
139 		kmem_free(zkobj->zko_children,
140 		    CHILD_TABLE_SIZE(zkobj->zko_child_count));
141 		zkobj->zko_child_count = 0;
142 		zkobj->zko_children = NULL;
143 	}
144 
145 	zkobj->zko_attr_count = 0;
146 }
147 
148 #ifndef sysfs_attr_init
149 #define	sysfs_attr_init(attr) do {} while (0)
150 #endif
151 
152 static void
153 zfs_kobj_add_attr(zfs_mod_kobj_t *zkobj, int attr_num, const char *attr_name)
154 {
155 	VERIFY3U(attr_num, <, zkobj->zko_attr_count);
156 	ASSERT(zkobj->zko_attr_list);
157 	ASSERT(zkobj->zko_default_attrs);
158 
159 	zkobj->zko_attr_list[attr_num].name = attr_name;
160 	zkobj->zko_attr_list[attr_num].mode = 0444;
161 	zkobj->zko_default_attrs[attr_num] = &zkobj->zko_attr_list[attr_num];
162 	sysfs_attr_init(&zkobj->zko_attr_list[attr_num]);
163 }
164 
165 static int
166 zfs_kobj_init(zfs_mod_kobj_t *zkobj, int attr_cnt, int child_cnt,
167     sysfs_show_func show_func)
168 {
169 	/*
170 	 * Initialize object's attributes. Count can be zero.
171 	 */
172 	if (attr_cnt > 0) {
173 		zkobj->zko_attr_list = kmem_zalloc(ATTR_TABLE_SIZE(attr_cnt),
174 		    KM_SLEEP);
175 		if (zkobj->zko_attr_list == NULL)
176 			return (ENOMEM);
177 	}
178 	/* this will always have at least one slot for NULL termination */
179 	zkobj->zko_default_attrs = kmem_zalloc(DEFAULT_ATTR_SIZE(attr_cnt),
180 	    KM_SLEEP);
181 	if (zkobj->zko_default_attrs == NULL) {
182 		if (zkobj->zko_attr_list != NULL) {
183 			kmem_free(zkobj->zko_attr_list,
184 			    ATTR_TABLE_SIZE(attr_cnt));
185 		}
186 		return (ENOMEM);
187 	}
188 	zkobj->zko_attr_count = attr_cnt;
189 	zkobj->zko_kobj_type.default_attrs = zkobj->zko_default_attrs;
190 
191 	if (child_cnt > 0) {
192 		zkobj->zko_children = kmem_zalloc(CHILD_TABLE_SIZE(child_cnt),
193 		    KM_SLEEP);
194 		if (zkobj->zko_children == NULL) {
195 			if (zkobj->zko_default_attrs != NULL) {
196 				kmem_free(zkobj->zko_default_attrs,
197 				    DEFAULT_ATTR_SIZE(attr_cnt));
198 			}
199 			if (zkobj->zko_attr_list != NULL) {
200 				kmem_free(zkobj->zko_attr_list,
201 				    ATTR_TABLE_SIZE(attr_cnt));
202 			}
203 			return (ENOMEM);
204 		}
205 		zkobj->zko_child_count = child_cnt;
206 	}
207 
208 	zkobj->zko_sysfs_ops.show = show_func;
209 	zkobj->zko_kobj_type.sysfs_ops = &zkobj->zko_sysfs_ops;
210 	zkobj->zko_kobj_type.release = zfs_kobj_release;
211 
212 	return (0);
213 }
214 
215 static int
216 zfs_kobj_add(zfs_mod_kobj_t *zkobj, struct kobject *parent, const char *name)
217 {
218 	/* zko_default_attrs must be NULL terminated */
219 	ASSERT(zkobj->zko_default_attrs != NULL);
220 	ASSERT(zkobj->zko_default_attrs[zkobj->zko_attr_count] == NULL);
221 
222 	kobject_init(&zkobj->zko_kobj, &zkobj->zko_kobj_type);
223 	return (kobject_add(&zkobj->zko_kobj, parent, name));
224 }
225 
226 /*
227  * Each zfs property has these common attributes
228  */
229 static const char *zprop_attrs[]  = {
230 	"type",
231 	"readonly",
232 	"setonce",
233 	"visible",
234 	"values",
235 	"default",
236 	"datasets"	/* zfs properties only */
237 };
238 
239 #define	ZFS_PROP_ATTR_COUNT	ARRAY_SIZE(zprop_attrs)
240 #define	ZPOOL_PROP_ATTR_COUNT	(ZFS_PROP_ATTR_COUNT - 1)
241 
242 static const char *zprop_types[]  = {
243 	"number",
244 	"string",
245 	"index",
246 };
247 
248 typedef struct zfs_type_map {
249 	zfs_type_t	ztm_type;
250 	const char	*ztm_name;
251 } zfs_type_map_t;
252 
253 static zfs_type_map_t type_map[] = {
254 	{ZFS_TYPE_FILESYSTEM,	"filesystem"},
255 	{ZFS_TYPE_SNAPSHOT,	"snapshot"},
256 	{ZFS_TYPE_VOLUME,	"volume"},
257 	{ZFS_TYPE_BOOKMARK,	"bookmark"}
258 };
259 
260 /*
261  * Show the content for a zfs property attribute
262  */
263 static ssize_t
264 zprop_sysfs_show(const char *attr_name, const zprop_desc_t *property,
265     char *buf, size_t buflen)
266 {
267 	const char *show_str;
268 	char number[32];
269 
270 	/* For dataset properties list the dataset types that apply */
271 	if (strcmp(attr_name, "datasets") == 0 &&
272 	    property->pd_types != ZFS_TYPE_POOL) {
273 		int len = 0;
274 
275 		for (int i = 0; i < ARRAY_SIZE(type_map); i++) {
276 			if (type_map[i].ztm_type & property->pd_types)  {
277 				len += snprintf(buf + len, buflen - len, "%s ",
278 				    type_map[i].ztm_name);
279 			}
280 		}
281 		len += snprintf(buf + len, buflen - len, "\n");
282 		return (len);
283 	}
284 
285 	if (strcmp(attr_name, "type") == 0) {
286 		show_str = zprop_types[property->pd_proptype];
287 	} else if (strcmp(attr_name, "readonly") == 0) {
288 		show_str = property->pd_attr == PROP_READONLY ? "1" : "0";
289 	} else if (strcmp(attr_name, "setonce") == 0) {
290 		show_str = property->pd_attr == PROP_ONETIME ? "1" : "0";
291 	} else if (strcmp(attr_name, "visible") == 0) {
292 		show_str = property->pd_visible ? "1" : "0";
293 	} else if (strcmp(attr_name, "values") == 0) {
294 		show_str = property->pd_values ? property->pd_values : "";
295 	} else if (strcmp(attr_name, "default") == 0) {
296 		switch (property->pd_proptype) {
297 		case PROP_TYPE_NUMBER:
298 			(void) snprintf(number, sizeof (number), "%llu",
299 			    (u_longlong_t)property->pd_numdefault);
300 			show_str = number;
301 			break;
302 		case PROP_TYPE_STRING:
303 			show_str = property->pd_strdefault ?
304 			    property->pd_strdefault : "";
305 			break;
306 		case PROP_TYPE_INDEX:
307 			if (zprop_index_to_string(property->pd_propnum,
308 			    property->pd_numdefault, &show_str,
309 			    property->pd_types) != 0) {
310 				show_str = "";
311 			}
312 			break;
313 		default:
314 			return (0);
315 		}
316 	} else {
317 		return (0);
318 	}
319 
320 	return (snprintf(buf, buflen, "%s\n", show_str));
321 }
322 
323 static ssize_t
324 dataset_property_show(struct kobject *kobj, struct attribute *attr, char *buf)
325 {
326 	zfs_prop_t prop = zfs_name_to_prop(kobject_name(kobj));
327 	zprop_desc_t *prop_tbl = zfs_prop_get_table();
328 	ssize_t len;
329 
330 	ASSERT3U(prop, <, ZFS_NUM_PROPS);
331 
332 	len = zprop_sysfs_show(attr->name, &prop_tbl[prop], buf, PAGE_SIZE);
333 
334 	return (len);
335 }
336 
337 static ssize_t
338 vdev_property_show(struct kobject *kobj, struct attribute *attr, char *buf)
339 {
340 	vdev_prop_t prop = vdev_name_to_prop(kobject_name(kobj));
341 	zprop_desc_t *prop_tbl = vdev_prop_get_table();
342 	ssize_t len;
343 
344 	ASSERT3U(prop, <, VDEV_NUM_PROPS);
345 
346 	len = zprop_sysfs_show(attr->name, &prop_tbl[prop], buf, PAGE_SIZE);
347 
348 	return (len);
349 }
350 
351 static ssize_t
352 pool_property_show(struct kobject *kobj, struct attribute *attr, char *buf)
353 {
354 	zpool_prop_t prop = zpool_name_to_prop(kobject_name(kobj));
355 	zprop_desc_t *prop_tbl = zpool_prop_get_table();
356 	ssize_t len;
357 
358 	ASSERT3U(prop, <, ZPOOL_NUM_PROPS);
359 
360 	len = zprop_sysfs_show(attr->name, &prop_tbl[prop], buf, PAGE_SIZE);
361 
362 	return (len);
363 }
364 
365 /*
366  * ZFS kernel feature attributes for '/sys/module/zfs/features.kernel'
367  *
368  * This list is intended for kernel features that don't have a pool feature
369  * association or that extend existing user kernel interfaces.
370  *
371  * A user process can easily check if the running zfs kernel module
372  * supports the new feature.
373  */
374 static const char *zfs_kernel_features[] = {
375 	/* --> Add new kernel features here */
376 	"com.delphix:vdev_initialize",
377 	"org.zfsonlinux:vdev_trim",
378 	"org.openzfs:l2arc_persistent",
379 };
380 
381 #define	KERNEL_FEATURE_COUNT	ARRAY_SIZE(zfs_kernel_features)
382 
383 static ssize_t
384 kernel_feature_show(struct kobject *kobj, struct attribute *attr, char *buf)
385 {
386 	if (strcmp(attr->name, "supported") == 0)
387 		return (snprintf(buf, PAGE_SIZE, "yes\n"));
388 	return (0);
389 }
390 
391 static void
392 kernel_feature_to_kobj(zfs_mod_kobj_t *parent, int slot, const char *name)
393 {
394 	zfs_mod_kobj_t *zfs_kobj = &parent->zko_children[slot];
395 
396 	ASSERT3U(slot, <, KERNEL_FEATURE_COUNT);
397 	ASSERT(name);
398 
399 	int err = zfs_kobj_init(zfs_kobj, 1, 0, kernel_feature_show);
400 	if (err)
401 		return;
402 
403 	zfs_kobj_add_attr(zfs_kobj, 0, "supported");
404 
405 	err = zfs_kobj_add(zfs_kobj, &parent->zko_kobj, name);
406 	if (err)
407 		zfs_kobj_release(&zfs_kobj->zko_kobj);
408 }
409 
410 static int
411 zfs_kernel_features_init(zfs_mod_kobj_t *zfs_kobj, struct kobject *parent)
412 {
413 	/*
414 	 * Create a parent kobject to host kernel features.
415 	 *
416 	 * '/sys/module/zfs/features.kernel'
417 	 */
418 	int err = zfs_kobj_init(zfs_kobj, 0, KERNEL_FEATURE_COUNT,
419 	    kernel_feature_show);
420 	if (err)
421 		return (err);
422 	err = zfs_kobj_add(zfs_kobj, parent, ZFS_SYSFS_KERNEL_FEATURES);
423 	if (err) {
424 		zfs_kobj_release(&zfs_kobj->zko_kobj);
425 		return (err);
426 	}
427 
428 	/*
429 	 * Now create a kobject for each feature.
430 	 *
431 	 * '/sys/module/zfs/features.kernel/<feature>'
432 	 */
433 	for (int f = 0; f < KERNEL_FEATURE_COUNT; f++)
434 		kernel_feature_to_kobj(zfs_kobj, f, zfs_kernel_features[f]);
435 
436 	return (0);
437 }
438 
439 /*
440  * Each pool feature has these common attributes
441  */
442 static const char *pool_feature_attrs[]  = {
443 	"description",
444 	"guid",
445 	"uname",
446 	"readonly_compatible",
447 	"required_for_mos",
448 	"activate_on_enable",
449 	"per_dataset"
450 };
451 
452 #define	ZPOOL_FEATURE_ATTR_COUNT	ARRAY_SIZE(pool_feature_attrs)
453 
454 /*
455  * Show the content for the given zfs pool feature attribute
456  */
457 static ssize_t
458 pool_feature_show(struct kobject *kobj, struct attribute *attr, char *buf)
459 {
460 	spa_feature_t fid;
461 
462 	if (zfeature_lookup_guid(kobject_name(kobj), &fid) != 0)
463 		return (0);
464 
465 	ASSERT3U(fid, <, SPA_FEATURES);
466 
467 	zfeature_flags_t flags = spa_feature_table[fid].fi_flags;
468 	const char *show_str = NULL;
469 
470 	if (strcmp(attr->name, "description") == 0) {
471 		show_str = spa_feature_table[fid].fi_desc;
472 	} else if (strcmp(attr->name, "guid") == 0) {
473 		show_str = spa_feature_table[fid].fi_guid;
474 	} else if (strcmp(attr->name, "uname") == 0) {
475 		show_str = spa_feature_table[fid].fi_uname;
476 	} else if (strcmp(attr->name, "readonly_compatible") == 0) {
477 		show_str = flags & ZFEATURE_FLAG_READONLY_COMPAT ? "1" : "0";
478 	} else if (strcmp(attr->name, "required_for_mos") == 0) {
479 		show_str = flags & ZFEATURE_FLAG_MOS ? "1" : "0";
480 	} else if (strcmp(attr->name, "activate_on_enable") == 0) {
481 		show_str = flags & ZFEATURE_FLAG_ACTIVATE_ON_ENABLE ? "1" : "0";
482 	} else if (strcmp(attr->name, "per_dataset") == 0) {
483 		show_str = flags & ZFEATURE_FLAG_PER_DATASET ? "1" : "0";
484 	}
485 	if (show_str == NULL)
486 		return (0);
487 
488 	return (snprintf(buf, PAGE_SIZE, "%s\n", show_str));
489 }
490 
491 static void
492 pool_feature_to_kobj(zfs_mod_kobj_t *parent, spa_feature_t fid,
493     const char *name)
494 {
495 	zfs_mod_kobj_t *zfs_kobj = &parent->zko_children[fid];
496 
497 	ASSERT3U(fid, <, SPA_FEATURES);
498 	ASSERT(name);
499 
500 	int err = zfs_kobj_init(zfs_kobj, ZPOOL_FEATURE_ATTR_COUNT, 0,
501 	    pool_feature_show);
502 	if (err)
503 		return;
504 
505 	for (int i = 0; i < ZPOOL_FEATURE_ATTR_COUNT; i++)
506 		zfs_kobj_add_attr(zfs_kobj, i, pool_feature_attrs[i]);
507 
508 	err = zfs_kobj_add(zfs_kobj, &parent->zko_kobj, name);
509 	if (err)
510 		zfs_kobj_release(&zfs_kobj->zko_kobj);
511 }
512 
513 static int
514 zfs_pool_features_init(zfs_mod_kobj_t *zfs_kobj, struct kobject *parent)
515 {
516 	/*
517 	 * Create a parent kobject to host pool features.
518 	 *
519 	 * '/sys/module/zfs/features.pool'
520 	 */
521 	int err = zfs_kobj_init(zfs_kobj, 0, SPA_FEATURES, pool_feature_show);
522 	if (err)
523 		return (err);
524 	err = zfs_kobj_add(zfs_kobj, parent, ZFS_SYSFS_POOL_FEATURES);
525 	if (err) {
526 		zfs_kobj_release(&zfs_kobj->zko_kobj);
527 		return (err);
528 	}
529 
530 	/*
531 	 * Now create a kobject for each feature.
532 	 *
533 	 * '/sys/module/zfs/features.pool/<feature>'
534 	 */
535 	for (spa_feature_t i = 0; i < SPA_FEATURES; i++)
536 		pool_feature_to_kobj(zfs_kobj, i, spa_feature_table[i].fi_guid);
537 
538 	return (0);
539 }
540 
541 typedef struct prop_to_kobj_arg {
542 	zprop_desc_t	*p2k_table;
543 	zfs_mod_kobj_t	*p2k_parent;
544 	sysfs_show_func	p2k_show_func;
545 	int		p2k_attr_count;
546 } prop_to_kobj_arg_t;
547 
548 static int
549 zprop_to_kobj(int prop, void *args)
550 {
551 	prop_to_kobj_arg_t *data = args;
552 	zfs_mod_kobj_t *parent = data->p2k_parent;
553 	zfs_mod_kobj_t *zfs_kobj = &parent->zko_children[prop];
554 	const char *name = data->p2k_table[prop].pd_name;
555 	int err;
556 
557 	ASSERT(name);
558 
559 	err = zfs_kobj_init(zfs_kobj, data->p2k_attr_count, 0,
560 	    data->p2k_show_func);
561 	if (err)
562 		return (ZPROP_CONT);
563 
564 	for (int i = 0; i < data->p2k_attr_count; i++)
565 		zfs_kobj_add_attr(zfs_kobj, i, zprop_attrs[i]);
566 
567 	err = zfs_kobj_add(zfs_kobj, &parent->zko_kobj, name);
568 	if (err)
569 		zfs_kobj_release(&zfs_kobj->zko_kobj);
570 
571 	return (ZPROP_CONT);
572 }
573 
574 static int
575 zfs_sysfs_properties_init(zfs_mod_kobj_t *zfs_kobj, struct kobject *parent,
576     zfs_type_t type)
577 {
578 	prop_to_kobj_arg_t context;
579 	const char *name;
580 	int err;
581 
582 	/*
583 	 * Create a parent kobject to host properties.
584 	 *
585 	 * '/sys/module/zfs/properties.<type>'
586 	 */
587 	if (type == ZFS_TYPE_POOL) {
588 		name = ZFS_SYSFS_POOL_PROPERTIES;
589 		context.p2k_table = zpool_prop_get_table();
590 		context.p2k_attr_count = ZPOOL_PROP_ATTR_COUNT;
591 		context.p2k_parent = zfs_kobj;
592 		context.p2k_show_func = pool_property_show;
593 		err = zfs_kobj_init(zfs_kobj, 0, ZPOOL_NUM_PROPS,
594 		    pool_property_show);
595 	} else if (type == ZFS_TYPE_VDEV) {
596 		name = ZFS_SYSFS_VDEV_PROPERTIES;
597 		context.p2k_table = vdev_prop_get_table();
598 		context.p2k_attr_count = ZPOOL_PROP_ATTR_COUNT;
599 		context.p2k_parent = zfs_kobj;
600 		context.p2k_show_func = vdev_property_show;
601 		err = zfs_kobj_init(zfs_kobj, 0, VDEV_NUM_PROPS,
602 		    vdev_property_show);
603 	} else {
604 		name = ZFS_SYSFS_DATASET_PROPERTIES;
605 		context.p2k_table = zfs_prop_get_table();
606 		context.p2k_attr_count = ZFS_PROP_ATTR_COUNT;
607 		context.p2k_parent = zfs_kobj;
608 		context.p2k_show_func = dataset_property_show;
609 		err = zfs_kobj_init(zfs_kobj, 0, ZFS_NUM_PROPS,
610 		    dataset_property_show);
611 	}
612 
613 	if (err)
614 		return (err);
615 
616 	err = zfs_kobj_add(zfs_kobj, parent, name);
617 	if (err) {
618 		zfs_kobj_release(&zfs_kobj->zko_kobj);
619 		return (err);
620 	}
621 
622 	/*
623 	 * Create a kobject for each property.
624 	 *
625 	 * '/sys/module/zfs/properties.<type>/<property>'
626 	 */
627 	(void) zprop_iter_common(zprop_to_kobj, &context, B_TRUE,
628 	    B_FALSE, type);
629 
630 	return (err);
631 }
632 
633 void
634 zfs_sysfs_init(void)
635 {
636 	struct kobject *parent;
637 #if defined(CONFIG_ZFS) && !defined(CONFIG_ZFS_MODULE)
638 	parent = kobject_create_and_add("zfs", fs_kobj);
639 #else
640 	parent = &(((struct module *)(THIS_MODULE))->mkobj).kobj;
641 #endif
642 	int err;
643 
644 	if (parent == NULL)
645 		return;
646 
647 	err = zfs_kernel_features_init(&kernel_features_kobj, parent);
648 	if (err)
649 		return;
650 
651 	err = zfs_pool_features_init(&pool_features_kobj, parent);
652 	if (err) {
653 		zfs_kobj_fini(&kernel_features_kobj);
654 		return;
655 	}
656 
657 	err = zfs_sysfs_properties_init(&pool_props_kobj, parent,
658 	    ZFS_TYPE_POOL);
659 	if (err) {
660 		zfs_kobj_fini(&kernel_features_kobj);
661 		zfs_kobj_fini(&pool_features_kobj);
662 		return;
663 	}
664 
665 	err = zfs_sysfs_properties_init(&vdev_props_kobj, parent,
666 	    ZFS_TYPE_VDEV);
667 	if (err) {
668 		zfs_kobj_fini(&kernel_features_kobj);
669 		zfs_kobj_fini(&pool_features_kobj);
670 		zfs_kobj_fini(&pool_props_kobj);
671 		return;
672 	}
673 
674 	err = zfs_sysfs_properties_init(&dataset_props_kobj, parent,
675 	    ZFS_TYPE_FILESYSTEM);
676 	if (err) {
677 		zfs_kobj_fini(&kernel_features_kobj);
678 		zfs_kobj_fini(&pool_features_kobj);
679 		zfs_kobj_fini(&pool_props_kobj);
680 		zfs_kobj_fini(&vdev_props_kobj);
681 		return;
682 	}
683 }
684 
685 void
686 zfs_sysfs_fini(void)
687 {
688 	/*
689 	 * Remove top-level kobjects; each will remove any children kobjects
690 	 */
691 	zfs_kobj_fini(&kernel_features_kobj);
692 	zfs_kobj_fini(&pool_features_kobj);
693 	zfs_kobj_fini(&pool_props_kobj);
694 	zfs_kobj_fini(&vdev_props_kobj);
695 	zfs_kobj_fini(&dataset_props_kobj);
696 }
697