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