Blame Btrfs-progs-detect-if-the-disk-we-are-formatting-is-.patch

Josef Bacik 96158b
From fe4e9b20d9ffffbb6aade4083caa71d65f16230a Mon Sep 17 00:00:00 2001
Josef Bacik 96158b
From: Josef Bacik <jbacik@fusionio.com>
Josef Bacik 96158b
Date: Fri, 20 Jul 2012 11:09:43 -0400
Josef Bacik 96158b
Subject: [PATCH] Btrfs-progs: detect if the disk we are formatting is a ssd
Josef Bacik 96158b
Josef Bacik 96158b
SSD's do not gain anything by having metadata DUP turned on.  The underlying
Josef Bacik 96158b
file system that is a part of all SSD's could easily map duplicate metadat
Josef Bacik 96158b
blocks into the same erase block which effectively eliminates the benefit of
Josef Bacik 96158b
duplicating the metadata on disk.  So detect if we are formatting a single
Josef Bacik 96158b
SSD drive and if we are do not use DUP.  Thanks,
Josef Bacik 96158b
Josef Bacik 96158b
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Josef Bacik 96158b
---
Josef Bacik 96158b
 Makefile            |    2 +-
Josef Bacik 96158b
 man/mkfs.btrfs.8.in |    5 +++-
Josef Bacik 96158b
 mkfs.c              |   63 ++++++++++++++++++++++++++++++++++++++++++++++++--
Josef Bacik 96158b
 3 files changed, 65 insertions(+), 5 deletions(-)
Josef Bacik 96158b
Josef Bacik 96158b
diff --git a/Makefile b/Makefile
Josef Bacik 96158b
index 4894903..c7fd97d 100644
Josef Bacik 96158b
--- a/Makefile
Josef Bacik 96158b
+++ b/Makefile
Josef Bacik 0124ba
@@ -67,7 +67,7 @@ btrfsck: $(objects) btrfsck.o
Josef Bacik b5e03c
 	$(CC) $(CFLAGS) -o btrfsck btrfsck.o $(objects) $(LDFLAGS) $(LIBS)
Josef Bacik b5e03c
 
Josef Bacik b5e03c
 mkfs.btrfs: $(objects) mkfs.o
Josef Bacik b5e03c
-	$(CC) $(CFLAGS) -o mkfs.btrfs $(objects) mkfs.o $(LDFLAGS) $(LIBS)
Josef Bacik b5e03c
+	$(CC) $(CFLAGS) -o mkfs.btrfs $(objects) mkfs.o $(LDFLAGS) $(LIBS) -lblkid
Josef Bacik b5e03c
 
Josef Bacik b5e03c
 btrfs-debug-tree: $(objects) debug-tree.o
Josef Bacik b5e03c
 	$(CC) $(CFLAGS) -o btrfs-debug-tree $(objects) debug-tree.o $(LDFLAGS) $(LIBS)
Josef Bacik 96158b
diff --git a/man/mkfs.btrfs.8.in b/man/mkfs.btrfs.8.in
Josef Bacik 96158b
index 72025ed..b7bcc1b 100644
Josef Bacik 96158b
--- a/man/mkfs.btrfs.8.in
Josef Bacik 96158b
+++ b/man/mkfs.btrfs.8.in
Josef Bacik 0124ba
@@ -47,7 +47,10 @@ Specify a label for the filesystem.
Josef Bacik b5e03c
 .TP
Josef Bacik b5e03c
 \fB\-m\fR, \fB\-\-metadata \fIprofile\fR
Josef Bacik b5e03c
 Specify how metadata must be spanned across the devices specified. Valid
Josef Bacik b5e03c
-values are raid0, raid1, raid10 or single.
Josef Bacik b5e03c
+values are raid0, raid1, raid10, single or dup.  Single device will have dup
Josef Bacik b5e03c
+set by default except in the case of SSDs which will default to single.  This is
Josef Bacik b5e03c
+because SSDs can remap blocks internally so duplicate blocks could end up in the
Josef Bacik b5e03c
+same erase block which negates the benefits of doing metadata duplication.
Josef Bacik b5e03c
 .TP
Josef Bacik b5e03c
 \fB\-M\fR, \fB\-\-mixed\fR
Josef Bacik b5e03c
 Mix data and metadata chunks together for more efficient space 
Josef Bacik 96158b
diff --git a/mkfs.c b/mkfs.c
Josef Bacik 96158b
index 47f0c9c..72f10fa 100644
Josef Bacik 96158b
--- a/mkfs.c
Josef Bacik 96158b
+++ b/mkfs.c
Josef Bacik b5e03c
@@ -37,6 +37,7 @@
Josef Bacik b5e03c
 #include <linux/fs.h>
Josef Bacik b5e03c
 #include <ctype.h>
Josef Bacik b5e03c
 #include <attr/xattr.h>
Josef Bacik b5e03c
+#include <blkid/blkid.h>
Josef Bacik b5e03c
 #include "kerncompat.h"
Josef Bacik b5e03c
 #include "ctree.h"
Josef Bacik b5e03c
 #include "disk-io.h"
Josef Bacik 96158b
@@ -234,7 +235,7 @@ static int create_one_raid_group(struct btrfs_trans_handle *trans,
Josef Bacik b5e03c
 static int create_raid_groups(struct btrfs_trans_handle *trans,
Josef Bacik b5e03c
 			      struct btrfs_root *root, u64 data_profile,
Josef Bacik b5e03c
 			      int data_profile_opt, u64 metadata_profile,
Josef Bacik b5e03c
-			      int metadata_profile_opt, int mixed)
Josef Bacik b5e03c
+			      int metadata_profile_opt, int mixed, int ssd)
Josef Bacik b5e03c
 {
Josef Bacik b5e03c
 	u64 num_devices = btrfs_super_num_devices(&root->fs_info->super_copy);
Josef Bacik b5e03c
 	u64 allowed;
Josef Bacik 96158b
@@ -245,8 +246,12 @@ static int create_raid_groups(struct btrfs_trans_handle *trans,
Josef Bacik b5e03c
 	 * For mixed groups defaults are single/single.
Josef Bacik b5e03c
 	 */
Josef Bacik b5e03c
 	if (!metadata_profile_opt && !mixed) {
Josef Bacik b5e03c
+		if (num_devices == 1 && ssd)
Josef Bacik b5e03c
+			printf("Detected a SSD, turning off metadata "
Josef Bacik b5e03c
+			       "duplication.  Mkfs with -m dup if you want to "
Josef Bacik b5e03c
+			       "force metadata duplication.\n");
Josef Bacik b5e03c
 		metadata_profile = (num_devices > 1) ?
Josef Bacik b5e03c
-			BTRFS_BLOCK_GROUP_RAID1 : BTRFS_BLOCK_GROUP_DUP;
Josef Bacik b5e03c
+			BTRFS_BLOCK_GROUP_RAID1 : (ssd) ? 0: BTRFS_BLOCK_GROUP_DUP;
Josef Bacik b5e03c
 	}
Josef Bacik b5e03c
 	if (!data_profile_opt && !mixed) {
Josef Bacik b5e03c
 		data_profile = (num_devices > 1) ?
Josef Bacik 96158b
@@ -1222,6 +1227,54 @@ static int check_leaf_or_node_size(u32 size, u32 sectorsize)
Josef Bacik 0124ba
 	return 0;
Josef Bacik b5e03c
 }
Josef Bacik b5e03c
 
Josef Bacik b5e03c
+static int is_ssd(const char *file)
Josef Bacik b5e03c
+{
Josef Bacik b5e03c
+	char *devname;
Josef Bacik b5e03c
+	blkid_probe probe;
Josef Bacik b5e03c
+	char *dev;
Josef Bacik b5e03c
+	char path[PATH_MAX];
Josef Bacik b5e03c
+	dev_t disk;
Josef Bacik b5e03c
+	int fd;
Josef Bacik b5e03c
+	char rotational;
Josef Bacik b5e03c
+
Josef Bacik b5e03c
+	probe = blkid_new_probe_from_filename(file);
Josef Bacik b5e03c
+	if (!probe)
Josef Bacik b5e03c
+		return 0;
Josef Bacik b5e03c
+
Josef Bacik b5e03c
+	/*
Josef Bacik b5e03c
+	 * We want to use blkid_devno_to_wholedisk() but it's broken for some
Josef Bacik b5e03c
+	 * reason on F17 at least so we'll do this trickery
Josef Bacik b5e03c
+	 */
Josef Bacik b5e03c
+	disk = blkid_probe_get_wholedisk_devno(probe);
Josef Bacik 96158b
+	if (!disk)
Josef Bacik 96158b
+		return 0;
Josef Bacik 96158b
+
Josef Bacik b5e03c
+	devname = blkid_devno_to_devname(disk);
Josef Bacik 96158b
+	if (!devname)
Josef Bacik 96158b
+		return 0;
Josef Bacik b5e03c
+
Josef Bacik b5e03c
+	dev = strrchr(devname, '/');
Josef Bacik b5e03c
+	dev++;
Josef Bacik b5e03c
+
Josef Bacik b5e03c
+	snprintf(path, PATH_MAX, "/sys/block/%s/queue/rotational", dev);
Josef Bacik b5e03c
+
Josef Bacik b5e03c
+	free(devname);
Josef Bacik b5e03c
+	blkid_free_probe(probe);
Josef Bacik b5e03c
+
Josef Bacik b5e03c
+	fd = open(path, O_RDONLY);
Josef Bacik b5e03c
+	if (fd < 0) {
Josef Bacik b5e03c
+		return 0;
Josef Bacik b5e03c
+	}
Josef Bacik b5e03c
+
Josef Bacik b5e03c
+	if (read(fd, &rotational, sizeof(char)) < sizeof(char)) {
Josef Bacik b5e03c
+		close(fd);
Josef Bacik b5e03c
+		return 0;
Josef Bacik b5e03c
+	}
Josef Bacik b5e03c
+	close(fd);
Josef Bacik b5e03c
+
Josef Bacik b5e03c
+	return !atoi((const char *)&rotational);
Josef Bacik b5e03c
+}
Josef Bacik b5e03c
+
Josef Bacik b5e03c
 int main(int ac, char **av)
Josef Bacik b5e03c
 {
Josef Bacik b5e03c
 	char *file;
Josef Bacik 96158b
@@ -1248,6 +1301,7 @@ int main(int ac, char **av)
Josef Bacik b5e03c
 	int data_profile_opt = 0;
Josef Bacik b5e03c
 	int metadata_profile_opt = 0;
Josef Bacik b5e03c
 	int nodiscard = 0;
Josef Bacik b5e03c
+	int ssd = 0;
Josef Bacik b5e03c
 
Josef Bacik b5e03c
 	char *source_dir = NULL;
Josef Bacik b5e03c
 	int source_dir_set = 0;
Josef Bacik 96158b
@@ -1367,6 +1421,9 @@ int main(int ac, char **av)
Josef Bacik b5e03c
 			exit(1);
Josef Bacik b5e03c
 		}
Josef Bacik b5e03c
 	}
Josef Bacik b5e03c
+
Josef Bacik b5e03c
+	ssd = is_ssd(file);
Josef Bacik b5e03c
+
Josef Bacik b5e03c
 	if (mixed) {
Josef Bacik b5e03c
 		if (metadata_profile != data_profile) {
Josef Bacik b5e03c
 			fprintf(stderr, "With mixed block groups data and metadata "
Josef Bacik 96158b
@@ -1452,7 +1509,7 @@ raid_groups:
Josef Bacik b5e03c
 	if (!source_dir_set) {
Josef Bacik b5e03c
 		ret = create_raid_groups(trans, root, data_profile,
Josef Bacik b5e03c
 				 data_profile_opt, metadata_profile,
Josef Bacik b5e03c
-				 metadata_profile_opt, mixed);
Josef Bacik b5e03c
+				 metadata_profile_opt, mixed, ssd);
Josef Bacik b5e03c
 		BUG_ON(ret);
Josef Bacik b5e03c
 	}
Josef Bacik b5e03c
 
Josef Bacik 96158b
-- 
Josef Bacik 96158b
1.7.7.6
Josef Bacik 96158b