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

Josef Bacik b5e03c
From f507119002c6bb972df09a47edfa8998c0fc8172 Mon Sep 17 00:00:00 2001
Josef Bacik b5e03c
From: Josef Bacik <jbacik@fusionio.com>
Josef Bacik b5e03c
Date: Fri, 20 Jul 2012 11:09:43 -0400
Josef Bacik b5e03c
Subject: [PATCH 2/3] Btrfs-progs: detect if the disk we are formatting is a
Josef Bacik b5e03c
 ssd
Josef Bacik b5e03c
Josef Bacik b5e03c
SSD's do not gain anything by having metadata DUP turned on.  The underlying
Josef Bacik b5e03c
file system that is a part of all SSD's could easily map duplicate metadat
Josef Bacik b5e03c
blocks into the same erase block which effectively eliminates the benefit of
Josef Bacik b5e03c
duplicating the metadata on disk.  So detect if we are formatting a single
Josef Bacik b5e03c
SSD drive and if we are do not use DUP.  Thanks,
Josef Bacik b5e03c
Josef Bacik b5e03c
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Josef Bacik b5e03c
---
Josef Bacik b5e03c
 Makefile            |    2 +-
Josef Bacik b5e03c
 man/mkfs.btrfs.8.in |    5 +++-
Josef Bacik b5e03c
 mkfs.c              |   58 ++++++++++++++++++++++++++++++++++++++++++++++++--
Josef Bacik b5e03c
 3 files changed, 60 insertions(+), 5 deletions(-)
Josef Bacik b5e03c
Josef Bacik b5e03c
diff --git a/Makefile b/Makefile
Josef Bacik b5e03c
index c0aaa3d..1afef49 100644
Josef Bacik b5e03c
--- a/Makefile
Josef Bacik b5e03c
+++ b/Makefile
Josef Bacik b5e03c
@@ -66,7 +66,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 b5e03c
diff --git a/man/mkfs.btrfs.8.in b/man/mkfs.btrfs.8.in
Josef Bacik b5e03c
index fc2e1d2..dfa7996 100644
Josef Bacik b5e03c
--- a/man/mkfs.btrfs.8.in
Josef Bacik b5e03c
+++ b/man/mkfs.btrfs.8.in
Josef Bacik b5e03c
@@ -46,7 +46,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 b5e03c
diff --git a/mkfs.c b/mkfs.c
Josef Bacik b5e03c
index dff5eb8..8816db8 100644
Josef Bacik b5e03c
--- a/mkfs.c
Josef Bacik b5e03c
+++ 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 b5e03c
@@ -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 b5e03c
@@ -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 b5e03c
@@ -1201,6 +1206,49 @@ static int zero_output_file(int out_fd, u64 size, u32 sectorsize)
Josef Bacik b5e03c
 	return ret;
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 b5e03c
+	devname = blkid_devno_to_devname(disk);
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 b5e03c
@@ -1227,6 +1275,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 b5e03c
@@ -1352,6 +1401,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 b5e03c
@@ -1438,7 +1490,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 b5e03c
-- 
Josef Bacik b5e03c
1.7.7.6
Josef Bacik b5e03c