The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/openzfs/module/zcommon/zprop_common.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 10e64ad0a5a08811737509783e869f79


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.