usr/src/common/zfs/zfs_prop.c
changeset 4787 602d3f97842c
parent 4597 cd30043e9dc2
child 4849 3a61e0a9a953
equal deleted inserted replaced
4786:9c83486af455 4787:602d3f97842c
    23  * Use is subject to license terms.
    23  * Use is subject to license terms.
    24  */
    24  */
    25 
    25 
    26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
    26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
    27 
    27 
    28 /*
       
    29  * Master property table.
       
    30  *
       
    31  * This table keeps track of all the properties supported by ZFS, and their
       
    32  * various attributes.  Not all of these are needed by the kernel, and several
       
    33  * are only used by a single libzfs client.  But having them here centralizes
       
    34  * all property information in one location.
       
    35  *
       
    36  * 	name		The human-readable string representing this property
       
    37  * 	proptype	Basic type (string, boolean, number)
       
    38  * 	default		Default value for the property.  Sadly, C only allows
       
    39  * 			you to initialize the first member of a union, so we
       
    40  * 			have two default members for each property.
       
    41  * 	attr		Attributes (readonly, inheritable) for the property
       
    42  * 	types		Valid dataset types to which this applies
       
    43  * 	values		String describing acceptable values for the property
       
    44  * 	colname		The column header for 'zfs list'
       
    45  *	colfmt		The column formatting for 'zfs list'
       
    46  *
       
    47  * This table must match the order of property types in libzfs.h.
       
    48  */
       
    49 
       
    50 #include <sys/zio.h>
    28 #include <sys/zio.h>
    51 #include <sys/spa.h>
    29 #include <sys/spa.h>
    52 #include <sys/zfs_acl.h>
    30 #include <sys/zfs_acl.h>
    53 #include <sys/zfs_ioctl.h>
    31 #include <sys/zfs_ioctl.h>
    54 #include <sys/zfs_znode.h>
    32 #include <sys/zfs_znode.h>
    64 #include <string.h>
    42 #include <string.h>
    65 #include <ctype.h>
    43 #include <ctype.h>
    66 #endif
    44 #endif
    67 
    45 
    68 typedef enum {
    46 typedef enum {
    69 	prop_default,
    47 	PROP_DEFAULT,
    70 	prop_readonly,
    48 	PROP_READONLY,
    71 	prop_inherit
    49 	PROP_INHERIT
    72 } prop_attr_t;
    50 } prop_attr_t;
    73 
    51 
       
    52 typedef struct zfs_index {
       
    53 	const char *name;
       
    54 	uint64_t index;
       
    55 } zfs_index_t;
       
    56 
    74 typedef struct {
    57 typedef struct {
    75 	const char	*pd_name;
    58 	const char *pd_name;		/* human-readable property name */
    76 	zfs_proptype_t	pd_proptype;
    59 	zfs_proptype_t pd_proptype;	/* string, boolean, index, number */
    77 	uint64_t	pd_numdefault;
    60 	const char *pd_strdefault;	/* default for strings */
    78 	const char	*pd_strdefault;
    61 	uint64_t pd_numdefault;		/* for boolean / index / number */
    79 	prop_attr_t	pd_attr;
    62 	prop_attr_t pd_attr;		/* default, readonly, inherit */
    80 	int		pd_types;
    63 	int pd_types;			/* bitfield of valid dataset types */
    81 	const char	*pd_values;
    64 					/* fs | vol | snap; or pool */
    82 	const char	*pd_colname;
    65 	const char *pd_values;		/* string telling acceptable values */
    83 	boolean_t	pd_rightalign;
    66 	const char *pd_colname;		/* column header for "zfs list" */
    84 	boolean_t	pd_visible;
    67 	boolean_t pd_rightalign;	/* column alignment for "zfs list" */
    85 	const char	*pd_perm;
    68 	boolean_t pd_visible;		/* do we list this property with the */
       
    69 					/* "zfs get" help message */
       
    70 	const zfs_index_t *pd_table;	/* for index properties, a table */
       
    71 					/* defining the possible values */
    86 } prop_desc_t;
    72 } prop_desc_t;
    87 
    73 
    88 static prop_desc_t zfs_prop_table[] = {
    74 static prop_desc_t zfs_prop_table[ZFS_NUM_PROPS];
    89 	{ "type",	prop_type_string,	0,	NULL,	prop_readonly,
    75 
    90 	    ZFS_TYPE_ANY, "filesystem | volume | snapshot", "TYPE", B_TRUE,
    76 static void
    91 	    B_TRUE, ZFS_DELEG_PERM_NONE },
    77 register_impl(zfs_prop_t prop, const char *name, zfs_proptype_t type,
    92 	{ "creation",	prop_type_number,	0,	NULL,	prop_readonly,
    78     uint64_t numdefault, const char *strdefault, prop_attr_t attr,
    93 	    ZFS_TYPE_ANY, "<date>", "CREATION", B_FALSE, B_TRUE,
    79     int objset_types, const char *values, const char *colname,
    94 	    ZFS_DELEG_PERM_NONE },
    80     boolean_t rightalign, boolean_t visible, const zfs_index_t *table)
    95 	{ "used",	prop_type_number,	0,	NULL,	prop_readonly,
    81 {
    96 	    ZFS_TYPE_ANY, "<size>",	"USED", B_TRUE, B_TRUE,
    82 	prop_desc_t *pd = &zfs_prop_table[prop];
    97 	    ZFS_DELEG_PERM_NONE },
    83 
    98 	{ "available",	prop_type_number,	0,	NULL,	prop_readonly,
    84 	ASSERT(pd->pd_name == NULL || pd->pd_name == name);
    99 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "<size>", "AVAIL", B_TRUE,
    85 
   100 	    B_TRUE, ZFS_DELEG_PERM_NONE },
    86 	pd->pd_name = name;
   101 	{ "referenced",	prop_type_number,	0,	NULL,	prop_readonly,
    87 	pd->pd_proptype = type;
   102 	    ZFS_TYPE_ANY,
    88 	pd->pd_numdefault = numdefault;
   103 	    "<size>", "REFER", B_TRUE, B_TRUE, ZFS_DELEG_PERM_NONE },
    89 	pd->pd_strdefault = strdefault;
   104 	{ "compressratio", prop_type_number,	0,	NULL,	prop_readonly,
    90 	pd->pd_attr = attr;
   105 	    ZFS_TYPE_ANY, "<1.00x or higher if compressed>", "RATIO", B_TRUE,
    91 	pd->pd_types = objset_types;
   106 	    B_TRUE, ZFS_DELEG_PERM_NONE },
    92 	pd->pd_values = values;
   107 	{ "mounted",	prop_type_boolean,	0,	NULL,	prop_readonly,
    93 	pd->pd_colname = colname;
   108 	    ZFS_TYPE_FILESYSTEM, "yes | no | -", "MOUNTED", B_TRUE, B_TRUE,
    94 	pd->pd_rightalign = rightalign;
   109 	    ZFS_DELEG_PERM_NONE },
    95 	pd->pd_visible = visible;
   110 	{ "origin",	prop_type_string,	0,	NULL,	prop_readonly,
    96 	pd->pd_table = table;
   111 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "<snapshot>", "ORIGIN",
    97 }
   112 	    B_FALSE, B_TRUE, ZFS_DELEG_PERM_NONE },
    98 
   113 	{ "quota",	prop_type_number,	0,	NULL,	prop_default,
    99 static void
   114 	    ZFS_TYPE_FILESYSTEM, "<size> | none", "QUOTA", B_TRUE, B_TRUE,
   100 register_string(zfs_prop_t prop, const char *name, const char *def,
   115 	    ZFS_DELEG_PERM_QUOTA },
   101     prop_attr_t attr, int objset_types, const char *values,
   116 	{ "reservation", prop_type_number,	0,	NULL,	prop_default,
   102     const char *colname)
       
   103 {
       
   104 	register_impl(prop, name, PROP_TYPE_STRING, 0, def, attr,
       
   105 	    objset_types, values, colname, B_FALSE, B_TRUE, NULL);
       
   106 
       
   107 }
       
   108 
       
   109 static void
       
   110 register_number(zfs_prop_t prop, const char *name, uint64_t def,
       
   111     prop_attr_t attr, int objset_types, const char *values, const char *colname)
       
   112 {
       
   113 	register_impl(prop, name, PROP_TYPE_NUMBER, def, NULL, attr,
       
   114 	    objset_types, values, colname, B_TRUE, B_TRUE, NULL);
       
   115 }
       
   116 
       
   117 static void
       
   118 register_boolean(zfs_prop_t prop, const char *name, uint64_t def,
       
   119     prop_attr_t attr, int objset_types, const char *values, const char *colname)
       
   120 {
       
   121 	register_impl(prop, name, PROP_TYPE_BOOLEAN, def, NULL, attr,
       
   122 	    objset_types, values, colname, B_TRUE, B_TRUE, NULL);
       
   123 }
       
   124 
       
   125 static void
       
   126 register_index(zfs_prop_t prop, const char *name, uint64_t def,
       
   127     int objset_types, const char *values, const char *colname,
       
   128     const zfs_index_t *table)
       
   129 {
       
   130 	register_impl(prop, name, PROP_TYPE_INDEX, def, NULL, PROP_INHERIT,
       
   131 	    objset_types, values, colname, B_TRUE, B_TRUE, table);
       
   132 }
       
   133 
       
   134 static void
       
   135 register_hidden(zfs_prop_t prop, const char *name, zfs_proptype_t type,
       
   136     prop_attr_t attr, int objset_types, const char *colname)
       
   137 {
       
   138 	register_impl(prop, name, type, 0, NULL, attr,
       
   139 	    objset_types, NULL, colname, B_FALSE, B_FALSE, NULL);
       
   140 }
       
   141 
       
   142 void
       
   143 zfs_prop_init(void)
       
   144 {
       
   145 	static zfs_index_t checksum_table[] = {
       
   146 		{ "on",		ZIO_CHECKSUM_ON },
       
   147 		{ "off",	ZIO_CHECKSUM_OFF },
       
   148 		{ "fletcher2",	ZIO_CHECKSUM_FLETCHER_2 },
       
   149 		{ "fletcher4",	ZIO_CHECKSUM_FLETCHER_4 },
       
   150 		{ "sha256",	ZIO_CHECKSUM_SHA256 },
       
   151 		{ NULL }
       
   152 	};
       
   153 
       
   154 	static zfs_index_t compress_table[] = {
       
   155 		{ "on",		ZIO_COMPRESS_ON },
       
   156 		{ "off",	ZIO_COMPRESS_OFF },
       
   157 		{ "lzjb",	ZIO_COMPRESS_LZJB },
       
   158 		{ "gzip",	ZIO_COMPRESS_GZIP_6 },	/* gzip default */
       
   159 		{ "gzip-1",	ZIO_COMPRESS_GZIP_1 },
       
   160 		{ "gzip-2",	ZIO_COMPRESS_GZIP_2 },
       
   161 		{ "gzip-3",	ZIO_COMPRESS_GZIP_3 },
       
   162 		{ "gzip-4",	ZIO_COMPRESS_GZIP_4 },
       
   163 		{ "gzip-5",	ZIO_COMPRESS_GZIP_5 },
       
   164 		{ "gzip-6",	ZIO_COMPRESS_GZIP_6 },
       
   165 		{ "gzip-7",	ZIO_COMPRESS_GZIP_7 },
       
   166 		{ "gzip-8",	ZIO_COMPRESS_GZIP_8 },
       
   167 		{ "gzip-9",	ZIO_COMPRESS_GZIP_9 },
       
   168 		{ NULL }
       
   169 	};
       
   170 
       
   171 	static zfs_index_t snapdir_table[] = {
       
   172 		{ "hidden",	ZFS_SNAPDIR_HIDDEN },
       
   173 		{ "visible",	ZFS_SNAPDIR_VISIBLE },
       
   174 		{ NULL }
       
   175 	};
       
   176 
       
   177 	static zfs_index_t acl_mode_table[] = {
       
   178 		{ "discard",	ZFS_ACL_DISCARD },
       
   179 		{ "groupmask",	ZFS_ACL_GROUPMASK },
       
   180 		{ "passthrough", ZFS_ACL_PASSTHROUGH },
       
   181 		{ NULL }
       
   182 	};
       
   183 
       
   184 	static zfs_index_t acl_inherit_table[] = {
       
   185 		{ "discard",	ZFS_ACL_DISCARD },
       
   186 		{ "noallow",	ZFS_ACL_NOALLOW },
       
   187 		{ "secure",	ZFS_ACL_SECURE },
       
   188 		{ "passthrough", ZFS_ACL_PASSTHROUGH },
       
   189 		{ NULL }
       
   190 	};
       
   191 
       
   192 	static zfs_index_t copies_table[] = {
       
   193 		{ "1",		1 },
       
   194 		{ "2",		2 },
       
   195 		{ "3",		3 },
       
   196 		{ NULL }
       
   197 	};
       
   198 
       
   199 	static zfs_index_t version_table[] = {
       
   200 		{ "1",		1 },
       
   201 		{ "2",		2 },
       
   202 		{ "current",	ZPL_VERSION },
       
   203 		{ NULL }
       
   204 	};
       
   205 
       
   206 	/* inherit index properties */
       
   207 	register_index(ZFS_PROP_CHECKSUM, "checksum", ZIO_CHECKSUM_DEFAULT,
   117 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
   208 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
   118 	    "<size> | none", "RESERV", B_TRUE, B_TRUE,
   209 	    "on | off | fletcher2 | fletcher4 | sha256", "CHECKSUM",
   119 	    ZFS_DELEG_PERM_RESERVATION },
   210 	    checksum_table);
   120 	{ "volsize",	prop_type_number,	0,	NULL,	prop_default,
   211 	register_index(ZFS_PROP_COMPRESSION, "compression",
   121 	    ZFS_TYPE_VOLUME, "<size>", "VOLSIZE", B_TRUE, B_TRUE,
   212 	    ZIO_COMPRESS_DEFAULT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
   122 	    ZFS_DELEG_PERM_VOLSIZE },
   213 	    "on | off | lzjb | gzip | gzip-[1-9]", "COMPRESS", compress_table);
   123 	{ "volblocksize", prop_type_number,	8192,	NULL,	prop_readonly,
   214 	register_index(ZFS_PROP_SNAPDIR, "snapdir", ZFS_SNAPDIR_HIDDEN,
   124 	    ZFS_TYPE_VOLUME, "512 to 128k, power of 2",	"VOLBLOCK", B_TRUE,
   215 	    ZFS_TYPE_FILESYSTEM, "hidden | visible", "SNAPDIR", snapdir_table);
   125 	    B_TRUE, ZFS_DELEG_PERM_NONE },
   216 	register_index(ZFS_PROP_ACLMODE, "aclmode", ZFS_ACL_GROUPMASK,
   126 	{ "recordsize",	prop_type_number,	SPA_MAXBLOCKSIZE,	NULL,
   217 	    ZFS_TYPE_FILESYSTEM, "discard | groupmask | passthrough", "ACLMODE",
   127 	    prop_inherit,
   218 	    acl_mode_table);
       
   219 	register_index(ZFS_PROP_ACLINHERIT, "aclinherit", ZFS_ACL_SECURE,
   128 	    ZFS_TYPE_FILESYSTEM,
   220 	    ZFS_TYPE_FILESYSTEM,
   129 	    "512 to 128k, power of 2", "RECSIZE", B_TRUE, B_TRUE,
   221 	    "discard | noallow | secure | passthrough", "ACLINHERIT",
   130 	    ZFS_DELEG_PERM_RECORDSIZE },
   222 	    acl_inherit_table);
   131 	{ "mountpoint",	prop_type_string,	0,	"/",	prop_inherit,
   223 	register_index(ZFS_PROP_COPIES, "copies", 1,
   132 	    ZFS_TYPE_FILESYSTEM,
   224 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
   133 	    "<path> | legacy | none", "MOUNTPOINT", B_FALSE, B_TRUE,
   225 	    "1 | 2 | 3", "COPIES", copies_table);
   134 	    ZFS_DELEG_PERM_MOUNTPOINT },
   226 	register_index(ZFS_PROP_VERSION, "version", 0,
   135 	{ "sharenfs",	prop_type_string,	0,	"off",	prop_inherit,
       
   136 	    ZFS_TYPE_FILESYSTEM,
       
   137 	    "on | off | share(1M) options", "SHARENFS", B_FALSE, B_TRUE,
       
   138 	    ZFS_DELEG_PERM_SHARENFS },
       
   139 	{ "checksum",	prop_type_index,	ZIO_CHECKSUM_DEFAULT,	"on",
       
   140 	    prop_inherit,	ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
       
   141 	    "on | off | fletcher2 | fletcher4 | sha256", "CHECKSUM", B_TRUE,
       
   142 	    B_TRUE, ZFS_DELEG_PERM_CHECKSUM },
       
   143 	{ "compression", prop_type_index,	ZIO_COMPRESS_DEFAULT,	"off",
       
   144 	    prop_inherit,	ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
       
   145 	    "on | off | lzjb | gzip | gzip-[1-9]", "COMPRESS", B_TRUE, B_TRUE,
       
   146 	    ZFS_DELEG_PERM_COMPRESSION },
       
   147 	{ "atime",	prop_type_boolean,	1,	NULL,	prop_inherit,
       
   148 	    ZFS_TYPE_FILESYSTEM,
       
   149 	    "on | off", "ATIME", B_TRUE, B_TRUE, ZFS_DELEG_PERM_ATIME },
       
   150 	{ "devices",	prop_type_boolean,	1,	NULL,	prop_inherit,
       
   151 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT,
   227 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT,
   152 	    "on | off", "DEVICES", B_TRUE, B_TRUE, ZFS_DELEG_PERM_DEVICES },
   228 	    "1 | 2 | current", "VERSION", version_table);
   153 	{ "exec",	prop_type_boolean,	1,	NULL,	prop_inherit,
   229 
   154 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT,
   230 	/* string properties */
   155 	    "on | off", "EXEC", B_TRUE, B_TRUE, ZFS_DELEG_PERM_EXEC },
   231 	register_string(ZFS_PROP_ORIGIN, "origin", NULL, PROP_READONLY,
   156 	{ "setuid",	prop_type_boolean,	1,	NULL,	prop_inherit,
   232 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "<snapshot>", "ORIGIN");
   157 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "on | off", "SETUID",
   233 	register_string(ZPOOL_PROP_BOOTFS, "bootfs", NULL, PROP_DEFAULT,
   158 	    B_TRUE, B_TRUE, ZFS_DELEG_PERM_SETUID },
   234 	    ZFS_TYPE_POOL, "<filesystem>", "BOOTFS");
   159 	{ "readonly",	prop_type_boolean,	0,	NULL,	prop_inherit,
   235 	register_string(ZFS_PROP_MOUNTPOINT, "mountpoint", "/", PROP_INHERIT,
       
   236 	    ZFS_TYPE_FILESYSTEM, "<path> | legacy | none", "MOUNTPOINT");
       
   237 	register_string(ZFS_PROP_SHARENFS, "sharenfs", "off", PROP_INHERIT,
       
   238 	    ZFS_TYPE_FILESYSTEM, "on | off | share(1M) options", "SHARENFS");
       
   239 	register_string(ZFS_PROP_SHAREISCSI, "shareiscsi", "off", PROP_INHERIT,
       
   240 	    ZFS_TYPE_ANY, "on | off | type=<type>", "SHAREISCSI");
       
   241 	register_string(ZFS_PROP_TYPE, "type", NULL, PROP_READONLY,
       
   242 	    ZFS_TYPE_ANY, "filesystem | volume | snapshot", "TYPE");
       
   243 
       
   244 	/* readonly number properties */
       
   245 	register_number(ZFS_PROP_USED, "used", 0, PROP_READONLY,
       
   246 	    ZFS_TYPE_ANY, "<size>", "USED");
       
   247 	register_number(ZFS_PROP_AVAILABLE, "available", 0, PROP_READONLY,
   160 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
   248 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
   161 	    "on | off", "RDONLY", B_TRUE, B_TRUE, ZFS_DELEG_PERM_READONLY },
   249 	    "<size>", "AVAIL");
   162 	{ "zoned",	prop_type_boolean,	0,	NULL,	prop_inherit,
   250 	register_number(ZFS_PROP_REFERENCED, "referenced", 0, PROP_READONLY,
   163 	    ZFS_TYPE_FILESYSTEM,
   251 	    ZFS_TYPE_ANY, "<size>", "REFER");
   164 	    "on | off", "ZONED", B_TRUE, B_TRUE, ZFS_DELEG_PERM_ZONED },
   252 	register_number(ZFS_PROP_COMPRESSRATIO, "compressratio", 0,
   165 	{ "snapdir",	prop_type_index,	ZFS_SNAPDIR_HIDDEN, "hidden",
   253 	    PROP_READONLY, ZFS_TYPE_ANY,
   166 	    prop_inherit,
   254 	    "<1.00x or higher if compressed>", "RATIO");
   167 	    ZFS_TYPE_FILESYSTEM,
   255 	register_number(ZFS_PROP_VOLBLOCKSIZE, "volblocksize", 8192,
   168 	    "hidden | visible", "SNAPDIR", B_TRUE, B_TRUE,
   256 	    PROP_READONLY,
   169 	    ZFS_DELEG_PERM_SNAPDIR },
   257 	    ZFS_TYPE_VOLUME, "512 to 128k, power of 2",	"VOLBLOCK");
   170 	{ "aclmode", prop_type_index,	ZFS_ACL_GROUPMASK, "groupmask",
   258 
   171 	    prop_inherit, ZFS_TYPE_FILESYSTEM,
   259 	/* default number properties */
   172 	    "discard | groupmask | passthrough", "ACLMODE", B_TRUE,
   260 	register_number(ZFS_PROP_QUOTA, "quota", 0, PROP_DEFAULT,
   173 	    B_TRUE, ZFS_DELEG_PERM_ACLMODE },
   261 	    ZFS_TYPE_FILESYSTEM, "<size> | none", "QUOTA");
   174 	{ "aclinherit", prop_type_index,	ZFS_ACL_SECURE,	"secure",
   262 	register_number(ZFS_PROP_RESERVATION, "reservation", 0, PROP_DEFAULT,
   175 	    prop_inherit, ZFS_TYPE_FILESYSTEM,
   263 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "<size> | none", "RESERV");
   176 	    "discard | noallow | secure | passthrough", "ACLINHERIT", B_TRUE,
   264 	register_number(ZFS_PROP_VOLSIZE, "volsize", 0, PROP_DEFAULT,
   177 	    B_TRUE, ZFS_DELEG_PERM_ACLINHERIT },
   265 	    ZFS_TYPE_VOLUME, "<size>", "VOLSIZE");
   178 	{ "createtxg",	prop_type_number,	0,	NULL,	prop_readonly,
   266 
   179 	    ZFS_TYPE_ANY, NULL, NULL, B_FALSE, B_FALSE, ZFS_DELEG_PERM_NONE },
   267 	/* inherit number properties */
   180 	{ "name",	prop_type_string,	0,	NULL,	prop_readonly,
   268 	register_number(ZFS_PROP_RECORDSIZE, "recordsize", SPA_MAXBLOCKSIZE,
   181 	    ZFS_TYPE_ANY, NULL, "NAME", B_FALSE, B_FALSE, ZFS_DELEG_PERM_NONE },
   269 	    PROP_INHERIT,
   182 	{ "canmount",	prop_type_boolean,	1,	NULL,	prop_default,
   270 	    ZFS_TYPE_FILESYSTEM, "512 to 128k, power of 2", "RECSIZE");
   183 	    ZFS_TYPE_FILESYSTEM,
   271 
   184 	    "on | off", "CANMOUNT", B_TRUE, B_TRUE, ZFS_DELEG_PERM_CANMOUNT },
   272 	/* readonly boolean properties */
   185 	{ "shareiscsi",	prop_type_string,	0,	"off",	prop_inherit,
   273 	register_boolean(ZFS_PROP_MOUNTED, "mounted", 0, PROP_READONLY,
   186 	    ZFS_TYPE_ANY,
   274 	    ZFS_TYPE_FILESYSTEM, "yes | no | -", "MOUNTED");
   187 	    "on | off | type=<type>", "SHAREISCSI", B_FALSE, B_TRUE,
   275 
   188 	    ZFS_DELEG_PERM_SHAREISCSI },
   276 	/* default boolean properties */
   189 	{ "iscsioptions", prop_type_string,	0,	NULL,	prop_inherit,
   277 	register_boolean(ZFS_PROP_CANMOUNT, "canmount", 1, PROP_DEFAULT,
   190 	    ZFS_TYPE_VOLUME, NULL, "ISCSIOPTIONS", B_FALSE, B_FALSE,
   278 	    ZFS_TYPE_FILESYSTEM, "on | off", "CANMOUNT");
   191 	    ZFS_DELEG_PERM_NONE },
   279 	register_boolean(ZPOOL_PROP_DELEGATION, "delegation", 1, PROP_DEFAULT,
   192 	{ "xattr",	prop_type_boolean,	1,	NULL,	prop_inherit,
   280 	    ZFS_TYPE_POOL, "on | off", "DELEGATION");
   193 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT,
   281 	register_boolean(ZPOOL_PROP_AUTOREPLACE, "autoreplace", 0, PROP_DEFAULT,
   194 	    "on | off", "XATTR", B_TRUE, B_TRUE, ZFS_DELEG_PERM_XATTR },
   282 	    ZFS_TYPE_POOL, "on | off", "REPLACE");
   195 	{ "numclones", prop_type_number,	0,	NULL,	prop_readonly,
   283 
   196 	    ZFS_TYPE_SNAPSHOT, NULL, NULL, B_FALSE, B_FALSE,
   284 	/* inherit boolean properties */
   197 	    ZFS_DELEG_PERM_NONE },
   285 	register_boolean(ZFS_PROP_ATIME, "atime", 1, PROP_INHERIT,
   198 	{ "copies",	prop_type_index,	1,	"1",	prop_inherit,
   286 	    ZFS_TYPE_FILESYSTEM, "on | off", "ATIME");
   199 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
   287 	register_boolean(ZFS_PROP_DEVICES, "devices", 1, PROP_INHERIT,
   200 	    "1 | 2 | 3", "COPIES", B_TRUE, B_TRUE, ZFS_DELEG_PERM_COPIES },
   288 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "on | off", "DEVICES");
   201 	{ "bootfs", prop_type_string,	0,	NULL,	prop_default,
   289 	register_boolean(ZFS_PROP_EXEC, "exec", 1, PROP_INHERIT,
   202 	    ZFS_TYPE_POOL, "<filesystem>", "BOOTFS", B_FALSE,
   290 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "on | off", "EXEC");
   203 	    B_TRUE, ZFS_DELEG_PERM_NONE },
   291 	register_boolean(ZFS_PROP_SETUID, "setuid", 1, PROP_INHERIT,
   204 	{ "autoreplace", prop_type_boolean,	0,	NULL, prop_default,
   292 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "on | off", "SETUID");
   205 	    ZFS_TYPE_POOL, "on | off", "REPLACE", B_FALSE, B_TRUE,
   293 	register_boolean(ZFS_PROP_READONLY, "readonly", 0, PROP_INHERIT,
   206 	    ZFS_DELEG_PERM_NONE },
   294 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "on | off", "RDONLY");
   207 	{ "delegation", prop_type_boolean,	1,	NULL,	prop_default,
   295 	register_boolean(ZFS_PROP_ZONED, "zoned", 0, PROP_INHERIT,
   208 	    ZFS_TYPE_POOL, "on | off", "DELEGATION", B_TRUE,
   296 	    ZFS_TYPE_FILESYSTEM, "on | off", "ZONED");
   209 	    B_TRUE, ZFS_DELEG_PERM_NONE },
   297 	register_boolean(ZFS_PROP_XATTR, "xattr", 1, PROP_INHERIT,
   210 	{ "version",	prop_type_index,	0,	NULL,	prop_default,
   298 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "on | off", "XATTR");
   211 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "1 | 2 | current",
   299 
   212 	    "VERSION", B_TRUE, B_TRUE, ZFS_DELEG_PERM_VERSION },
   300 	/* hidden properties */
   213 };
   301 	register_hidden(ZFS_PROP_CREATETXG, "createtxg", PROP_TYPE_NUMBER,
   214 
   302 	    PROP_READONLY, ZFS_TYPE_ANY, NULL);
   215 #define	ZFS_PROP_COUNT	((sizeof (zfs_prop_table))/(sizeof (prop_desc_t)))
   303 	register_hidden(ZFS_PROP_NUMCLONES, "numclones", PROP_TYPE_NUMBER,
   216 
   304 	    PROP_READONLY, ZFS_TYPE_SNAPSHOT, NULL);
   217 /*
   305 	register_hidden(ZFS_PROP_NAME, "name", PROP_TYPE_STRING,
   218  * Returns TRUE if the property applies to the given dataset types.
   306 	    PROP_READONLY, ZFS_TYPE_ANY, "NAME");
       
   307 	register_hidden(ZFS_PROP_ISCSIOPTIONS, "iscsioptions", PROP_TYPE_STRING,
       
   308 	    PROP_INHERIT, ZFS_TYPE_VOLUME, "ISCSIOPTIONS");
       
   309 	register_hidden(ZPOOL_PROP_NAME, "zpoolname", PROP_TYPE_STRING,
       
   310 	    PROP_READONLY, ZFS_TYPE_POOL, NULL);
       
   311 
       
   312 	/* oddball properties */
       
   313 	register_impl(ZFS_PROP_CREATION, "creation", PROP_TYPE_NUMBER, 0, NULL,
       
   314 	    PROP_READONLY, ZFS_TYPE_ANY,
       
   315 	    "<date>", "CREATION", B_FALSE, B_TRUE, NULL);
       
   316 }
       
   317 
       
   318 
       
   319 /*
       
   320  * Returns TRUE if the property applies to any of the given dataset types.
   219  */
   321  */
   220 int
   322 int
   221 zfs_prop_valid_for_type(zfs_prop_t prop, int types)
   323 zfs_prop_valid_for_type(zfs_prop_t prop, int types)
   222 {
   324 {
   223 	return ((zfs_prop_table[prop].pd_types & types) != 0);
   325 	return ((zfs_prop_table[prop].pd_types & types) != 0);
   238 /*
   340 /*
   239  * A comparison function we can use to order indexes into the
   341  * A comparison function we can use to order indexes into the
   240  * zfs_prop_table[]
   342  * zfs_prop_table[]
   241  */
   343  */
   242 static int
   344 static int
   243 zfs_prop_compare(const void *p1, const void *p2)
   345 zfs_prop_compare(const void *arg1, const void *arg2)
   244 {
   346 {
   245 	int i, j;
   347 	const zfs_prop_t *p1 = arg1;
   246 	prop_attr_t iattr, jattr;
   348 	const zfs_prop_t *p2 = arg2;
   247 
   349 	boolean_t p1ro, p2ro;
   248 	i = *((int *)p1);
   350 
   249 	j = *((int *)p2);
   351 	p1ro = (zfs_prop_table[*p1].pd_attr == PROP_READONLY);
   250 
   352 	p2ro = (zfs_prop_table[*p2].pd_attr == PROP_READONLY);
   251 	iattr = zfs_prop_table[i].pd_attr;
   353 
   252 	jattr = zfs_prop_table[j].pd_attr;
   354 	if (p1ro == p2ro) {
   253 
   355 		return (strcmp(zfs_prop_table[*p1].pd_name,
   254 	/* first, sort by whether the property is readonly or not */
   356 		    zfs_prop_table[*p2].pd_name));
   255 	if (iattr != prop_readonly &&
   357 	}
   256 	    jattr == prop_readonly)
   358 
   257 		return (1);
   359 	return (p1ro ? -1 : 1);
   258 	if (iattr == prop_readonly &&
       
   259 	    jattr != prop_readonly)
       
   260 		return (-1);
       
   261 
       
   262 	/* otherwise, sort by the property name */
       
   263 	return (strcmp(zfs_prop_table[i].pd_name,
       
   264 	    zfs_prop_table[j].pd_name));
       
   265 }
   360 }
   266 
   361 
   267 /*
   362 /*
   268  * Iterate over all properties, calling back into the specified function
   363  * Iterate over all properties, calling back into the specified function
   269  * for each property. We will continue to iterate until we either
   364  * for each property. We will continue to iterate until we either
   273 zfs_prop_t
   368 zfs_prop_t
   274 zfs_prop_iter_common(zfs_prop_f func, void *cb, zfs_type_t type,
   369 zfs_prop_iter_common(zfs_prop_f func, void *cb, zfs_type_t type,
   275     boolean_t show_all, boolean_t ordered)
   370     boolean_t show_all, boolean_t ordered)
   276 {
   371 {
   277 	int i;
   372 	int i;
   278 	int order[ZFS_PROP_COUNT];
   373 	zfs_prop_t order[ZFS_NUM_PROPS];
   279 
   374 
   280 	for (int j = 0; j < ZFS_PROP_COUNT; j++) {
   375 	for (int j = 0; j < ZFS_NUM_PROPS; j++)
   281 		order[j] = j;
   376 		order[j] = j;
   282 	}
       
   283 
   377 
   284 
   378 
   285 	if (ordered) {
   379 	if (ordered) {
   286 		qsort((void *)order, ZFS_PROP_COUNT, sizeof (zfs_prop_t),
   380 		qsort((void *)order, ZFS_NUM_PROPS, sizeof (zfs_prop_t),
   287 		    zfs_prop_compare);
   381 		    zfs_prop_compare);
   288 	}
   382 	}
   289 
   383 
   290 	for (i = 0; i < ZFS_PROP_COUNT; i++) {
   384 	for (i = 0; i < ZFS_NUM_PROPS; i++) {
   291 		if (zfs_prop_valid_for_type(order[i], type) &&
   385 		if (zfs_prop_valid_for_type(order[i], type) &&
   292 		    (zfs_prop_is_visible(order[i]) || show_all)) {
   386 		    (zfs_prop_is_visible(order[i]) || show_all)) {
   293 			if (func(order[i], cb) != ZFS_PROP_CONT)
   387 			if (func(order[i], cb) != ZFS_PROP_CONT)
   294 				return (order[i]);
   388 				return (order[i]);
   295 		}
   389 		}
   296 	}
   390 	}
   297 	return (ZFS_PROP_CONT);
   391 	return (ZFS_PROP_CONT);
   298 }
   392 }
   299 
   393 
   300 zfs_prop_t
   394 zfs_prop_t
   301 zfs_prop_iter(zfs_prop_f func, void *cb, boolean_t show_all)
   395 zfs_prop_iter(zfs_prop_f func, void *cb)
   302 {
   396 {
   303 	return (zfs_prop_iter_common(func, cb, ZFS_TYPE_ANY, show_all,
   397 	return (zfs_prop_iter_common(func, cb, ZFS_TYPE_ANY, B_FALSE, B_FALSE));
   304 	    B_FALSE));
       
   305 }
   398 }
   306 
   399 
   307 zfs_prop_t
   400 zfs_prop_t
   308 zfs_prop_iter_ordered(zfs_prop_f func, void *cb, boolean_t show_all)
   401 zfs_prop_iter_ordered(zfs_prop_f func, void *cb)
   309 {
   402 {
   310 	return (zfs_prop_iter_common(func, cb, ZFS_TYPE_ANY, show_all,
   403 	return (zfs_prop_iter_common(func, cb, ZFS_TYPE_ANY, B_FALSE, B_TRUE));
   311 	    B_TRUE));
       
   312 }
   404 }
   313 
   405 
   314 zpool_prop_t
   406 zpool_prop_t
   315 zpool_prop_iter(zpool_prop_f func, void *cb, boolean_t show_all)
   407 zpool_prop_iter(zpool_prop_f func, void *cb)
   316 {
   408 {
   317 	return (zfs_prop_iter_common(func, cb, ZFS_TYPE_POOL, show_all,
   409 	return (zfs_prop_iter_common(func, cb, ZFS_TYPE_POOL, B_FALSE,
   318 	    B_FALSE));
   410 	    B_FALSE));
   319 }
   411 }
   320 
   412 
   321 zfs_proptype_t
   413 zfs_proptype_t
   322 zfs_prop_get_type(zfs_prop_t prop)
   414 zfs_prop_get_type(zfs_prop_t prop)
   335 {
   427 {
   336 	const char *propname = zfs_prop_table[prop].pd_name;
   428 	const char *propname = zfs_prop_table[prop].pd_name;
   337 #ifndef _KERNEL
   429 #ifndef _KERNEL
   338 	const char *colname = zfs_prop_table[prop].pd_colname;
   430 	const char *colname = zfs_prop_table[prop].pd_colname;
   339 	int c;
   431 	int c;
   340 #endif
   432 
   341 
       
   342 #ifndef _KERNEL
       
   343 	if (colname == NULL)
   433 	if (colname == NULL)
   344 		return (B_FALSE);
   434 		return (B_FALSE);
   345 #endif
   435 #endif
   346 
   436 
   347 	if (len == strlen(propname) &&
   437 	if (len == strlen(propname) &&
   365 zfs_prop_t
   455 zfs_prop_t
   366 zfs_name_to_prop_cb(zfs_prop_t prop, void *cb_data)
   456 zfs_name_to_prop_cb(zfs_prop_t prop, void *cb_data)
   367 {
   457 {
   368 	const char *propname = cb_data;
   458 	const char *propname = cb_data;
   369 
   459 
   370 	if (propname_match(propname, prop, strlen(propname))) {
   460 	if (propname_match(propname, prop, strlen(propname)))
   371 		return (prop);
   461 		return (prop);
   372 	}
       
   373 
   462 
   374 	return (ZFS_PROP_CONT);
   463 	return (ZFS_PROP_CONT);
   375 }
   464 }
   376 
   465 
   377 /*
   466 /*
   403 zpool_name_to_prop(const char *propname)
   492 zpool_name_to_prop(const char *propname)
   404 {
   493 {
   405 	return (zfs_name_to_prop_common(propname, ZFS_TYPE_POOL));
   494 	return (zfs_name_to_prop_common(propname, ZFS_TYPE_POOL));
   406 }
   495 }
   407 
   496 
   408 const char *
   497 boolean_t
   409 zfs_prop_perm(zfs_prop_t prop)
   498 zfs_prop_delegatable(zfs_prop_t prop)
   410 {
   499 {
   411 	return (zfs_prop_table[prop].pd_perm);
   500 	prop_desc_t *pd = &zfs_prop_table[prop];
       
   501 	return (pd->pd_attr != PROP_READONLY && pd->pd_types != ZFS_TYPE_POOL);
   412 }
   502 }
   413 
   503 
   414 /*
   504 /*
   415  * For user property names, we allow all lowercase alphanumeric characters, plus
   505  * For user property names, we allow all lowercase alphanumeric characters, plus
   416  * a few useful punctuation characters.
   506  * a few useful punctuation characters.
   478  * Returns TRUE if the property is readonly.
   568  * Returns TRUE if the property is readonly.
   479  */
   569  */
   480 int
   570 int
   481 zfs_prop_readonly(zfs_prop_t prop)
   571 zfs_prop_readonly(zfs_prop_t prop)
   482 {
   572 {
   483 	return (zfs_prop_table[prop].pd_attr == prop_readonly);
   573 	return (zfs_prop_table[prop].pd_attr == PROP_READONLY);
   484 }
   574 }
   485 
   575 
   486 /*
   576 /*
   487  * Given a dataset property ID, returns the corresponding name.
   577  * Given a dataset property ID, returns the corresponding name.
   488  * Assuming the zfs dataset property ID is valid.
   578  * Assuming the zfs dataset property ID is valid.
   507  * Returns TRUE if the property is inheritable.
   597  * Returns TRUE if the property is inheritable.
   508  */
   598  */
   509 int
   599 int
   510 zfs_prop_inheritable(zfs_prop_t prop)
   600 zfs_prop_inheritable(zfs_prop_t prop)
   511 {
   601 {
   512 	return (zfs_prop_table[prop].pd_attr == prop_inherit);
   602 	return (zfs_prop_table[prop].pd_attr == PROP_INHERIT);
   513 }
       
   514 
       
   515 typedef struct zfs_index {
       
   516 	const char *name;
       
   517 	uint64_t index;
       
   518 } zfs_index_t;
       
   519 
       
   520 static zfs_index_t checksum_table[] = {
       
   521 	{ "on",		ZIO_CHECKSUM_ON },
       
   522 	{ "off",	ZIO_CHECKSUM_OFF },
       
   523 	{ "fletcher2",	ZIO_CHECKSUM_FLETCHER_2 },
       
   524 	{ "fletcher4",	ZIO_CHECKSUM_FLETCHER_4 },
       
   525 	{ "sha256",	ZIO_CHECKSUM_SHA256 },
       
   526 	{ NULL }
       
   527 };
       
   528 
       
   529 static zfs_index_t compress_table[] = {
       
   530 	{ "on",		ZIO_COMPRESS_ON },
       
   531 	{ "off",	ZIO_COMPRESS_OFF },
       
   532 	{ "lzjb",	ZIO_COMPRESS_LZJB },
       
   533 	{ "gzip",	ZIO_COMPRESS_GZIP_6 },	/* the default gzip level */
       
   534 	{ "gzip-1",	ZIO_COMPRESS_GZIP_1 },
       
   535 	{ "gzip-2",	ZIO_COMPRESS_GZIP_2 },
       
   536 	{ "gzip-3",	ZIO_COMPRESS_GZIP_3 },
       
   537 	{ "gzip-4",	ZIO_COMPRESS_GZIP_4 },
       
   538 	{ "gzip-5",	ZIO_COMPRESS_GZIP_5 },
       
   539 	{ "gzip-6",	ZIO_COMPRESS_GZIP_6 },
       
   540 	{ "gzip-7",	ZIO_COMPRESS_GZIP_7 },
       
   541 	{ "gzip-8",	ZIO_COMPRESS_GZIP_8 },
       
   542 	{ "gzip-9",	ZIO_COMPRESS_GZIP_9 },
       
   543 	{ NULL }
       
   544 };
       
   545 
       
   546 static zfs_index_t snapdir_table[] = {
       
   547 	{ "hidden",	ZFS_SNAPDIR_HIDDEN },
       
   548 	{ "visible",	ZFS_SNAPDIR_VISIBLE },
       
   549 	{ NULL }
       
   550 };
       
   551 
       
   552 static zfs_index_t acl_mode_table[] = {
       
   553 	{ "discard",	ZFS_ACL_DISCARD },
       
   554 	{ "groupmask",	ZFS_ACL_GROUPMASK },
       
   555 	{ "passthrough", ZFS_ACL_PASSTHROUGH },
       
   556 	{ NULL }
       
   557 };
       
   558 
       
   559 static zfs_index_t acl_inherit_table[] = {
       
   560 	{ "discard",	ZFS_ACL_DISCARD },
       
   561 	{ "noallow",	ZFS_ACL_NOALLOW },
       
   562 	{ "secure",	ZFS_ACL_SECURE },
       
   563 	{ "passthrough", ZFS_ACL_PASSTHROUGH },
       
   564 	{ NULL }
       
   565 };
       
   566 
       
   567 static zfs_index_t copies_table[] = {
       
   568 	{ "1",	1 },
       
   569 	{ "2",	2 },
       
   570 	{ "3",	3 },
       
   571 	{ NULL }
       
   572 };
       
   573 
       
   574 static zfs_index_t version_table[] = {
       
   575 	{ "1",		1 },
       
   576 	{ "2",		2 },
       
   577 	{ "current",	ZPL_VERSION },
       
   578 	{ NULL }
       
   579 };
       
   580 
       
   581 static zfs_index_t *
       
   582 zfs_prop_index_table(zfs_prop_t prop)
       
   583 {
       
   584 	switch (prop) {
       
   585 	case ZFS_PROP_CHECKSUM:
       
   586 		return (checksum_table);
       
   587 	case ZFS_PROP_COMPRESSION:
       
   588 		return (compress_table);
       
   589 	case ZFS_PROP_SNAPDIR:
       
   590 		return (snapdir_table);
       
   591 	case ZFS_PROP_ACLMODE:
       
   592 		return (acl_mode_table);
       
   593 	case ZFS_PROP_ACLINHERIT:
       
   594 		return (acl_inherit_table);
       
   595 	case ZFS_PROP_COPIES:
       
   596 		return (copies_table);
       
   597 	case ZFS_PROP_VERSION:
       
   598 		return (version_table);
       
   599 	default:
       
   600 		return (NULL);
       
   601 	}
       
   602 }
   603 }
   603 
   604 
   604 /*
   605 /*
   605  * Tables of index types, plus functions to convert between the user view
   606  * Tables of index types, plus functions to convert between the user view
   606  * (strings) and internal representation (uint64_t).
   607  * (strings) and internal representation (uint64_t).
   607  */
   608  */
   608 int
   609 int
   609 zfs_prop_string_to_index(zfs_prop_t prop, const char *string, uint64_t *index)
   610 zfs_prop_string_to_index(zfs_prop_t prop, const char *string, uint64_t *index)
   610 {
   611 {
   611 	zfs_index_t *table;
   612 	const zfs_index_t *table;
   612 	int i;
   613 	int i;
   613 
   614 
   614 	if ((table = zfs_prop_index_table(prop)) == NULL)
   615 	if ((table = zfs_prop_table[prop].pd_table) == NULL)
   615 		return (-1);
   616 		return (-1);
   616 
   617 
   617 	for (i = 0; table[i].name != NULL; i++) {
   618 	for (i = 0; table[i].name != NULL; i++) {
   618 		if (strcmp(string, table[i].name) == 0) {
   619 		if (strcmp(string, table[i].name) == 0) {
   619 			*index = table[i].index;
   620 			*index = table[i].index;
   625 }
   626 }
   626 
   627 
   627 int
   628 int
   628 zfs_prop_index_to_string(zfs_prop_t prop, uint64_t index, const char **string)
   629 zfs_prop_index_to_string(zfs_prop_t prop, uint64_t index, const char **string)
   629 {
   630 {
   630 	zfs_index_t *table;
   631 	const zfs_index_t *table;
   631 	int i;
   632 	int i;
   632 
   633 
   633 	if ((table = zfs_prop_index_table(prop)) == NULL)
   634 	if ((table = zfs_prop_table[prop].pd_table) == NULL)
   634 		return (-1);
   635 		return (-1);
   635 
   636 
   636 	for (i = 0; table[i].name != NULL; i++) {
   637 	for (i = 0; table[i].name != NULL; i++) {
   637 		if (table[i].index == index) {
   638 		if (table[i].index == index) {
   638 			*string = table[i].name;
   639 			*string = table[i].name;
   677  * are stored numerically on disk.
   678  * are stored numerically on disk.
   678  */
   679  */
   679 int
   680 int
   680 zfs_prop_is_string(zfs_prop_t prop)
   681 zfs_prop_is_string(zfs_prop_t prop)
   681 {
   682 {
   682 	return (zfs_prop_table[prop].pd_proptype == prop_type_string ||
   683 	return (zfs_prop_table[prop].pd_proptype == PROP_TYPE_STRING ||
   683 	    zfs_prop_table[prop].pd_proptype == prop_type_index);
   684 	    zfs_prop_table[prop].pd_proptype == PROP_TYPE_INDEX);
   684 }
   685 }
   685 
   686 
   686 /*
   687 /*
   687  * Returns the column header for the given property.  Used only in
   688  * Returns the column header for the given property.  Used only in
   688  * 'zfs list -o', but centralized here with the other property information.
   689  * 'zfs list -o', but centralized here with the other property information.
   709  */
   710  */
   710 size_t
   711 size_t
   711 zfs_prop_width(zfs_prop_t prop, boolean_t *fixed)
   712 zfs_prop_width(zfs_prop_t prop, boolean_t *fixed)
   712 {
   713 {
   713 	prop_desc_t *pd = &zfs_prop_table[prop];
   714 	prop_desc_t *pd = &zfs_prop_table[prop];
   714 	zfs_index_t *idx;
   715 	const zfs_index_t *idx;
   715 	size_t ret;
   716 	size_t ret;
   716 	int i;
   717 	int i;
   717 
   718 
   718 	*fixed = B_TRUE;
   719 	*fixed = B_TRUE;
   719 
   720 
   725 	/*
   726 	/*
   726 	 * For fixed-width values, make sure the width is large enough to hold
   727 	 * For fixed-width values, make sure the width is large enough to hold
   727 	 * any possible value.
   728 	 * any possible value.
   728 	 */
   729 	 */
   729 	switch (pd->pd_proptype) {
   730 	switch (pd->pd_proptype) {
   730 	case prop_type_number:
   731 	case PROP_TYPE_NUMBER:
   731 		/*
   732 		/*
   732 		 * The maximum length of a human-readable number is 5 characters
   733 		 * The maximum length of a human-readable number is 5 characters
   733 		 * ("20.4M", for example).
   734 		 * ("20.4M", for example).
   734 		 */
   735 		 */
   735 		if (ret < 5)
   736 		if (ret < 5)
   739 		 * internally, but displayed as a date string.
   740 		 * internally, but displayed as a date string.
   740 		 */
   741 		 */
   741 		if (prop == ZFS_PROP_CREATION)
   742 		if (prop == ZFS_PROP_CREATION)
   742 			*fixed = B_FALSE;
   743 			*fixed = B_FALSE;
   743 		break;
   744 		break;
   744 	case prop_type_boolean:
   745 	case PROP_TYPE_BOOLEAN:
   745 		/*
   746 		/*
   746 		 * The maximum length of a boolean value is 3 characters, for
   747 		 * The maximum length of a boolean value is 3 characters, for
   747 		 * "off".
   748 		 * "off".
   748 		 */
   749 		 */
   749 		if (ret < 3)
   750 		if (ret < 3)
   750 			ret = 3;
   751 			ret = 3;
   751 		break;
   752 		break;
   752 	case prop_type_index:
   753 	case PROP_TYPE_INDEX:
   753 		idx = zfs_prop_index_table(prop);
   754 		idx = zfs_prop_table[prop].pd_table;
   754 		for (i = 0; idx[i].name != NULL; i++) {
   755 		for (i = 0; idx[i].name != NULL; i++) {
   755 			if (strlen(idx[i].name) > ret)
   756 			if (strlen(idx[i].name) > ret)
   756 				ret = strlen(idx[i].name);
   757 				ret = strlen(idx[i].name);
   757 		}
   758 		}
   758 		break;
   759 		break;
   759 
   760 
   760 	case prop_type_string:
   761 	case PROP_TYPE_STRING:
   761 		*fixed = B_FALSE;
   762 		*fixed = B_FALSE;
   762 		break;
   763 		break;
   763 	}
   764 	}
   764 
   765 
   765 	return (ret);
   766 	return (ret);