From a20142ed719d98caa1b27f6ec48bda29ec26f009 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Thu, 26 Jan 2017 13:27:58 +0100 Subject: [PATCH] btrfs-progs: move fs features implementation to own file Signed-off-by: David Sterba --- Makefile.in | 3 +- fsfeatures.c | 227 +++++++++++++++++++++++++++++++++++++++++++++++++++ utils.c | 208 +--------------------------------------------- 3 files changed, 230 insertions(+), 208 deletions(-) create mode 100644 fsfeatures.c diff --git a/Makefile.in b/Makefile.in index de409ba8..18b80e0a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -98,7 +98,8 @@ objects = ctree.o disk-io.o kernel-lib/radix-tree.o extent-tree.o print-tree.o \ extent-cache.o extent_io.o volumes.o utils.o repair.o \ qgroup.o raid56.o free-space-cache.o kernel-lib/list_sort.o props.o \ ulist.o qgroup-verify.o backref.o string-table.o task-utils.o \ - inode.o file.o find-root.o free-space-tree.o help.o send-dump.o + inode.o file.o find-root.o free-space-tree.o help.o send-dump.o \ + fsfeatures.o cmds_objects = cmds-subvolume.o cmds-filesystem.o cmds-device.o cmds-scrub.o \ cmds-inspect.o cmds-balance.o cmds-send.o cmds-receive.o \ cmds-quota.o cmds-qgroup.o cmds-replace.o cmds-check.o \ diff --git a/fsfeatures.c b/fsfeatures.c new file mode 100644 index 00000000..7d85d60f --- /dev/null +++ b/fsfeatures.c @@ -0,0 +1,227 @@ +/* + * 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 +#include +#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; +} + diff --git a/utils.c b/utils.c index 9de1ca2b..794f4e68 100644 --- a/utils.c +++ b/utils.c @@ -37,8 +37,7 @@ #include #include #include -#include -#include +#include #include "kerncompat.h" #include "radix-tree.h" @@ -50,7 +49,6 @@ #include "volumes.h" #include "ioctl.h" #include "commands.h" -#include "fsfeatures.h" #ifndef BLKDISCARD #define BLKDISCARD _IO(0x12,119) @@ -124,210 +122,6 @@ int test_uuid_unique(char *fs_uuid) 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;