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"
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
{
38 const char *sysfs_name
;
40 * Compatibility with kernel of given version. Filesystem can be
43 const char *compat_str
;
46 * Considered safe for use, but is not on by default, even if the
47 * kernel supports the feature.
52 * Considered safe for use and will be turned on by default if
53 * supported by the running kernel.
55 const char *default_str
;
59 { "mixed-bg", BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS
,
61 VERSION_TO_STRING3(2,6,37),
62 VERSION_TO_STRING3(2,6,37),
64 "mixed data and metadata block groups" },
65 { "extref", BTRFS_FEATURE_INCOMPAT_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
,
73 VERSION_TO_STRING2(3,9),
76 "raid56 extended format" },
77 { "skinny-metadata", BTRFS_FEATURE_INCOMPAT_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
,
85 VERSION_TO_STRING2(3,14),
86 VERSION_TO_STRING2(4,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
)
98 for (i
= 0; i
< ARRAY_SIZE(mkfs_features
); i
++) {
100 !strcmp(mkfs_features
[i
].name
, name
+ 1)) {
101 *flags
&= ~ mkfs_features
[i
].flag
;
103 } else if (!strcmp(mkfs_features
[i
].name
, name
)) {
104 *flags
|= mkfs_features
[i
].flag
;
112 void btrfs_parse_features_to_string(char *buf
, u64 flags
)
118 for (i
= 0; i
< ARRAY_SIZE(mkfs_features
); i
++) {
119 if (flags
& mkfs_features
[i
].flag
) {
122 strcat(buf
, mkfs_features
[i
].name
);
127 void btrfs_process_fs_features(u64 flags
)
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
)
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
)
150 fprintf(stderr
, "%-20s- %s (0x%llx", feat
->name
, feat
->desc
,
152 if (feat
->compat_ver
)
153 fprintf(stderr
, ", compat=%s", feat
->compat_str
);
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
)
169 char *save_ptr
= NULL
; /* Satisfy static checkers */
171 for (this_char
= strtok_r(namelist
, ",", &save_ptr
);
173 this_char
= strtok_r(NULL
, ",", &save_ptr
)) {
174 if (parse_one_fs_feature(this_char
, flags
))
181 void print_kernel_version(FILE *stream
, u32 version
)
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]);
190 fprintf(stream
, ".%u", v
[0]);
193 u32
get_running_kernel_version(void)
195 struct utsname utsbuf
;
197 char *saveptr
= NULL
;
201 if (strcmp(utsbuf
.sysname
, "Linux") != 0) {
202 error("unsupported system: %s", utsbuf
.sysname
);
206 tmp
= strchr(utsbuf
.release
, '-');
210 tmp
= strtok_r(utsbuf
.release
, ".", &saveptr
);
211 if (!string_is_numerical(tmp
))
213 version
= atoi(tmp
) << 16;
214 tmp
= strtok_r(NULL
, ".", &saveptr
);
215 if (!string_is_numerical(tmp
))
217 version
|= atoi(tmp
) << 8;
218 tmp
= strtok_r(NULL
, ".", &saveptr
);
220 if (!string_is_numerical(tmp
))
222 version
|= atoi(tmp
);