xref: /illumos-gate/usr/src/common/zfs/zfs_prop.c (revision fa9e4066f08beec538e775443c5be79dd423fcab)
1*fa9e4066Sahrens /*
2*fa9e4066Sahrens  * CDDL HEADER START
3*fa9e4066Sahrens  *
4*fa9e4066Sahrens  * The contents of this file are subject to the terms of the
5*fa9e4066Sahrens  * Common Development and Distribution License, Version 1.0 only
6*fa9e4066Sahrens  * (the "License").  You may not use this file except in compliance
7*fa9e4066Sahrens  * with the License.
8*fa9e4066Sahrens  *
9*fa9e4066Sahrens  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*fa9e4066Sahrens  * or http://www.opensolaris.org/os/licensing.
11*fa9e4066Sahrens  * See the License for the specific language governing permissions
12*fa9e4066Sahrens  * and limitations under the License.
13*fa9e4066Sahrens  *
14*fa9e4066Sahrens  * When distributing Covered Code, include this CDDL HEADER in each
15*fa9e4066Sahrens  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*fa9e4066Sahrens  * If applicable, add the following below this CDDL HEADER, with the
17*fa9e4066Sahrens  * fields enclosed by brackets "[]" replaced with your own identifying
18*fa9e4066Sahrens  * information: Portions Copyright [yyyy] [name of copyright owner]
19*fa9e4066Sahrens  *
20*fa9e4066Sahrens  * CDDL HEADER END
21*fa9e4066Sahrens  */
22*fa9e4066Sahrens /*
23*fa9e4066Sahrens  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*fa9e4066Sahrens  * Use is subject to license terms.
25*fa9e4066Sahrens  */
26*fa9e4066Sahrens 
27*fa9e4066Sahrens #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*fa9e4066Sahrens 
29*fa9e4066Sahrens /*
30*fa9e4066Sahrens  * Master property table.
31*fa9e4066Sahrens  *
32*fa9e4066Sahrens  * This table keeps track of all the properties supported by ZFS, and their
33*fa9e4066Sahrens  * various attributes.  Not all of these are needed by the kernel, and several
34*fa9e4066Sahrens  * are only used by a single libzfs client.  But having them here centralizes
35*fa9e4066Sahrens  * all property information in one location.
36*fa9e4066Sahrens  *
37*fa9e4066Sahrens  * 	name		The human-readable string representing this property
38*fa9e4066Sahrens  * 	proptype	Basic type (string, boolean, number)
39*fa9e4066Sahrens  * 	default		Default value for the property.  Sadly, C only allows
40*fa9e4066Sahrens  * 			you to initialize the first member of a union, so we
41*fa9e4066Sahrens  * 			have two default members for each property.
42*fa9e4066Sahrens  * 	attr		Attributes (readonly, inheritable) for the property
43*fa9e4066Sahrens  * 	types		Valid dataset types to which this applies
44*fa9e4066Sahrens  * 	values		String describing acceptable values for the property
45*fa9e4066Sahrens  * 	colname		The column header for 'zfs list'
46*fa9e4066Sahrens  *	colfmt		The column formatting for 'zfs list'
47*fa9e4066Sahrens  *
48*fa9e4066Sahrens  * This table must match the order of property types in libzfs.h.
49*fa9e4066Sahrens  */
50*fa9e4066Sahrens 
51*fa9e4066Sahrens #include <sys/zio.h>
52*fa9e4066Sahrens #include <sys/spa.h>
53*fa9e4066Sahrens #include <sys/zfs_acl.h>
54*fa9e4066Sahrens #include <sys/zfs_ioctl.h>
55*fa9e4066Sahrens 
56*fa9e4066Sahrens #include "zfs_prop.h"
57*fa9e4066Sahrens 
58*fa9e4066Sahrens #if defined(_KERNEL)
59*fa9e4066Sahrens #include <sys/systm.h>
60*fa9e4066Sahrens #else
61*fa9e4066Sahrens #include <stdlib.h>
62*fa9e4066Sahrens #include <string.h>
63*fa9e4066Sahrens #include <ctype.h>
64*fa9e4066Sahrens #endif
65*fa9e4066Sahrens 
66*fa9e4066Sahrens typedef enum {
67*fa9e4066Sahrens 	prop_default,
68*fa9e4066Sahrens 	prop_readonly,
69*fa9e4066Sahrens 	prop_inherit
70*fa9e4066Sahrens } prop_attr_t;
71*fa9e4066Sahrens 
72*fa9e4066Sahrens typedef struct {
73*fa9e4066Sahrens 	const char	*pd_name;
74*fa9e4066Sahrens 	zfs_proptype_t	pd_proptype;
75*fa9e4066Sahrens 	uint64_t	pd_numdefault;
76*fa9e4066Sahrens 	const char	*pd_strdefault;
77*fa9e4066Sahrens 	prop_attr_t	pd_attr;
78*fa9e4066Sahrens 	int		pd_types;
79*fa9e4066Sahrens 	const char	*pd_values;
80*fa9e4066Sahrens 	const char	*pd_colname;
81*fa9e4066Sahrens 	const char	*pd_colfmt;
82*fa9e4066Sahrens } prop_desc_t;
83*fa9e4066Sahrens 
84*fa9e4066Sahrens static prop_desc_t zfs_prop_table[ZFS_NPROP_ALL] = {
85*fa9e4066Sahrens 	{ "type",	prop_type_string,	0,	NULL,	prop_readonly,
86*fa9e4066Sahrens 	    ZFS_TYPE_ANY, "filesystem | volume | snapshot", "TYPE", "%10s" },
87*fa9e4066Sahrens 	{ "creation",	prop_type_number,	0,	NULL,	prop_readonly,
88*fa9e4066Sahrens 	    ZFS_TYPE_ANY, "<date>", "CREATION", "%-20s" },
89*fa9e4066Sahrens 	{ "used",	prop_type_number,	0,	NULL,	prop_readonly,
90*fa9e4066Sahrens 	    ZFS_TYPE_ANY, "<size>",	"USED", "%5s" },
91*fa9e4066Sahrens 	{ "available",	prop_type_number,	0,	NULL,	prop_readonly,
92*fa9e4066Sahrens 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "<size>", "AVAIL", "%5s" },
93*fa9e4066Sahrens 	{ "referenced",	prop_type_number,	0,	NULL,	prop_readonly,
94*fa9e4066Sahrens 	    ZFS_TYPE_SNAPSHOT | ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
95*fa9e4066Sahrens 	    "<size>", "REFER", "%5s" },
96*fa9e4066Sahrens 	{ "compressratio", prop_type_number,	0,	NULL,	prop_readonly,
97*fa9e4066Sahrens 	    ZFS_TYPE_ANY, "<1.00x or higher if compressed>", "RATIO", "%5s" },
98*fa9e4066Sahrens 	{ "mounted",	prop_type_boolean,	0,	NULL,	prop_readonly,
99*fa9e4066Sahrens 	    ZFS_TYPE_FILESYSTEM, "yes | no | -", "MOUNTED", "%7s" },
100*fa9e4066Sahrens 	{ "origin",	prop_type_string,	0,	NULL,	prop_readonly,
101*fa9e4066Sahrens 	    ZFS_TYPE_FILESYSTEM, "<snapshot>", "ORIGIN", "%-20s" },
102*fa9e4066Sahrens 	{ "quota",	prop_type_number,	0,	NULL,	prop_default,
103*fa9e4066Sahrens 	    ZFS_TYPE_FILESYSTEM, "<size> | none", "QUOTA", "%5s" },
104*fa9e4066Sahrens 	{ "reservation", prop_type_number,	0,	NULL,	prop_default,
105*fa9e4066Sahrens 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
106*fa9e4066Sahrens 	    "<size> | none", "RESERV", "%6s" },
107*fa9e4066Sahrens 	{ "volsize",	prop_type_number,	0,	NULL,	prop_default,
108*fa9e4066Sahrens 	    ZFS_TYPE_VOLUME, "<size>", "VOLSIZE", "%7s" },
109*fa9e4066Sahrens 	{ "volblocksize", prop_type_number,	8192,	NULL,	prop_default,
110*fa9e4066Sahrens 	    ZFS_TYPE_VOLUME, "512 to 128k, power of 2",	"VOLBLOCK", "%8s" },
111*fa9e4066Sahrens 	{ "recordsize",	prop_type_number,	SPA_MAXBLOCKSIZE,	NULL,
112*fa9e4066Sahrens 	    prop_inherit,
113*fa9e4066Sahrens 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT,
114*fa9e4066Sahrens 	    "512 to 128k, power of 2", "RECSIZE", "%7s" },
115*fa9e4066Sahrens 	{ "mountpoint",	prop_type_string,	0,	"/",	prop_inherit,
116*fa9e4066Sahrens 	    ZFS_TYPE_FILESYSTEM,
117*fa9e4066Sahrens 	    "<path> | legacy | none", "MOUNTPOINT", "%-20s" },
118*fa9e4066Sahrens 	{ "sharenfs",	prop_type_string,	0,	"off",	prop_inherit,
119*fa9e4066Sahrens 	    ZFS_TYPE_FILESYSTEM,
120*fa9e4066Sahrens 	    "on | off | share(1M) options", "SHARENFS", "%-15s" },
121*fa9e4066Sahrens 	{ "checksum",	prop_type_index,	ZIO_CHECKSUM_DEFAULT,	NULL,
122*fa9e4066Sahrens 	    prop_inherit,	ZFS_TYPE_ANY,
123*fa9e4066Sahrens 	    "on | off | fletcher2 | fletcher4 | sha256", "CHECKSUM", "%10s" },
124*fa9e4066Sahrens 	{ "compression", prop_type_index,	ZIO_COMPRESS_DEFAULT,	NULL,
125*fa9e4066Sahrens 	    prop_inherit,	ZFS_TYPE_ANY,
126*fa9e4066Sahrens 	    "on | off | lzjb", "COMPRESS", "%8s" },
127*fa9e4066Sahrens 	{ "atime",	prop_type_boolean,	1,	NULL,	prop_inherit,
128*fa9e4066Sahrens 	    ZFS_TYPE_FILESYSTEM,
129*fa9e4066Sahrens 	    "on | off", "ATIME", "%5s" },
130*fa9e4066Sahrens 	{ "devices",	prop_type_boolean,	1,	NULL,	prop_inherit,
131*fa9e4066Sahrens 	    ZFS_TYPE_FILESYSTEM,
132*fa9e4066Sahrens 	    "on | off", "DEVICES", "%7s" },
133*fa9e4066Sahrens 	{ "exec",	prop_type_boolean,	1,	NULL,	prop_inherit,
134*fa9e4066Sahrens 	    ZFS_TYPE_FILESYSTEM,
135*fa9e4066Sahrens 	    "on | off", "EXEC", "%4s" },
136*fa9e4066Sahrens 	{ "setuid",	prop_type_boolean,	1,	NULL,	prop_inherit,
137*fa9e4066Sahrens 	    ZFS_TYPE_FILESYSTEM, "on | off", "SETUID", "%6s" },
138*fa9e4066Sahrens 	{ "readonly",	prop_type_boolean,	0,	NULL,	prop_inherit,
139*fa9e4066Sahrens 	    ZFS_TYPE_ANY, "on | off", "RDONLY", "%6s" },
140*fa9e4066Sahrens 	{ "zoned",	prop_type_boolean,	0,	NULL,	prop_inherit,
141*fa9e4066Sahrens 	    ZFS_TYPE_ANY,
142*fa9e4066Sahrens 	    "on | off", "ZONED", "%5s" },
143*fa9e4066Sahrens 	{ "snapdir",	prop_type_index,	VISIBLE, NULL,	prop_inherit,
144*fa9e4066Sahrens 	    ZFS_TYPE_FILESYSTEM,
145*fa9e4066Sahrens 	    "hidden | visible", "SNAPDIR", "%7s" },
146*fa9e4066Sahrens 	{ "aclmode", prop_type_index,	GROUPMASK,	 NULL,	prop_inherit,
147*fa9e4066Sahrens 	    ZFS_TYPE_FILESYSTEM,
148*fa9e4066Sahrens 	    "discard | groupmask | passthrough", "ACLMODE", "%11s" },
149*fa9e4066Sahrens 	{ "aclinherit", prop_type_index,	SECURE,	NULL, 	prop_inherit,
150*fa9e4066Sahrens 	    ZFS_TYPE_FILESYSTEM,
151*fa9e4066Sahrens 	    "discard | noallow | secure | passthrough", "ACLINHERIT", "%11s" },
152*fa9e4066Sahrens 	{ "createtxg",	prop_type_number,	0,	NULL,	prop_readonly,
153*fa9e4066Sahrens 	    ZFS_TYPE_ANY, NULL, NULL, NULL},
154*fa9e4066Sahrens 	{ "name",	prop_type_string,	0,	NULL,	prop_readonly,
155*fa9e4066Sahrens 	    ZFS_TYPE_ANY,
156*fa9e4066Sahrens 	    NULL, "NAME", "%-20s" },
157*fa9e4066Sahrens };
158*fa9e4066Sahrens 
159*fa9e4066Sahrens zfs_proptype_t
160*fa9e4066Sahrens zfs_prop_get_type(zfs_prop_t prop)
161*fa9e4066Sahrens {
162*fa9e4066Sahrens 	return (zfs_prop_table[prop].pd_proptype);
163*fa9e4066Sahrens }
164*fa9e4066Sahrens 
165*fa9e4066Sahrens /*
166*fa9e4066Sahrens  * Given a property name, returns the corresponding property ID.
167*fa9e4066Sahrens  */
168*fa9e4066Sahrens zfs_prop_t
169*fa9e4066Sahrens zfs_name_to_prop(const char *propname)
170*fa9e4066Sahrens {
171*fa9e4066Sahrens 	int i;
172*fa9e4066Sahrens 
173*fa9e4066Sahrens 	for (i = 0; i < ZFS_NPROP_ALL; i++) {
174*fa9e4066Sahrens 		if (strcmp(zfs_prop_table[i].pd_name, propname) == 0)
175*fa9e4066Sahrens 			return (i);
176*fa9e4066Sahrens #ifndef _KERNEL
177*fa9e4066Sahrens 		if (zfs_prop_table[i].pd_colname != NULL &&
178*fa9e4066Sahrens 		    strcasecmp(zfs_prop_table[i].pd_colname, propname) == 0)
179*fa9e4066Sahrens 			return (i);
180*fa9e4066Sahrens #endif
181*fa9e4066Sahrens 	}
182*fa9e4066Sahrens 
183*fa9e4066Sahrens 	return (ZFS_PROP_INVAL);
184*fa9e4066Sahrens }
185*fa9e4066Sahrens 
186*fa9e4066Sahrens /*
187*fa9e4066Sahrens  * Return the default value for the given property.
188*fa9e4066Sahrens  */
189*fa9e4066Sahrens void
190*fa9e4066Sahrens zfs_prop_default_string(zfs_prop_t prop, char *buf, size_t buflen)
191*fa9e4066Sahrens {
192*fa9e4066Sahrens 	/*
193*fa9e4066Sahrens 	 * For index types (compression and checksum), we want the numeric value
194*fa9e4066Sahrens 	 * in the kernel, but the string value in userland.  The kernel will
195*fa9e4066Sahrens 	 * call zfs_prop_default_numeric() based on the property type.  In
196*fa9e4066Sahrens 	 * userland, the zfs_prop_is_string() will return TRUE for index types,
197*fa9e4066Sahrens 	 * and we'll return "on" from this function.
198*fa9e4066Sahrens 	 */
199*fa9e4066Sahrens 	if (zfs_prop_table[prop].pd_proptype == prop_type_index)
200*fa9e4066Sahrens 		(void) strncpy(buf, "on", buflen);
201*fa9e4066Sahrens 	else
202*fa9e4066Sahrens 		(void) strncpy(buf, zfs_prop_table[prop].pd_strdefault, buflen);
203*fa9e4066Sahrens }
204*fa9e4066Sahrens 
205*fa9e4066Sahrens uint64_t
206*fa9e4066Sahrens zfs_prop_default_numeric(zfs_prop_t prop)
207*fa9e4066Sahrens {
208*fa9e4066Sahrens 	return (zfs_prop_table[prop].pd_numdefault);
209*fa9e4066Sahrens }
210*fa9e4066Sahrens 
211*fa9e4066Sahrens /*
212*fa9e4066Sahrens  * Returns TRUE if the property is readonly.
213*fa9e4066Sahrens  */
214*fa9e4066Sahrens int
215*fa9e4066Sahrens zfs_prop_readonly(zfs_prop_t prop)
216*fa9e4066Sahrens {
217*fa9e4066Sahrens 	return (zfs_prop_table[prop].pd_attr == prop_readonly);
218*fa9e4066Sahrens }
219*fa9e4066Sahrens 
220*fa9e4066Sahrens #ifndef _KERNEL
221*fa9e4066Sahrens /*
222*fa9e4066Sahrens  * Given a property ID, returns the corresponding name.
223*fa9e4066Sahrens  */
224*fa9e4066Sahrens const char *
225*fa9e4066Sahrens zfs_prop_to_name(zfs_prop_t prop)
226*fa9e4066Sahrens {
227*fa9e4066Sahrens 	return (zfs_prop_table[prop].pd_name);
228*fa9e4066Sahrens }
229*fa9e4066Sahrens 
230*fa9e4066Sahrens /*
231*fa9e4066Sahrens  * Returns TRUE if the property is inheritable.
232*fa9e4066Sahrens  */
233*fa9e4066Sahrens int
234*fa9e4066Sahrens zfs_prop_inheritable(zfs_prop_t prop)
235*fa9e4066Sahrens {
236*fa9e4066Sahrens 	return (zfs_prop_table[prop].pd_attr == prop_inherit);
237*fa9e4066Sahrens }
238*fa9e4066Sahrens 
239*fa9e4066Sahrens /*
240*fa9e4066Sahrens  * Returns TRUE if the property applies to the given dataset types.
241*fa9e4066Sahrens  */
242*fa9e4066Sahrens int
243*fa9e4066Sahrens zfs_prop_valid_for_type(zfs_prop_t prop, int types)
244*fa9e4066Sahrens {
245*fa9e4066Sahrens 	return ((zfs_prop_table[prop].pd_types & types) != 0);
246*fa9e4066Sahrens }
247*fa9e4066Sahrens 
248*fa9e4066Sahrens /*
249*fa9e4066Sahrens  * Returns a string describing the set of acceptable values for the given
250*fa9e4066Sahrens  * property, or NULL if it cannot be set.
251*fa9e4066Sahrens  */
252*fa9e4066Sahrens const char *
253*fa9e4066Sahrens zfs_prop_values(zfs_prop_t prop)
254*fa9e4066Sahrens {
255*fa9e4066Sahrens 	return (zfs_prop_table[prop].pd_values);
256*fa9e4066Sahrens }
257*fa9e4066Sahrens 
258*fa9e4066Sahrens /*
259*fa9e4066Sahrens  * Returns TRUE if this property is a string type.  Note that index types
260*fa9e4066Sahrens  * (compression, checksum) are treated as strings in userland, even though they
261*fa9e4066Sahrens  * are stored numerically on disk.
262*fa9e4066Sahrens  */
263*fa9e4066Sahrens int
264*fa9e4066Sahrens zfs_prop_is_string(zfs_prop_t prop)
265*fa9e4066Sahrens {
266*fa9e4066Sahrens 	return (zfs_prop_table[prop].pd_proptype == prop_type_string ||
267*fa9e4066Sahrens 	    zfs_prop_table[prop].pd_proptype == prop_type_index);
268*fa9e4066Sahrens }
269*fa9e4066Sahrens 
270*fa9e4066Sahrens /*
271*fa9e4066Sahrens  * Returns the column header for the given property.  Used only in
272*fa9e4066Sahrens  * 'zfs list -o', but centralized here with the other property information.
273*fa9e4066Sahrens  */
274*fa9e4066Sahrens const char *
275*fa9e4066Sahrens zfs_prop_column_name(zfs_prop_t prop)
276*fa9e4066Sahrens {
277*fa9e4066Sahrens 	return (zfs_prop_table[prop].pd_colname);
278*fa9e4066Sahrens }
279*fa9e4066Sahrens 
280*fa9e4066Sahrens /*
281*fa9e4066Sahrens  * Returns the column formatting for the given property.  Used only in
282*fa9e4066Sahrens  * 'zfs list -o', but centralized here with the other property information.
283*fa9e4066Sahrens  */
284*fa9e4066Sahrens const char *
285*fa9e4066Sahrens zfs_prop_column_format(zfs_prop_t prop)
286*fa9e4066Sahrens {
287*fa9e4066Sahrens 	return (zfs_prop_table[prop].pd_colfmt);
288*fa9e4066Sahrens }
289*fa9e4066Sahrens 
290*fa9e4066Sahrens /*
291*fa9e4066Sahrens  * Returns an array of names suitable for passing to getsubopt() to determine
292*fa9e4066Sahrens  * the property index.
293*fa9e4066Sahrens  */
294*fa9e4066Sahrens char **
295*fa9e4066Sahrens zfs_prop_column_subopts(void)
296*fa9e4066Sahrens {
297*fa9e4066Sahrens 	char **ret = malloc((ZFS_NPROP_ALL + 1) * sizeof (char *));
298*fa9e4066Sahrens 	int i;
299*fa9e4066Sahrens 
300*fa9e4066Sahrens 	for (i = 0; i < ZFS_NPROP_ALL; i++)
301*fa9e4066Sahrens 		ret[i] = (char *)zfs_prop_table[i].pd_name;
302*fa9e4066Sahrens 
303*fa9e4066Sahrens 	ret[i] = NULL;
304*fa9e4066Sahrens 
305*fa9e4066Sahrens 	return (ret);
306*fa9e4066Sahrens }
307*fa9e4066Sahrens 
308*fa9e4066Sahrens /*
309*fa9e4066Sahrens  * Same as above, but using the short (abbreviated) column names as indices.
310*fa9e4066Sahrens  */
311*fa9e4066Sahrens char **
312*fa9e4066Sahrens zfs_prop_column_short_subopts(void)
313*fa9e4066Sahrens {
314*fa9e4066Sahrens 	char **ret = malloc((ZFS_NPROP_ALL + 1) * sizeof (char *) * 2);
315*fa9e4066Sahrens 	char *cur;
316*fa9e4066Sahrens 	int i;
317*fa9e4066Sahrens 
318*fa9e4066Sahrens 	for (i = 0; i < ZFS_NPROP_ALL; i++) {
319*fa9e4066Sahrens 		if (zfs_prop_table[i].pd_colname == NULL) {
320*fa9e4066Sahrens 			ret[i] = "";
321*fa9e4066Sahrens 		} else {
322*fa9e4066Sahrens 			ret[i] = strdup(zfs_prop_table[i].pd_colname);
323*fa9e4066Sahrens 			for (cur = ret[i]; *cur != '\0'; cur++)
324*fa9e4066Sahrens 				*cur = tolower(*cur);
325*fa9e4066Sahrens 		}
326*fa9e4066Sahrens 	}
327*fa9e4066Sahrens 
328*fa9e4066Sahrens 
329*fa9e4066Sahrens 	ret[i] = NULL;
330*fa9e4066Sahrens 
331*fa9e4066Sahrens 	return (ret);
332*fa9e4066Sahrens }
333*fa9e4066Sahrens 
334*fa9e4066Sahrens #endif
335