1990b4856Slling /* 2990b4856Slling * CDDL HEADER START 3990b4856Slling * 4990b4856Slling * The contents of this file are subject to the terms of the 5990b4856Slling * Common Development and Distribution License (the "License"). 6990b4856Slling * You may not use this file except in compliance with the License. 7990b4856Slling * 8990b4856Slling * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9990b4856Slling * or http://www.opensolaris.org/os/licensing. 10990b4856Slling * See the License for the specific language governing permissions 11990b4856Slling * and limitations under the License. 12990b4856Slling * 13990b4856Slling * When distributing Covered Code, include this CDDL HEADER in each 14990b4856Slling * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15990b4856Slling * If applicable, add the following below this CDDL HEADER, with the 16990b4856Slling * fields enclosed by brackets "[]" replaced with your own identifying 17990b4856Slling * information: Portions Copyright [yyyy] [name of copyright owner] 18990b4856Slling * 19990b4856Slling * CDDL HEADER END 20990b4856Slling */ 21990b4856Slling /* 22*79912923Sgw * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23990b4856Slling * Use is subject to license terms. 24990b4856Slling */ 25990b4856Slling 26990b4856Slling #pragma ident "%Z%%M% %I% %E% SMI" 27990b4856Slling 28990b4856Slling /* 29990b4856Slling * Common routines used by zfs and zpool property management. 30990b4856Slling */ 31990b4856Slling 32990b4856Slling #include <sys/zio.h> 33990b4856Slling #include <sys/spa.h> 34990b4856Slling #include <sys/zfs_acl.h> 35990b4856Slling #include <sys/zfs_ioctl.h> 36990b4856Slling #include <sys/zfs_znode.h> 37990b4856Slling #include <sys/fs/zfs.h> 38990b4856Slling 39990b4856Slling #include "zfs_prop.h" 40990b4856Slling #include "zfs_deleg.h" 41990b4856Slling 42990b4856Slling #if defined(_KERNEL) 43990b4856Slling #include <sys/systm.h> 44990b4856Slling #include <util/qsort.h> 45990b4856Slling #else 46990b4856Slling #include <stdlib.h> 47990b4856Slling #include <string.h> 48990b4856Slling #include <ctype.h> 49990b4856Slling #endif 50990b4856Slling 51990b4856Slling static zprop_desc_t * 52990b4856Slling zprop_get_proptable(zfs_type_t type) 53990b4856Slling { 54990b4856Slling if (type == ZFS_TYPE_POOL) 55990b4856Slling return (zpool_prop_get_table()); 56990b4856Slling else 57990b4856Slling return (zfs_prop_get_table()); 58990b4856Slling } 59990b4856Slling 60990b4856Slling static int 61990b4856Slling zprop_get_numprops(zfs_type_t type) 62990b4856Slling { 63990b4856Slling if (type == ZFS_TYPE_POOL) 64990b4856Slling return (ZPOOL_NUM_PROPS); 65990b4856Slling else 66990b4856Slling return (ZFS_NUM_PROPS); 67990b4856Slling } 68990b4856Slling 69990b4856Slling void 70990b4856Slling register_impl(int prop, const char *name, zprop_type_t type, 71990b4856Slling uint64_t numdefault, const char *strdefault, zprop_attr_t attr, 72990b4856Slling int objset_types, const char *values, const char *colname, 73990b4856Slling boolean_t rightalign, boolean_t visible, const zprop_index_t *idx_tbl) 74990b4856Slling { 75990b4856Slling zprop_desc_t *prop_tbl = zprop_get_proptable(objset_types); 76990b4856Slling zprop_desc_t *pd; 77990b4856Slling 78990b4856Slling pd = &prop_tbl[prop]; 79990b4856Slling 80990b4856Slling ASSERT(pd->pd_name == NULL || pd->pd_name == name); 81990b4856Slling 82990b4856Slling pd->pd_name = name; 83990b4856Slling pd->pd_propnum = prop; 84990b4856Slling pd->pd_proptype = type; 85990b4856Slling pd->pd_numdefault = numdefault; 86990b4856Slling pd->pd_strdefault = strdefault; 87990b4856Slling pd->pd_attr = attr; 88990b4856Slling pd->pd_types = objset_types; 89990b4856Slling pd->pd_values = values; 90990b4856Slling pd->pd_colname = colname; 91990b4856Slling pd->pd_rightalign = rightalign; 92990b4856Slling pd->pd_visible = visible; 93990b4856Slling pd->pd_table = idx_tbl; 94990b4856Slling } 95990b4856Slling 96990b4856Slling void 97990b4856Slling register_string(int prop, const char *name, const char *def, 98990b4856Slling zprop_attr_t attr, int objset_types, const char *values, 99990b4856Slling const char *colname) 100990b4856Slling { 101990b4856Slling register_impl(prop, name, PROP_TYPE_STRING, 0, def, attr, 102990b4856Slling objset_types, values, colname, B_FALSE, B_TRUE, NULL); 103990b4856Slling 104990b4856Slling } 105990b4856Slling 106990b4856Slling void 107990b4856Slling register_number(int prop, const char *name, uint64_t def, zprop_attr_t attr, 108990b4856Slling int objset_types, const char *values, const char *colname) 109990b4856Slling { 110990b4856Slling register_impl(prop, name, PROP_TYPE_NUMBER, def, NULL, attr, 111990b4856Slling objset_types, values, colname, B_TRUE, B_TRUE, NULL); 112990b4856Slling } 113990b4856Slling 114990b4856Slling void 115990b4856Slling register_index(int prop, const char *name, uint64_t def, zprop_attr_t attr, 116990b4856Slling int objset_types, const char *values, const char *colname, 117990b4856Slling const zprop_index_t *idx_tbl) 118990b4856Slling { 119990b4856Slling register_impl(prop, name, PROP_TYPE_INDEX, def, NULL, attr, 120990b4856Slling objset_types, values, colname, B_TRUE, B_TRUE, idx_tbl); 121990b4856Slling } 122990b4856Slling 123990b4856Slling void 124990b4856Slling register_hidden(int prop, const char *name, zprop_type_t type, 125990b4856Slling zprop_attr_t attr, int objset_types, const char *colname) 126990b4856Slling { 127990b4856Slling register_impl(prop, name, type, 0, NULL, attr, 128990b4856Slling objset_types, NULL, colname, B_FALSE, B_FALSE, NULL); 129990b4856Slling } 130990b4856Slling 131990b4856Slling 132990b4856Slling /* 133990b4856Slling * A comparison function we can use to order indexes into property tables. 134990b4856Slling */ 135990b4856Slling static int 136990b4856Slling zprop_compare(const void *arg1, const void *arg2) 137990b4856Slling { 138990b4856Slling const zprop_desc_t *p1 = *((zprop_desc_t **)arg1); 139990b4856Slling const zprop_desc_t *p2 = *((zprop_desc_t **)arg2); 140990b4856Slling boolean_t p1ro, p2ro; 141990b4856Slling 142990b4856Slling p1ro = (p1->pd_attr == PROP_READONLY); 143990b4856Slling p2ro = (p2->pd_attr == PROP_READONLY); 144990b4856Slling 145990b4856Slling if (p1ro == p2ro) 146990b4856Slling return (strcmp(p1->pd_name, p2->pd_name)); 147990b4856Slling 148990b4856Slling return (p1ro ? -1 : 1); 149990b4856Slling } 150990b4856Slling 151990b4856Slling /* 152990b4856Slling * Iterate over all properties in the given property table, calling back 153990b4856Slling * into the specified function for each property. We will continue to 154990b4856Slling * iterate until we either reach the end or the callback function returns 155990b4856Slling * something other than ZPROP_CONT. 156990b4856Slling */ 157990b4856Slling int 158990b4856Slling zprop_iter_common(zprop_func func, void *cb, boolean_t show_all, 159990b4856Slling boolean_t ordered, zfs_type_t type) 160990b4856Slling { 161990b4856Slling int i, num_props, size, prop; 162990b4856Slling zprop_desc_t *prop_tbl; 163990b4856Slling zprop_desc_t **order; 164990b4856Slling 165990b4856Slling prop_tbl = zprop_get_proptable(type); 166990b4856Slling num_props = zprop_get_numprops(type); 167990b4856Slling size = num_props * sizeof (zprop_desc_t *); 168990b4856Slling 169990b4856Slling #if defined(_KERNEL) 170990b4856Slling order = kmem_alloc(size, KM_SLEEP); 171990b4856Slling #else 172990b4856Slling if ((order = malloc(size)) == NULL) 173990b4856Slling return (ZPROP_CONT); 174990b4856Slling #endif 175990b4856Slling 176990b4856Slling for (int j = 0; j < num_props; j++) 177990b4856Slling order[j] = &prop_tbl[j]; 178990b4856Slling 179990b4856Slling if (ordered) { 180990b4856Slling qsort((void *)order, num_props, sizeof (zprop_desc_t *), 181990b4856Slling zprop_compare); 182990b4856Slling } 183990b4856Slling 184990b4856Slling prop = ZPROP_CONT; 185990b4856Slling for (i = 0; i < num_props; i++) { 186990b4856Slling if ((order[i]->pd_visible || show_all) && 187990b4856Slling (func(order[i]->pd_propnum, cb) != ZPROP_CONT)) { 188990b4856Slling prop = order[i]->pd_propnum; 189990b4856Slling break; 190990b4856Slling } 191990b4856Slling } 192990b4856Slling 193990b4856Slling #if defined(_KERNEL) 194990b4856Slling kmem_free(order, size); 195990b4856Slling #else 196990b4856Slling free(order); 197990b4856Slling #endif 198990b4856Slling return (prop); 199990b4856Slling } 200990b4856Slling 201990b4856Slling static boolean_t 202990b4856Slling propname_match(const char *p, size_t len, zprop_desc_t *prop_entry) 203990b4856Slling { 204990b4856Slling const char *propname = prop_entry->pd_name; 205990b4856Slling #ifndef _KERNEL 206990b4856Slling const char *colname = prop_entry->pd_colname; 207990b4856Slling int c; 208990b4856Slling 209990b4856Slling if (colname == NULL) 210990b4856Slling return (B_FALSE); 211990b4856Slling #endif 212990b4856Slling 213990b4856Slling if (len == strlen(propname) && 214990b4856Slling strncmp(p, propname, len) == 0) 215990b4856Slling return (B_TRUE); 216990b4856Slling 217990b4856Slling #ifndef _KERNEL 218990b4856Slling if (len != strlen(colname)) 219990b4856Slling return (B_FALSE); 220990b4856Slling 221990b4856Slling for (c = 0; c < len; c++) 222990b4856Slling if (p[c] != tolower(colname[c])) 223990b4856Slling break; 224990b4856Slling 225990b4856Slling return (colname[c] == '\0'); 226990b4856Slling #else 227990b4856Slling return (B_FALSE); 228990b4856Slling #endif 229990b4856Slling } 230990b4856Slling 231990b4856Slling typedef struct name_to_prop_cb { 232990b4856Slling const char *propname; 233990b4856Slling zprop_desc_t *prop_tbl; 234990b4856Slling } name_to_prop_cb_t; 235990b4856Slling 236990b4856Slling static int 237990b4856Slling zprop_name_to_prop_cb(int prop, void *cb_data) 238990b4856Slling { 239990b4856Slling name_to_prop_cb_t *data = cb_data; 240990b4856Slling 241990b4856Slling if (propname_match(data->propname, strlen(data->propname), 242990b4856Slling &data->prop_tbl[prop])) 243990b4856Slling return (prop); 244990b4856Slling 245990b4856Slling return (ZPROP_CONT); 246990b4856Slling } 247990b4856Slling 248990b4856Slling int 249990b4856Slling zprop_name_to_prop(const char *propname, zfs_type_t type) 250990b4856Slling { 251990b4856Slling int prop; 252990b4856Slling name_to_prop_cb_t cb_data; 253990b4856Slling 254990b4856Slling cb_data.propname = propname; 255990b4856Slling cb_data.prop_tbl = zprop_get_proptable(type); 256990b4856Slling 257990b4856Slling prop = zprop_iter_common(zprop_name_to_prop_cb, &cb_data, 258990b4856Slling B_TRUE, B_FALSE, type); 259990b4856Slling 260990b4856Slling return (prop == ZPROP_CONT ? ZPROP_INVAL : prop); 261990b4856Slling } 262990b4856Slling 263990b4856Slling int 264990b4856Slling zprop_string_to_index(int prop, const char *string, uint64_t *index, 265990b4856Slling zfs_type_t type) 266990b4856Slling { 267990b4856Slling zprop_desc_t *prop_tbl; 268990b4856Slling const zprop_index_t *idx_tbl; 269990b4856Slling int i; 270990b4856Slling 271*79912923Sgw if (prop == ZPROP_INVAL || prop == ZPROP_CONT) 272*79912923Sgw return (-1); 273*79912923Sgw 274*79912923Sgw ASSERT(prop < zprop_get_numprops(type)); 275990b4856Slling prop_tbl = zprop_get_proptable(type); 276990b4856Slling if ((idx_tbl = prop_tbl[prop].pd_table) == NULL) 277990b4856Slling return (-1); 278990b4856Slling 279990b4856Slling for (i = 0; idx_tbl[i].pi_name != NULL; i++) { 280990b4856Slling if (strcmp(string, idx_tbl[i].pi_name) == 0) { 281990b4856Slling *index = idx_tbl[i].pi_value; 282990b4856Slling return (0); 283990b4856Slling } 284990b4856Slling } 285990b4856Slling 286990b4856Slling return (-1); 287990b4856Slling } 288990b4856Slling 289990b4856Slling int 290990b4856Slling zprop_index_to_string(int prop, uint64_t index, const char **string, 291990b4856Slling zfs_type_t type) 292990b4856Slling { 293990b4856Slling zprop_desc_t *prop_tbl; 294990b4856Slling const zprop_index_t *idx_tbl; 295990b4856Slling int i; 296990b4856Slling 297*79912923Sgw if (prop == ZPROP_INVAL || prop == ZPROP_CONT) 298*79912923Sgw return (-1); 299*79912923Sgw 300*79912923Sgw ASSERT(prop < zprop_get_numprops(type)); 301990b4856Slling prop_tbl = zprop_get_proptable(type); 302990b4856Slling if ((idx_tbl = prop_tbl[prop].pd_table) == NULL) 303990b4856Slling return (-1); 304990b4856Slling 305990b4856Slling for (i = 0; idx_tbl[i].pi_name != NULL; i++) { 306990b4856Slling if (idx_tbl[i].pi_value == index) { 307990b4856Slling *string = idx_tbl[i].pi_name; 308990b4856Slling return (0); 309990b4856Slling } 310990b4856Slling } 311990b4856Slling 312990b4856Slling return (-1); 313990b4856Slling } 314990b4856Slling 315990b4856Slling const char * 316990b4856Slling zprop_values(int prop, zfs_type_t type) 317990b4856Slling { 318990b4856Slling zprop_desc_t *prop_tbl; 319990b4856Slling 320*79912923Sgw ASSERT(prop != ZPROP_INVAL && prop != ZPROP_CONT); 321*79912923Sgw ASSERT(prop < zprop_get_numprops(type)); 322*79912923Sgw 323990b4856Slling prop_tbl = zprop_get_proptable(type); 324990b4856Slling 325990b4856Slling return (prop_tbl[prop].pd_values); 326990b4856Slling } 327990b4856Slling 328990b4856Slling /* 329990b4856Slling * Returns TRUE if the property applies to any of the given dataset types. 330990b4856Slling */ 331*79912923Sgw boolean_t 332990b4856Slling zprop_valid_for_type(int prop, zfs_type_t type) 333990b4856Slling { 334*79912923Sgw zprop_desc_t *prop_tbl; 335*79912923Sgw 336*79912923Sgw if (prop == ZPROP_INVAL || prop == ZPROP_CONT) 337*79912923Sgw return (B_FALSE); 338990b4856Slling 339*79912923Sgw ASSERT(prop < zprop_get_numprops(type)); 340*79912923Sgw prop_tbl = zprop_get_proptable(type); 341990b4856Slling return ((prop_tbl[prop].pd_types & type) != 0); 342990b4856Slling } 343990b4856Slling 344990b4856Slling #ifndef _KERNEL 345990b4856Slling 346990b4856Slling /* 347990b4856Slling * Determines the minimum width for the column, and indicates whether it's fixed 348990b4856Slling * or not. Only string columns are non-fixed. 349990b4856Slling */ 350990b4856Slling size_t 351990b4856Slling zprop_width(int prop, boolean_t *fixed, zfs_type_t type) 352990b4856Slling { 353990b4856Slling zprop_desc_t *prop_tbl, *pd; 354990b4856Slling const zprop_index_t *idx; 355990b4856Slling size_t ret; 356990b4856Slling int i; 357990b4856Slling 358*79912923Sgw ASSERT(prop != ZPROP_INVAL && prop != ZPROP_CONT); 359*79912923Sgw ASSERT(prop < zprop_get_numprops(type)); 360*79912923Sgw 361990b4856Slling prop_tbl = zprop_get_proptable(type); 362990b4856Slling pd = &prop_tbl[prop]; 363990b4856Slling 364990b4856Slling *fixed = B_TRUE; 365990b4856Slling 366990b4856Slling /* 367990b4856Slling * Start with the width of the column name. 368990b4856Slling */ 369990b4856Slling ret = strlen(pd->pd_colname); 370990b4856Slling 371990b4856Slling /* 372990b4856Slling * For fixed-width values, make sure the width is large enough to hold 373990b4856Slling * any possible value. 374990b4856Slling */ 375990b4856Slling switch (pd->pd_proptype) { 376990b4856Slling case PROP_TYPE_NUMBER: 377990b4856Slling /* 378990b4856Slling * The maximum length of a human-readable number is 5 characters 379990b4856Slling * ("20.4M", for example). 380990b4856Slling */ 381990b4856Slling if (ret < 5) 382990b4856Slling ret = 5; 383990b4856Slling /* 384990b4856Slling * 'creation' is handled specially because it's a number 385990b4856Slling * internally, but displayed as a date string. 386990b4856Slling */ 387990b4856Slling if (prop == ZFS_PROP_CREATION) 388990b4856Slling *fixed = B_FALSE; 389990b4856Slling break; 390990b4856Slling case PROP_TYPE_INDEX: 391990b4856Slling idx = prop_tbl[prop].pd_table; 392990b4856Slling for (i = 0; idx[i].pi_name != NULL; i++) { 393990b4856Slling if (strlen(idx[i].pi_name) > ret) 394990b4856Slling ret = strlen(idx[i].pi_name); 395990b4856Slling } 396990b4856Slling break; 397990b4856Slling 398990b4856Slling case PROP_TYPE_STRING: 399990b4856Slling *fixed = B_FALSE; 400990b4856Slling break; 401990b4856Slling } 402990b4856Slling 403990b4856Slling return (ret); 404990b4856Slling } 405990b4856Slling 406990b4856Slling #endif 407