--- /dev/null
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License v2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ */
+
+#include "kerncompat.h"
+#include <sys/utsname.h>
+#include <linux/version.h>
+#include "fsfeatures.h"
+#include "ctree.h"
+#include "utils.h"
+
+/*
+ * Insert a root item for temporary tree root
+ *
+ * Only used in make_btrfs_v2().
+ */
+#define VERSION_TO_STRING3(a,b,c) #a "." #b "." #c, KERNEL_VERSION(a,b,c)
+#define VERSION_TO_STRING2(a,b) #a "." #b, KERNEL_VERSION(a,b,0)
+
+/*
+ * Feature stability status and versions: compat <= safe <= default
+ */
+static const struct btrfs_fs_feature {
+ const char *name;
+ u64 flag;
+ const char *sysfs_name;
+ /*
+ * Compatibility with kernel of given version. Filesystem can be
+ * mounted.
+ */
+ const char *compat_str;
+ u32 compat_ver;
+ /*
+ * Considered safe for use, but is not on by default, even if the
+ * kernel supports the feature.
+ */
+ const char *safe_str;
+ u32 safe_ver;
+ /*
+ * Considered safe for use and will be turned on by default if
+ * supported by the running kernel.
+ */
+ const char *default_str;
+ u32 default_ver;
+ const char *desc;
+} mkfs_features[] = {
+ { "mixed-bg", BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS,
+ "mixed_groups",
+ VERSION_TO_STRING3(2,6,37),
+ VERSION_TO_STRING3(2,6,37),
+ NULL, 0,
+ "mixed data and metadata block groups" },
+ { "extref", BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF,
+ "extended_iref",
+ VERSION_TO_STRING2(3,7),
+ VERSION_TO_STRING2(3,12),
+ VERSION_TO_STRING2(3,12),
+ "increased hardlink limit per file to 65536" },
+ { "raid56", BTRFS_FEATURE_INCOMPAT_RAID56,
+ "raid56",
+ VERSION_TO_STRING2(3,9),
+ NULL, 0,
+ NULL, 0,
+ "raid56 extended format" },
+ { "skinny-metadata", BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA,
+ "skinny_metadata",
+ VERSION_TO_STRING2(3,10),
+ VERSION_TO_STRING2(3,18),
+ VERSION_TO_STRING2(3,18),
+ "reduced-size metadata extent refs" },
+ { "no-holes", BTRFS_FEATURE_INCOMPAT_NO_HOLES,
+ "no_holes",
+ VERSION_TO_STRING2(3,14),
+ VERSION_TO_STRING2(4,0),
+ NULL, 0,
+ "no explicit hole extents for files" },
+ /* Keep this one last */
+ { "list-all", BTRFS_FEATURE_LIST_ALL, NULL }
+};
+
+static int parse_one_fs_feature(const char *name, u64 *flags)
+{
+ int i;
+ int found = 0;
+
+ for (i = 0; i < ARRAY_SIZE(mkfs_features); i++) {
+ if (name[0] == '^' &&
+ !strcmp(mkfs_features[i].name, name + 1)) {
+ *flags &= ~ mkfs_features[i].flag;
+ found = 1;
+ } else if (!strcmp(mkfs_features[i].name, name)) {
+ *flags |= mkfs_features[i].flag;
+ found = 1;
+ }
+ }
+
+ return !found;
+}
+
+void btrfs_parse_features_to_string(char *buf, u64 flags)
+{
+ int i;
+
+ buf[0] = 0;
+
+ for (i = 0; i < ARRAY_SIZE(mkfs_features); i++) {
+ if (flags & mkfs_features[i].flag) {
+ if (*buf)
+ strcat(buf, ", ");
+ strcat(buf, mkfs_features[i].name);
+ }
+ }
+}
+
+void btrfs_process_fs_features(u64 flags)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mkfs_features); i++) {
+ if (flags & mkfs_features[i].flag) {
+ printf("Turning ON incompat feature '%s': %s\n",
+ mkfs_features[i].name,
+ mkfs_features[i].desc);
+ }
+ }
+}
+
+void btrfs_list_all_fs_features(u64 mask_disallowed)
+{
+ int i;
+
+ fprintf(stderr, "Filesystem features available:\n");
+ for (i = 0; i < ARRAY_SIZE(mkfs_features) - 1; i++) {
+ const struct btrfs_fs_feature *feat = &mkfs_features[i];
+
+ if (feat->flag & mask_disallowed)
+ continue;
+ fprintf(stderr, "%-20s- %s (0x%llx", feat->name, feat->desc,
+ feat->flag);
+ if (feat->compat_ver)
+ fprintf(stderr, ", compat=%s", feat->compat_str);
+ if (feat->safe_ver)
+ fprintf(stderr, ", safe=%s", feat->safe_str);
+ if (feat->default_ver)
+ fprintf(stderr, ", default=%s", feat->default_str);
+ fprintf(stderr, ")\n");
+ }
+}
+
+/*
+ * Return NULL if all features were parsed fine, otherwise return the name of
+ * the first unparsed.
+ */
+char* btrfs_parse_fs_features(char *namelist, u64 *flags)
+{
+ char *this_char;
+ char *save_ptr = NULL; /* Satisfy static checkers */
+
+ for (this_char = strtok_r(namelist, ",", &save_ptr);
+ this_char != NULL;
+ this_char = strtok_r(NULL, ",", &save_ptr)) {
+ if (parse_one_fs_feature(this_char, flags))
+ return this_char;
+ }
+
+ return NULL;
+}
+
+void print_kernel_version(FILE *stream, u32 version)
+{
+ u32 v[3];
+
+ v[0] = version & 0xFF;
+ v[1] = (version >> 8) & 0xFF;
+ v[2] = version >> 16;
+ fprintf(stream, "%u.%u", v[2], v[1]);
+ if (v[0])
+ fprintf(stream, ".%u", v[0]);
+}
+
+u32 get_running_kernel_version(void)
+{
+ struct utsname utsbuf;
+ char *tmp;
+ char *saveptr = NULL;
+ u32 version;
+
+ uname(&utsbuf);
+ if (strcmp(utsbuf.sysname, "Linux") != 0) {
+ error("unsupported system: %s", utsbuf.sysname);
+ exit(1);
+ }
+ /* 1.2.3-4-name */
+ tmp = strchr(utsbuf.release, '-');
+ if (tmp)
+ *tmp = 0;
+
+ tmp = strtok_r(utsbuf.release, ".", &saveptr);
+ if (!string_is_numerical(tmp))
+ return (u32)-1;
+ version = atoi(tmp) << 16;
+ tmp = strtok_r(NULL, ".", &saveptr);
+ if (!string_is_numerical(tmp))
+ return (u32)-1;
+ version |= atoi(tmp) << 8;
+ tmp = strtok_r(NULL, ".", &saveptr);
+ if (tmp) {
+ if (!string_is_numerical(tmp))
+ return (u32)-1;
+ version |= atoi(tmp);
+ }
+
+ return version;
+}
+
#include <sys/vfs.h>
#include <sys/statfs.h>
#include <linux/magic.h>
-#include <sys/utsname.h>
-#include <linux/version.h>
+#include <getopt.h>
#include "kerncompat.h"
#include "radix-tree.h"
#include "volumes.h"
#include "ioctl.h"
#include "commands.h"
-#include "fsfeatures.h"
#ifndef BLKDISCARD
#define BLKDISCARD _IO(0x12,119)
return unique;
}
-/*
- * Insert a root item for temporary tree root
- *
- * Only used in make_btrfs_v2().
- */
-#define VERSION_TO_STRING3(a,b,c) #a "." #b "." #c, KERNEL_VERSION(a,b,c)
-#define VERSION_TO_STRING2(a,b) #a "." #b, KERNEL_VERSION(a,b,0)
-
-/*
- * Feature stability status and versions: compat <= safe <= default
- */
-static const struct btrfs_fs_feature {
- const char *name;
- u64 flag;
- const char *sysfs_name;
- /*
- * Compatibility with kernel of given version. Filesystem can be
- * mounted.
- */
- const char *compat_str;
- u32 compat_ver;
- /*
- * Considered safe for use, but is not on by default, even if the
- * kernel supports the feature.
- */
- const char *safe_str;
- u32 safe_ver;
- /*
- * Considered safe for use and will be turned on by default if
- * supported by the running kernel.
- */
- const char *default_str;
- u32 default_ver;
- const char *desc;
-} mkfs_features[] = {
- { "mixed-bg", BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS,
- "mixed_groups",
- VERSION_TO_STRING3(2,6,37),
- VERSION_TO_STRING3(2,6,37),
- NULL, 0,
- "mixed data and metadata block groups" },
- { "extref", BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF,
- "extended_iref",
- VERSION_TO_STRING2(3,7),
- VERSION_TO_STRING2(3,12),
- VERSION_TO_STRING2(3,12),
- "increased hardlink limit per file to 65536" },
- { "raid56", BTRFS_FEATURE_INCOMPAT_RAID56,
- "raid56",
- VERSION_TO_STRING2(3,9),
- NULL, 0,
- NULL, 0,
- "raid56 extended format" },
- { "skinny-metadata", BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA,
- "skinny_metadata",
- VERSION_TO_STRING2(3,10),
- VERSION_TO_STRING2(3,18),
- VERSION_TO_STRING2(3,18),
- "reduced-size metadata extent refs" },
- { "no-holes", BTRFS_FEATURE_INCOMPAT_NO_HOLES,
- "no_holes",
- VERSION_TO_STRING2(3,14),
- VERSION_TO_STRING2(4,0),
- NULL, 0,
- "no explicit hole extents for files" },
- /* Keep this one last */
- { "list-all", BTRFS_FEATURE_LIST_ALL, NULL }
-};
-
-static int parse_one_fs_feature(const char *name, u64 *flags)
-{
- int i;
- int found = 0;
-
- for (i = 0; i < ARRAY_SIZE(mkfs_features); i++) {
- if (name[0] == '^' &&
- !strcmp(mkfs_features[i].name, name + 1)) {
- *flags &= ~ mkfs_features[i].flag;
- found = 1;
- } else if (!strcmp(mkfs_features[i].name, name)) {
- *flags |= mkfs_features[i].flag;
- found = 1;
- }
- }
-
- return !found;
-}
-
-void btrfs_parse_features_to_string(char *buf, u64 flags)
-{
- int i;
-
- buf[0] = 0;
-
- for (i = 0; i < ARRAY_SIZE(mkfs_features); i++) {
- if (flags & mkfs_features[i].flag) {
- if (*buf)
- strcat(buf, ", ");
- strcat(buf, mkfs_features[i].name);
- }
- }
-}
-
-void btrfs_process_fs_features(u64 flags)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(mkfs_features); i++) {
- if (flags & mkfs_features[i].flag) {
- printf("Turning ON incompat feature '%s': %s\n",
- mkfs_features[i].name,
- mkfs_features[i].desc);
- }
- }
-}
-
-void btrfs_list_all_fs_features(u64 mask_disallowed)
-{
- int i;
-
- fprintf(stderr, "Filesystem features available:\n");
- for (i = 0; i < ARRAY_SIZE(mkfs_features) - 1; i++) {
- const struct btrfs_fs_feature *feat = &mkfs_features[i];
-
- if (feat->flag & mask_disallowed)
- continue;
- fprintf(stderr, "%-20s- %s (0x%llx", feat->name, feat->desc,
- feat->flag);
- if (feat->compat_ver)
- fprintf(stderr, ", compat=%s", feat->compat_str);
- if (feat->safe_ver)
- fprintf(stderr, ", safe=%s", feat->safe_str);
- if (feat->default_ver)
- fprintf(stderr, ", default=%s", feat->default_str);
- fprintf(stderr, ")\n");
- }
-}
-
-/*
- * Return NULL if all features were parsed fine, otherwise return the name of
- * the first unparsed.
- */
-char* btrfs_parse_fs_features(char *namelist, u64 *flags)
-{
- char *this_char;
- char *save_ptr = NULL; /* Satisfy static checkers */
-
- for (this_char = strtok_r(namelist, ",", &save_ptr);
- this_char != NULL;
- this_char = strtok_r(NULL, ",", &save_ptr)) {
- if (parse_one_fs_feature(this_char, flags))
- return this_char;
- }
-
- return NULL;
-}
-
-void print_kernel_version(FILE *stream, u32 version)
-{
- u32 v[3];
-
- v[0] = version & 0xFF;
- v[1] = (version >> 8) & 0xFF;
- v[2] = version >> 16;
- fprintf(stream, "%u.%u", v[2], v[1]);
- if (v[0])
- fprintf(stream, ".%u", v[0]);
-}
-
-u32 get_running_kernel_version(void)
-{
- struct utsname utsbuf;
- char *tmp;
- char *saveptr = NULL;
- u32 version;
-
- uname(&utsbuf);
- if (strcmp(utsbuf.sysname, "Linux") != 0) {
- error("unsupported system: %s", utsbuf.sysname);
- exit(1);
- }
- /* 1.2.3-4-name */
- tmp = strchr(utsbuf.release, '-');
- if (tmp)
- *tmp = 0;
-
- tmp = strtok_r(utsbuf.release, ".", &saveptr);
- if (!string_is_numerical(tmp))
- return (u32)-1;
- version = atoi(tmp) << 16;
- tmp = strtok_r(NULL, ".", &saveptr);
- if (!string_is_numerical(tmp))
- return (u32)-1;
- version |= atoi(tmp) << 8;
- tmp = strtok_r(NULL, ".", &saveptr);
- if (tmp) {
- if (!string_is_numerical(tmp))
- return (u32)-1;
- version |= atoi(tmp);
- }
-
- return version;
-}
-
u64 btrfs_device_size(int fd, struct stat *st)
{
u64 size;