Upstream-Status: Inappropriate [Backport]
From e6bd18d8938986c997c45f0ea95b221d4edec095 Mon Sep 17 00:00:00 2001
From: Christoph Hellwig <hch@lst.de>
Date: Thu, 21 Apr 2011 16:24:07 -0400
Subject: [PATCH 15/15] btrfs-progs: add discard support to mkfs

Discard the whole device before starting to create the filesystem structures.
Modelled after similar support in mkfs.xfs.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
---
 btrfs_cmds.c |   21 +++++++++++++++++----
 utils.c      |   21 +++++++++++++++++++++
 2 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/btrfs_cmds.c b/btrfs_cmds.c
index 6de73f4..32f6b25 100644
--- a/btrfs_cmds.c
+++ b/btrfs_cmds.c
@@ -732,13 +732,26 @@ int do_add_volume(int nargs, char **args)
 		return 12;
 	}
 
-	for(i=1 ; i < (nargs-1) ; i++ ){
+	for (i = 1; i < (nargs-1); i++ ){
 		struct btrfs_ioctl_vol_args ioctl_args;
 		int	devfd, res;
 		u64 dev_block_count = 0;
 		struct stat st;
 		int mixed = 0;
 
+		res = check_mounted(args[i]);
+		if (res < 0) {
+			fprintf(stderr, "error checking %s mount status\n",
+				args[i]);
+			ret++;
+			continue;
+		}
+		if (res == 1) {
+			fprintf(stderr, "%s is mounted\n", args[i]);
+			ret++;
+			continue;
+		}
+
 		devfd = open(args[i], O_RDWR);
 		if (!devfd) {
 			fprintf(stderr, "ERROR: Unable to open device '%s'\n", args[i]);
@@ -746,8 +759,8 @@ int do_add_volume(int nargs, char **args)
 			ret++;
 			continue;
 		}
-		ret = fstat(devfd, &st);
-		if (ret) {
+		res = fstat(devfd, &st);
+		if (res) {
 			fprintf(stderr, "ERROR: Unable to stat '%s'\n", args[i]);
 			close(devfd);
 			ret++;
@@ -781,7 +794,7 @@ int do_add_volume(int nargs, char **args)
 	}
 
 	close(fdmnt);
-	if( ret)
+	if (ret)
 		return ret+20;
 	else
 		return 0;
diff --git a/utils.c b/utils.c
index 13373c9..17e5afe 100644
--- a/utils.c
+++ b/utils.c
@@ -50,6 +50,20 @@
 static inline int ioctl(int fd, int define, u64 *size) { return 0; }
 #endif
 
+#ifndef BLKDISCARD
+#define BLKDISCARD	_IO(0x12,119)
+#endif
+
+static int
+discard_blocks(int fd, u64 start, u64 len)
+{
+	u64 range[2] = { start, len };
+
+	if (ioctl(fd, BLKDISCARD, &range) < 0)
+		return errno;
+	return 0;
+}
+
 static u64 reference_root_table[] = {
 	[1] =	BTRFS_ROOT_TREE_OBJECTID,
 	[2] =	BTRFS_EXTENT_TREE_OBJECTID,
@@ -537,6 +551,13 @@ int btrfs_prepare_device(int fd, char *file, int zero_end, u64 *block_count_ret,
 		printf("SMALL VOLUME: forcing mixed metadata/data groups\n");
 		*mixed = 1;
 	}
+
+	/*
+	 * We intentionally ignore errors from the discard ioctl.  It is
+	 * not necessary for the mkfs functionality but just an optimization.
+	 */
+	discard_blocks(fd, 0, block_count);
+
 	ret = zero_dev_start(fd);
 	if (ret) {
 		fprintf(stderr, "failed to zero device start %d\n", ret);
-- 
1.7.2.3

