diff options
Diffstat (limited to 'mkfs.c')
-rw-r--r-- | mkfs.c | 92 |
1 files changed, 74 insertions, 18 deletions
@@ -39,6 +39,7 @@ #include <linux/fs.h> #include <ctype.h> #include <attr/xattr.h> +#include <blkid/blkid.h> #include "ctree.h" #include "disk-io.h" #include "volumes.h" @@ -204,7 +205,7 @@ static int create_one_raid_group(struct btrfs_trans_handle *trans, static int create_raid_groups(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 data_profile, int data_profile_opt, u64 metadata_profile, - int metadata_profile_opt, int mixed) + int metadata_profile_opt, int mixed, int ssd) { u64 num_devices = btrfs_super_num_devices(&root->fs_info->super_copy); u64 allowed = 0; @@ -216,8 +217,12 @@ static int create_raid_groups(struct btrfs_trans_handle *trans, * For mixed groups defaults are single/single. */ if (!metadata_profile_opt && !mixed) { + if (num_devices == 1 && ssd) + printf("Detected a SSD, turning off metadata " + "duplication. Mkfs with -m dup if you want to " + "force metadata duplication.\n"); metadata_profile = (num_devices > 1) ? - BTRFS_BLOCK_GROUP_RAID1 : BTRFS_BLOCK_GROUP_DUP; + BTRFS_BLOCK_GROUP_RAID1 : (ssd) ? 0: BTRFS_BLOCK_GROUP_DUP; } if (!data_profile_opt && !mixed) { data_profile = (num_devices > 1) ? @@ -366,7 +371,6 @@ static u64 parse_profile(char *s) static char *parse_label(char *input) { - int i; int len = strlen(input); if (len >= BTRFS_LABEL_SIZE) { @@ -374,12 +378,6 @@ static char *parse_label(char *input) BTRFS_LABEL_SIZE - 1); exit(1); } - for (i = 0; i < len; i++) { - if (input[i] == '/' || input[i] == '\\') { - fprintf(stderr, "invalid label %s\n", input); - exit(1); - } - } return strdup(input); } @@ -1207,6 +1205,54 @@ static int check_leaf_or_node_size(u32 size, u32 sectorsize) return 0; } +static int is_ssd(const char *file) +{ + char *devname; + blkid_probe probe; + char *dev; + char path[PATH_MAX]; + dev_t disk; + int fd; + char rotational; + + probe = blkid_new_probe_from_filename(file); + if (!probe) + return 0; + + /* + * We want to use blkid_devno_to_wholedisk() but it's broken for some + * reason on F17 at least so we'll do this trickery + */ + disk = blkid_probe_get_wholedisk_devno(probe); + if (!disk) + return 0; + + devname = blkid_devno_to_devname(disk); + if (!devname) + return 0; + + dev = strrchr(devname, '/'); + dev++; + + snprintf(path, PATH_MAX, "/sys/block/%s/queue/rotational", dev); + + free(devname); + blkid_free_probe(probe); + + fd = open(path, O_RDONLY); + if (fd < 0) { + return 0; + } + + if (read(fd, &rotational, sizeof(char)) < sizeof(char)) { + close(fd); + return 0; + } + close(fd); + + return !atoi((const char *)&rotational); +} + int main(int ac, char **av) { char *file; @@ -1220,7 +1266,7 @@ int main(int ac, char **av) u64 alloc_start = 0; u64 metadata_profile = 0; u64 data_profile = 0; - u32 leafsize = getpagesize(); + u32 leafsize = sysconf(_SC_PAGESIZE); u32 sectorsize = 4096; u32 nodesize = leafsize; u32 stripesize = 4096; @@ -1233,6 +1279,7 @@ int main(int ac, char **av) int data_profile_opt = 0; int metadata_profile_opt = 0; int nodiscard = 0; + int ssd = 0; char *source_dir = NULL; int source_dir_set = 0; @@ -1240,6 +1287,8 @@ int main(int ac, char **av) u64 size_of_data = 0; u64 source_dir_size = 0; char *pretty_buf; + struct btrfs_super_block *super; + u64 flags; while(1) { int c; @@ -1296,7 +1345,7 @@ int main(int ac, char **av) print_usage(); } } - sectorsize = max(sectorsize, (u32)getpagesize()); + sectorsize = max(sectorsize, (u32)sysconf(_SC_PAGESIZE)); if (check_leaf_or_node_size(leafsize, sectorsize)) exit(1); if (check_leaf_or_node_size(nodesize, sectorsize)) @@ -1351,7 +1400,12 @@ int main(int ac, char **av) fprintf(stderr, "unable to zero the output file\n"); exit(1); } + /* our "device" is the new image file */ + dev_block_count = block_count; } + + ssd = is_ssd(file); + if (mixed) { if (metadata_profile != data_profile) { fprintf(stderr, "With mixed block groups data and metadata " @@ -1376,7 +1430,8 @@ int main(int ac, char **av) root = open_ctree(file, 0, O_RDWR); if (!root) { - fprintf(stderr, "ctree init failed\n"); + fprintf(stderr, "Open ctree failed\n"); + close(fd); exit(1); } root->fs_info->alloc_start = alloc_start; @@ -1437,20 +1492,21 @@ raid_groups: if (!source_dir_set) { ret = create_raid_groups(trans, root, data_profile, data_profile_opt, metadata_profile, - metadata_profile_opt, mixed); + metadata_profile_opt, mixed, ssd); BUG_ON(ret); } ret = create_data_reloc_tree(trans, root); BUG_ON(ret); - if (mixed) { - struct btrfs_super_block *super = &root->fs_info->super_copy; - u64 flags = btrfs_super_incompat_flags(super); + super = &root->fs_info->super_copy; + flags = btrfs_super_incompat_flags(super); + flags |= BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF; + if (mixed) flags |= BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS; - btrfs_set_super_incompat_flags(super, flags); - } + + btrfs_set_super_incompat_flags(super, flags); if ((data_profile | metadata_profile) & (BTRFS_BLOCK_GROUP_RAID5 | BTRFS_BLOCK_GROUP_RAID6)) { |