From: Hans Reiser <reiser@namesys.com>

This patch reduces reiser4's stack usage by kmalloc-ing big structure
instead of having in on stack.

Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/fs/reiser4/carry.c             |   16 ++++---
 25-akpm/fs/reiser4/carry.h             |    2 
 25-akpm/fs/reiser4/eottl.c             |   15 ++++--
 25-akpm/fs/reiser4/flush.c             |   20 +++++---
 25-akpm/fs/reiser4/plugin/item/ctail.c |   14 ++++--
 25-akpm/fs/reiser4/reiser4.h           |    4 -
 25-akpm/fs/reiser4/tree.c              |   74 +++++++++++++++++++--------------
 7 files changed, 86 insertions(+), 59 deletions(-)

diff -puN fs/reiser4/carry.c~reiser4-reduce-stack-usage fs/reiser4/carry.c
--- 25/fs/reiser4/carry.c~reiser4-reduce-stack-usage	Fri Nov 12 16:02:04 2004
+++ 25-akpm/fs/reiser4/carry.c	Fri Nov 12 16:02:04 2004
@@ -462,22 +462,28 @@ init_carry_level(carry_level * level /* 
 	pool_level_list_init(&level->ops);
 }
 
-/* initialise pools within queue */
-reiser4_internal void
-init_carry_pool(carry_pool * pool /* pool to initialise */ )
+/* allocate carry pool and initialise pools within queue */
+reiser4_internal carry_pool *
+init_carry_pool(void)
 {
-	assert("nikita-945", pool != NULL);
+	carry_pool * pool;
+
+	pool = kmalloc(sizeof(carry_pool), GFP_KERNEL);
+	if (pool == NULL)
+		return ERR_PTR(RETERR(-ENOMEM));
 
 	reiser4_init_pool(&pool->op_pool, sizeof (carry_op), CARRIES_POOL_SIZE, (char *) pool->op);
 	reiser4_init_pool(&pool->node_pool, sizeof (carry_node), NODES_LOCKED_POOL_SIZE, (char *) pool->node);
+	return pool;
 }
 
 /* finish with queue pools */
 reiser4_internal void
-done_carry_pool(carry_pool * pool UNUSED_ARG /* pool to destroy */ )
+done_carry_pool(carry_pool * pool /* pool to destroy */ )
 {
 	reiser4_done_pool(&pool->op_pool);
 	reiser4_done_pool(&pool->node_pool);
+	kfree(pool);
 }
 
 /* add new carry node to the @level.
diff -puN fs/reiser4/carry.h~reiser4-reduce-stack-usage fs/reiser4/carry.h
--- 25/fs/reiser4/carry.h~reiser4-reduce-stack-usage	Fri Nov 12 16:02:04 2004
+++ 25-akpm/fs/reiser4/carry.h	Fri Nov 12 16:02:04 2004
@@ -343,7 +343,7 @@ extern carry_node *add_carry_atplace(car
 
 extern carry_node *find_begetting_brother(carry_node * node, carry_level * kin);
 
-extern void init_carry_pool(carry_pool * pool);
+extern carry_pool *init_carry_pool(void);
 extern void done_carry_pool(carry_pool * pool);
 
 extern void init_carry_level(carry_level * level, carry_pool * pool);
diff -puN fs/reiser4/eottl.c~reiser4-reduce-stack-usage fs/reiser4/eottl.c
--- 25/fs/reiser4/eottl.c~reiser4-reduce-stack-usage	Fri Nov 12 16:02:04 2004
+++ 25-akpm/fs/reiser4/eottl.c	Fri Nov 12 16:02:04 2004
@@ -169,24 +169,27 @@ static int
 add_empty_leaf(coord_t * insert_coord, lock_handle * lh, const reiser4_key * key, const reiser4_key * rdkey)
 {
 	int result;
-	carry_pool pool;
+	carry_pool *pool;
 	carry_level todo;
 	carry_op *op;
-	/*znode *parent_node;*/
 	znode *node;
 	reiser4_item_data item;
 	carry_insert_data cdata;
 	reiser4_tree *tree;
 
-	init_carry_pool(&pool);
-	init_carry_level(&todo, &pool);
+	pool = init_carry_pool();
+	if (IS_ERR(pool))
+		return PTR_ERR(pool);
+	init_carry_level(&todo, pool);
 	ON_STATS(todo.level_no = TWIG_LEVEL);
 	assert("vs-49827", znode_contains_key_lock(insert_coord->node, key));
 
 	tree = znode_get_tree(insert_coord->node);
 	node = new_node(insert_coord->node, LEAF_LEVEL);
-	if (IS_ERR(node))
+	if (IS_ERR(node)) {
+		done_carry_pool(pool);
 		return PTR_ERR(node);
+	}
 
 	/* setup delimiting keys for node being inserted */
 	WLOCK_DK(tree);
@@ -264,7 +267,7 @@ add_empty_leaf(coord_t * insert_coord, l
 	} else
 		result = PTR_ERR(op);
 	zput(node);
-	done_carry_pool(&pool);
+	done_carry_pool(pool);
 	return result;
 }
 
diff -puN fs/reiser4/flush.c~reiser4-reduce-stack-usage fs/reiser4/flush.c
--- 25/fs/reiser4/flush.c~reiser4-reduce-stack-usage	Fri Nov 12 16:02:04 2004
+++ 25-akpm/fs/reiser4/flush.c	Fri Nov 12 16:02:04 2004
@@ -2620,7 +2620,7 @@ static int
 squeeze_right_non_twig(znode * left, znode * right)
 {
 	int ret;
-	carry_pool pool;
+	carry_pool *pool;
 	carry_level todo;
 	ON_STATS(int old_items; int old_free_space);
 
@@ -2629,8 +2629,10 @@ squeeze_right_non_twig(znode * left, zno
 	if (!znode_is_dirty(left) || !znode_is_dirty(right))
 		return SQUEEZE_TARGET_FULL;
 
-	init_carry_pool(&pool);
-	init_carry_level(&todo, &pool);
+	pool = init_carry_pool();
+	if (IS_ERR(pool))
+		return PTR_ERR(pool);
+	init_carry_level(&todo, pool);
 
 	ON_STATS(old_items = node_num_items(left); old_free_space = znode_free_space(left));
 
@@ -2665,7 +2667,7 @@ squeeze_right_non_twig(znode * left, zno
 		ret = node_is_empty(right) ? SQUEEZE_SOURCE_EMPTY : SQUEEZE_TARGET_FULL;
 	}
 
-	done_carry_pool(&pool);
+	done_carry_pool(pool);
 
 #if REISER4_STATS
 	if (znode_get_level(left) == LEAF_LEVEL) {
@@ -2685,7 +2687,7 @@ static int
 shift_one_internal_unit(znode * left, znode * right)
 {
 	int ret;
-	carry_pool pool;
+	carry_pool *pool;
 	carry_level todo;
 	coord_t coord;
 	int size, moved;
@@ -2713,8 +2715,10 @@ shift_one_internal_unit(znode * left, zn
 
 	assert("jmacd-2007", item_is_internal(&coord));
 
-	init_carry_pool(&pool);
-	init_carry_level(&todo, &pool);
+	pool = init_carry_pool();
+	if (IS_ERR(pool))
+		return PTR_ERR(pool);
+	init_carry_level(&todo, pool);
 
 	size = item_length_by_coord(&coord);
 	info.todo = &todo;
@@ -2754,7 +2758,7 @@ shift_one_internal_unit(znode * left, zn
 		 "shift_one %s an item: left has %u items, right has %u items\n",
 		 moved > 0 ? "moved" : "did not move", node_num_items(left), node_num_items(right));
 
-	done_carry_pool(&pool);
+	done_carry_pool(pool);
 
 	if (ret != 0) {
 		/* Shift or carry operation failed. */
diff -puN fs/reiser4/plugin/item/ctail.c~reiser4-reduce-stack-usage fs/reiser4/plugin/item/ctail.c
--- 25/fs/reiser4/plugin/item/ctail.c~reiser4-reduce-stack-usage	Fri Nov 12 16:02:04 2004
+++ 25-akpm/fs/reiser4/plugin/item/ctail.c	Fri Nov 12 16:02:04 2004
@@ -809,14 +809,16 @@ static int
 insert_crc_flow(coord_t * coord, lock_handle * lh, flow_t * f, struct inode * inode)
 {
 	int result;
-	carry_pool pool;
+	carry_pool *pool;
 	carry_level lowest_level;
 	carry_op *op;
 	reiser4_item_data data;
 	__u8 cluster_shift = inode_cluster_shift(inode);
 
-	init_carry_pool(&pool);
-	init_carry_level(&lowest_level, &pool);
+	pool = init_carry_pool();
+	if (IS_ERR(pool))
+		return PTR_ERR(pool);
+	init_carry_level(&lowest_level, pool);
 
 	assert("edward-466", coord->between == AFTER_ITEM || coord->between == AFTER_UNIT ||
 	       coord->between == BEFORE_ITEM);
@@ -826,8 +828,10 @@ insert_crc_flow(coord_t * coord, lock_ha
 		coord->between = AFTER_ITEM;
 	}
 	op = post_carry(&lowest_level, COP_INSERT_FLOW, coord->node, 0 /* operate directly on coord -> node */ );
-	if (IS_ERR(op) || (op == NULL))
+	if (IS_ERR(op) || (op == NULL)) {
+		done_carry_pool(pool);
 		return RETERR(op ? PTR_ERR(op) : -EIO);
+	}
 	data.user = 0;
 	data.iplug = item_plugin_by_id(CTAIL_ID);
 	data.arg = &cluster_shift;
@@ -846,7 +850,7 @@ insert_crc_flow(coord_t * coord, lock_ha
 
 	ON_STATS(lowest_level.level_no = znode_get_level(coord->node));
 	result = carry(&lowest_level, 0);
-	done_carry_pool(&pool);
+	done_carry_pool(pool);
 
 	return result;
 }
diff -puN fs/reiser4/reiser4.h~reiser4-reduce-stack-usage fs/reiser4/reiser4.h
--- 25/fs/reiser4/reiser4.h~reiser4-reduce-stack-usage	Fri Nov 12 16:02:04 2004
+++ 25-akpm/fs/reiser4/reiser4.h	Fri Nov 12 16:02:04 2004
@@ -14,10 +14,6 @@
 #include <asm/hardirq.h>
 #include <linux/sched.h>
 
-#if defined(CONFIG_4KSTACKS)
-#error "Please turn 4k stack off"
-#endif
-
 /*
  * reiser4 compilation options.
  */
diff -puN fs/reiser4/tree.c~reiser4-reduce-stack-usage fs/reiser4/tree.c
--- 25/fs/reiser4/tree.c~reiser4-reduce-stack-usage	Fri Nov 12 16:02:04 2004
+++ 25-akpm/fs/reiser4/tree.c	Fri Nov 12 16:02:04 2004
@@ -264,19 +264,23 @@ insert_with_carry_by_coord(coord_t * coo
 			   cop_insert_flag flags /* carry flags */)
 {
 	int result;
-	carry_pool pool;
+	carry_pool *pool;
 	carry_level lowest_level;
 	carry_op *op;
 	carry_insert_data cdata;
 
 	assert("umka-314", coord != NULL);
 
-	init_carry_pool(&pool);
-	init_carry_level(&lowest_level, &pool);
+	pool = init_carry_pool();
+	if (IS_ERR(pool))
+		return PTR_ERR(pool);
+	init_carry_level(&lowest_level, pool);
 
 	op = post_carry(&lowest_level, cop, coord->node, 0);
-	if (IS_ERR(op) || (op == NULL))
+	if (IS_ERR(op) || (op == NULL)) {
+		done_carry_pool(pool);
 		return RETERR(op ? PTR_ERR(op) : -EIO);
+	}
 	cdata.coord = coord;
 	cdata.data = data;
 	cdata.key = key;
@@ -294,7 +298,7 @@ insert_with_carry_by_coord(coord_t * coo
 
 	ON_STATS(lowest_level.level_no = znode_get_level(coord->node));
 	result = carry(&lowest_level, 0);
-	done_carry_pool(&pool);
+	done_carry_pool(pool);
 
 	return result;
 }
@@ -317,7 +321,7 @@ paste_with_carry(coord_t * coord /* coor
 		 unsigned flags /* paste flags */ )
 {
 	int result;
-	carry_pool pool;
+	carry_pool *pool;
 	carry_level lowest_level;
 	carry_op *op;
 	carry_insert_data cdata;
@@ -325,12 +329,16 @@ paste_with_carry(coord_t * coord /* coor
 	assert("umka-315", coord != NULL);
 	assert("umka-316", key != NULL);
 
-	init_carry_pool(&pool);
-	init_carry_level(&lowest_level, &pool);
+	pool = init_carry_pool();
+	if (IS_ERR(pool))
+		return PTR_ERR(pool);
+	init_carry_level(&lowest_level, pool);
 
 	op = post_carry(&lowest_level, COP_PASTE, coord->node, 0);
-	if (IS_ERR(op) || (op == NULL))
+	if (IS_ERR(op) || (op == NULL)) {
+		done_carry_pool(pool);
 		return RETERR(op ? PTR_ERR(op) : -EIO);
+	}
 	cdata.coord = coord;
 	cdata.data = data;
 	cdata.key = key;
@@ -346,7 +354,7 @@ paste_with_carry(coord_t * coord /* coor
 
 	ON_STATS(lowest_level.level_no = znode_get_level(coord->node));
 	result = carry(&lowest_level, 0);
-	done_carry_pool(&pool);
+	done_carry_pool(pool);
 
 	return result;
 }
@@ -527,8 +535,6 @@ resize_item(coord_t * coord /* coord of 
 	    cop_insert_flag flags /* carry flags */ )
 {
 	int result;
-	carry_pool pool;
-	carry_level lowest_level;
 	znode *node;
 
 	assert("nikita-362", coord != NULL);
@@ -541,9 +547,6 @@ resize_item(coord_t * coord /* coord of 
 	if (result != 0)
 		return result;
 
-	init_carry_pool(&pool);
-	init_carry_level(&lowest_level, &pool);
-
 	if (data->length < 0)
 		result = node_plugin_by_coord(coord)->shrink_item(coord,
 								  data->length);
@@ -559,17 +562,21 @@ reiser4_internal int
 insert_flow(coord_t * coord, lock_handle * lh, flow_t * f)
 {
 	int result;
-	carry_pool pool;
+	carry_pool *pool;
 	carry_level lowest_level;
 	carry_op *op;
 	reiser4_item_data data;
 
-	init_carry_pool(&pool);
-	init_carry_level(&lowest_level, &pool);
+	pool = init_carry_pool();
+	if (IS_ERR(pool))
+		return PTR_ERR(pool);
+	init_carry_level(&lowest_level, pool);
 
 	op = post_carry(&lowest_level, COP_INSERT_FLOW, coord->node, 0 /* operate directly on coord -> node */ );
-	if (IS_ERR(op) || (op == NULL))
+	if (IS_ERR(op) || (op == NULL)) {
+		done_carry_pool(pool);
 		return RETERR(op ? PTR_ERR(op) : -EIO);
+	}
 
 	/* these are permanent during insert_flow */
 	data.user = 1;
@@ -591,7 +598,7 @@ insert_flow(coord_t * coord, lock_handle
 
 	ON_STATS(lowest_level.level_no = znode_get_level(coord->node));
 	result = carry(&lowest_level, 0);
-	done_carry_pool(&pool);
+	done_carry_pool(pool);
 
 	return result;
 }
@@ -1240,21 +1247,25 @@ cut_node_content(coord_t *from, coord_t 
 		 const reiser4_key * to_key /* last key to be removed */ ,
 		 reiser4_key * smallest_removed	/* smallest key actually removed */)
 {
-	carry_pool pool;
+	carry_pool *pool;
 	carry_level lowest_level;
 	carry_op *op;
 	carry_cut_data cut_data;
 	int result;
 
-	assert("", coord_compare(from, to) != COORD_CMP_ON_RIGHT);
+	assert("vs-1715", coord_compare(from, to) != COORD_CMP_ON_RIGHT);
 
-	init_carry_pool(&pool);
-	init_carry_level(&lowest_level, &pool);
+	pool = init_carry_pool();
+	if (IS_ERR(pool))
+		return PTR_ERR(pool);
+	init_carry_level(&lowest_level, pool);
 
 	op = post_carry(&lowest_level, COP_CUT, from->node, 0);
 	assert("vs-1509", op != 0);
-	if (IS_ERR(op))
+	if (IS_ERR(op)) {
+		done_carry_pool(pool);
 		return PTR_ERR(op);
+	}
 
 	cut_data.params.from = from;
 	cut_data.params.to = to;
@@ -1267,7 +1278,7 @@ cut_node_content(coord_t *from, coord_t 
 
 	ON_STATS(lowest_level.level_no = znode_get_level(from->node));
 	result = carry(&lowest_level, 0);
-	done_carry_pool(&pool);
+	done_carry_pool(pool);
 
 	return result;
 }
@@ -1297,7 +1308,7 @@ kill_node_content(coord_t * from /* coor
 					 invalidate pages together with item pointing to them */)
 {
 	int result;
-	carry_pool pool;
+	carry_pool *pool;
 	carry_level lowest_level;
 	carry_op *op;
 	carry_kill_data kdata;
@@ -1332,11 +1343,14 @@ kill_node_content(coord_t * from /* coor
 		}
 	}
 
-	init_carry_pool(&pool);
-	init_carry_level(&lowest_level, &pool);
+	pool = init_carry_pool();
+	if (IS_ERR(pool))
+		return PTR_ERR(pool);
+	init_carry_level(&lowest_level, pool);
 
 	op = post_carry(&lowest_level, COP_CUT, from->node, 0);
 	if (IS_ERR(op) || (op == NULL)) {
+		done_carry_pool(pool);
 		done_children(&kdata);
 		return RETERR(op ? PTR_ERR(op) : -EIO);
 	}
@@ -1346,8 +1360,8 @@ kill_node_content(coord_t * from /* coor
 
 	ON_STATS(lowest_level.level_no = znode_get_level(from->node));
 	result = carry(&lowest_level, 0);
-	done_carry_pool(&pool);
 
+	done_carry_pool(pool);
 	done_children(&kdata);
 	return result;
 }
_