]> git.proxmox.com Git - mirror_zfs-debian.git/blame - module/zfs/zfeature_common.c
Imported Upstream version 0.6.4.2
[mirror_zfs-debian.git] / module / zfs / zfeature_common.c
CommitLineData
9ae529ec
CS
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 http://www.opensolaris.org/os/licensing.
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/*
ea04106b 23 * Copyright (c) 2013 by Delphix. All rights reserved.
9759c60f 24 * Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
ea04106b 25 * Copyright (c) 2014, Nexenta Systems, Inc. All rights reserved.
9ae529ec
CS
26 */
27
28#ifdef _KERNEL
29#include <sys/systm.h>
30#else
31#include <errno.h>
32#include <string.h>
33#endif
34#include <sys/debug.h>
35#include <sys/fs/zfs.h>
36#include <sys/inttypes.h>
37#include <sys/types.h>
38#include "zfeature_common.h"
39
40/*
41 * Set to disable all feature checks while opening pools, allowing pools with
42 * unsupported features to be opened. Set for testing only.
43 */
44boolean_t zfeature_checks_disable = B_FALSE;
45
46zfeature_info_t spa_feature_table[SPA_FEATURES];
47
48/*
49 * Valid characters for feature guids. This list is mainly for aesthetic
50 * purposes and could be expanded in the future. There are different allowed
51 * characters in the guids reverse dns portion (before the colon) and its
52 * short name (after the colon).
53 */
54static int
55valid_char(char c, boolean_t after_colon)
56{
57 return ((c >= 'a' && c <= 'z') ||
58 (c >= '0' && c <= '9') ||
59 c == (after_colon ? '_' : '.'));
60}
61
62/*
63 * Every feature guid must contain exactly one colon which separates a reverse
64 * dns organization name from the feature's "short" name (e.g.
65 * "com.company:feature_name").
66 */
67boolean_t
68zfeature_is_valid_guid(const char *name)
69{
70 int i;
71 boolean_t has_colon = B_FALSE;
72
73 i = 0;
74 while (name[i] != '\0') {
75 char c = name[i++];
76 if (c == ':') {
77 if (has_colon)
78 return (B_FALSE);
79 has_colon = B_TRUE;
80 continue;
81 }
82 if (!valid_char(c, has_colon))
83 return (B_FALSE);
84 }
85
86 return (has_colon);
87}
88
89boolean_t
90zfeature_is_supported(const char *guid)
91{
ea04106b
AX
92 spa_feature_t i;
93
9ae529ec
CS
94 if (zfeature_checks_disable)
95 return (B_TRUE);
96
9ae529ec
CS
97 for (i = 0; i < SPA_FEATURES; i++) {
98 zfeature_info_t *feature = &spa_feature_table[i];
ea04106b
AX
99 if (strcmp(guid, feature->fi_guid) == 0)
100 return (B_TRUE);
9ae529ec
CS
101 }
102
ea04106b 103 return (B_FALSE);
9ae529ec
CS
104}
105
106int
ea04106b 107zfeature_lookup_name(const char *name, spa_feature_t *res)
9ae529ec 108{
ea04106b 109 spa_feature_t i;
9ae529ec
CS
110
111 for (i = 0; i < SPA_FEATURES; i++) {
112 zfeature_info_t *feature = &spa_feature_table[i];
113 if (strcmp(name, feature->fi_uname) == 0) {
114 if (res != NULL)
ea04106b 115 *res = i;
9ae529ec
CS
116 return (0);
117 }
118 }
119
120 return (ENOENT);
121}
122
ea04106b
AX
123boolean_t
124zfeature_depends_on(spa_feature_t fid, spa_feature_t check) {
125 zfeature_info_t *feature = &spa_feature_table[fid];
126 int i;
127
128 for (i = 0; feature->fi_depends[i] != SPA_FEATURE_NONE; i++) {
129 if (feature->fi_depends[i] == check)
130 return (B_TRUE);
131 }
132 return (B_FALSE);
133}
134
9ae529ec 135static void
ea04106b
AX
136zfeature_register(spa_feature_t fid, const char *guid, const char *name,
137 const char *desc, boolean_t readonly, boolean_t mos,
138 boolean_t activate_on_enable, const spa_feature_t *deps)
9ae529ec
CS
139{
140 zfeature_info_t *feature = &spa_feature_table[fid];
ea04106b 141 static spa_feature_t nodeps[] = { SPA_FEATURE_NONE };
9ae529ec
CS
142
143 ASSERT(name != NULL);
144 ASSERT(desc != NULL);
145 ASSERT(!readonly || !mos);
146 ASSERT3U(fid, <, SPA_FEATURES);
147 ASSERT(zfeature_is_valid_guid(guid));
148
149 if (deps == NULL)
150 deps = nodeps;
151
ea04106b 152 feature->fi_feature = fid;
9ae529ec
CS
153 feature->fi_guid = guid;
154 feature->fi_uname = name;
155 feature->fi_desc = desc;
156 feature->fi_can_readonly = readonly;
157 feature->fi_mos = mos;
ea04106b 158 feature->fi_activate_on_enable = activate_on_enable;
9ae529ec
CS
159 feature->fi_depends = deps;
160}
161
162void
163zpool_feature_init(void)
164{
165 zfeature_register(SPA_FEATURE_ASYNC_DESTROY,
166 "com.delphix:async_destroy", "async_destroy",
ea04106b
AX
167 "Destroy filesystems asynchronously.", B_TRUE, B_FALSE,
168 B_FALSE, NULL);
169
753c3839
MA
170 zfeature_register(SPA_FEATURE_EMPTY_BPOBJ,
171 "com.delphix:empty_bpobj", "empty_bpobj",
ea04106b
AX
172 "Snapshots use less space.", B_TRUE, B_FALSE,
173 B_FALSE, NULL);
174
9759c60f
ED
175 zfeature_register(SPA_FEATURE_LZ4_COMPRESS,
176 "org.illumos:lz4_compress", "lz4_compress",
ea04106b
AX
177 "LZ4 compression algorithm support.", B_FALSE, B_FALSE,
178 B_TRUE, NULL);
179
180 zfeature_register(SPA_FEATURE_SPACEMAP_HISTOGRAM,
181 "com.delphix:spacemap_histogram", "spacemap_histogram",
182 "Spacemaps maintain space histograms.", B_TRUE, B_FALSE,
183 B_FALSE, NULL);
184
185 zfeature_register(SPA_FEATURE_ENABLED_TXG,
186 "com.delphix:enabled_txg", "enabled_txg",
187 "Record txg at which a feature is enabled", B_TRUE, B_FALSE,
188 B_FALSE, NULL);
189
190 {
191 static const spa_feature_t hole_birth_deps[] = {
192 SPA_FEATURE_ENABLED_TXG,
193 SPA_FEATURE_NONE
194 };
195 zfeature_register(SPA_FEATURE_HOLE_BIRTH,
196 "com.delphix:hole_birth", "hole_birth",
197 "Retain hole birth txg for more precise zfs send",
198 B_FALSE, B_TRUE, B_TRUE, hole_birth_deps);
199 }
200
201 zfeature_register(SPA_FEATURE_EXTENSIBLE_DATASET,
202 "com.delphix:extensible_dataset", "extensible_dataset",
203 "Enhanced dataset functionality, used by other features.",
204 B_FALSE, B_FALSE, B_FALSE, NULL);
205
206 {
207 static const spa_feature_t bookmarks_deps[] = {
208 SPA_FEATURE_EXTENSIBLE_DATASET,
209 SPA_FEATURE_NONE
210 };
211
212 zfeature_register(SPA_FEATURE_BOOKMARKS,
213 "com.delphix:bookmarks", "bookmarks",
214 "\"zfs bookmark\" command",
215 B_TRUE, B_FALSE, B_FALSE, bookmarks_deps);
216 }
217
218 zfeature_register(SPA_FEATURE_EMBEDDED_DATA,
219 "com.delphix:embedded_data", "embedded_data",
220 "Blocks which compress very well use even less space.",
221 B_FALSE, B_TRUE, B_TRUE, NULL);
9ae529ec 222}