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 2009 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 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
);
81 pd
->pd_propnum
= prop
;
82 pd
->pd_proptype
= type
;
83 pd
->pd_numdefault
= numdefault
;
84 pd
->pd_strdefault
= strdefault
;
86 pd
->pd_types
= objset_types
;
87 pd
->pd_values
= values
;
88 pd
->pd_colname
= colname
;
89 pd
->pd_rightalign
= rightalign
;
90 pd
->pd_visible
= visible
;
91 pd
->pd_table
= idx_tbl
;
95 register_string(int prop
, const char *name
, const char *def
,
96 zprop_attr_t attr
, int objset_types
, const char *values
,
99 register_impl(prop
, name
, PROP_TYPE_STRING
, 0, def
, attr
,
100 objset_types
, values
, colname
, B_FALSE
, B_TRUE
, NULL
);
105 register_number(int prop
, const char *name
, uint64_t def
, zprop_attr_t attr
,
106 int objset_types
, const char *values
, const char *colname
)
108 register_impl(prop
, name
, PROP_TYPE_NUMBER
, def
, NULL
, attr
,
109 objset_types
, values
, colname
, B_TRUE
, B_TRUE
, NULL
);
113 register_index(int prop
, const char *name
, uint64_t def
, zprop_attr_t attr
,
114 int objset_types
, const char *values
, const char *colname
,
115 const zprop_index_t
*idx_tbl
)
117 register_impl(prop
, name
, PROP_TYPE_INDEX
, def
, NULL
, attr
,
118 objset_types
, values
, colname
, B_TRUE
, B_TRUE
, idx_tbl
);
122 register_hidden(int prop
, const char *name
, zprop_type_t type
,
123 zprop_attr_t attr
, int objset_types
, const char *colname
)
125 register_impl(prop
, name
, type
, 0, NULL
, attr
,
126 objset_types
, NULL
, colname
, B_FALSE
, B_FALSE
, NULL
);
131 * A comparison function we can use to order indexes into property tables.
134 zprop_compare(const void *arg1
, const void *arg2
)
136 const zprop_desc_t
*p1
= *((zprop_desc_t
**)arg1
);
137 const zprop_desc_t
*p2
= *((zprop_desc_t
**)arg2
);
138 boolean_t p1ro
, p2ro
;
140 p1ro
= (p1
->pd_attr
== PROP_READONLY
);
141 p2ro
= (p2
->pd_attr
== PROP_READONLY
);
144 return (strcmp(p1
->pd_name
, p2
->pd_name
));
146 return (p1ro
? -1 : 1);
150 * Iterate over all properties in the given property table, calling back
151 * into the specified function for each property. We will continue to
152 * iterate until we either reach the end or the callback function returns
153 * something other than ZPROP_CONT.
156 zprop_iter_common(zprop_func func
, void *cb
, boolean_t show_all
,
157 boolean_t ordered
, zfs_type_t type
)
159 int i
, num_props
, size
, prop
;
160 zprop_desc_t
*prop_tbl
;
161 zprop_desc_t
**order
;
163 prop_tbl
= zprop_get_proptable(type
);
164 num_props
= zprop_get_numprops(type
);
165 size
= num_props
* sizeof (zprop_desc_t
*);
168 order
= kmem_alloc(size
, KM_SLEEP
);
170 if ((order
= malloc(size
)) == NULL
)
174 for (int j
= 0; j
< num_props
; j
++)
175 order
[j
] = &prop_tbl
[j
];
178 qsort((void *)order
, num_props
, sizeof (zprop_desc_t
*),
183 for (i
= 0; i
< num_props
; i
++) {
184 if ((order
[i
]->pd_visible
|| show_all
) &&
185 (func(order
[i
]->pd_propnum
, cb
) != ZPROP_CONT
)) {
186 prop
= order
[i
]->pd_propnum
;
192 kmem_free(order
, size
);
200 propname_match(const char *p
, size_t len
, zprop_desc_t
*prop_entry
)
202 const char *propname
= prop_entry
->pd_name
;
204 const char *colname
= prop_entry
->pd_colname
;
208 if (len
== strlen(propname
) &&
209 strncmp(p
, propname
, len
) == 0)
213 if (colname
== NULL
|| len
!= strlen(colname
))
216 for (c
= 0; c
< len
; c
++)
217 if (p
[c
] != tolower(colname
[c
]))
220 return (colname
[c
] == '\0');
226 typedef struct name_to_prop_cb
{
227 const char *propname
;
228 zprop_desc_t
*prop_tbl
;
232 zprop_name_to_prop_cb(int prop
, void *cb_data
)
234 name_to_prop_cb_t
*data
= cb_data
;
236 if (propname_match(data
->propname
, strlen(data
->propname
),
237 &data
->prop_tbl
[prop
]))
244 zprop_name_to_prop(const char *propname
, zfs_type_t type
)
247 name_to_prop_cb_t cb_data
;
249 cb_data
.propname
= propname
;
250 cb_data
.prop_tbl
= zprop_get_proptable(type
);
252 prop
= zprop_iter_common(zprop_name_to_prop_cb
, &cb_data
,
253 B_TRUE
, B_FALSE
, type
);
255 return (prop
== ZPROP_CONT
? ZPROP_INVAL
: prop
);
259 zprop_string_to_index(int prop
, const char *string
, uint64_t *index
,
262 zprop_desc_t
*prop_tbl
;
263 const zprop_index_t
*idx_tbl
;
266 if (prop
== ZPROP_INVAL
|| prop
== ZPROP_CONT
)
269 ASSERT(prop
< zprop_get_numprops(type
));
270 prop_tbl
= zprop_get_proptable(type
);
271 if ((idx_tbl
= prop_tbl
[prop
].pd_table
) == NULL
)
274 for (i
= 0; idx_tbl
[i
].pi_name
!= NULL
; i
++) {
275 if (strcmp(string
, idx_tbl
[i
].pi_name
) == 0) {
276 *index
= idx_tbl
[i
].pi_value
;
285 zprop_index_to_string(int prop
, uint64_t index
, const char **string
,
288 zprop_desc_t
*prop_tbl
;
289 const zprop_index_t
*idx_tbl
;
292 if (prop
== ZPROP_INVAL
|| prop
== ZPROP_CONT
)
295 ASSERT(prop
< zprop_get_numprops(type
));
296 prop_tbl
= zprop_get_proptable(type
);
297 if ((idx_tbl
= prop_tbl
[prop
].pd_table
) == NULL
)
300 for (i
= 0; idx_tbl
[i
].pi_name
!= NULL
; i
++) {
301 if (idx_tbl
[i
].pi_value
== index
) {
302 *string
= idx_tbl
[i
].pi_name
;
311 zprop_values(int prop
, zfs_type_t type
)
313 zprop_desc_t
*prop_tbl
;
315 ASSERT(prop
!= ZPROP_INVAL
&& prop
!= ZPROP_CONT
);
316 ASSERT(prop
< zprop_get_numprops(type
));
318 prop_tbl
= zprop_get_proptable(type
);
320 return (prop_tbl
[prop
].pd_values
);
324 * Returns TRUE if the property applies to any of the given dataset types.
327 zprop_valid_for_type(int prop
, zfs_type_t type
)
329 zprop_desc_t
*prop_tbl
;
331 if (prop
== ZPROP_INVAL
|| prop
== ZPROP_CONT
)
334 ASSERT(prop
< zprop_get_numprops(type
));
335 prop_tbl
= zprop_get_proptable(type
);
336 return ((prop_tbl
[prop
].pd_types
& type
) != 0);
342 * Determines the minimum width for the column, and indicates whether it's fixed
343 * or not. Only string columns are non-fixed.
346 zprop_width(int prop
, boolean_t
*fixed
, zfs_type_t type
)
348 zprop_desc_t
*prop_tbl
, *pd
;
349 const zprop_index_t
*idx
;
353 ASSERT(prop
!= ZPROP_INVAL
&& prop
!= ZPROP_CONT
);
354 ASSERT(prop
< zprop_get_numprops(type
));
356 prop_tbl
= zprop_get_proptable(type
);
357 pd
= &prop_tbl
[prop
];
362 * Start with the width of the column name.
364 ret
= strlen(pd
->pd_colname
);
367 * For fixed-width values, make sure the width is large enough to hold
368 * any possible value.
370 switch (pd
->pd_proptype
) {
371 case PROP_TYPE_NUMBER
:
373 * The maximum length of a human-readable number is 5 characters
374 * ("20.4M", for example).
379 * 'creation' is handled specially because it's a number
380 * internally, but displayed as a date string.
382 if (prop
== ZFS_PROP_CREATION
)
385 case PROP_TYPE_INDEX
:
386 idx
= prop_tbl
[prop
].pd_table
;
387 for (i
= 0; idx
[i
].pi_name
!= NULL
; i
++) {
388 if (strlen(idx
[i
].pi_name
) > ret
)
389 ret
= strlen(idx
[i
].pi_name
);
393 case PROP_TYPE_STRING
: