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