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
zfs_allocatable_devs(nvlist_t * nv)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
zfs_special_devs(nvlist_t * nv,const char * type)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
zpool_get_load_policy(nvlist_t * nvl,zpool_load_policy_t * zlpp)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_maxmeta = 0;
97 zlpp->zlp_maxdata = UINT64_MAX;
98 zlpp->zlp_txg = UINT64_MAX;
99
100 if (nvl == NULL)
101 return;
102
103 elem = NULL;
104 while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) {
105 nm = nvpair_name(elem);
106 if (strcmp(nm, ZPOOL_LOAD_POLICY) == 0) {
107 if (nvpair_value_nvlist(elem, &policy) == 0)
108 zpool_get_load_policy(policy, zlpp);
109 return;
110 } else if (strcmp(nm, ZPOOL_LOAD_REWIND_POLICY) == 0) {
111 if (nvpair_value_uint32(elem, &zlpp->zlp_rewind) == 0)
112 if (zlpp->zlp_rewind & ~ZPOOL_REWIND_POLICIES)
113 zlpp->zlp_rewind = ZPOOL_NO_REWIND;
114 } else if (strcmp(nm, ZPOOL_LOAD_REQUEST_TXG) == 0) {
115 (void) nvpair_value_uint64(elem, &zlpp->zlp_txg);
116 } else if (strcmp(nm, ZPOOL_LOAD_META_THRESH) == 0) {
117 (void) nvpair_value_uint64(elem, &zlpp->zlp_maxmeta);
118 } else if (strcmp(nm, ZPOOL_LOAD_DATA_THRESH) == 0) {
119 (void) nvpair_value_uint64(elem, &zlpp->zlp_maxdata);
120 }
121 }
122 if (zlpp->zlp_rewind == 0)
123 zlpp->zlp_rewind = ZPOOL_NO_REWIND;
124 }
125
126 typedef struct zfs_version_spa_map {
127 int version_zpl;
128 int version_spa;
129 } zfs_version_spa_map_t;
130
131 /*
132 * Keep this table in monotonically increasing version number order.
133 */
134 static zfs_version_spa_map_t zfs_version_table[] = {
135 {ZPL_VERSION_INITIAL, SPA_VERSION_INITIAL},
136 {ZPL_VERSION_DIRENT_TYPE, SPA_VERSION_INITIAL},
137 {ZPL_VERSION_FUID, SPA_VERSION_FUID},
138 {ZPL_VERSION_USERSPACE, SPA_VERSION_USERSPACE},
139 {ZPL_VERSION_SA, SPA_VERSION_SA},
140 {0, 0}
141 };
142
143 /*
144 * Return the max zpl version for a corresponding spa version
145 * -1 is returned if no mapping exists.
146 */
147 int
zfs_zpl_version_map(int spa_version)148 zfs_zpl_version_map(int spa_version)
149 {
150 int version = -1;
151
152 for (int i = 0; zfs_version_table[i].version_spa; i++)
153 if (spa_version >= zfs_version_table[i].version_spa)
154 version = zfs_version_table[i].version_zpl;
155
156 return (version);
157 }
158
159 /*
160 * Return the min spa version for a corresponding spa version
161 * -1 is returned if no mapping exists.
162 */
163 int
zfs_spa_version_map(int zpl_version)164 zfs_spa_version_map(int zpl_version)
165 {
166 for (int i = 0; zfs_version_table[i].version_zpl; i++)
167 if (zfs_version_table[i].version_zpl >= zpl_version)
168 return (zfs_version_table[i].version_spa);
169
170 return (-1);
171 }
172
173 /*
174 * This is the table of legacy internal event names; it should not be modified.
175 * The internal events are now stored in the history log as strings.
176 */
177 const char *const zfs_history_event_names[ZFS_NUM_LEGACY_HISTORY_EVENTS] = {
178 "invalid event",
179 "pool create",
180 "vdev add",
181 "pool remove",
182 "pool destroy",
183 "pool export",
184 "pool import",
185 "vdev attach",
186 "vdev replace",
187 "vdev detach",
188 "vdev online",
189 "vdev offline",
190 "vdev upgrade",
191 "pool clear",
192 "pool scrub",
193 "pool property set",
194 "create",
195 "clone",
196 "destroy",
197 "destroy_begin_sync",
198 "inherit",
199 "property set",
200 "quota set",
201 "permission update",
202 "permission remove",
203 "permission who remove",
204 "promote",
205 "receive",
206 "rename",
207 "reservation set",
208 "replay_inc_sync",
209 "replay_full_sync",
210 "rollback",
211 "snapshot",
212 "filesystem version upgrade",
213 "refquota set",
214 "refreservation set",
215 "pool scrub done",
216 "user hold",
217 "user release",
218 "pool split",
219 };
220
221 boolean_t
zfs_dataset_name_hidden(const char * name)222 zfs_dataset_name_hidden(const char *name)
223 {
224 /*
225 * Skip over datasets that are not visible in this zone,
226 * internal datasets (which have a $ in their name), and
227 * temporary datasets (which have a % in their name).
228 */
229 if (strpbrk(name, "$%") != NULL)
230 return (B_TRUE);
231 if (!INGLOBALZONE(curproc) && !zone_dataset_visible(name, NULL))
232 return (B_TRUE);
233 return (B_FALSE);
234 }
235
236 #if defined(_KERNEL)
237 EXPORT_SYMBOL(zfs_allocatable_devs);
238 EXPORT_SYMBOL(zfs_special_devs);
239 EXPORT_SYMBOL(zpool_get_load_policy);
240 EXPORT_SYMBOL(zfs_zpl_version_map);
241 EXPORT_SYMBOL(zfs_spa_version_map);
242 EXPORT_SYMBOL(zfs_history_event_names);
243 EXPORT_SYMBOL(zfs_dataset_name_hidden);
244 #endif
245