diff -up btrfs-progs-0.20.rc1.20121017git91d9eec/Makefile.patch4 btrfs-progs-0.20.rc1.20121017git91d9eec/Makefile --- btrfs-progs-0.20.rc1.20121017git91d9eec/Makefile.patch4 2012-10-04 20:35:31.000000000 -0400 +++ btrfs-progs-0.20.rc1.20121017git91d9eec/Makefile 2012-10-17 13:48:02.331453645 -0400 @@ -67,7 +67,7 @@ btrfsck: $(objects) btrfsck.o $(CC) $(CFLAGS) -o btrfsck btrfsck.o $(objects) $(LDFLAGS) $(LIBS) mkfs.btrfs: $(objects) mkfs.o - $(CC) $(CFLAGS) -o mkfs.btrfs $(objects) mkfs.o $(LDFLAGS) $(LIBS) + $(CC) $(CFLAGS) -o mkfs.btrfs $(objects) mkfs.o $(LDFLAGS) $(LIBS) -lblkid btrfs-debug-tree: $(objects) debug-tree.o $(CC) $(CFLAGS) -o btrfs-debug-tree $(objects) debug-tree.o $(LDFLAGS) $(LIBS) diff -up btrfs-progs-0.20.rc1.20121017git91d9eec/man/mkfs.btrfs.8.in.patch4 btrfs-progs-0.20.rc1.20121017git91d9eec/man/mkfs.btrfs.8.in --- btrfs-progs-0.20.rc1.20121017git91d9eec/man/mkfs.btrfs.8.in.patch4 2012-10-04 20:35:31.000000000 -0400 +++ btrfs-progs-0.20.rc1.20121017git91d9eec/man/mkfs.btrfs.8.in 2012-10-17 13:48:02.331453645 -0400 @@ -47,7 +47,10 @@ Specify a label for the filesystem. .TP \fB\-m\fR, \fB\-\-metadata \fIprofile\fR Specify how metadata must be spanned across the devices specified. Valid -values are raid0, raid1, raid10 or single. +values are raid0, raid1, raid10, single or dup. Single device will have dup +set by default except in the case of SSDs which will default to single. This is +because SSDs can remap blocks internally so duplicate blocks could end up in the +same erase block which negates the benefits of doing metadata duplication. .TP \fB\-M\fR, \fB\-\-mixed\fR Mix data and metadata chunks together for more efficient space diff -up btrfs-progs-0.20.rc1.20121017git91d9eec/mkfs.c.patch4 btrfs-progs-0.20.rc1.20121017git91d9eec/mkfs.c --- btrfs-progs-0.20.rc1.20121017git91d9eec/mkfs.c.patch4 2012-10-17 13:48:02.329453660 -0400 +++ btrfs-progs-0.20.rc1.20121017git91d9eec/mkfs.c 2012-10-17 13:53:36.954806793 -0400 @@ -37,6 +37,7 @@ #include #include #include +#include #include "kerncompat.h" #include "ctree.h" #include "disk-io.h" @@ -234,7 +235,7 @@ static int create_one_raid_group(struct 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; @@ -245,8 +246,12 @@ static int create_raid_groups(struct btr * 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) ? @@ -1215,6 +1220,49 @@ static int check_leaf_or_node_size(u32 s 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); + devname = blkid_devno_to_devname(disk); + + 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; @@ -1241,6 +1289,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; @@ -1360,6 +1409,9 @@ int main(int ac, char **av) exit(1); } } + + ssd = is_ssd(file); + if (mixed) { if (metadata_profile != data_profile) { fprintf(stderr, "With mixed block groups data and metadata " @@ -1445,7 +1497,7 @@ 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); }