btrfs-progs: fsck-tests: add test case to check symlinks with bad flags
[btrfs-progs-unstable/devel.git] / fsfeatures.c
blob7d85d60f127754331352c3b312c7c8375259f68a
1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public
4 * License v2 as published by the Free Software Foundation.
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * General Public License for more details.
11 * You should have received a copy of the GNU General Public
12 * License along with this program; if not, write to the
13 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14 * Boston, MA 021110-1307, USA.
17 #include "kerncompat.h"
18 #include <sys/utsname.h>
19 #include <linux/version.h>
20 #include "fsfeatures.h"
21 #include "ctree.h"
22 #include "utils.h"
25 * Insert a root item for temporary tree root
27 * Only used in make_btrfs_v2().
29 #define VERSION_TO_STRING3(a,b,c) #a "." #b "." #c, KERNEL_VERSION(a,b,c)
30 #define VERSION_TO_STRING2(a,b) #a "." #b, KERNEL_VERSION(a,b,0)
33 * Feature stability status and versions: compat <= safe <= default
35 static const struct btrfs_fs_feature {
36 const char *name;
37 u64 flag;
38 const char *sysfs_name;
40 * Compatibility with kernel of given version. Filesystem can be
41 * mounted.
43 const char *compat_str;
44 u32 compat_ver;
46 * Considered safe for use, but is not on by default, even if the
47 * kernel supports the feature.
49 const char *safe_str;
50 u32 safe_ver;
52 * Considered safe for use and will be turned on by default if
53 * supported by the running kernel.
55 const char *default_str;
56 u32 default_ver;
57 const char *desc;
58 } mkfs_features[] = {
59 { "mixed-bg", BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS,
60 "mixed_groups",
61 VERSION_TO_STRING3(2,6,37),
62 VERSION_TO_STRING3(2,6,37),
63 NULL, 0,
64 "mixed data and metadata block groups" },
65 { "extref", BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF,
66 "extended_iref",
67 VERSION_TO_STRING2(3,7),
68 VERSION_TO_STRING2(3,12),
69 VERSION_TO_STRING2(3,12),
70 "increased hardlink limit per file to 65536" },
71 { "raid56", BTRFS_FEATURE_INCOMPAT_RAID56,
72 "raid56",
73 VERSION_TO_STRING2(3,9),
74 NULL, 0,
75 NULL, 0,
76 "raid56 extended format" },
77 { "skinny-metadata", BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA,
78 "skinny_metadata",
79 VERSION_TO_STRING2(3,10),
80 VERSION_TO_STRING2(3,18),
81 VERSION_TO_STRING2(3,18),
82 "reduced-size metadata extent refs" },
83 { "no-holes", BTRFS_FEATURE_INCOMPAT_NO_HOLES,
84 "no_holes",
85 VERSION_TO_STRING2(3,14),
86 VERSION_TO_STRING2(4,0),
87 NULL, 0,
88 "no explicit hole extents for files" },
89 /* Keep this one last */
90 { "list-all", BTRFS_FEATURE_LIST_ALL, NULL }
93 static int parse_one_fs_feature(const char *name, u64 *flags)
95 int i;
96 int found = 0;
98 for (i = 0; i < ARRAY_SIZE(mkfs_features); i++) {
99 if (name[0] == '^' &&
100 !strcmp(mkfs_features[i].name, name + 1)) {
101 *flags &= ~ mkfs_features[i].flag;
102 found = 1;
103 } else if (!strcmp(mkfs_features[i].name, name)) {
104 *flags |= mkfs_features[i].flag;
105 found = 1;
109 return !found;
112 void btrfs_parse_features_to_string(char *buf, u64 flags)
114 int i;
116 buf[0] = 0;
118 for (i = 0; i < ARRAY_SIZE(mkfs_features); i++) {
119 if (flags & mkfs_features[i].flag) {
120 if (*buf)
121 strcat(buf, ", ");
122 strcat(buf, mkfs_features[i].name);
127 void btrfs_process_fs_features(u64 flags)
129 int i;
131 for (i = 0; i < ARRAY_SIZE(mkfs_features); i++) {
132 if (flags & mkfs_features[i].flag) {
133 printf("Turning ON incompat feature '%s': %s\n",
134 mkfs_features[i].name,
135 mkfs_features[i].desc);
140 void btrfs_list_all_fs_features(u64 mask_disallowed)
142 int i;
144 fprintf(stderr, "Filesystem features available:\n");
145 for (i = 0; i < ARRAY_SIZE(mkfs_features) - 1; i++) {
146 const struct btrfs_fs_feature *feat = &mkfs_features[i];
148 if (feat->flag & mask_disallowed)
149 continue;
150 fprintf(stderr, "%-20s- %s (0x%llx", feat->name, feat->desc,
151 feat->flag);
152 if (feat->compat_ver)
153 fprintf(stderr, ", compat=%s", feat->compat_str);
154 if (feat->safe_ver)
155 fprintf(stderr, ", safe=%s", feat->safe_str);
156 if (feat->default_ver)
157 fprintf(stderr, ", default=%s", feat->default_str);
158 fprintf(stderr, ")\n");
163 * Return NULL if all features were parsed fine, otherwise return the name of
164 * the first unparsed.
166 char* btrfs_parse_fs_features(char *namelist, u64 *flags)
168 char *this_char;
169 char *save_ptr = NULL; /* Satisfy static checkers */
171 for (this_char = strtok_r(namelist, ",", &save_ptr);
172 this_char != NULL;
173 this_char = strtok_r(NULL, ",", &save_ptr)) {
174 if (parse_one_fs_feature(this_char, flags))
175 return this_char;
178 return NULL;
181 void print_kernel_version(FILE *stream, u32 version)
183 u32 v[3];
185 v[0] = version & 0xFF;
186 v[1] = (version >> 8) & 0xFF;
187 v[2] = version >> 16;
188 fprintf(stream, "%u.%u", v[2], v[1]);
189 if (v[0])
190 fprintf(stream, ".%u", v[0]);
193 u32 get_running_kernel_version(void)
195 struct utsname utsbuf;
196 char *tmp;
197 char *saveptr = NULL;
198 u32 version;
200 uname(&utsbuf);
201 if (strcmp(utsbuf.sysname, "Linux") != 0) {
202 error("unsupported system: %s", utsbuf.sysname);
203 exit(1);
205 /* 1.2.3-4-name */
206 tmp = strchr(utsbuf.release, '-');
207 if (tmp)
208 *tmp = 0;
210 tmp = strtok_r(utsbuf.release, ".", &saveptr);
211 if (!string_is_numerical(tmp))
212 return (u32)-1;
213 version = atoi(tmp) << 16;
214 tmp = strtok_r(NULL, ".", &saveptr);
215 if (!string_is_numerical(tmp))
216 return (u32)-1;
217 version |= atoi(tmp) << 8;
218 tmp = strtok_r(NULL, ".", &saveptr);
219 if (tmp) {
220 if (!string_is_numerical(tmp))
221 return (u32)-1;
222 version |= atoi(tmp);
225 return version;