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_sysfs.h>
38 #include <sys/zfs_znode.h>
39 #include <sys/fs/zfs.h>
42 #include "zfs_deleg.h"
45 #include <linux/sort.h>
46 #define qsort(base, num, size, cmp) \
47 sort(base, num, size, cmp, NULL)
56 zprop_get_proptable(zfs_type_t type
)
58 if (type
== ZFS_TYPE_POOL
)
59 return (zpool_prop_get_table());
61 return (zfs_prop_get_table());
65 zprop_get_numprops(zfs_type_t type
)
67 if (type
== ZFS_TYPE_POOL
)
68 return (ZPOOL_NUM_PROPS
);
70 return (ZFS_NUM_PROPS
);
74 zfs_mod_supported_prop(const char *name
, zfs_type_t type
)
77 * The zfs module spa_feature_table[], whether in-kernel or in libzpool,
78 * always supports all the properties. libzfs needs to query the running
79 * module, via sysfs, to determine which properties are supported.
81 #if defined(_KERNEL) || defined(LIB_ZPOOL_BUILD)
84 struct stat64 statbuf
;
86 boolean_t supported
= B_FALSE
;
89 len
= asprintf(&path
, "%s/%s/%s", ZFS_SYSFS_DIR
,
90 (type
== ZFS_TYPE_POOL
) ? ZFS_SYSFS_POOL_PROPERTIES
:
91 ZFS_SYSFS_DATASET_PROPERTIES
, name
);
94 supported
= !!(stat64(path
, &statbuf
) == 0);
102 zprop_register_impl(int prop
, const char *name
, zprop_type_t type
,
103 uint64_t numdefault
, const char *strdefault
, zprop_attr_t attr
,
104 int objset_types
, const char *values
, const char *colname
,
105 boolean_t rightalign
, boolean_t visible
, const zprop_index_t
*idx_tbl
)
107 zprop_desc_t
*prop_tbl
= zprop_get_proptable(objset_types
);
110 pd
= &prop_tbl
[prop
];
112 ASSERT(pd
->pd_name
== NULL
|| pd
->pd_name
== name
);
113 ASSERT(name
!= NULL
);
114 ASSERT(colname
!= NULL
);
117 pd
->pd_propnum
= prop
;
118 pd
->pd_proptype
= type
;
119 pd
->pd_numdefault
= numdefault
;
120 pd
->pd_strdefault
= strdefault
;
122 pd
->pd_types
= objset_types
;
123 pd
->pd_values
= values
;
124 pd
->pd_colname
= colname
;
125 pd
->pd_rightalign
= rightalign
;
126 pd
->pd_visible
= visible
;
127 pd
->pd_zfs_mod_supported
= zfs_mod_supported_prop(name
, objset_types
);
128 pd
->pd_table
= idx_tbl
;
129 pd
->pd_table_size
= 0;
130 while (idx_tbl
&& (idx_tbl
++)->pi_name
!= NULL
)
135 zprop_register_string(int prop
, const char *name
, const char *def
,
136 zprop_attr_t attr
, int objset_types
, const char *values
,
139 zprop_register_impl(prop
, name
, PROP_TYPE_STRING
, 0, def
, attr
,
140 objset_types
, values
, colname
, B_FALSE
, 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
,
149 zprop_register_impl(prop
, name
, PROP_TYPE_NUMBER
, def
, NULL
, attr
,
150 objset_types
, values
, colname
, B_TRUE
, B_TRUE
, NULL
);
154 zprop_register_index(int prop
, const char *name
, uint64_t def
,
155 zprop_attr_t attr
, int objset_types
, const char *values
,
156 const char *colname
, const zprop_index_t
*idx_tbl
)
158 zprop_register_impl(prop
, name
, PROP_TYPE_INDEX
, def
, NULL
, attr
,
159 objset_types
, values
, colname
, B_TRUE
, B_TRUE
, idx_tbl
);
163 zprop_register_hidden(int prop
, const char *name
, zprop_type_t type
,
164 zprop_attr_t attr
, int objset_types
, const char *colname
)
166 zprop_register_impl(prop
, name
, type
, 0, NULL
, attr
,
167 objset_types
, NULL
, colname
,
168 type
== PROP_TYPE_NUMBER
, B_FALSE
, NULL
);
173 * A comparison function we can use to order indexes into property tables.
176 zprop_compare(const void *arg1
, const void *arg2
)
178 const zprop_desc_t
*p1
= *((zprop_desc_t
**)arg1
);
179 const zprop_desc_t
*p2
= *((zprop_desc_t
**)arg2
);
180 boolean_t p1ro
, p2ro
;
182 p1ro
= (p1
->pd_attr
== PROP_READONLY
);
183 p2ro
= (p2
->pd_attr
== PROP_READONLY
);
186 return (strcmp(p1
->pd_name
, p2
->pd_name
));
188 return (p1ro
? -1 : 1);
192 * Iterate over all properties in the given property table, calling back
193 * into the specified function for each property. We will continue to
194 * iterate until we either reach the end or the callback function returns
195 * something other than ZPROP_CONT.
198 zprop_iter_common(zprop_func func
, void *cb
, boolean_t show_all
,
199 boolean_t ordered
, zfs_type_t type
)
201 int i
, num_props
, size
, prop
;
202 zprop_desc_t
*prop_tbl
;
203 zprop_desc_t
**order
;
205 prop_tbl
= zprop_get_proptable(type
);
206 num_props
= zprop_get_numprops(type
);
207 size
= num_props
* sizeof (zprop_desc_t
*);
210 order
= kmem_alloc(size
, KM_SLEEP
);
212 if ((order
= malloc(size
)) == NULL
)
216 for (int j
= 0; j
< num_props
; j
++)
217 order
[j
] = &prop_tbl
[j
];
220 qsort((void *)order
, num_props
, sizeof (zprop_desc_t
*),
225 for (i
= 0; i
< num_props
; i
++) {
226 if ((order
[i
]->pd_visible
|| show_all
) &&
227 order
[i
]->pd_zfs_mod_supported
&&
228 (func(order
[i
]->pd_propnum
, cb
) != ZPROP_CONT
)) {
229 prop
= order
[i
]->pd_propnum
;
235 kmem_free(order
, size
);
243 propname_match(const char *p
, size_t len
, zprop_desc_t
*prop_entry
)
245 const char *propname
= prop_entry
->pd_name
;
247 const char *colname
= prop_entry
->pd_colname
;
251 if (len
== strlen(propname
) &&
252 strncmp(p
, propname
, len
) == 0)
256 if (colname
== NULL
|| len
!= strlen(colname
))
259 for (c
= 0; c
< len
; c
++)
260 if (p
[c
] != tolower(colname
[c
]))
263 return (colname
[c
] == '\0');
269 typedef struct name_to_prop_cb
{
270 const char *propname
;
271 zprop_desc_t
*prop_tbl
;
275 zprop_name_to_prop_cb(int prop
, void *cb_data
)
277 name_to_prop_cb_t
*data
= cb_data
;
279 if (propname_match(data
->propname
, strlen(data
->propname
),
280 &data
->prop_tbl
[prop
]))
287 zprop_name_to_prop(const char *propname
, zfs_type_t type
)
290 name_to_prop_cb_t cb_data
;
292 cb_data
.propname
= propname
;
293 cb_data
.prop_tbl
= zprop_get_proptable(type
);
295 prop
= zprop_iter_common(zprop_name_to_prop_cb
, &cb_data
,
296 B_TRUE
, B_FALSE
, type
);
298 return (prop
== ZPROP_CONT
? ZPROP_INVAL
: prop
);
302 zprop_string_to_index(int prop
, const char *string
, uint64_t *index
,
305 zprop_desc_t
*prop_tbl
;
306 const zprop_index_t
*idx_tbl
;
309 if (prop
== ZPROP_INVAL
|| prop
== ZPROP_CONT
)
312 ASSERT(prop
< zprop_get_numprops(type
));
313 prop_tbl
= zprop_get_proptable(type
);
314 if ((idx_tbl
= prop_tbl
[prop
].pd_table
) == NULL
)
317 for (i
= 0; idx_tbl
[i
].pi_name
!= NULL
; i
++) {
318 if (strcmp(string
, idx_tbl
[i
].pi_name
) == 0) {
319 *index
= idx_tbl
[i
].pi_value
;
328 zprop_index_to_string(int prop
, uint64_t index
, const char **string
,
331 zprop_desc_t
*prop_tbl
;
332 const zprop_index_t
*idx_tbl
;
335 if (prop
== ZPROP_INVAL
|| prop
== ZPROP_CONT
)
338 ASSERT(prop
< zprop_get_numprops(type
));
339 prop_tbl
= zprop_get_proptable(type
);
340 if ((idx_tbl
= prop_tbl
[prop
].pd_table
) == NULL
)
343 for (i
= 0; idx_tbl
[i
].pi_name
!= NULL
; i
++) {
344 if (idx_tbl
[i
].pi_value
== index
) {
345 *string
= idx_tbl
[i
].pi_name
;
354 * Return a random valid property value. Used by ztest.
357 zprop_random_value(int prop
, uint64_t seed
, zfs_type_t type
)
359 zprop_desc_t
*prop_tbl
;
360 const zprop_index_t
*idx_tbl
;
362 ASSERT((uint_t
)prop
< zprop_get_numprops(type
));
363 prop_tbl
= zprop_get_proptable(type
);
364 idx_tbl
= prop_tbl
[prop
].pd_table
;
369 return (idx_tbl
[seed
% prop_tbl
[prop
].pd_table_size
].pi_value
);
373 zprop_values(int prop
, zfs_type_t type
)
375 zprop_desc_t
*prop_tbl
;
377 ASSERT(prop
!= ZPROP_INVAL
&& prop
!= ZPROP_CONT
);
378 ASSERT(prop
< zprop_get_numprops(type
));
380 prop_tbl
= zprop_get_proptable(type
);
382 return (prop_tbl
[prop
].pd_values
);
386 * Returns TRUE if the property applies to any of the given dataset types.
388 * If headcheck is set, the check is being made against the head dataset
389 * type of a snapshot which requires to return B_TRUE when the property
390 * is only valid for snapshots.
393 zprop_valid_for_type(int prop
, zfs_type_t type
, boolean_t headcheck
)
395 zprop_desc_t
*prop_tbl
;
397 if (prop
== ZPROP_INVAL
|| prop
== ZPROP_CONT
)
400 ASSERT(prop
< zprop_get_numprops(type
));
401 prop_tbl
= zprop_get_proptable(type
);
402 if (headcheck
&& prop_tbl
[prop
].pd_types
== ZFS_TYPE_SNAPSHOT
)
404 return ((prop_tbl
[prop
].pd_types
& type
) != 0);
410 * Determines the minimum width for the column, and indicates whether it's fixed
411 * or not. Only string columns are non-fixed.
414 zprop_width(int prop
, boolean_t
*fixed
, zfs_type_t type
)
416 zprop_desc_t
*prop_tbl
, *pd
;
417 const zprop_index_t
*idx
;
421 ASSERT(prop
!= ZPROP_INVAL
&& prop
!= ZPROP_CONT
);
422 ASSERT(prop
< zprop_get_numprops(type
));
424 prop_tbl
= zprop_get_proptable(type
);
425 pd
= &prop_tbl
[prop
];
430 * Start with the width of the column name.
432 ret
= strlen(pd
->pd_colname
);
435 * For fixed-width values, make sure the width is large enough to hold
436 * any possible value.
438 switch (pd
->pd_proptype
) {
439 case PROP_TYPE_NUMBER
:
441 * The maximum length of a human-readable number is 5 characters
442 * ("20.4M", for example).
447 * 'creation' is handled specially because it's a number
448 * internally, but displayed as a date string.
450 if (prop
== ZFS_PROP_CREATION
)
453 case PROP_TYPE_INDEX
:
454 idx
= prop_tbl
[prop
].pd_table
;
455 for (i
= 0; idx
[i
].pi_name
!= NULL
; i
++) {
456 if (strlen(idx
[i
].pi_name
) > ret
)
457 ret
= strlen(idx
[i
].pi_name
);
461 case PROP_TYPE_STRING
:
472 /* Common routines to initialize property tables */
473 EXPORT_SYMBOL(zprop_register_impl
);
474 EXPORT_SYMBOL(zprop_register_string
);
475 EXPORT_SYMBOL(zprop_register_number
);
476 EXPORT_SYMBOL(zprop_register_index
);
477 EXPORT_SYMBOL(zprop_register_hidden
);
479 /* Common routines for zfs and zpool property management */
480 EXPORT_SYMBOL(zprop_iter_common
);
481 EXPORT_SYMBOL(zprop_name_to_prop
);
482 EXPORT_SYMBOL(zprop_string_to_index
);
483 EXPORT_SYMBOL(zprop_index_to_string
);
484 EXPORT_SYMBOL(zprop_random_value
);
485 EXPORT_SYMBOL(zprop_values
);
486 EXPORT_SYMBOL(zprop_valid_for_type
);