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 https://opensource.org/licenses/CDDL-1.0.
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.
26 * Copyright (c) 2012 by Delphix. All rights reserved.
30 * Common routines used by zfs and zpool property management.
35 #include <sys/zfs_acl.h>
36 #include <sys/zfs_ioctl.h>
37 #include <sys/zfs_sysfs.h>
38 #include <sys/zfs_znode.h>
39 #include <sys/fs/zfs.h>
42 #include "zfs_deleg.h"
52 zprop_get_proptable(zfs_type_t type
)
54 if (type
== ZFS_TYPE_POOL
)
55 return (zpool_prop_get_table());
56 else if (type
== ZFS_TYPE_VDEV
)
57 return (vdev_prop_get_table());
59 return (zfs_prop_get_table());
63 zprop_get_numprops(zfs_type_t type
)
65 if (type
== ZFS_TYPE_POOL
)
66 return (ZPOOL_NUM_PROPS
);
67 else if (type
== ZFS_TYPE_VDEV
)
68 return (VDEV_NUM_PROPS
);
70 return (ZFS_NUM_PROPS
);
74 zfs_mod_supported_prop(const char *name
, zfs_type_t type
,
75 const struct zfs_mod_supported_features
*sfeatures
)
78 * The zfs module spa_feature_table[], whether in-kernel or in libzpool,
79 * always supports all the properties. libzfs needs to query the running
80 * module, via sysfs, to determine which properties are supported.
82 * The equivalent _can_ be done on FreeBSD by way of the sysctl
83 * tree, but this has not been done yet.
85 #if defined(_KERNEL) || defined(LIB_ZPOOL_BUILD) || defined(__FreeBSD__)
86 (void) name
, (void) type
, (void) sfeatures
;
89 return (zfs_mod_supported(type
== ZFS_TYPE_POOL
?
90 ZFS_SYSFS_POOL_PROPERTIES
: (type
== ZFS_TYPE_VDEV
?
91 ZFS_SYSFS_VDEV_PROPERTIES
: ZFS_SYSFS_DATASET_PROPERTIES
),
97 zprop_register_impl(int prop
, const char *name
, zprop_type_t type
,
98 uint64_t numdefault
, const char *strdefault
, zprop_attr_t attr
,
99 int objset_types
, const char *values
, const char *colname
,
100 boolean_t rightalign
, boolean_t visible
, boolean_t flex
,
101 const zprop_index_t
*idx_tbl
,
102 const struct zfs_mod_supported_features
*sfeatures
)
104 zprop_desc_t
*prop_tbl
= zprop_get_proptable(objset_types
);
107 pd
= &prop_tbl
[prop
];
109 ASSERT(pd
->pd_name
== NULL
|| pd
->pd_name
== name
);
110 ASSERT(name
!= NULL
);
111 ASSERT(colname
!= NULL
);
114 pd
->pd_propnum
= prop
;
115 pd
->pd_proptype
= type
;
116 pd
->pd_numdefault
= numdefault
;
117 pd
->pd_strdefault
= strdefault
;
119 pd
->pd_types
= objset_types
;
120 pd
->pd_values
= values
;
121 pd
->pd_colname
= colname
;
122 pd
->pd_rightalign
= rightalign
;
123 pd
->pd_visible
= visible
;
124 pd
->pd_zfs_mod_supported
=
125 zfs_mod_supported_prop(name
, objset_types
, sfeatures
);
126 pd
->pd_always_flex
= flex
;
127 pd
->pd_table
= idx_tbl
;
128 pd
->pd_table_size
= 0;
129 while (idx_tbl
&& (idx_tbl
++)->pi_name
!= NULL
)
134 zprop_register_string(int prop
, const char *name
, const char *def
,
135 zprop_attr_t attr
, int objset_types
, const char *values
,
136 const char *colname
, const struct zfs_mod_supported_features
*sfeatures
)
138 zprop_register_impl(prop
, name
, PROP_TYPE_STRING
, 0, def
, attr
,
139 objset_types
, values
, colname
, B_FALSE
, B_TRUE
, B_TRUE
, NULL
,
145 zprop_register_number(int prop
, const char *name
, uint64_t def
,
146 zprop_attr_t attr
, int objset_types
, const char *values
,
147 const char *colname
, boolean_t flex
,
148 const struct zfs_mod_supported_features
*sfeatures
)
150 zprop_register_impl(prop
, name
, PROP_TYPE_NUMBER
, def
, NULL
, attr
,
151 objset_types
, values
, colname
, B_TRUE
, B_TRUE
, flex
, NULL
,
156 zprop_register_index(int prop
, const char *name
, uint64_t def
,
157 zprop_attr_t attr
, int objset_types
, const char *values
,
158 const char *colname
, const zprop_index_t
*idx_tbl
,
159 const struct zfs_mod_supported_features
*sfeatures
)
161 zprop_register_impl(prop
, name
, PROP_TYPE_INDEX
, def
, NULL
, attr
,
162 objset_types
, values
, colname
, B_FALSE
, B_TRUE
, B_TRUE
, idx_tbl
,
167 zprop_register_hidden(int prop
, const char *name
, zprop_type_t type
,
168 zprop_attr_t attr
, int objset_types
, const char *colname
, boolean_t flex
,
169 const struct zfs_mod_supported_features
*sfeatures
)
171 zprop_register_impl(prop
, name
, type
, 0, NULL
, attr
,
172 objset_types
, NULL
, colname
,
173 type
== PROP_TYPE_NUMBER
, B_FALSE
, flex
, NULL
, sfeatures
);
178 * A comparison function we can use to order indexes into property tables.
181 zprop_compare(const void *arg1
, const void *arg2
)
183 const zprop_desc_t
*p1
= *((zprop_desc_t
**)arg1
);
184 const zprop_desc_t
*p2
= *((zprop_desc_t
**)arg2
);
185 boolean_t p1ro
, p2ro
;
187 p1ro
= (p1
->pd_attr
== PROP_READONLY
);
188 p2ro
= (p2
->pd_attr
== PROP_READONLY
);
191 return (strcmp(p1
->pd_name
, p2
->pd_name
));
193 return (p1ro
? -1 : 1);
197 * Iterate over all properties in the given property table, calling back
198 * into the specified function for each property. We will continue to
199 * iterate until we either reach the end or the callback function returns
200 * something other than ZPROP_CONT.
203 zprop_iter_common(zprop_func func
, void *cb
, boolean_t show_all
,
204 boolean_t ordered
, zfs_type_t type
)
206 int i
, num_props
, size
, prop
;
207 zprop_desc_t
*prop_tbl
;
208 zprop_desc_t
**order
;
210 prop_tbl
= zprop_get_proptable(type
);
211 num_props
= zprop_get_numprops(type
);
212 size
= num_props
* sizeof (zprop_desc_t
*);
215 order
= kmem_alloc(size
, KM_SLEEP
);
217 if ((order
= malloc(size
)) == NULL
)
221 for (int j
= 0; j
< num_props
; j
++)
222 order
[j
] = &prop_tbl
[j
];
225 qsort((void *)order
, num_props
, sizeof (zprop_desc_t
*),
230 for (i
= 0; i
< num_props
; i
++) {
231 if ((order
[i
]->pd_visible
|| show_all
) &&
232 order
[i
]->pd_zfs_mod_supported
&&
233 (func(order
[i
]->pd_propnum
, cb
) != ZPROP_CONT
)) {
234 prop
= order
[i
]->pd_propnum
;
240 kmem_free(order
, size
);
248 propname_match(const char *p
, size_t len
, zprop_desc_t
*prop_entry
)
250 const char *propname
= prop_entry
->pd_name
;
252 const char *colname
= prop_entry
->pd_colname
;
256 ASSERT(propname
!= NULL
);
258 if (len
== strlen(propname
) &&
259 strncmp(p
, propname
, len
) == 0)
263 if (colname
== NULL
|| len
!= strlen(colname
))
266 for (c
= 0; c
< len
; c
++)
267 if (p
[c
] != tolower(colname
[c
]))
270 return (colname
[c
] == '\0');
276 typedef struct name_to_prop_cb
{
277 const char *propname
;
278 zprop_desc_t
*prop_tbl
;
282 zprop_name_to_prop_cb(int prop
, void *cb_data
)
284 name_to_prop_cb_t
*data
= cb_data
;
286 if (propname_match(data
->propname
, strlen(data
->propname
),
287 &data
->prop_tbl
[prop
]))
294 zprop_name_to_prop(const char *propname
, zfs_type_t type
)
297 name_to_prop_cb_t cb_data
;
299 cb_data
.propname
= propname
;
300 cb_data
.prop_tbl
= zprop_get_proptable(type
);
302 prop
= zprop_iter_common(zprop_name_to_prop_cb
, &cb_data
,
303 B_TRUE
, B_FALSE
, type
);
305 return (prop
== ZPROP_CONT
? ZPROP_INVAL
: prop
);
309 zprop_string_to_index(int prop
, const char *string
, uint64_t *index
,
312 zprop_desc_t
*prop_tbl
;
313 const zprop_index_t
*idx_tbl
;
316 if (prop
== ZPROP_INVAL
|| prop
== ZPROP_CONT
)
319 ASSERT(prop
< zprop_get_numprops(type
));
320 prop_tbl
= zprop_get_proptable(type
);
321 if ((idx_tbl
= prop_tbl
[prop
].pd_table
) == NULL
)
324 for (i
= 0; idx_tbl
[i
].pi_name
!= NULL
; i
++) {
325 if (strcmp(string
, idx_tbl
[i
].pi_name
) == 0) {
326 *index
= idx_tbl
[i
].pi_value
;
335 zprop_index_to_string(int prop
, uint64_t index
, const char **string
,
338 zprop_desc_t
*prop_tbl
;
339 const zprop_index_t
*idx_tbl
;
342 if (prop
== ZPROP_INVAL
|| prop
== ZPROP_CONT
)
345 ASSERT(prop
< zprop_get_numprops(type
));
346 prop_tbl
= zprop_get_proptable(type
);
347 if ((idx_tbl
= prop_tbl
[prop
].pd_table
) == NULL
)
350 for (i
= 0; idx_tbl
[i
].pi_name
!= NULL
; i
++) {
351 if (idx_tbl
[i
].pi_value
== index
) {
352 *string
= idx_tbl
[i
].pi_name
;
361 * Return a random valid property value. Used by ztest.
364 zprop_random_value(int prop
, uint64_t seed
, zfs_type_t type
)
366 zprop_desc_t
*prop_tbl
;
367 const zprop_index_t
*idx_tbl
;
369 ASSERT((uint_t
)prop
< zprop_get_numprops(type
));
370 prop_tbl
= zprop_get_proptable(type
);
371 idx_tbl
= prop_tbl
[prop
].pd_table
;
376 return (idx_tbl
[seed
% prop_tbl
[prop
].pd_table_size
].pi_value
);
380 zprop_values(int prop
, zfs_type_t type
)
382 zprop_desc_t
*prop_tbl
;
384 ASSERT(prop
!= ZPROP_INVAL
&& prop
!= ZPROP_CONT
);
385 ASSERT(prop
< zprop_get_numprops(type
));
387 prop_tbl
= zprop_get_proptable(type
);
389 return (prop_tbl
[prop
].pd_values
);
393 * Returns TRUE if the property applies to any of the given dataset types.
395 * If headcheck is set, the check is being made against the head dataset
396 * type of a snapshot which requires to return B_TRUE when the property
397 * is only valid for snapshots.
400 zprop_valid_for_type(int prop
, zfs_type_t type
, boolean_t headcheck
)
402 zprop_desc_t
*prop_tbl
;
404 if (prop
== ZPROP_INVAL
|| prop
== ZPROP_CONT
)
407 ASSERT(prop
< zprop_get_numprops(type
));
408 prop_tbl
= zprop_get_proptable(type
);
409 if (headcheck
&& prop_tbl
[prop
].pd_types
== ZFS_TYPE_SNAPSHOT
)
411 return ((prop_tbl
[prop
].pd_types
& type
) != 0);
415 * For user property names, we allow all lowercase alphanumeric characters, plus
416 * a few useful punctuation characters.
419 zprop_valid_char(char c
)
421 return ((c
>= 'a' && c
<= 'z') ||
422 (c
>= '0' && c
<= '9') ||
423 c
== '-' || c
== '_' || c
== '.' || c
== ':');
429 * Determines the minimum width for the column, and indicates whether it's fixed
430 * or not. Only string columns are non-fixed.
433 zprop_width(int prop
, boolean_t
*fixed
, zfs_type_t type
)
435 zprop_desc_t
*prop_tbl
, *pd
;
436 const zprop_index_t
*idx
;
440 ASSERT(prop
!= ZPROP_INVAL
&& prop
!= ZPROP_CONT
);
441 ASSERT(prop
< zprop_get_numprops(type
));
443 prop_tbl
= zprop_get_proptable(type
);
444 pd
= &prop_tbl
[prop
];
446 if (type
!= ZFS_TYPE_POOL
&& type
!= ZFS_TYPE_VDEV
)
447 type
= ZFS_TYPE_FILESYSTEM
;
449 *fixed
= !pd
->pd_always_flex
;
452 * Start with the width of the column name.
454 ret
= strlen(pd
->pd_colname
);
457 * For fixed-width values, make sure the width is large enough to hold
458 * any possible value.
460 switch (pd
->pd_proptype
) {
461 case PROP_TYPE_NUMBER
:
463 * The maximum length of a human-readable number is 5 characters
464 * ("20.4M", for example).
469 * 'health' is handled specially because it's a number
470 * internally, but displayed as a fixed 8 character string.
472 if (type
== ZFS_TYPE_POOL
&& prop
== ZPOOL_PROP_HEALTH
)
476 case PROP_TYPE_INDEX
:
477 idx
= prop_tbl
[prop
].pd_table
;
478 for (i
= 0; idx
[i
].pi_name
!= NULL
; i
++) {
479 if (strlen(idx
[i
].pi_name
) > ret
)
480 ret
= strlen(idx
[i
].pi_name
);
484 case PROP_TYPE_STRING
:
494 /* Common routines to initialize property tables */
495 EXPORT_SYMBOL(zprop_register_impl
);
496 EXPORT_SYMBOL(zprop_register_string
);
497 EXPORT_SYMBOL(zprop_register_number
);
498 EXPORT_SYMBOL(zprop_register_index
);
499 EXPORT_SYMBOL(zprop_register_hidden
);
501 /* Common routines for zfs and zpool property management */
502 EXPORT_SYMBOL(zprop_iter_common
);
503 EXPORT_SYMBOL(zprop_name_to_prop
);
504 EXPORT_SYMBOL(zprop_string_to_index
);
505 EXPORT_SYMBOL(zprop_index_to_string
);
506 EXPORT_SYMBOL(zprop_random_value
);
507 EXPORT_SYMBOL(zprop_values
);
508 EXPORT_SYMBOL(zprop_valid_for_type
);
509 EXPORT_SYMBOL(zprop_valid_char
);