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*14843421SMatthew Ahrens * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23990b4856Slling * Use is subject to license terms. 24990b4856Slling */ 25990b4856Slling 26990b4856Slling /* 27990b4856Slling * Common routines used by zfs and zpool property management. 28990b4856Slling */ 29990b4856Slling 30990b4856Slling #include <sys/zio.h> 31990b4856Slling #include <sys/spa.h> 32990b4856Slling #include <sys/zfs_acl.h> 33990b4856Slling #include <sys/zfs_ioctl.h> 34990b4856Slling #include <sys/zfs_znode.h> 35990b4856Slling #include <sys/fs/zfs.h> 36990b4856Slling 37990b4856Slling #include "zfs_prop.h" 38990b4856Slling #include "zfs_deleg.h" 39990b4856Slling 40990b4856Slling #if defined(_KERNEL) 41990b4856Slling #include <sys/systm.h> 42990b4856Slling #include <util/qsort.h> 43990b4856Slling #else 44990b4856Slling #include <stdlib.h> 45990b4856Slling #include <string.h> 46990b4856Slling #include <ctype.h> 47990b4856Slling #endif 48990b4856Slling 49990b4856Slling static zprop_desc_t * 50990b4856Slling zprop_get_proptable(zfs_type_t type) 51990b4856Slling { 52990b4856Slling if (type == ZFS_TYPE_POOL) 53990b4856Slling return (zpool_prop_get_table()); 54990b4856Slling else 55990b4856Slling return (zfs_prop_get_table()); 56990b4856Slling } 57990b4856Slling 58990b4856Slling static int 59990b4856Slling zprop_get_numprops(zfs_type_t type) 60990b4856Slling { 61990b4856Slling if (type == ZFS_TYPE_POOL) 62990b4856Slling return (ZPOOL_NUM_PROPS); 63990b4856Slling else 64990b4856Slling return (ZFS_NUM_PROPS); 65990b4856Slling } 66990b4856Slling 67990b4856Slling void 68990b4856Slling register_impl(int prop, const char *name, zprop_type_t type, 69990b4856Slling uint64_t numdefault, const char *strdefault, zprop_attr_t attr, 70990b4856Slling int objset_types, const char *values, const char *colname, 71990b4856Slling boolean_t rightalign, boolean_t visible, const zprop_index_t *idx_tbl) 72990b4856Slling { 73990b4856Slling zprop_desc_t *prop_tbl = zprop_get_proptable(objset_types); 74990b4856Slling zprop_desc_t *pd; 75990b4856Slling 76990b4856Slling pd = &prop_tbl[prop]; 77990b4856Slling 78990b4856Slling ASSERT(pd->pd_name == NULL || pd->pd_name == name); 79990b4856Slling 80990b4856Slling pd->pd_name = name; 81990b4856Slling pd->pd_propnum = prop; 82990b4856Slling pd->pd_proptype = type; 83990b4856Slling pd->pd_numdefault = numdefault; 84990b4856Slling pd->pd_strdefault = strdefault; 85990b4856Slling pd->pd_attr = attr; 86990b4856Slling pd->pd_types = objset_types; 87990b4856Slling pd->pd_values = values; 88990b4856Slling pd->pd_colname = colname; 89990b4856Slling pd->pd_rightalign = rightalign; 90990b4856Slling pd->pd_visible = visible; 91990b4856Slling pd->pd_table = idx_tbl; 92990b4856Slling } 93990b4856Slling 94990b4856Slling void 95990b4856Slling register_string(int prop, const char *name, const char *def, 96990b4856Slling zprop_attr_t attr, int objset_types, const char *values, 97990b4856Slling const char *colname) 98990b4856Slling { 99990b4856Slling register_impl(prop, name, PROP_TYPE_STRING, 0, def, attr, 100990b4856Slling objset_types, values, colname, B_FALSE, B_TRUE, NULL); 101990b4856Slling 102990b4856Slling } 103990b4856Slling 104990b4856Slling void 105990b4856Slling register_number(int prop, const char *name, uint64_t def, zprop_attr_t attr, 106990b4856Slling int objset_types, const char *values, const char *colname) 107990b4856Slling { 108990b4856Slling register_impl(prop, name, PROP_TYPE_NUMBER, def, NULL, attr, 109990b4856Slling objset_types, values, colname, B_TRUE, B_TRUE, NULL); 110990b4856Slling } 111990b4856Slling 112990b4856Slling void 113990b4856Slling register_index(int prop, const char *name, uint64_t def, zprop_attr_t attr, 114990b4856Slling int objset_types, const char *values, const char *colname, 115990b4856Slling const zprop_index_t *idx_tbl) 116990b4856Slling { 117990b4856Slling register_impl(prop, name, PROP_TYPE_INDEX, def, NULL, attr, 118990b4856Slling objset_types, values, colname, B_TRUE, B_TRUE, idx_tbl); 119990b4856Slling } 120990b4856Slling 121990b4856Slling void 122990b4856Slling register_hidden(int prop, const char *name, zprop_type_t type, 123990b4856Slling zprop_attr_t attr, int objset_types, const char *colname) 124990b4856Slling { 125990b4856Slling register_impl(prop, name, type, 0, NULL, attr, 126990b4856Slling objset_types, NULL, colname, B_FALSE, B_FALSE, NULL); 127990b4856Slling } 128990b4856Slling 129990b4856Slling 130990b4856Slling /* 131990b4856Slling * A comparison function we can use to order indexes into property tables. 132990b4856Slling */ 133990b4856Slling static int 134990b4856Slling zprop_compare(const void *arg1, const void *arg2) 135990b4856Slling { 136990b4856Slling const zprop_desc_t *p1 = *((zprop_desc_t **)arg1); 137990b4856Slling const zprop_desc_t *p2 = *((zprop_desc_t **)arg2); 138990b4856Slling boolean_t p1ro, p2ro; 139990b4856Slling 140990b4856Slling p1ro = (p1->pd_attr == PROP_READONLY); 141990b4856Slling p2ro = (p2->pd_attr == PROP_READONLY); 142990b4856Slling 143990b4856Slling if (p1ro == p2ro) 144990b4856Slling return (strcmp(p1->pd_name, p2->pd_name)); 145990b4856Slling 146990b4856Slling return (p1ro ? -1 : 1); 147990b4856Slling } 148990b4856Slling 149990b4856Slling /* 150990b4856Slling * Iterate over all properties in the given property table, calling back 151990b4856Slling * into the specified function for each property. We will continue to 152990b4856Slling * iterate until we either reach the end or the callback function returns 153990b4856Slling * something other than ZPROP_CONT. 154990b4856Slling */ 155990b4856Slling int 156990b4856Slling zprop_iter_common(zprop_func func, void *cb, boolean_t show_all, 157990b4856Slling boolean_t ordered, zfs_type_t type) 158990b4856Slling { 159990b4856Slling int i, num_props, size, prop; 160990b4856Slling zprop_desc_t *prop_tbl; 161990b4856Slling zprop_desc_t **order; 162990b4856Slling 163990b4856Slling prop_tbl = zprop_get_proptable(type); 164990b4856Slling num_props = zprop_get_numprops(type); 165990b4856Slling size = num_props * sizeof (zprop_desc_t *); 166990b4856Slling 167990b4856Slling #if defined(_KERNEL) 168990b4856Slling order = kmem_alloc(size, KM_SLEEP); 169990b4856Slling #else 170990b4856Slling if ((order = malloc(size)) == NULL) 171990b4856Slling return (ZPROP_CONT); 172990b4856Slling #endif 173990b4856Slling 174990b4856Slling for (int j = 0; j < num_props; j++) 175990b4856Slling order[j] = &prop_tbl[j]; 176990b4856Slling 177990b4856Slling if (ordered) { 178990b4856Slling qsort((void *)order, num_props, sizeof (zprop_desc_t *), 179990b4856Slling zprop_compare); 180990b4856Slling } 181990b4856Slling 182990b4856Slling prop = ZPROP_CONT; 183990b4856Slling for (i = 0; i < num_props; i++) { 184990b4856Slling if ((order[i]->pd_visible || show_all) && 185990b4856Slling (func(order[i]->pd_propnum, cb) != ZPROP_CONT)) { 186990b4856Slling prop = order[i]->pd_propnum; 187990b4856Slling break; 188990b4856Slling } 189990b4856Slling } 190990b4856Slling 191990b4856Slling #if defined(_KERNEL) 192990b4856Slling kmem_free(order, size); 193990b4856Slling #else 194990b4856Slling free(order); 195990b4856Slling #endif 196990b4856Slling return (prop); 197990b4856Slling } 198990b4856Slling 199990b4856Slling static boolean_t 200990b4856Slling propname_match(const char *p, size_t len, zprop_desc_t *prop_entry) 201990b4856Slling { 202990b4856Slling const char *propname = prop_entry->pd_name; 203990b4856Slling #ifndef _KERNEL 204990b4856Slling const char *colname = prop_entry->pd_colname; 205990b4856Slling int c; 206990b4856Slling #endif 207990b4856Slling 208990b4856Slling if (len == strlen(propname) && 209990b4856Slling strncmp(p, propname, len) == 0) 210990b4856Slling return (B_TRUE); 211990b4856Slling 212990b4856Slling #ifndef _KERNEL 213*14843421SMatthew Ahrens if (colname == NULL || len != strlen(colname)) 214990b4856Slling return (B_FALSE); 215990b4856Slling 216990b4856Slling for (c = 0; c < len; c++) 217990b4856Slling if (p[c] != tolower(colname[c])) 218990b4856Slling break; 219990b4856Slling 220990b4856Slling return (colname[c] == '\0'); 221990b4856Slling #else 222990b4856Slling return (B_FALSE); 223990b4856Slling #endif 224990b4856Slling } 225990b4856Slling 226990b4856Slling typedef struct name_to_prop_cb { 227990b4856Slling const char *propname; 228990b4856Slling zprop_desc_t *prop_tbl; 229990b4856Slling } name_to_prop_cb_t; 230990b4856Slling 231990b4856Slling static int 232990b4856Slling zprop_name_to_prop_cb(int prop, void *cb_data) 233990b4856Slling { 234990b4856Slling name_to_prop_cb_t *data = cb_data; 235990b4856Slling 236990b4856Slling if (propname_match(data->propname, strlen(data->propname), 237990b4856Slling &data->prop_tbl[prop])) 238990b4856Slling return (prop); 239990b4856Slling 240990b4856Slling return (ZPROP_CONT); 241990b4856Slling } 242990b4856Slling 243990b4856Slling int 244990b4856Slling zprop_name_to_prop(const char *propname, zfs_type_t type) 245990b4856Slling { 246990b4856Slling int prop; 247990b4856Slling name_to_prop_cb_t cb_data; 248990b4856Slling 249990b4856Slling cb_data.propname = propname; 250990b4856Slling cb_data.prop_tbl = zprop_get_proptable(type); 251990b4856Slling 252990b4856Slling prop = zprop_iter_common(zprop_name_to_prop_cb, &cb_data, 253990b4856Slling B_TRUE, B_FALSE, type); 254990b4856Slling 255990b4856Slling return (prop == ZPROP_CONT ? ZPROP_INVAL : prop); 256990b4856Slling } 257990b4856Slling 258990b4856Slling int 259990b4856Slling zprop_string_to_index(int prop, const char *string, uint64_t *index, 260990b4856Slling zfs_type_t type) 261990b4856Slling { 262990b4856Slling zprop_desc_t *prop_tbl; 263990b4856Slling const zprop_index_t *idx_tbl; 264990b4856Slling int i; 265990b4856Slling 26679912923Sgw25295 if (prop == ZPROP_INVAL || prop == ZPROP_CONT) 26779912923Sgw25295 return (-1); 26879912923Sgw25295 26979912923Sgw25295 ASSERT(prop < zprop_get_numprops(type)); 270990b4856Slling prop_tbl = zprop_get_proptable(type); 271990b4856Slling if ((idx_tbl = prop_tbl[prop].pd_table) == NULL) 272990b4856Slling return (-1); 273990b4856Slling 274990b4856Slling for (i = 0; idx_tbl[i].pi_name != NULL; i++) { 275990b4856Slling if (strcmp(string, idx_tbl[i].pi_name) == 0) { 276990b4856Slling *index = idx_tbl[i].pi_value; 277990b4856Slling return (0); 278990b4856Slling } 279990b4856Slling } 280990b4856Slling 281990b4856Slling return (-1); 282990b4856Slling } 283990b4856Slling 284990b4856Slling int 285990b4856Slling zprop_index_to_string(int prop, uint64_t index, const char **string, 286990b4856Slling zfs_type_t type) 287990b4856Slling { 288990b4856Slling zprop_desc_t *prop_tbl; 289990b4856Slling const zprop_index_t *idx_tbl; 290990b4856Slling int i; 291990b4856Slling 29279912923Sgw25295 if (prop == ZPROP_INVAL || prop == ZPROP_CONT) 29379912923Sgw25295 return (-1); 29479912923Sgw25295 29579912923Sgw25295 ASSERT(prop < zprop_get_numprops(type)); 296990b4856Slling prop_tbl = zprop_get_proptable(type); 297990b4856Slling if ((idx_tbl = prop_tbl[prop].pd_table) == NULL) 298990b4856Slling return (-1); 299990b4856Slling 300990b4856Slling for (i = 0; idx_tbl[i].pi_name != NULL; i++) { 301990b4856Slling if (idx_tbl[i].pi_value == index) { 302990b4856Slling *string = idx_tbl[i].pi_name; 303990b4856Slling return (0); 304990b4856Slling } 305990b4856Slling } 306990b4856Slling 307990b4856Slling return (-1); 308990b4856Slling } 309990b4856Slling 310990b4856Slling const char * 311990b4856Slling zprop_values(int prop, zfs_type_t type) 312990b4856Slling { 313990b4856Slling zprop_desc_t *prop_tbl; 314990b4856Slling 31579912923Sgw25295 ASSERT(prop != ZPROP_INVAL && prop != ZPROP_CONT); 31679912923Sgw25295 ASSERT(prop < zprop_get_numprops(type)); 31779912923Sgw25295 318990b4856Slling prop_tbl = zprop_get_proptable(type); 319990b4856Slling 320990b4856Slling return (prop_tbl[prop].pd_values); 321990b4856Slling } 322990b4856Slling 323990b4856Slling /* 324990b4856Slling * Returns TRUE if the property applies to any of the given dataset types. 325990b4856Slling */ 32679912923Sgw25295 boolean_t 327990b4856Slling zprop_valid_for_type(int prop, zfs_type_t type) 328990b4856Slling { 32979912923Sgw25295 zprop_desc_t *prop_tbl; 330990b4856Slling 33179912923Sgw25295 if (prop == ZPROP_INVAL || prop == ZPROP_CONT) 33279912923Sgw25295 return (B_FALSE); 33379912923Sgw25295 33479912923Sgw25295 ASSERT(prop < zprop_get_numprops(type)); 33579912923Sgw25295 prop_tbl = zprop_get_proptable(type); 336990b4856Slling return ((prop_tbl[prop].pd_types & type) != 0); 337990b4856Slling } 338990b4856Slling 339990b4856Slling #ifndef _KERNEL 340990b4856Slling 341990b4856Slling /* 342990b4856Slling * Determines the minimum width for the column, and indicates whether it's fixed 343990b4856Slling * or not. Only string columns are non-fixed. 344990b4856Slling */ 345990b4856Slling size_t 346990b4856Slling zprop_width(int prop, boolean_t *fixed, zfs_type_t type) 347990b4856Slling { 348990b4856Slling zprop_desc_t *prop_tbl, *pd; 349990b4856Slling const zprop_index_t *idx; 350990b4856Slling size_t ret; 351990b4856Slling int i; 352990b4856Slling 35379912923Sgw25295 ASSERT(prop != ZPROP_INVAL && prop != ZPROP_CONT); 35479912923Sgw25295 ASSERT(prop < zprop_get_numprops(type)); 35579912923Sgw25295 356990b4856Slling prop_tbl = zprop_get_proptable(type); 357990b4856Slling pd = &prop_tbl[prop]; 358990b4856Slling 359990b4856Slling *fixed = B_TRUE; 360990b4856Slling 361990b4856Slling /* 362990b4856Slling * Start with the width of the column name. 363990b4856Slling */ 364990b4856Slling ret = strlen(pd->pd_colname); 365990b4856Slling 366990b4856Slling /* 367990b4856Slling * For fixed-width values, make sure the width is large enough to hold 368990b4856Slling * any possible value. 369990b4856Slling */ 370990b4856Slling switch (pd->pd_proptype) { 371990b4856Slling case PROP_TYPE_NUMBER: 372990b4856Slling /* 373990b4856Slling * The maximum length of a human-readable number is 5 characters 374990b4856Slling * ("20.4M", for example). 375990b4856Slling */ 376990b4856Slling if (ret < 5) 377990b4856Slling ret = 5; 378990b4856Slling /* 379990b4856Slling * 'creation' is handled specially because it's a number 380990b4856Slling * internally, but displayed as a date string. 381990b4856Slling */ 382990b4856Slling if (prop == ZFS_PROP_CREATION) 383990b4856Slling *fixed = B_FALSE; 384990b4856Slling break; 385990b4856Slling case PROP_TYPE_INDEX: 386990b4856Slling idx = prop_tbl[prop].pd_table; 387990b4856Slling for (i = 0; idx[i].pi_name != NULL; i++) { 388990b4856Slling if (strlen(idx[i].pi_name) > ret) 389990b4856Slling ret = strlen(idx[i].pi_name); 390990b4856Slling } 391990b4856Slling break; 392990b4856Slling 393990b4856Slling case PROP_TYPE_STRING: 394990b4856Slling *fixed = B_FALSE; 395990b4856Slling break; 396990b4856Slling } 397990b4856Slling 398990b4856Slling return (ret); 399990b4856Slling } 400990b4856Slling 401990b4856Slling #endif 402