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.
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_znode.h>
38 #include <sys/fs/zfs.h>
41 #include "zfs_deleg.h"
44 #include <sys/systm.h>
45 #include <util/qsort.h>
53 zprop_get_proptable(zfs_type_t type
)
55 if (type
== ZFS_TYPE_POOL
)
56 return (zpool_prop_get_table());
58 return (zfs_prop_get_table());
62 zprop_get_numprops(zfs_type_t type
)
64 if (type
== ZFS_TYPE_POOL
)
65 return (ZPOOL_NUM_PROPS
);
67 return (ZFS_NUM_PROPS
);
71 zprop_register_impl(int prop
, const char *name
, zprop_type_t type
,
72 uint64_t numdefault
, const char *strdefault
, zprop_attr_t attr
,
73 int objset_types
, const char *values
, const char *colname
,
74 boolean_t rightalign
, boolean_t visible
, const zprop_index_t
*idx_tbl
)
76 zprop_desc_t
*prop_tbl
= zprop_get_proptable(objset_types
);
81 ASSERT(pd
->pd_name
== NULL
|| pd
->pd_name
== name
);
83 ASSERT(colname
!= NULL
);
86 pd
->pd_propnum
= prop
;
87 pd
->pd_proptype
= type
;
88 pd
->pd_numdefault
= numdefault
;
89 pd
->pd_strdefault
= strdefault
;
91 pd
->pd_types
= objset_types
;
92 pd
->pd_values
= values
;
93 pd
->pd_colname
= colname
;
94 pd
->pd_rightalign
= rightalign
;
95 pd
->pd_visible
= visible
;
96 pd
->pd_table
= idx_tbl
;
97 pd
->pd_table_size
= 0;
98 while (idx_tbl
&& (idx_tbl
++)->pi_name
!= NULL
)
103 zprop_register_string(int prop
, const char *name
, const char *def
,
104 zprop_attr_t attr
, int objset_types
, const char *values
,
107 zprop_register_impl(prop
, name
, PROP_TYPE_STRING
, 0, def
, attr
,
108 objset_types
, values
, colname
, B_FALSE
, B_TRUE
, NULL
);
113 zprop_register_number(int prop
, const char *name
, uint64_t def
,
114 zprop_attr_t attr
, int objset_types
, const char *values
,
117 zprop_register_impl(prop
, name
, PROP_TYPE_NUMBER
, def
, NULL
, attr
,
118 objset_types
, values
, colname
, B_TRUE
, B_TRUE
, NULL
);
122 zprop_register_index(int prop
, const char *name
, uint64_t def
,
123 zprop_attr_t attr
, int objset_types
, const char *values
,
124 const char *colname
, const zprop_index_t
*idx_tbl
)
126 zprop_register_impl(prop
, name
, PROP_TYPE_INDEX
, def
, NULL
, attr
,
127 objset_types
, values
, colname
, B_TRUE
, B_TRUE
, idx_tbl
);
131 zprop_register_hidden(int prop
, const char *name
, zprop_type_t type
,
132 zprop_attr_t attr
, int objset_types
, const char *colname
)
134 zprop_register_impl(prop
, name
, type
, 0, NULL
, attr
,
135 objset_types
, NULL
, colname
,
136 type
== PROP_TYPE_NUMBER
, B_FALSE
, NULL
);
141 * A comparison function we can use to order indexes into property tables.
144 zprop_compare(const void *arg1
, const void *arg2
)
146 const zprop_desc_t
*p1
= *((zprop_desc_t
**)arg1
);
147 const zprop_desc_t
*p2
= *((zprop_desc_t
**)arg2
);
148 boolean_t p1ro
, p2ro
;
150 p1ro
= (p1
->pd_attr
== PROP_READONLY
);
151 p2ro
= (p2
->pd_attr
== PROP_READONLY
);
154 return (strcmp(p1
->pd_name
, p2
->pd_name
));
156 return (p1ro
? -1 : 1);
160 * Iterate over all properties in the given property table, calling back
161 * into the specified function for each property. We will continue to
162 * iterate until we either reach the end or the callback function returns
163 * something other than ZPROP_CONT.
166 zprop_iter_common(zprop_func func
, void *cb
, boolean_t show_all
,
167 boolean_t ordered
, zfs_type_t type
)
169 int i
, num_props
, size
, prop
;
170 zprop_desc_t
*prop_tbl
;
171 zprop_desc_t
**order
;
173 prop_tbl
= zprop_get_proptable(type
);
174 num_props
= zprop_get_numprops(type
);
175 size
= num_props
* sizeof (zprop_desc_t
*);
178 order
= kmem_alloc(size
, KM_SLEEP
);
180 if ((order
= malloc(size
)) == NULL
)
184 for (int j
= 0; j
< num_props
; j
++)
185 order
[j
] = &prop_tbl
[j
];
188 qsort((void *)order
, num_props
, sizeof (zprop_desc_t
*),
193 for (i
= 0; i
< num_props
; i
++) {
194 if ((order
[i
]->pd_visible
|| show_all
) &&
195 (func(order
[i
]->pd_propnum
, cb
) != ZPROP_CONT
)) {
196 prop
= order
[i
]->pd_propnum
;
202 kmem_free(order
, size
);
210 propname_match(const char *p
, size_t len
, zprop_desc_t
*prop_entry
)
212 const char *propname
= prop_entry
->pd_name
;
214 const char *colname
= prop_entry
->pd_colname
;
218 if (len
== strlen(propname
) &&
219 strncmp(p
, propname
, len
) == 0)
223 if (colname
== NULL
|| len
!= strlen(colname
))
226 for (c
= 0; c
< len
; c
++)
227 if (p
[c
] != tolower(colname
[c
]))
230 return (colname
[c
] == '\0');
236 typedef struct name_to_prop_cb
{
237 const char *propname
;
238 zprop_desc_t
*prop_tbl
;
242 zprop_name_to_prop_cb(int prop
, void *cb_data
)
244 name_to_prop_cb_t
*data
= cb_data
;
246 if (propname_match(data
->propname
, strlen(data
->propname
),
247 &data
->prop_tbl
[prop
]))
254 zprop_name_to_prop(const char *propname
, zfs_type_t type
)
257 name_to_prop_cb_t cb_data
;
259 cb_data
.propname
= propname
;
260 cb_data
.prop_tbl
= zprop_get_proptable(type
);
262 prop
= zprop_iter_common(zprop_name_to_prop_cb
, &cb_data
,
263 B_TRUE
, B_FALSE
, type
);
265 return (prop
== ZPROP_CONT
? ZPROP_INVAL
: prop
);
269 zprop_string_to_index(int prop
, const char *string
, uint64_t *index
,
272 zprop_desc_t
*prop_tbl
;
273 const zprop_index_t
*idx_tbl
;
276 if (prop
== ZPROP_INVAL
|| prop
== ZPROP_CONT
)
279 ASSERT(prop
< zprop_get_numprops(type
));
280 prop_tbl
= zprop_get_proptable(type
);
281 if ((idx_tbl
= prop_tbl
[prop
].pd_table
) == NULL
)
284 for (i
= 0; idx_tbl
[i
].pi_name
!= NULL
; i
++) {
285 if (strcmp(string
, idx_tbl
[i
].pi_name
) == 0) {
286 *index
= idx_tbl
[i
].pi_value
;
295 zprop_index_to_string(int prop
, uint64_t index
, const char **string
,
298 zprop_desc_t
*prop_tbl
;
299 const zprop_index_t
*idx_tbl
;
302 if (prop
== ZPROP_INVAL
|| prop
== ZPROP_CONT
)
305 ASSERT(prop
< zprop_get_numprops(type
));
306 prop_tbl
= zprop_get_proptable(type
);
307 if ((idx_tbl
= prop_tbl
[prop
].pd_table
) == NULL
)
310 for (i
= 0; idx_tbl
[i
].pi_name
!= NULL
; i
++) {
311 if (idx_tbl
[i
].pi_value
== index
) {
312 *string
= idx_tbl
[i
].pi_name
;
321 * Return a random valid property value. Used by ztest.
324 zprop_random_value(int prop
, uint64_t seed
, zfs_type_t type
)
326 zprop_desc_t
*prop_tbl
;
327 const zprop_index_t
*idx_tbl
;
329 ASSERT((uint_t
)prop
< zprop_get_numprops(type
));
330 prop_tbl
= zprop_get_proptable(type
);
331 idx_tbl
= prop_tbl
[prop
].pd_table
;
336 return (idx_tbl
[seed
% prop_tbl
[prop
].pd_table_size
].pi_value
);
340 zprop_values(int prop
, zfs_type_t type
)
342 zprop_desc_t
*prop_tbl
;
344 ASSERT(prop
!= ZPROP_INVAL
&& prop
!= ZPROP_CONT
);
345 ASSERT(prop
< zprop_get_numprops(type
));
347 prop_tbl
= zprop_get_proptable(type
);
349 return (prop_tbl
[prop
].pd_values
);
353 * Returns TRUE if the property applies to any of the given dataset types.
356 zprop_valid_for_type(int prop
, zfs_type_t type
)
358 zprop_desc_t
*prop_tbl
;
360 if (prop
== ZPROP_INVAL
|| prop
== ZPROP_CONT
)
363 ASSERT(prop
< zprop_get_numprops(type
));
364 prop_tbl
= zprop_get_proptable(type
);
365 return ((prop_tbl
[prop
].pd_types
& type
) != 0);
371 * Determines the minimum width for the column, and indicates whether it's fixed
372 * or not. Only string columns are non-fixed.
375 zprop_width(int prop
, boolean_t
*fixed
, zfs_type_t type
)
377 zprop_desc_t
*prop_tbl
, *pd
;
378 const zprop_index_t
*idx
;
382 ASSERT(prop
!= ZPROP_INVAL
&& prop
!= ZPROP_CONT
);
383 ASSERT(prop
< zprop_get_numprops(type
));
385 prop_tbl
= zprop_get_proptable(type
);
386 pd
= &prop_tbl
[prop
];
391 * Start with the width of the column name.
393 ret
= strlen(pd
->pd_colname
);
396 * For fixed-width values, make sure the width is large enough to hold
397 * any possible value.
399 switch (pd
->pd_proptype
) {
400 case PROP_TYPE_NUMBER
:
402 * The maximum length of a human-readable number is 5 characters
403 * ("20.4M", for example).
408 * 'creation' is handled specially because it's a number
409 * internally, but displayed as a date string.
411 if (prop
== ZFS_PROP_CREATION
)
414 case PROP_TYPE_INDEX
:
415 idx
= prop_tbl
[prop
].pd_table
;
416 for (i
= 0; idx
[i
].pi_name
!= NULL
; i
++) {
417 if (strlen(idx
[i
].pi_name
) > ret
)
418 ret
= strlen(idx
[i
].pi_name
);
422 case PROP_TYPE_STRING
: