Btrfs: Add simple stripe size parameter

Signed-off-by: Chris Mason <chris.mason@oracle.com>
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index b29b911..9bc1b0a 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -135,6 +135,7 @@
 	__le32 sectorsize;
 	__le32 nodesize;
 	__le32 leafsize;
+	__le32 stripesize;
 	u8 root_level;
 } __attribute__ ((__packed__));
 
@@ -353,6 +354,8 @@
 	/* leaf allocations are done in leafsize units */
 	u32 leafsize;
 
+	u32 stripesize;
+
 	u32 type;
 	u64 highest_inode;
 	u64 last_inode_alloc;
@@ -776,6 +779,8 @@
 			 nodesize, 32);
 BTRFS_SETGET_STACK_FUNCS(super_leafsize, struct btrfs_super_block,
 			 leafsize, 32);
+BTRFS_SETGET_STACK_FUNCS(super_stripesize, struct btrfs_super_block,
+			 stripesize, 32);
 BTRFS_SETGET_STACK_FUNCS(super_root_dir, struct btrfs_super_block,
 			 root_dir_objectid, 64);
 
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index eef4ab5..60a30da 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -355,7 +355,7 @@
 }
 
 static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
-			struct btrfs_root *root,
+			u32 stripesize, struct btrfs_root *root,
 			struct btrfs_fs_info *fs_info,
 			u64 objectid)
 {
@@ -365,6 +365,7 @@
 	root->sectorsize = sectorsize;
 	root->nodesize = nodesize;
 	root->leafsize = leafsize;
+	root->stripesize = stripesize;
 	root->ref_cows = 0;
 	root->fs_info = fs_info;
 	root->objectid = objectid;
@@ -393,7 +394,8 @@
 	u32 blocksize;
 
 	__setup_root(tree_root->nodesize, tree_root->leafsize,
-		     tree_root->sectorsize, root, fs_info, objectid);
+		     tree_root->sectorsize, tree_root->stripesize,
+		     root, fs_info, objectid);
 	ret = btrfs_find_last_root(tree_root, objectid,
 				   &root->root_item, &root->root_key);
 	BUG_ON(ret);
@@ -430,8 +432,8 @@
 	}
 
 	__setup_root(tree_root->nodesize, tree_root->leafsize,
-		     tree_root->sectorsize, root, fs_info,
-		     location->objectid);
+		     tree_root->sectorsize, tree_root->stripesize,
+		     root, fs_info, location->objectid);
 
 	path = btrfs_alloc_path();
 	BUG_ON(!path);
@@ -537,6 +539,7 @@
 	u32 nodesize;
 	u32 leafsize;
 	u32 blocksize;
+	u32 stripesize;
 	struct btrfs_root *extent_root = kmalloc(sizeof(struct btrfs_root),
 						 GFP_NOFS);
 	struct btrfs_root *tree_root = kmalloc(sizeof(struct btrfs_root),
@@ -607,7 +610,7 @@
 		goto fail_iput;
 	}
 #endif
-	__setup_root(512, 512, 512, tree_root,
+	__setup_root(512, 512, 512, 512, tree_root,
 		     fs_info, BTRFS_ROOT_TREE_OBJECTID);
 
 	fs_info->sb_buffer = read_tree_block(tree_root,
@@ -630,9 +633,11 @@
 	nodesize = btrfs_super_nodesize(disk_super);
 	leafsize = btrfs_super_leafsize(disk_super);
 	sectorsize = btrfs_super_sectorsize(disk_super);
+	stripesize = btrfs_super_stripesize(disk_super);
 	tree_root->nodesize = nodesize;
 	tree_root->leafsize = leafsize;
 	tree_root->sectorsize = sectorsize;
+	tree_root->stripesize = stripesize;
 	sb_set_blocksize(sb, sectorsize);
 
 	i_size_write(fs_info->btree_inode,
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 55abdf9..91397e9 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -932,6 +932,13 @@
 	return ret ? ret : pending_ret;
 }
 
+static u64 stripe_align(struct btrfs_root *root, u64 val)
+{
+	u64 mask = ((u64)root->stripesize - 1);
+	u64 ret = (val + mask) & ~mask;
+	return ret;
+}
+
 /*
  * walks the btree of allocated extents and find a hole of a given size.
  * The key ins is changed to record the hole:
@@ -948,8 +955,9 @@
 {
 	struct btrfs_path *path;
 	struct btrfs_key key;
-	int ret;
 	u64 hole_size = 0;
+	u64 aligned;
+	int ret;
 	int slot = 0;
 	u64 last_byte = 0;
 	u64 orig_search_start = search_start;
@@ -990,6 +998,7 @@
 check_failed:
 	search_start = find_search_start(root, &block_group, search_start,
 					 total_needed, data, full_scan);
+	search_start = stripe_align(root, search_start);
 	cached_start = search_start;
 	btrfs_init_path(path);
 	ins->objectid = search_start;
@@ -1039,13 +1048,23 @@
 			search_start = max(search_start,
 					   block_group->key.objectid);
 			if (!start_found) {
-				ins->objectid = search_start;
-				ins->offset = search_end - search_start;
+				aligned = stripe_align(root, search_start);
+				ins->objectid = aligned;
+				if (aligned >= search_end) {
+					ret = -ENOSPC;
+					goto error;
+				}
+				ins->offset = search_end - aligned;
 				start_found = 1;
 				goto check_pending;
 			}
-			ins->objectid = last_byte > search_start ?
-					last_byte : search_start;
+			ins->objectid = stripe_align(root,
+						     last_byte > search_start ?
+						     last_byte : search_start);
+			if (search_end <= ins->objectid) {
+				ret = -ENOSPC;
+				goto error;
+			}
 			ins->offset = search_end - ins->objectid;
 			BUG_ON(ins->objectid >= search_end);
 			goto check_pending;
@@ -1056,9 +1075,10 @@
 		    start_found) {
 			if (last_byte < search_start)
 				last_byte = search_start;
-			hole_size = key.objectid - last_byte;
-			if (hole_size >= num_bytes) {
-				ins->objectid = last_byte;
+			aligned = stripe_align(root, last_byte);
+			hole_size = key.objectid - aligned;
+			if (key.objectid > aligned && hole_size >= num_bytes) {
+				ins->objectid = aligned;
 				ins->offset = hole_size;
 				goto check_pending;
 			}