Print this page
2882 implement libzfs_core
2883 changing "canmount" property to "on" should not always remount dataset
2900 "zfs snapshot" should be able to create multiple, arbitrary snapshots at once
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Chris Siden <christopher.siden@delphix.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Bill Pijewski <wdp@joyent.com>
Reviewed by: Dan Kruchinin <dan.kruchinin@gmail.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/common/zfs/zprop_common.c
+++ new/usr/src/common/zfs/zprop_common.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 +/*
26 + * Copyright (c) 2012 by Delphix. All rights reserved.
27 + */
25 28
26 29 /*
27 30 * Common routines used by zfs and zpool property management.
28 31 */
29 32
30 33 #include <sys/zio.h>
31 34 #include <sys/spa.h>
32 35 #include <sys/zfs_acl.h>
33 36 #include <sys/zfs_ioctl.h>
34 37 #include <sys/zfs_znode.h>
35 38 #include <sys/fs/zfs.h>
36 39
37 40 #include "zfs_prop.h"
38 41 #include "zfs_deleg.h"
39 42
40 43 #if defined(_KERNEL)
41 44 #include <sys/systm.h>
42 45 #include <util/qsort.h>
43 46 #else
44 47 #include <stdlib.h>
45 48 #include <string.h>
46 49 #include <ctype.h>
47 50 #endif
48 51
49 52 static zprop_desc_t *
50 53 zprop_get_proptable(zfs_type_t type)
51 54 {
52 55 if (type == ZFS_TYPE_POOL)
53 56 return (zpool_prop_get_table());
54 57 else
55 58 return (zfs_prop_get_table());
56 59 }
57 60
58 61 static int
59 62 zprop_get_numprops(zfs_type_t type)
60 63 {
61 64 if (type == ZFS_TYPE_POOL)
62 65 return (ZPOOL_NUM_PROPS);
63 66 else
64 67 return (ZFS_NUM_PROPS);
65 68 }
66 69
67 70 void
68 71 zprop_register_impl(int prop, const char *name, zprop_type_t type,
69 72 uint64_t numdefault, const char *strdefault, zprop_attr_t attr,
70 73 int objset_types, const char *values, const char *colname,
71 74 boolean_t rightalign, boolean_t visible, const zprop_index_t *idx_tbl)
72 75 {
73 76 zprop_desc_t *prop_tbl = zprop_get_proptable(objset_types);
74 77 zprop_desc_t *pd;
75 78
76 79 pd = &prop_tbl[prop];
77 80
78 81 ASSERT(pd->pd_name == NULL || pd->pd_name == name);
79 82 ASSERT(name != NULL);
80 83 ASSERT(colname != NULL);
81 84
82 85 pd->pd_name = name;
83 86 pd->pd_propnum = prop;
84 87 pd->pd_proptype = type;
85 88 pd->pd_numdefault = numdefault;
86 89 pd->pd_strdefault = strdefault;
87 90 pd->pd_attr = attr;
88 91 pd->pd_types = objset_types;
89 92 pd->pd_values = values;
90 93 pd->pd_colname = colname;
91 94 pd->pd_rightalign = rightalign;
92 95 pd->pd_visible = visible;
93 96 pd->pd_table = idx_tbl;
94 97 pd->pd_table_size = 0;
95 98 while (idx_tbl && (idx_tbl++)->pi_name != NULL)
96 99 pd->pd_table_size++;
97 100 }
98 101
99 102 void
100 103 zprop_register_string(int prop, const char *name, const char *def,
101 104 zprop_attr_t attr, int objset_types, const char *values,
102 105 const char *colname)
103 106 {
104 107 zprop_register_impl(prop, name, PROP_TYPE_STRING, 0, def, attr,
105 108 objset_types, values, colname, B_FALSE, B_TRUE, NULL);
106 109
107 110 }
108 111
109 112 void
110 113 zprop_register_number(int prop, const char *name, uint64_t def,
111 114 zprop_attr_t attr, int objset_types, const char *values,
112 115 const char *colname)
113 116 {
114 117 zprop_register_impl(prop, name, PROP_TYPE_NUMBER, def, NULL, attr,
115 118 objset_types, values, colname, B_TRUE, B_TRUE, NULL);
116 119 }
117 120
118 121 void
119 122 zprop_register_index(int prop, const char *name, uint64_t def,
120 123 zprop_attr_t attr, int objset_types, const char *values,
121 124 const char *colname, const zprop_index_t *idx_tbl)
↓ open down ↓ |
87 lines elided |
↑ open up ↑ |
122 125 {
123 126 zprop_register_impl(prop, name, PROP_TYPE_INDEX, def, NULL, attr,
124 127 objset_types, values, colname, B_TRUE, B_TRUE, idx_tbl);
125 128 }
126 129
127 130 void
128 131 zprop_register_hidden(int prop, const char *name, zprop_type_t type,
129 132 zprop_attr_t attr, int objset_types, const char *colname)
130 133 {
131 134 zprop_register_impl(prop, name, type, 0, NULL, attr,
132 - objset_types, NULL, colname, B_FALSE, B_FALSE, NULL);
135 + objset_types, NULL, colname,
136 + type == PROP_TYPE_NUMBER, B_FALSE, NULL);
133 137 }
134 138
135 139
136 140 /*
137 141 * A comparison function we can use to order indexes into property tables.
138 142 */
139 143 static int
140 144 zprop_compare(const void *arg1, const void *arg2)
141 145 {
142 146 const zprop_desc_t *p1 = *((zprop_desc_t **)arg1);
143 147 const zprop_desc_t *p2 = *((zprop_desc_t **)arg2);
144 148 boolean_t p1ro, p2ro;
145 149
146 150 p1ro = (p1->pd_attr == PROP_READONLY);
147 151 p2ro = (p2->pd_attr == PROP_READONLY);
148 152
149 153 if (p1ro == p2ro)
150 154 return (strcmp(p1->pd_name, p2->pd_name));
151 155
152 156 return (p1ro ? -1 : 1);
153 157 }
154 158
155 159 /*
156 160 * Iterate over all properties in the given property table, calling back
157 161 * into the specified function for each property. We will continue to
158 162 * iterate until we either reach the end or the callback function returns
159 163 * something other than ZPROP_CONT.
160 164 */
161 165 int
162 166 zprop_iter_common(zprop_func func, void *cb, boolean_t show_all,
163 167 boolean_t ordered, zfs_type_t type)
164 168 {
165 169 int i, num_props, size, prop;
166 170 zprop_desc_t *prop_tbl;
167 171 zprop_desc_t **order;
168 172
169 173 prop_tbl = zprop_get_proptable(type);
170 174 num_props = zprop_get_numprops(type);
171 175 size = num_props * sizeof (zprop_desc_t *);
172 176
173 177 #if defined(_KERNEL)
174 178 order = kmem_alloc(size, KM_SLEEP);
175 179 #else
176 180 if ((order = malloc(size)) == NULL)
177 181 return (ZPROP_CONT);
178 182 #endif
179 183
180 184 for (int j = 0; j < num_props; j++)
181 185 order[j] = &prop_tbl[j];
182 186
183 187 if (ordered) {
184 188 qsort((void *)order, num_props, sizeof (zprop_desc_t *),
185 189 zprop_compare);
186 190 }
187 191
188 192 prop = ZPROP_CONT;
189 193 for (i = 0; i < num_props; i++) {
190 194 if ((order[i]->pd_visible || show_all) &&
191 195 (func(order[i]->pd_propnum, cb) != ZPROP_CONT)) {
192 196 prop = order[i]->pd_propnum;
193 197 break;
194 198 }
195 199 }
196 200
197 201 #if defined(_KERNEL)
198 202 kmem_free(order, size);
199 203 #else
200 204 free(order);
201 205 #endif
202 206 return (prop);
203 207 }
204 208
205 209 static boolean_t
206 210 propname_match(const char *p, size_t len, zprop_desc_t *prop_entry)
207 211 {
208 212 const char *propname = prop_entry->pd_name;
209 213 #ifndef _KERNEL
210 214 const char *colname = prop_entry->pd_colname;
211 215 int c;
212 216 #endif
213 217
214 218 if (len == strlen(propname) &&
215 219 strncmp(p, propname, len) == 0)
216 220 return (B_TRUE);
217 221
218 222 #ifndef _KERNEL
219 223 if (colname == NULL || len != strlen(colname))
220 224 return (B_FALSE);
221 225
222 226 for (c = 0; c < len; c++)
223 227 if (p[c] != tolower(colname[c]))
224 228 break;
225 229
226 230 return (colname[c] == '\0');
227 231 #else
228 232 return (B_FALSE);
229 233 #endif
230 234 }
231 235
232 236 typedef struct name_to_prop_cb {
233 237 const char *propname;
234 238 zprop_desc_t *prop_tbl;
235 239 } name_to_prop_cb_t;
236 240
237 241 static int
238 242 zprop_name_to_prop_cb(int prop, void *cb_data)
239 243 {
240 244 name_to_prop_cb_t *data = cb_data;
241 245
242 246 if (propname_match(data->propname, strlen(data->propname),
243 247 &data->prop_tbl[prop]))
244 248 return (prop);
245 249
246 250 return (ZPROP_CONT);
247 251 }
248 252
249 253 int
250 254 zprop_name_to_prop(const char *propname, zfs_type_t type)
251 255 {
252 256 int prop;
253 257 name_to_prop_cb_t cb_data;
254 258
255 259 cb_data.propname = propname;
256 260 cb_data.prop_tbl = zprop_get_proptable(type);
257 261
258 262 prop = zprop_iter_common(zprop_name_to_prop_cb, &cb_data,
259 263 B_TRUE, B_FALSE, type);
260 264
261 265 return (prop == ZPROP_CONT ? ZPROP_INVAL : prop);
262 266 }
263 267
264 268 int
265 269 zprop_string_to_index(int prop, const char *string, uint64_t *index,
266 270 zfs_type_t type)
267 271 {
268 272 zprop_desc_t *prop_tbl;
269 273 const zprop_index_t *idx_tbl;
270 274 int i;
271 275
272 276 if (prop == ZPROP_INVAL || prop == ZPROP_CONT)
273 277 return (-1);
274 278
275 279 ASSERT(prop < zprop_get_numprops(type));
276 280 prop_tbl = zprop_get_proptable(type);
277 281 if ((idx_tbl = prop_tbl[prop].pd_table) == NULL)
278 282 return (-1);
279 283
280 284 for (i = 0; idx_tbl[i].pi_name != NULL; i++) {
281 285 if (strcmp(string, idx_tbl[i].pi_name) == 0) {
282 286 *index = idx_tbl[i].pi_value;
283 287 return (0);
284 288 }
285 289 }
286 290
287 291 return (-1);
288 292 }
289 293
290 294 int
291 295 zprop_index_to_string(int prop, uint64_t index, const char **string,
292 296 zfs_type_t type)
293 297 {
294 298 zprop_desc_t *prop_tbl;
295 299 const zprop_index_t *idx_tbl;
296 300 int i;
297 301
298 302 if (prop == ZPROP_INVAL || prop == ZPROP_CONT)
299 303 return (-1);
300 304
301 305 ASSERT(prop < zprop_get_numprops(type));
302 306 prop_tbl = zprop_get_proptable(type);
303 307 if ((idx_tbl = prop_tbl[prop].pd_table) == NULL)
304 308 return (-1);
305 309
306 310 for (i = 0; idx_tbl[i].pi_name != NULL; i++) {
307 311 if (idx_tbl[i].pi_value == index) {
308 312 *string = idx_tbl[i].pi_name;
309 313 return (0);
310 314 }
311 315 }
312 316
313 317 return (-1);
314 318 }
315 319
316 320 /*
317 321 * Return a random valid property value. Used by ztest.
318 322 */
319 323 uint64_t
320 324 zprop_random_value(int prop, uint64_t seed, zfs_type_t type)
321 325 {
322 326 zprop_desc_t *prop_tbl;
323 327 const zprop_index_t *idx_tbl;
324 328
325 329 ASSERT((uint_t)prop < zprop_get_numprops(type));
326 330 prop_tbl = zprop_get_proptable(type);
327 331 idx_tbl = prop_tbl[prop].pd_table;
328 332
329 333 if (idx_tbl == NULL)
330 334 return (seed);
331 335
332 336 return (idx_tbl[seed % prop_tbl[prop].pd_table_size].pi_value);
333 337 }
334 338
335 339 const char *
336 340 zprop_values(int prop, zfs_type_t type)
337 341 {
338 342 zprop_desc_t *prop_tbl;
339 343
340 344 ASSERT(prop != ZPROP_INVAL && prop != ZPROP_CONT);
341 345 ASSERT(prop < zprop_get_numprops(type));
342 346
343 347 prop_tbl = zprop_get_proptable(type);
344 348
345 349 return (prop_tbl[prop].pd_values);
346 350 }
347 351
348 352 /*
349 353 * Returns TRUE if the property applies to any of the given dataset types.
350 354 */
351 355 boolean_t
352 356 zprop_valid_for_type(int prop, zfs_type_t type)
353 357 {
354 358 zprop_desc_t *prop_tbl;
355 359
356 360 if (prop == ZPROP_INVAL || prop == ZPROP_CONT)
357 361 return (B_FALSE);
358 362
359 363 ASSERT(prop < zprop_get_numprops(type));
360 364 prop_tbl = zprop_get_proptable(type);
361 365 return ((prop_tbl[prop].pd_types & type) != 0);
362 366 }
363 367
364 368 #ifndef _KERNEL
365 369
366 370 /*
367 371 * Determines the minimum width for the column, and indicates whether it's fixed
368 372 * or not. Only string columns are non-fixed.
369 373 */
370 374 size_t
371 375 zprop_width(int prop, boolean_t *fixed, zfs_type_t type)
372 376 {
373 377 zprop_desc_t *prop_tbl, *pd;
374 378 const zprop_index_t *idx;
375 379 size_t ret;
376 380 int i;
377 381
378 382 ASSERT(prop != ZPROP_INVAL && prop != ZPROP_CONT);
379 383 ASSERT(prop < zprop_get_numprops(type));
380 384
381 385 prop_tbl = zprop_get_proptable(type);
382 386 pd = &prop_tbl[prop];
383 387
384 388 *fixed = B_TRUE;
385 389
386 390 /*
387 391 * Start with the width of the column name.
388 392 */
389 393 ret = strlen(pd->pd_colname);
390 394
391 395 /*
392 396 * For fixed-width values, make sure the width is large enough to hold
393 397 * any possible value.
394 398 */
395 399 switch (pd->pd_proptype) {
396 400 case PROP_TYPE_NUMBER:
397 401 /*
398 402 * The maximum length of a human-readable number is 5 characters
399 403 * ("20.4M", for example).
400 404 */
401 405 if (ret < 5)
402 406 ret = 5;
403 407 /*
404 408 * 'creation' is handled specially because it's a number
405 409 * internally, but displayed as a date string.
406 410 */
407 411 if (prop == ZFS_PROP_CREATION)
408 412 *fixed = B_FALSE;
409 413 break;
410 414 case PROP_TYPE_INDEX:
411 415 idx = prop_tbl[prop].pd_table;
412 416 for (i = 0; idx[i].pi_name != NULL; i++) {
413 417 if (strlen(idx[i].pi_name) > ret)
414 418 ret = strlen(idx[i].pi_name);
415 419 }
416 420 break;
417 421
418 422 case PROP_TYPE_STRING:
419 423 *fixed = B_FALSE;
420 424 break;
421 425 }
422 426
423 427 return (ret);
424 428 }
425 429
426 430 #endif
↓ open down ↓ |
284 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX