xref: /freebsd/sys/contrib/openzfs/module/zcommon/zprop_common.c (revision eda14cbc264d6969b02f2b1994cef11148e914f1)
1*eda14cbcSMatt Macy /*
2*eda14cbcSMatt Macy  * CDDL HEADER START
3*eda14cbcSMatt Macy  *
4*eda14cbcSMatt Macy  * The contents of this file are subject to the terms of the
5*eda14cbcSMatt Macy  * Common Development and Distribution License (the "License").
6*eda14cbcSMatt Macy  * You may not use this file except in compliance with the License.
7*eda14cbcSMatt Macy  *
8*eda14cbcSMatt Macy  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*eda14cbcSMatt Macy  * or http://www.opensolaris.org/os/licensing.
10*eda14cbcSMatt Macy  * See the License for the specific language governing permissions
11*eda14cbcSMatt Macy  * and limitations under the License.
12*eda14cbcSMatt Macy  *
13*eda14cbcSMatt Macy  * When distributing Covered Code, include this CDDL HEADER in each
14*eda14cbcSMatt Macy  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*eda14cbcSMatt Macy  * If applicable, add the following below this CDDL HEADER, with the
16*eda14cbcSMatt Macy  * fields enclosed by brackets "[]" replaced with your own identifying
17*eda14cbcSMatt Macy  * information: Portions Copyright [yyyy] [name of copyright owner]
18*eda14cbcSMatt Macy  *
19*eda14cbcSMatt Macy  * CDDL HEADER END
20*eda14cbcSMatt Macy  */
21*eda14cbcSMatt Macy /*
22*eda14cbcSMatt Macy  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23*eda14cbcSMatt Macy  * Use is subject to license terms.
24*eda14cbcSMatt Macy  */
25*eda14cbcSMatt Macy /*
26*eda14cbcSMatt Macy  * Copyright (c) 2012 by Delphix. All rights reserved.
27*eda14cbcSMatt Macy  */
28*eda14cbcSMatt Macy 
29*eda14cbcSMatt Macy /*
30*eda14cbcSMatt Macy  * Common routines used by zfs and zpool property management.
31*eda14cbcSMatt Macy  */
32*eda14cbcSMatt Macy 
33*eda14cbcSMatt Macy #include <sys/zio.h>
34*eda14cbcSMatt Macy #include <sys/spa.h>
35*eda14cbcSMatt Macy #include <sys/zfs_acl.h>
36*eda14cbcSMatt Macy #include <sys/zfs_ioctl.h>
37*eda14cbcSMatt Macy #include <sys/zfs_sysfs.h>
38*eda14cbcSMatt Macy #include <sys/zfs_znode.h>
39*eda14cbcSMatt Macy #include <sys/fs/zfs.h>
40*eda14cbcSMatt Macy 
41*eda14cbcSMatt Macy #include "zfs_prop.h"
42*eda14cbcSMatt Macy #include "zfs_deleg.h"
43*eda14cbcSMatt Macy 
44*eda14cbcSMatt Macy #if !defined(_KERNEL)
45*eda14cbcSMatt Macy #include <stdlib.h>
46*eda14cbcSMatt Macy #include <string.h>
47*eda14cbcSMatt Macy #include <ctype.h>
48*eda14cbcSMatt Macy #include <sys/stat.h>
49*eda14cbcSMatt Macy #endif
50*eda14cbcSMatt Macy 
51*eda14cbcSMatt Macy static zprop_desc_t *
52*eda14cbcSMatt Macy zprop_get_proptable(zfs_type_t type)
53*eda14cbcSMatt Macy {
54*eda14cbcSMatt Macy 	if (type == ZFS_TYPE_POOL)
55*eda14cbcSMatt Macy 		return (zpool_prop_get_table());
56*eda14cbcSMatt Macy 	else
57*eda14cbcSMatt Macy 		return (zfs_prop_get_table());
58*eda14cbcSMatt Macy }
59*eda14cbcSMatt Macy 
60*eda14cbcSMatt Macy static int
61*eda14cbcSMatt Macy zprop_get_numprops(zfs_type_t type)
62*eda14cbcSMatt Macy {
63*eda14cbcSMatt Macy 	if (type == ZFS_TYPE_POOL)
64*eda14cbcSMatt Macy 		return (ZPOOL_NUM_PROPS);
65*eda14cbcSMatt Macy 	else
66*eda14cbcSMatt Macy 		return (ZFS_NUM_PROPS);
67*eda14cbcSMatt Macy }
68*eda14cbcSMatt Macy 
69*eda14cbcSMatt Macy static boolean_t
70*eda14cbcSMatt Macy zfs_mod_supported_prop(const char *name, zfs_type_t type)
71*eda14cbcSMatt Macy {
72*eda14cbcSMatt Macy /*
73*eda14cbcSMatt Macy  * The zfs module spa_feature_table[], whether in-kernel or in libzpool,
74*eda14cbcSMatt Macy  * always supports all the properties. libzfs needs to query the running
75*eda14cbcSMatt Macy  * module, via sysfs, to determine which properties are supported.
76*eda14cbcSMatt Macy  *
77*eda14cbcSMatt Macy  * The equivalent _can_ be done on FreeBSD by way of the sysctl
78*eda14cbcSMatt Macy  * tree, but this has not been done yet.
79*eda14cbcSMatt Macy  */
80*eda14cbcSMatt Macy #if defined(_KERNEL) || defined(LIB_ZPOOL_BUILD) || defined(__FreeBSD__)
81*eda14cbcSMatt Macy 	return (B_TRUE);
82*eda14cbcSMatt Macy #else
83*eda14cbcSMatt Macy 	return (zfs_mod_supported(type == ZFS_TYPE_POOL ?
84*eda14cbcSMatt Macy 	    ZFS_SYSFS_POOL_PROPERTIES : ZFS_SYSFS_DATASET_PROPERTIES, name));
85*eda14cbcSMatt Macy #endif
86*eda14cbcSMatt Macy }
87*eda14cbcSMatt Macy 
88*eda14cbcSMatt Macy void
89*eda14cbcSMatt Macy zprop_register_impl(int prop, const char *name, zprop_type_t type,
90*eda14cbcSMatt Macy     uint64_t numdefault, const char *strdefault, zprop_attr_t attr,
91*eda14cbcSMatt Macy     int objset_types, const char *values, const char *colname,
92*eda14cbcSMatt Macy     boolean_t rightalign, boolean_t visible, const zprop_index_t *idx_tbl)
93*eda14cbcSMatt Macy {
94*eda14cbcSMatt Macy 	zprop_desc_t *prop_tbl = zprop_get_proptable(objset_types);
95*eda14cbcSMatt Macy 	zprop_desc_t *pd;
96*eda14cbcSMatt Macy 
97*eda14cbcSMatt Macy 	pd = &prop_tbl[prop];
98*eda14cbcSMatt Macy 
99*eda14cbcSMatt Macy 	ASSERT(pd->pd_name == NULL || pd->pd_name == name);
100*eda14cbcSMatt Macy 	ASSERT(name != NULL);
101*eda14cbcSMatt Macy 	ASSERT(colname != NULL);
102*eda14cbcSMatt Macy 
103*eda14cbcSMatt Macy 	pd->pd_name = name;
104*eda14cbcSMatt Macy 	pd->pd_propnum = prop;
105*eda14cbcSMatt Macy 	pd->pd_proptype = type;
106*eda14cbcSMatt Macy 	pd->pd_numdefault = numdefault;
107*eda14cbcSMatt Macy 	pd->pd_strdefault = strdefault;
108*eda14cbcSMatt Macy 	pd->pd_attr = attr;
109*eda14cbcSMatt Macy 	pd->pd_types = objset_types;
110*eda14cbcSMatt Macy 	pd->pd_values = values;
111*eda14cbcSMatt Macy 	pd->pd_colname = colname;
112*eda14cbcSMatt Macy 	pd->pd_rightalign = rightalign;
113*eda14cbcSMatt Macy 	pd->pd_visible = visible;
114*eda14cbcSMatt Macy 	pd->pd_zfs_mod_supported = zfs_mod_supported_prop(name, objset_types);
115*eda14cbcSMatt Macy 	pd->pd_table = idx_tbl;
116*eda14cbcSMatt Macy 	pd->pd_table_size = 0;
117*eda14cbcSMatt Macy 	while (idx_tbl && (idx_tbl++)->pi_name != NULL)
118*eda14cbcSMatt Macy 		pd->pd_table_size++;
119*eda14cbcSMatt Macy }
120*eda14cbcSMatt Macy 
121*eda14cbcSMatt Macy void
122*eda14cbcSMatt Macy zprop_register_string(int prop, const char *name, const char *def,
123*eda14cbcSMatt Macy     zprop_attr_t attr, int objset_types, const char *values,
124*eda14cbcSMatt Macy     const char *colname)
125*eda14cbcSMatt Macy {
126*eda14cbcSMatt Macy 	zprop_register_impl(prop, name, PROP_TYPE_STRING, 0, def, attr,
127*eda14cbcSMatt Macy 	    objset_types, values, colname, B_FALSE, B_TRUE, NULL);
128*eda14cbcSMatt Macy 
129*eda14cbcSMatt Macy }
130*eda14cbcSMatt Macy 
131*eda14cbcSMatt Macy void
132*eda14cbcSMatt Macy zprop_register_number(int prop, const char *name, uint64_t def,
133*eda14cbcSMatt Macy     zprop_attr_t attr, int objset_types, const char *values,
134*eda14cbcSMatt Macy     const char *colname)
135*eda14cbcSMatt Macy {
136*eda14cbcSMatt Macy 	zprop_register_impl(prop, name, PROP_TYPE_NUMBER, def, NULL, attr,
137*eda14cbcSMatt Macy 	    objset_types, values, colname, B_TRUE, B_TRUE, NULL);
138*eda14cbcSMatt Macy }
139*eda14cbcSMatt Macy 
140*eda14cbcSMatt Macy void
141*eda14cbcSMatt Macy zprop_register_index(int prop, const char *name, uint64_t def,
142*eda14cbcSMatt Macy     zprop_attr_t attr, int objset_types, const char *values,
143*eda14cbcSMatt Macy     const char *colname, const zprop_index_t *idx_tbl)
144*eda14cbcSMatt Macy {
145*eda14cbcSMatt Macy 	zprop_register_impl(prop, name, PROP_TYPE_INDEX, def, NULL, attr,
146*eda14cbcSMatt Macy 	    objset_types, values, colname, B_FALSE, B_TRUE, idx_tbl);
147*eda14cbcSMatt Macy }
148*eda14cbcSMatt Macy 
149*eda14cbcSMatt Macy void
150*eda14cbcSMatt Macy zprop_register_hidden(int prop, const char *name, zprop_type_t type,
151*eda14cbcSMatt Macy     zprop_attr_t attr, int objset_types, const char *colname)
152*eda14cbcSMatt Macy {
153*eda14cbcSMatt Macy 	zprop_register_impl(prop, name, type, 0, NULL, attr,
154*eda14cbcSMatt Macy 	    objset_types, NULL, colname,
155*eda14cbcSMatt Macy 	    type == PROP_TYPE_NUMBER, B_FALSE, NULL);
156*eda14cbcSMatt Macy }
157*eda14cbcSMatt Macy 
158*eda14cbcSMatt Macy 
159*eda14cbcSMatt Macy /*
160*eda14cbcSMatt Macy  * A comparison function we can use to order indexes into property tables.
161*eda14cbcSMatt Macy  */
162*eda14cbcSMatt Macy static int
163*eda14cbcSMatt Macy zprop_compare(const void *arg1, const void *arg2)
164*eda14cbcSMatt Macy {
165*eda14cbcSMatt Macy 	const zprop_desc_t *p1 = *((zprop_desc_t **)arg1);
166*eda14cbcSMatt Macy 	const zprop_desc_t *p2 = *((zprop_desc_t **)arg2);
167*eda14cbcSMatt Macy 	boolean_t p1ro, p2ro;
168*eda14cbcSMatt Macy 
169*eda14cbcSMatt Macy 	p1ro = (p1->pd_attr == PROP_READONLY);
170*eda14cbcSMatt Macy 	p2ro = (p2->pd_attr == PROP_READONLY);
171*eda14cbcSMatt Macy 
172*eda14cbcSMatt Macy 	if (p1ro == p2ro)
173*eda14cbcSMatt Macy 		return (strcmp(p1->pd_name, p2->pd_name));
174*eda14cbcSMatt Macy 
175*eda14cbcSMatt Macy 	return (p1ro ? -1 : 1);
176*eda14cbcSMatt Macy }
177*eda14cbcSMatt Macy 
178*eda14cbcSMatt Macy /*
179*eda14cbcSMatt Macy  * Iterate over all properties in the given property table, calling back
180*eda14cbcSMatt Macy  * into the specified function for each property. We will continue to
181*eda14cbcSMatt Macy  * iterate until we either reach the end or the callback function returns
182*eda14cbcSMatt Macy  * something other than ZPROP_CONT.
183*eda14cbcSMatt Macy  */
184*eda14cbcSMatt Macy int
185*eda14cbcSMatt Macy zprop_iter_common(zprop_func func, void *cb, boolean_t show_all,
186*eda14cbcSMatt Macy     boolean_t ordered, zfs_type_t type)
187*eda14cbcSMatt Macy {
188*eda14cbcSMatt Macy 	int i, num_props, size, prop;
189*eda14cbcSMatt Macy 	zprop_desc_t *prop_tbl;
190*eda14cbcSMatt Macy 	zprop_desc_t **order;
191*eda14cbcSMatt Macy 
192*eda14cbcSMatt Macy 	prop_tbl = zprop_get_proptable(type);
193*eda14cbcSMatt Macy 	num_props = zprop_get_numprops(type);
194*eda14cbcSMatt Macy 	size = num_props * sizeof (zprop_desc_t *);
195*eda14cbcSMatt Macy 
196*eda14cbcSMatt Macy #if defined(_KERNEL)
197*eda14cbcSMatt Macy 	order = kmem_alloc(size, KM_SLEEP);
198*eda14cbcSMatt Macy #else
199*eda14cbcSMatt Macy 	if ((order = malloc(size)) == NULL)
200*eda14cbcSMatt Macy 		return (ZPROP_CONT);
201*eda14cbcSMatt Macy #endif
202*eda14cbcSMatt Macy 
203*eda14cbcSMatt Macy 	for (int j = 0; j < num_props; j++)
204*eda14cbcSMatt Macy 		order[j] = &prop_tbl[j];
205*eda14cbcSMatt Macy 
206*eda14cbcSMatt Macy 	if (ordered) {
207*eda14cbcSMatt Macy 		qsort((void *)order, num_props, sizeof (zprop_desc_t *),
208*eda14cbcSMatt Macy 		    zprop_compare);
209*eda14cbcSMatt Macy 	}
210*eda14cbcSMatt Macy 
211*eda14cbcSMatt Macy 	prop = ZPROP_CONT;
212*eda14cbcSMatt Macy 	for (i = 0; i < num_props; i++) {
213*eda14cbcSMatt Macy 		if ((order[i]->pd_visible || show_all) &&
214*eda14cbcSMatt Macy 		    order[i]->pd_zfs_mod_supported &&
215*eda14cbcSMatt Macy 		    (func(order[i]->pd_propnum, cb) != ZPROP_CONT)) {
216*eda14cbcSMatt Macy 			prop = order[i]->pd_propnum;
217*eda14cbcSMatt Macy 			break;
218*eda14cbcSMatt Macy 		}
219*eda14cbcSMatt Macy 	}
220*eda14cbcSMatt Macy 
221*eda14cbcSMatt Macy #if defined(_KERNEL)
222*eda14cbcSMatt Macy 	kmem_free(order, size);
223*eda14cbcSMatt Macy #else
224*eda14cbcSMatt Macy 	free(order);
225*eda14cbcSMatt Macy #endif
226*eda14cbcSMatt Macy 	return (prop);
227*eda14cbcSMatt Macy }
228*eda14cbcSMatt Macy 
229*eda14cbcSMatt Macy static boolean_t
230*eda14cbcSMatt Macy propname_match(const char *p, size_t len, zprop_desc_t *prop_entry)
231*eda14cbcSMatt Macy {
232*eda14cbcSMatt Macy 	const char *propname = prop_entry->pd_name;
233*eda14cbcSMatt Macy #ifndef _KERNEL
234*eda14cbcSMatt Macy 	const char *colname = prop_entry->pd_colname;
235*eda14cbcSMatt Macy 	int c;
236*eda14cbcSMatt Macy #endif
237*eda14cbcSMatt Macy 
238*eda14cbcSMatt Macy 	if (len == strlen(propname) &&
239*eda14cbcSMatt Macy 	    strncmp(p, propname, len) == 0)
240*eda14cbcSMatt Macy 		return (B_TRUE);
241*eda14cbcSMatt Macy 
242*eda14cbcSMatt Macy #ifndef _KERNEL
243*eda14cbcSMatt Macy 	if (colname == NULL || len != strlen(colname))
244*eda14cbcSMatt Macy 		return (B_FALSE);
245*eda14cbcSMatt Macy 
246*eda14cbcSMatt Macy 	for (c = 0; c < len; c++)
247*eda14cbcSMatt Macy 		if (p[c] != tolower(colname[c]))
248*eda14cbcSMatt Macy 			break;
249*eda14cbcSMatt Macy 
250*eda14cbcSMatt Macy 	return (colname[c] == '\0');
251*eda14cbcSMatt Macy #else
252*eda14cbcSMatt Macy 	return (B_FALSE);
253*eda14cbcSMatt Macy #endif
254*eda14cbcSMatt Macy }
255*eda14cbcSMatt Macy 
256*eda14cbcSMatt Macy typedef struct name_to_prop_cb {
257*eda14cbcSMatt Macy 	const char *propname;
258*eda14cbcSMatt Macy 	zprop_desc_t *prop_tbl;
259*eda14cbcSMatt Macy } name_to_prop_cb_t;
260*eda14cbcSMatt Macy 
261*eda14cbcSMatt Macy static int
262*eda14cbcSMatt Macy zprop_name_to_prop_cb(int prop, void *cb_data)
263*eda14cbcSMatt Macy {
264*eda14cbcSMatt Macy 	name_to_prop_cb_t *data = cb_data;
265*eda14cbcSMatt Macy 
266*eda14cbcSMatt Macy 	if (propname_match(data->propname, strlen(data->propname),
267*eda14cbcSMatt Macy 	    &data->prop_tbl[prop]))
268*eda14cbcSMatt Macy 		return (prop);
269*eda14cbcSMatt Macy 
270*eda14cbcSMatt Macy 	return (ZPROP_CONT);
271*eda14cbcSMatt Macy }
272*eda14cbcSMatt Macy 
273*eda14cbcSMatt Macy int
274*eda14cbcSMatt Macy zprop_name_to_prop(const char *propname, zfs_type_t type)
275*eda14cbcSMatt Macy {
276*eda14cbcSMatt Macy 	int prop;
277*eda14cbcSMatt Macy 	name_to_prop_cb_t cb_data;
278*eda14cbcSMatt Macy 
279*eda14cbcSMatt Macy 	cb_data.propname = propname;
280*eda14cbcSMatt Macy 	cb_data.prop_tbl = zprop_get_proptable(type);
281*eda14cbcSMatt Macy 
282*eda14cbcSMatt Macy 	prop = zprop_iter_common(zprop_name_to_prop_cb, &cb_data,
283*eda14cbcSMatt Macy 	    B_TRUE, B_FALSE, type);
284*eda14cbcSMatt Macy 
285*eda14cbcSMatt Macy 	return (prop == ZPROP_CONT ? ZPROP_INVAL : prop);
286*eda14cbcSMatt Macy }
287*eda14cbcSMatt Macy 
288*eda14cbcSMatt Macy int
289*eda14cbcSMatt Macy zprop_string_to_index(int prop, const char *string, uint64_t *index,
290*eda14cbcSMatt Macy     zfs_type_t type)
291*eda14cbcSMatt Macy {
292*eda14cbcSMatt Macy 	zprop_desc_t *prop_tbl;
293*eda14cbcSMatt Macy 	const zprop_index_t *idx_tbl;
294*eda14cbcSMatt Macy 	int i;
295*eda14cbcSMatt Macy 
296*eda14cbcSMatt Macy 	if (prop == ZPROP_INVAL || prop == ZPROP_CONT)
297*eda14cbcSMatt Macy 		return (-1);
298*eda14cbcSMatt Macy 
299*eda14cbcSMatt Macy 	ASSERT(prop < zprop_get_numprops(type));
300*eda14cbcSMatt Macy 	prop_tbl = zprop_get_proptable(type);
301*eda14cbcSMatt Macy 	if ((idx_tbl = prop_tbl[prop].pd_table) == NULL)
302*eda14cbcSMatt Macy 		return (-1);
303*eda14cbcSMatt Macy 
304*eda14cbcSMatt Macy 	for (i = 0; idx_tbl[i].pi_name != NULL; i++) {
305*eda14cbcSMatt Macy 		if (strcmp(string, idx_tbl[i].pi_name) == 0) {
306*eda14cbcSMatt Macy 			*index = idx_tbl[i].pi_value;
307*eda14cbcSMatt Macy 			return (0);
308*eda14cbcSMatt Macy 		}
309*eda14cbcSMatt Macy 	}
310*eda14cbcSMatt Macy 
311*eda14cbcSMatt Macy 	return (-1);
312*eda14cbcSMatt Macy }
313*eda14cbcSMatt Macy 
314*eda14cbcSMatt Macy int
315*eda14cbcSMatt Macy zprop_index_to_string(int prop, uint64_t index, const char **string,
316*eda14cbcSMatt Macy     zfs_type_t type)
317*eda14cbcSMatt Macy {
318*eda14cbcSMatt Macy 	zprop_desc_t *prop_tbl;
319*eda14cbcSMatt Macy 	const zprop_index_t *idx_tbl;
320*eda14cbcSMatt Macy 	int i;
321*eda14cbcSMatt Macy 
322*eda14cbcSMatt Macy 	if (prop == ZPROP_INVAL || prop == ZPROP_CONT)
323*eda14cbcSMatt Macy 		return (-1);
324*eda14cbcSMatt Macy 
325*eda14cbcSMatt Macy 	ASSERT(prop < zprop_get_numprops(type));
326*eda14cbcSMatt Macy 	prop_tbl = zprop_get_proptable(type);
327*eda14cbcSMatt Macy 	if ((idx_tbl = prop_tbl[prop].pd_table) == NULL)
328*eda14cbcSMatt Macy 		return (-1);
329*eda14cbcSMatt Macy 
330*eda14cbcSMatt Macy 	for (i = 0; idx_tbl[i].pi_name != NULL; i++) {
331*eda14cbcSMatt Macy 		if (idx_tbl[i].pi_value == index) {
332*eda14cbcSMatt Macy 			*string = idx_tbl[i].pi_name;
333*eda14cbcSMatt Macy 			return (0);
334*eda14cbcSMatt Macy 		}
335*eda14cbcSMatt Macy 	}
336*eda14cbcSMatt Macy 
337*eda14cbcSMatt Macy 	return (-1);
338*eda14cbcSMatt Macy }
339*eda14cbcSMatt Macy 
340*eda14cbcSMatt Macy /*
341*eda14cbcSMatt Macy  * Return a random valid property value.  Used by ztest.
342*eda14cbcSMatt Macy  */
343*eda14cbcSMatt Macy uint64_t
344*eda14cbcSMatt Macy zprop_random_value(int prop, uint64_t seed, zfs_type_t type)
345*eda14cbcSMatt Macy {
346*eda14cbcSMatt Macy 	zprop_desc_t *prop_tbl;
347*eda14cbcSMatt Macy 	const zprop_index_t *idx_tbl;
348*eda14cbcSMatt Macy 
349*eda14cbcSMatt Macy 	ASSERT((uint_t)prop < zprop_get_numprops(type));
350*eda14cbcSMatt Macy 	prop_tbl = zprop_get_proptable(type);
351*eda14cbcSMatt Macy 	idx_tbl = prop_tbl[prop].pd_table;
352*eda14cbcSMatt Macy 
353*eda14cbcSMatt Macy 	if (idx_tbl == NULL)
354*eda14cbcSMatt Macy 		return (seed);
355*eda14cbcSMatt Macy 
356*eda14cbcSMatt Macy 	return (idx_tbl[seed % prop_tbl[prop].pd_table_size].pi_value);
357*eda14cbcSMatt Macy }
358*eda14cbcSMatt Macy 
359*eda14cbcSMatt Macy const char *
360*eda14cbcSMatt Macy zprop_values(int prop, zfs_type_t type)
361*eda14cbcSMatt Macy {
362*eda14cbcSMatt Macy 	zprop_desc_t *prop_tbl;
363*eda14cbcSMatt Macy 
364*eda14cbcSMatt Macy 	ASSERT(prop != ZPROP_INVAL && prop != ZPROP_CONT);
365*eda14cbcSMatt Macy 	ASSERT(prop < zprop_get_numprops(type));
366*eda14cbcSMatt Macy 
367*eda14cbcSMatt Macy 	prop_tbl = zprop_get_proptable(type);
368*eda14cbcSMatt Macy 
369*eda14cbcSMatt Macy 	return (prop_tbl[prop].pd_values);
370*eda14cbcSMatt Macy }
371*eda14cbcSMatt Macy 
372*eda14cbcSMatt Macy /*
373*eda14cbcSMatt Macy  * Returns TRUE if the property applies to any of the given dataset types.
374*eda14cbcSMatt Macy  *
375*eda14cbcSMatt Macy  * If headcheck is set, the check is being made against the head dataset
376*eda14cbcSMatt Macy  * type of a snapshot which requires to return B_TRUE when the property
377*eda14cbcSMatt Macy  * is only valid for snapshots.
378*eda14cbcSMatt Macy  */
379*eda14cbcSMatt Macy boolean_t
380*eda14cbcSMatt Macy zprop_valid_for_type(int prop, zfs_type_t type, boolean_t headcheck)
381*eda14cbcSMatt Macy {
382*eda14cbcSMatt Macy 	zprop_desc_t *prop_tbl;
383*eda14cbcSMatt Macy 
384*eda14cbcSMatt Macy 	if (prop == ZPROP_INVAL || prop == ZPROP_CONT)
385*eda14cbcSMatt Macy 		return (B_FALSE);
386*eda14cbcSMatt Macy 
387*eda14cbcSMatt Macy 	ASSERT(prop < zprop_get_numprops(type));
388*eda14cbcSMatt Macy 	prop_tbl = zprop_get_proptable(type);
389*eda14cbcSMatt Macy 	if (headcheck && prop_tbl[prop].pd_types == ZFS_TYPE_SNAPSHOT)
390*eda14cbcSMatt Macy 		return (B_TRUE);
391*eda14cbcSMatt Macy 	return ((prop_tbl[prop].pd_types & type) != 0);
392*eda14cbcSMatt Macy }
393*eda14cbcSMatt Macy 
394*eda14cbcSMatt Macy #ifndef _KERNEL
395*eda14cbcSMatt Macy 
396*eda14cbcSMatt Macy /*
397*eda14cbcSMatt Macy  * Determines the minimum width for the column, and indicates whether it's fixed
398*eda14cbcSMatt Macy  * or not.  Only string columns are non-fixed.
399*eda14cbcSMatt Macy  */
400*eda14cbcSMatt Macy size_t
401*eda14cbcSMatt Macy zprop_width(int prop, boolean_t *fixed, zfs_type_t type)
402*eda14cbcSMatt Macy {
403*eda14cbcSMatt Macy 	zprop_desc_t *prop_tbl, *pd;
404*eda14cbcSMatt Macy 	const zprop_index_t *idx;
405*eda14cbcSMatt Macy 	size_t ret;
406*eda14cbcSMatt Macy 	int i;
407*eda14cbcSMatt Macy 
408*eda14cbcSMatt Macy 	ASSERT(prop != ZPROP_INVAL && prop != ZPROP_CONT);
409*eda14cbcSMatt Macy 	ASSERT(prop < zprop_get_numprops(type));
410*eda14cbcSMatt Macy 
411*eda14cbcSMatt Macy 	prop_tbl = zprop_get_proptable(type);
412*eda14cbcSMatt Macy 	pd = &prop_tbl[prop];
413*eda14cbcSMatt Macy 
414*eda14cbcSMatt Macy 	*fixed = B_TRUE;
415*eda14cbcSMatt Macy 
416*eda14cbcSMatt Macy 	/*
417*eda14cbcSMatt Macy 	 * Start with the width of the column name.
418*eda14cbcSMatt Macy 	 */
419*eda14cbcSMatt Macy 	ret = strlen(pd->pd_colname);
420*eda14cbcSMatt Macy 
421*eda14cbcSMatt Macy 	/*
422*eda14cbcSMatt Macy 	 * For fixed-width values, make sure the width is large enough to hold
423*eda14cbcSMatt Macy 	 * any possible value.
424*eda14cbcSMatt Macy 	 */
425*eda14cbcSMatt Macy 	switch (pd->pd_proptype) {
426*eda14cbcSMatt Macy 	case PROP_TYPE_NUMBER:
427*eda14cbcSMatt Macy 		/*
428*eda14cbcSMatt Macy 		 * The maximum length of a human-readable number is 5 characters
429*eda14cbcSMatt Macy 		 * ("20.4M", for example).
430*eda14cbcSMatt Macy 		 */
431*eda14cbcSMatt Macy 		if (ret < 5)
432*eda14cbcSMatt Macy 			ret = 5;
433*eda14cbcSMatt Macy 		/*
434*eda14cbcSMatt Macy 		 * 'creation' is handled specially because it's a number
435*eda14cbcSMatt Macy 		 * internally, but displayed as a date string.
436*eda14cbcSMatt Macy 		 */
437*eda14cbcSMatt Macy 		if (prop == ZFS_PROP_CREATION)
438*eda14cbcSMatt Macy 			*fixed = B_FALSE;
439*eda14cbcSMatt Macy 		/*
440*eda14cbcSMatt Macy 		 * 'health' is handled specially because it's a number
441*eda14cbcSMatt Macy 		 * internally, but displayed as a fixed 8 character string.
442*eda14cbcSMatt Macy 		 */
443*eda14cbcSMatt Macy 		if (prop == ZPOOL_PROP_HEALTH)
444*eda14cbcSMatt Macy 			ret = 8;
445*eda14cbcSMatt Macy 		break;
446*eda14cbcSMatt Macy 	case PROP_TYPE_INDEX:
447*eda14cbcSMatt Macy 		idx = prop_tbl[prop].pd_table;
448*eda14cbcSMatt Macy 		for (i = 0; idx[i].pi_name != NULL; i++) {
449*eda14cbcSMatt Macy 			if (strlen(idx[i].pi_name) > ret)
450*eda14cbcSMatt Macy 				ret = strlen(idx[i].pi_name);
451*eda14cbcSMatt Macy 		}
452*eda14cbcSMatt Macy 		break;
453*eda14cbcSMatt Macy 
454*eda14cbcSMatt Macy 	case PROP_TYPE_STRING:
455*eda14cbcSMatt Macy 		*fixed = B_FALSE;
456*eda14cbcSMatt Macy 		break;
457*eda14cbcSMatt Macy 	}
458*eda14cbcSMatt Macy 
459*eda14cbcSMatt Macy 	return (ret);
460*eda14cbcSMatt Macy }
461*eda14cbcSMatt Macy 
462*eda14cbcSMatt Macy #endif
463*eda14cbcSMatt Macy 
464*eda14cbcSMatt Macy #if defined(_KERNEL)
465*eda14cbcSMatt Macy /* Common routines to initialize property tables */
466*eda14cbcSMatt Macy EXPORT_SYMBOL(zprop_register_impl);
467*eda14cbcSMatt Macy EXPORT_SYMBOL(zprop_register_string);
468*eda14cbcSMatt Macy EXPORT_SYMBOL(zprop_register_number);
469*eda14cbcSMatt Macy EXPORT_SYMBOL(zprop_register_index);
470*eda14cbcSMatt Macy EXPORT_SYMBOL(zprop_register_hidden);
471*eda14cbcSMatt Macy 
472*eda14cbcSMatt Macy /* Common routines for zfs and zpool property management */
473*eda14cbcSMatt Macy EXPORT_SYMBOL(zprop_iter_common);
474*eda14cbcSMatt Macy EXPORT_SYMBOL(zprop_name_to_prop);
475*eda14cbcSMatt Macy EXPORT_SYMBOL(zprop_string_to_index);
476*eda14cbcSMatt Macy EXPORT_SYMBOL(zprop_index_to_string);
477*eda14cbcSMatt Macy EXPORT_SYMBOL(zprop_random_value);
478*eda14cbcSMatt Macy EXPORT_SYMBOL(zprop_values);
479*eda14cbcSMatt Macy EXPORT_SYMBOL(zprop_valid_for_type);
480*eda14cbcSMatt Macy #endif
481