Btrfs: Reduce stack usage in the resizer, fix 32 bit compiles

Signed-off-by: Chris Mason <chris.mason@oracle.com>
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index d6e5c19..9873975 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -386,6 +386,7 @@
 	int defrag_running;
 	int defrag_level;
 	char *name;
+	int in_sysfs;
 };
 
 /*
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index de026d9..67d9fd7 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -374,6 +374,7 @@
 	root->highest_inode = 0;
 	root->last_inode_alloc = 0;
 	root->name = NULL;
+	root->in_sysfs = 0;
 	memset(&root->root_key, 0, sizeof(root->root_key));
 	memset(&root->root_item, 0, sizeof(root->root_item));
 	memset(&root->defrag_progress, 0, sizeof(root->defrag_progress));
@@ -516,6 +517,9 @@
 	if (!root)
 		return NULL;
 
+	if (root->in_sysfs)
+		return root;
+
 	ret = btrfs_set_root_name(root, name, namelen);
 	if (ret) {
 		free_extent_buffer(root->node);
@@ -530,6 +534,7 @@
 		kfree(root);
 		return ERR_PTR(ret);
 	}
+	root->in_sysfs = 1;
 	return root;
 }
 #if 0
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 91c2b27..6137f06 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -751,7 +751,7 @@
 
 		if (found_objectid != root_objectid) {
 			total_count = 2;
-			break;
+			goto out;
 		}
 		total_count = 1;
 		path->slots[0]++;
@@ -760,8 +760,6 @@
 		total_count = 0;
 		goto out;
 	}
-	if (total_count > 1)
-		goto out;
 	if (level >= 0 && root->node == count_path->nodes[level])
 		goto out;
 	level++;
@@ -2109,22 +2107,23 @@
 	u64 delalloc_start;
 	u64 existing_delalloc;
 	unsigned long last_index;
-	unsigned long first_index;
 	unsigned long i;
 	struct page *page;
 	struct btrfs_root *root = BTRFS_I(inode)->root;
 	struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
-	struct file_ra_state ra;
+	struct file_ra_state *ra;
+
+	ra = kzalloc(sizeof(*ra), GFP_NOFS);
 
 	mutex_lock(&inode->i_mutex);
-	first_index = start >> PAGE_CACHE_SHIFT;
+	i = start >> PAGE_CACHE_SHIFT;
 	last_index = (start + len - 1) >> PAGE_CACHE_SHIFT;
 
-	memset(&ra, 0, sizeof(ra));
-	file_ra_state_init(&ra, inode->i_mapping);
-	btrfs_force_ra(inode->i_mapping, &ra, NULL, first_index, last_index);
+	file_ra_state_init(ra, inode->i_mapping);
+	btrfs_force_ra(inode->i_mapping, ra, NULL, i, last_index);
+	kfree(ra);
 
-	for (i = first_index; i <= last_index; i++) {
+	for (; i <= last_index; i++) {
 		page = grab_cache_page(inode->i_mapping, i);
 		if (!page)
 			goto out_unlock;
@@ -2167,27 +2166,43 @@
 	return 0;
 }
 
+/*
+ * note, this releases the path
+ */
 static int relocate_one_reference(struct btrfs_root *extent_root,
 				  struct btrfs_path *path,
-				  struct btrfs_key *extent_key,
-				  u64 ref_root, u64 ref_gen, u64 ref_objectid,
-				  u64 ref_offset)
+				  struct btrfs_key *extent_key)
 {
 	struct inode *inode;
 	struct btrfs_root *found_root;
-	struct btrfs_key root_location;
+	struct btrfs_key *root_location;
+	struct btrfs_extent_ref *ref;
+	u64 ref_root;
+	u64 ref_gen;
+	u64 ref_objectid;
+	u64 ref_offset;
 	int ret;
 
-	root_location.objectid = ref_root;
+	ref = btrfs_item_ptr(path->nodes[0], path->slots[0],
+			     struct btrfs_extent_ref);
+	ref_root = btrfs_ref_root(path->nodes[0], ref);
+	ref_gen = btrfs_ref_generation(path->nodes[0], ref);
+	ref_objectid = btrfs_ref_objectid(path->nodes[0], ref);
+	ref_offset = btrfs_ref_offset(path->nodes[0], ref);
+	btrfs_release_path(extent_root, path);
+
+	root_location = kmalloc(sizeof(*root_location), GFP_NOFS);
+	root_location->objectid = ref_root;
 	if (ref_gen == 0)
-		root_location.offset = 0;
+		root_location->offset = 0;
 	else
-		root_location.offset = (u64)-1;
-	root_location.type = BTRFS_ROOT_ITEM_KEY;
+		root_location->offset = (u64)-1;
+	root_location->type = BTRFS_ROOT_ITEM_KEY;
 
 	found_root = btrfs_read_fs_root_no_name(extent_root->fs_info,
-						&root_location);
+						root_location);
 	BUG_ON(!found_root);
+	kfree(root_location);
 
 	if (ref_objectid >= BTRFS_FIRST_FREE_OBJECTID) {
 		mutex_unlock(&extent_root->fs_info->fs_mutex);
@@ -2259,12 +2274,7 @@
 {
 	struct btrfs_key key;
 	struct btrfs_key found_key;
-	struct btrfs_extent_ref *ref;
 	struct extent_buffer *leaf;
-	u64 ref_root;
-	u64 ref_gen;
-	u64 ref_objectid;
-	u64 ref_offset;
 	u32 nritems;
 	u32 item_size;
 	int ret = 0;
@@ -2297,17 +2307,7 @@
 		key.offset = found_key.offset + 1;
 		item_size = btrfs_item_size_nr(leaf, path->slots[0]);
 
-		ref = btrfs_item_ptr(leaf, path->slots[0],
-				     struct btrfs_extent_ref);
-		ref_root = btrfs_ref_root(leaf, ref);
-		ref_gen = btrfs_ref_generation(leaf, ref);
-		ref_objectid = btrfs_ref_objectid(leaf, ref);
-		ref_offset = btrfs_ref_offset(leaf, ref);
-		btrfs_release_path(extent_root, path);
-
-		ret = relocate_one_reference(extent_root, path,
-					     extent_key, ref_root, ref_gen,
-					     ref_objectid, ref_offset);
+		ret = relocate_one_reference(extent_root, path, extent_key);
 		if (ret)
 			goto out;
 	}
@@ -2354,7 +2354,6 @@
 	struct btrfs_path *path;
 	u64 cur_byte;
 	u64 total_found;
-	u64 ptr;
 	struct btrfs_fs_info *info = root->fs_info;
 	struct extent_map_tree *block_group_cache;
 	struct btrfs_key key;
@@ -2377,6 +2376,7 @@
 	key.offset = 0;
 	key.type = 0;
 	while(1) {
+
 		ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
 		if (ret < 0)
 			goto out;
@@ -2441,6 +2441,8 @@
 	key.offset = 0;
 	key.type = 0;
 	while(1) {
+		u64 ptr;
+
 		ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
 		if (ret < 0)
 			goto out;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 5003a86..b62f35e 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2108,7 +2108,8 @@
 	btrfs_btree_balance_dirty(root, nr);
 }
 
-static int create_subvol(struct btrfs_root *root, char *name, int namelen)
+static int noinline create_subvol(struct btrfs_root *root, char *name,
+				  int namelen)
 {
 	struct btrfs_trans_handle *trans;
 	struct btrfs_key key;
@@ -2492,7 +2493,8 @@
 	return ret;
 }
 
-static int btrfs_ioctl_snap_create(struct btrfs_root *root, void __user *arg)
+static int noinline btrfs_ioctl_snap_create(struct btrfs_root *root,
+					    void __user *arg)
 {
 	struct btrfs_ioctl_vol_args *vol_args;
 	struct btrfs_dir_item *di;
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 1ad611b..02721ee 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -481,12 +481,10 @@
 	struct btrfs_transaction *cur_trans;
 	struct btrfs_transaction *prev_trans = NULL;
 	struct list_head dirty_fs_roots;
-	struct extent_map_tree pinned_copy;
+	struct extent_map_tree *pinned_copy;
 	DEFINE_WAIT(wait);
 	int ret;
 
-	extent_map_tree_init(&pinned_copy,
-			     root->fs_info->btree_inode->i_mapping, GFP_NOFS);
 	INIT_LIST_HEAD(&dirty_fs_roots);
 
 	mutex_lock(&root->fs_info->trans_mutex);
@@ -507,6 +505,14 @@
 		mutex_lock(&root->fs_info->fs_mutex);
 		return 0;
 	}
+
+	pinned_copy = kmalloc(sizeof(*pinned_copy), GFP_NOFS);
+	if (!pinned_copy)
+		return -ENOMEM;
+
+	extent_map_tree_init(pinned_copy,
+			     root->fs_info->btree_inode->i_mapping, GFP_NOFS);
+
 	trans->transaction->in_commit = 1;
 	cur_trans = trans->transaction;
 	if (cur_trans->list.prev != &root->fs_info->trans_list) {
@@ -568,16 +574,20 @@
 			    &root->fs_info->super_copy, 0,
 			    sizeof(root->fs_info->super_copy));
 
-	btrfs_copy_pinned(root, &pinned_copy);
+	btrfs_copy_pinned(root, pinned_copy);
 
 	mutex_unlock(&root->fs_info->trans_mutex);
 	mutex_unlock(&root->fs_info->fs_mutex);
 	ret = btrfs_write_and_wait_transaction(trans, root);
 	BUG_ON(ret);
 	write_ctree_super(trans, root);
+
 	mutex_lock(&root->fs_info->fs_mutex);
-	btrfs_finish_extent_commit(trans, root, &pinned_copy);
+	btrfs_finish_extent_commit(trans, root, pinned_copy);
 	mutex_lock(&root->fs_info->trans_mutex);
+
+	kfree(pinned_copy);
+
 	cur_trans->commit_done = 1;
 	root->fs_info->last_trans_committed = cur_trans->transid;
 	wake_up(&cur_trans->commit_wait);