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.
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.
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]
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * Common routines used by zfs and zpool property management.
32 #include <sys/zfs_acl.h>
33 #include <sys/zfs_ioctl.h>
34 #include <sys/zfs_znode.h>
35 #include <sys/fs/zfs.h>
38 #include "zfs_deleg.h"
41 #include <sys/systm.h>
42 #include <util/qsort.h>
50 zprop_get_proptable(zfs_type_t type
)
52 if (type
== ZFS_TYPE_POOL
)
53 return (zpool_prop_get_table());
55 return (zfs_prop_get_table());
59 zprop_get_numprops(zfs_type_t type
)
61 if (type
== ZFS_TYPE_POOL
)
62 return (ZPOOL_NUM_PROPS
);
64 return (ZFS_NUM_PROPS
);
68 zprop_register_impl(int prop
, const char *name
, zprop_type_t type
,
69 uint64_t numdefault
, const char *strdefault
, zprop_attr_t attr
,
70 int objset_types
, const char *values
, const char *colname
,
71 boolean_t rightalign
, boolean_t visible
, const zprop_index_t
*idx_tbl
)
73 zprop_desc_t
*prop_tbl
= zprop_get_proptable(objset_types
);
78 ASSERT(pd
->pd_name
== NULL
|| pd
->pd_name
== name
);
80 ASSERT(colname
!= NULL
);
83 pd
->pd_propnum
= prop
;
84 pd
->pd_proptype
= type
;
85 pd
->pd_numdefault
= numdefault
;
86 pd
->pd_strdefault
= strdefault
;
88 pd
->pd_types
= objset_types
;
89 pd
->pd_values
= values
;
90 pd
->pd_colname
= colname
;
91 pd
->pd_rightalign
= rightalign
;
92 pd
->pd_visible
= visible
;
93 pd
->pd_table
= idx_tbl
;
94 pd
->pd_table_size
= 0;
95 while (idx_tbl
&& (idx_tbl
++)->pi_name
!= NULL
)
100 zprop_register_string(int prop
, const char *name
, const char *def
,
101 zprop_attr_t attr
, int objset_types
, const char *values
,
104 zprop_register_impl(prop
, name
, PROP_TYPE_STRING
, 0, def
, attr
,
105 objset_types
, values
, colname
, B_FALSE
, B_TRUE
, NULL
);
110 zprop_register_number(int prop
, const char *name
, uint64_t def
,
111 zprop_attr_t attr
, int objset_types
, const char *values
,
114 zprop_register_impl(prop
, name
, PROP_TYPE_NUMBER
, def
, NULL
, attr
,
115 objset_types
, values
, colname
, B_TRUE
, B_TRUE
, NULL
);
119 zprop_register_index(int prop
, const char *name
, uint64_t def
,
120 zprop_attr_t attr
, int objset_types
, const char *values
,
121 const char *colname
, const zprop_index_t
*idx_tbl
)
123 zprop_register_impl(prop
, name
, PROP_TYPE_INDEX
, def
, NULL
, attr
,
124 objset_types
, values
, colname
, B_TRUE
, B_TRUE
, idx_tbl
);
128 zprop_register_hidden(int prop
, const char *name
, zprop_type_t type
,
129 zprop_attr_t attr
, int objset_types
, const char *colname
)
131 zprop_register_impl(prop
, name
, type
, 0, NULL
, attr
,
132 objset_types
, NULL
, colname
, B_FALSE
, B_FALSE
, NULL
);
137 * A comparison function we can use to order indexes into property tables.
140 zprop_compare(const void *arg1
, const void *arg2
)
142 const zprop_desc_t
*p1
= *((zprop_desc_t
**)arg1
);
143 const zprop_desc_t
*p2
= *((zprop_desc_t
**)arg2
);
144 boolean_t p1ro
, p2ro
;
146 p1ro
= (p1
->pd_attr
== PROP_READONLY
);
147 p2ro
= (p2
->pd_attr
== PROP_READONLY
);
150 return (strcmp(p1
->pd_name
, p2
->pd_name
));
152 return (p1ro
? -1 : 1);
156 * Iterate over all properties in the given property table, calling back
157 * into the specified function for each property. We will continue to
158 * iterate until we either reach the end or the callback function returns
159 * something other than ZPROP_CONT.
162 zprop_iter_common(zprop_func func
, void *cb
, boolean_t show_all
,
163 boolean_t ordered
, zfs_type_t type
)
165 int i
, j
, num_props
, size
, prop
;
166 zprop_desc_t
*prop_tbl
;
167 zprop_desc_t
**order
;
169 prop_tbl
= zprop_get_proptable(type
);
170 num_props
= zprop_get_numprops(type
);
171 size
= num_props
* sizeof (zprop_desc_t
*);
174 order
= kmem_alloc(size
, KM_PUSHPAGE
);
176 if ((order
= malloc(size
)) == NULL
)
180 for (j
= 0; j
< num_props
; j
++)
181 order
[j
] = &prop_tbl
[j
];
184 qsort((void *)order
, num_props
, sizeof (zprop_desc_t
*),
189 for (i
= 0; i
< num_props
; i
++) {
190 if ((order
[i
]->pd_visible
|| show_all
) &&
191 (func(order
[i
]->pd_propnum
, cb
) != ZPROP_CONT
)) {
192 prop
= order
[i
]->pd_propnum
;
198 kmem_free(order
, size
);
206 propname_match(const char *p
, size_t len
, zprop_desc_t
*prop_entry
)
208 const char *propname
= prop_entry
->pd_name
;
210 const char *colname
= prop_entry
->pd_colname
;
214 if (len
== strlen(propname
) &&
215 strncmp(p
, propname
, len
) == 0)
219 if (colname
== NULL
|| len
!= strlen(colname
))
222 for (c
= 0; c
< len
; c
++)
223 if (p
[c
] != tolower(colname
[c
]))
226 return (colname
[c
] == '\0');
232 typedef struct name_to_prop_cb
{
233 const char *propname
;
234 zprop_desc_t
*prop_tbl
;
238 zprop_name_to_prop_cb(int prop
, void *cb_data
)
240 name_to_prop_cb_t
*data
= cb_data
;
242 if (propname_match(data
->propname
, strlen(data
->propname
),
243 &data
->prop_tbl
[prop
]))
250 zprop_name_to_prop(const char *propname
, zfs_type_t type
)
253 name_to_prop_cb_t cb_data
;
255 cb_data
.propname
= propname
;
256 cb_data
.prop_tbl
= zprop_get_proptable(type
);
258 prop
= zprop_iter_common(zprop_name_to_prop_cb
, &cb_data
,
259 B_TRUE
, B_FALSE
, type
);
261 return (prop
== ZPROP_CONT
? ZPROP_INVAL
: prop
);
265 zprop_string_to_index(int prop
, const char *string
, uint64_t *index
,
268 zprop_desc_t
*prop_tbl
;
269 const zprop_index_t
*idx_tbl
;
272 if (prop
== ZPROP_INVAL
|| prop
== ZPROP_CONT
)
275 ASSERT(prop
< zprop_get_numprops(type
));
276 prop_tbl
= zprop_get_proptable(type
);
277 if ((idx_tbl
= prop_tbl
[prop
].pd_table
) == NULL
)
280 for (i
= 0; idx_tbl
[i
].pi_name
!= NULL
; i
++) {
281 if (strcmp(string
, idx_tbl
[i
].pi_name
) == 0) {
282 *index
= idx_tbl
[i
].pi_value
;
291 zprop_index_to_string(int prop
, uint64_t index
, const char **string
,
294 zprop_desc_t
*prop_tbl
;
295 const zprop_index_t
*idx_tbl
;
298 if (prop
== ZPROP_INVAL
|| prop
== ZPROP_CONT
)
301 ASSERT(prop
< zprop_get_numprops(type
));
302 prop_tbl
= zprop_get_proptable(type
);
303 if ((idx_tbl
= prop_tbl
[prop
].pd_table
) == NULL
)
306 for (i
= 0; idx_tbl
[i
].pi_name
!= NULL
; i
++) {
307 if (idx_tbl
[i
].pi_value
== index
) {
308 *string
= idx_tbl
[i
].pi_name
;
317 * Return a random valid property value. Used by ztest.
320 zprop_random_value(int prop
, uint64_t seed
, zfs_type_t type
)
322 zprop_desc_t
*prop_tbl
;
323 const zprop_index_t
*idx_tbl
;
325 ASSERT((uint_t
)prop
< zprop_get_numprops(type
));
326 prop_tbl
= zprop_get_proptable(type
);
327 idx_tbl
= prop_tbl
[prop
].pd_table
;
332 return (idx_tbl
[seed
% prop_tbl
[prop
].pd_table_size
].pi_value
);
336 zprop_values(int prop
, zfs_type_t type
)
338 zprop_desc_t
*prop_tbl
;
340 ASSERT(prop
!= ZPROP_INVAL
&& prop
!= ZPROP_CONT
);
341 ASSERT(prop
< zprop_get_numprops(type
));
343 prop_tbl
= zprop_get_proptable(type
);
345 return (prop_tbl
[prop
].pd_values
);
349 * Returns TRUE if the property applies to any of the given dataset types.
352 zprop_valid_for_type(int prop
, zfs_type_t type
)
354 zprop_desc_t
*prop_tbl
;
356 if (prop
== ZPROP_INVAL
|| prop
== ZPROP_CONT
)
359 ASSERT(prop
< zprop_get_numprops(type
));
360 prop_tbl
= zprop_get_proptable(type
);
361 return ((prop_tbl
[prop
].pd_types
& type
) != 0);
367 * Determines the minimum width for the column, and indicates whether it's fixed
368 * or not. Only string columns are non-fixed.
371 zprop_width(int prop
, boolean_t
*fixed
, zfs_type_t type
)
373 zprop_desc_t
*prop_tbl
, *pd
;
374 const zprop_index_t
*idx
;
378 ASSERT(prop
!= ZPROP_INVAL
&& prop
!= ZPROP_CONT
);
379 ASSERT(prop
< zprop_get_numprops(type
));
381 prop_tbl
= zprop_get_proptable(type
);
382 pd
= &prop_tbl
[prop
];
387 * Start with the width of the column name.
389 ret
= strlen(pd
->pd_colname
);
392 * For fixed-width values, make sure the width is large enough to hold
393 * any possible value.
395 switch (pd
->pd_proptype
) {
396 case PROP_TYPE_NUMBER
:
398 * The maximum length of a human-readable number is 5 characters
399 * ("20.4M", for example).
404 * 'creation' is handled specially because it's a number
405 * internally, but displayed as a date string.
407 if (prop
== ZFS_PROP_CREATION
)
410 case PROP_TYPE_INDEX
:
411 idx
= prop_tbl
[prop
].pd_table
;
412 for (i
= 0; idx
[i
].pi_name
!= NULL
; i
++) {
413 if (strlen(idx
[i
].pi_name
) > ret
)
414 ret
= strlen(idx
[i
].pi_name
);
418 case PROP_TYPE_STRING
:
428 #if defined(_KERNEL) && defined(HAVE_SPL)
429 /* Common routines to initialize property tables */
430 EXPORT_SYMBOL(zprop_register_impl
);
431 EXPORT_SYMBOL(zprop_register_string
);
432 EXPORT_SYMBOL(zprop_register_number
);
433 EXPORT_SYMBOL(zprop_register_index
);
434 EXPORT_SYMBOL(zprop_register_hidden
);
436 /* Common routines for zfs and zpool property management */
437 EXPORT_SYMBOL(zprop_iter_common
);
438 EXPORT_SYMBOL(zprop_name_to_prop
);
439 EXPORT_SYMBOL(zprop_string_to_index
);
440 EXPORT_SYMBOL(zprop_index_to_string
);
441 EXPORT_SYMBOL(zprop_random_value
);
442 EXPORT_SYMBOL(zprop_values
);
443 EXPORT_SYMBOL(zprop_valid_for_type
);