xref: /freebsd/sys/contrib/openzfs/module/zcommon/zfs_comutil.c (revision 2f10ffc003be396f3fc23cd2888023896560252b)
1 // SPDX-License-Identifier: CDDL-1.0
2 /*
3  * This file and its contents are supplied under the terms of the
4  * Common Development and Distribution License ("CDDL"), version 1.0.
5  * You may only use this file in accordance with the terms of version
6  * 1.0 of the CDDL.
7  *
8  * A full copy of the text of the CDDL should have accompanied this
9  * source.  A copy of the CDDL is also available via the Internet at
10  * https://opensource.org/license/CDDL-1.0.
11  */
12 /*
13  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
14  * Copyright (c) 2012, 2017 by Delphix. All rights reserved.
15  */
16 
17 /*
18  * This file is intended for functions that ought to be common between user
19  * land (libzfs) and the kernel. When many common routines need to be shared
20  * then a separate file should be created.
21  */
22 
23 #if !defined(_KERNEL)
24 #include <string.h>
25 #endif
26 
27 #include <sys/types.h>
28 #include <sys/fs/zfs.h>
29 #include <sys/nvpair.h>
30 #include "zfs_comutil.h"
31 #include <sys/zfs_ratelimit.h>
32 
33 /*
34  * Are there allocatable vdevs?
35  */
36 boolean_t
37 zfs_allocatable_devs(nvlist_t *nv)
38 {
39 	uint64_t is_log;
40 	uint_t c;
41 	nvlist_t **child;
42 	uint_t children;
43 
44 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
45 	    &child, &children) != 0) {
46 		return (B_FALSE);
47 	}
48 	for (c = 0; c < children; c++) {
49 		is_log = 0;
50 		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
51 		    &is_log);
52 		if (!is_log)
53 			return (B_TRUE);
54 	}
55 	return (B_FALSE);
56 }
57 
58 /*
59  * Are there special vdevs?
60  */
61 boolean_t
62 zfs_special_devs(nvlist_t *nv, const char *type)
63 {
64 	const char *bias;
65 	uint_t c;
66 	nvlist_t **child;
67 	uint_t children;
68 
69 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
70 	    &child, &children) != 0) {
71 		return (B_FALSE);
72 	}
73 	for (c = 0; c < children; c++) {
74 		if (nvlist_lookup_string(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS,
75 		    &bias) == 0) {
76 			if (strcmp(bias, VDEV_ALLOC_BIAS_SPECIAL) == 0 ||
77 			    strcmp(bias, VDEV_ALLOC_BIAS_DEDUP) == 0) {
78 				if (type == NULL ||
79 				    (type != NULL && strcmp(bias, type) == 0))
80 					return (B_TRUE);
81 			}
82 		}
83 	}
84 	return (B_FALSE);
85 }
86 
87 void
88 zpool_get_load_policy(nvlist_t *nvl, zpool_load_policy_t *zlpp)
89 {
90 	nvlist_t *policy;
91 	nvpair_t *elem;
92 	const char *nm;
93 
94 	/* Defaults */
95 	zlpp->zlp_rewind = ZPOOL_NO_REWIND;
96 	zlpp->zlp_relaxmeta = B_FALSE;
97 	zlpp->zlp_maxmeta = 0;
98 	zlpp->zlp_maxdata = UINT64_MAX;
99 	zlpp->zlp_txg = UINT64_MAX;
100 
101 	if (nvl == NULL)
102 		return;
103 
104 	elem = NULL;
105 	while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) {
106 		nm = nvpair_name(elem);
107 		if (strcmp(nm, ZPOOL_LOAD_POLICY) == 0) {
108 			if (nvpair_value_nvlist(elem, &policy) == 0)
109 				zpool_get_load_policy(policy, zlpp);
110 			return;
111 		} else if (strcmp(nm, ZPOOL_LOAD_REWIND_POLICY) == 0) {
112 			if (nvpair_value_uint32(elem, &zlpp->zlp_rewind) == 0)
113 				if (zlpp->zlp_rewind & ~ZPOOL_REWIND_POLICIES)
114 					zlpp->zlp_rewind = ZPOOL_NO_REWIND;
115 		} else if (strcmp(nm, ZPOOL_LOAD_REQUEST_TXG) == 0) {
116 			(void) nvpair_value_uint64(elem, &zlpp->zlp_txg);
117 		} else if (strcmp(nm, ZPOOL_LOAD_RELAX_META) == 0) {
118 			(void) nvpair_value_boolean_value(elem,
119 			    &zlpp->zlp_relaxmeta);
120 		} else if (strcmp(nm, ZPOOL_LOAD_META_THRESH) == 0) {
121 			(void) nvpair_value_uint64(elem, &zlpp->zlp_maxmeta);
122 		} else if (strcmp(nm, ZPOOL_LOAD_DATA_THRESH) == 0) {
123 			(void) nvpair_value_uint64(elem, &zlpp->zlp_maxdata);
124 		}
125 	}
126 	if (zlpp->zlp_rewind == 0)
127 		zlpp->zlp_rewind = ZPOOL_NO_REWIND;
128 }
129 
130 typedef struct zfs_version_spa_map {
131 	int	version_zpl;
132 	int	version_spa;
133 } zfs_version_spa_map_t;
134 
135 /*
136  * Keep this table in monotonically increasing version number order.
137  */
138 static zfs_version_spa_map_t zfs_version_table[] = {
139 	{ZPL_VERSION_INITIAL, SPA_VERSION_INITIAL},
140 	{ZPL_VERSION_DIRENT_TYPE, SPA_VERSION_INITIAL},
141 	{ZPL_VERSION_FUID, SPA_VERSION_FUID},
142 	{ZPL_VERSION_USERSPACE, SPA_VERSION_USERSPACE},
143 	{ZPL_VERSION_SA, SPA_VERSION_SA},
144 	{0, 0}
145 };
146 
147 /*
148  * Return the max zpl version for a corresponding spa version
149  * -1 is returned if no mapping exists.
150  */
151 int
152 zfs_zpl_version_map(int spa_version)
153 {
154 	int version = -1;
155 
156 	for (int i = 0; zfs_version_table[i].version_spa; i++)
157 		if (spa_version >= zfs_version_table[i].version_spa)
158 			version = zfs_version_table[i].version_zpl;
159 
160 	return (version);
161 }
162 
163 /*
164  * Return the min spa version for a corresponding spa version
165  * -1 is returned if no mapping exists.
166  */
167 int
168 zfs_spa_version_map(int zpl_version)
169 {
170 	for (int i = 0; zfs_version_table[i].version_zpl; i++)
171 		if (zfs_version_table[i].version_zpl >= zpl_version)
172 			return (zfs_version_table[i].version_spa);
173 
174 	return (-1);
175 }
176 
177 /*
178  * This is the table of legacy internal event names; it should not be modified.
179  * The internal events are now stored in the history log as strings.
180  */
181 const char *const zfs_history_event_names[ZFS_NUM_LEGACY_HISTORY_EVENTS] = {
182 	"invalid event",
183 	"pool create",
184 	"vdev add",
185 	"pool remove",
186 	"pool destroy",
187 	"pool export",
188 	"pool import",
189 	"vdev attach",
190 	"vdev replace",
191 	"vdev detach",
192 	"vdev online",
193 	"vdev offline",
194 	"vdev upgrade",
195 	"pool clear",
196 	"pool scrub",
197 	"pool property set",
198 	"create",
199 	"clone",
200 	"destroy",
201 	"destroy_begin_sync",
202 	"inherit",
203 	"property set",
204 	"quota set",
205 	"permission update",
206 	"permission remove",
207 	"permission who remove",
208 	"promote",
209 	"receive",
210 	"rename",
211 	"reservation set",
212 	"replay_inc_sync",
213 	"replay_full_sync",
214 	"rollback",
215 	"snapshot",
216 	"filesystem version upgrade",
217 	"refquota set",
218 	"refreservation set",
219 	"pool scrub done",
220 	"user hold",
221 	"user release",
222 	"pool split",
223 };
224 
225 boolean_t
226 zfs_dataset_name_hidden(const char *name)
227 {
228 	/*
229 	 * Skip over datasets that are not visible in this zone,
230 	 * internal datasets (which have a $ in their name), and
231 	 * temporary datasets (which have a % in their name).
232 	 */
233 	if (strpbrk(name, "$%") != NULL)
234 		return (B_TRUE);
235 	if (!INGLOBALZONE(curproc) && !zone_dataset_visible(name, NULL))
236 		return (B_TRUE);
237 	return (B_FALSE);
238 }
239 
240 #if defined(_KERNEL)
241 EXPORT_SYMBOL(zfs_allocatable_devs);
242 EXPORT_SYMBOL(zfs_special_devs);
243 EXPORT_SYMBOL(zpool_get_load_policy);
244 EXPORT_SYMBOL(zfs_zpl_version_map);
245 EXPORT_SYMBOL(zfs_spa_version_map);
246 EXPORT_SYMBOL(zfs_history_event_names);
247 EXPORT_SYMBOL(zfs_dataset_name_hidden);
248 #endif
249