From: Alex Tomas <alex@clusterfs.com>

Dynamically allocate the holding array for kjournald write patching rather
than allocating it on the stack.

Signed-off-by: Alex Tomas <alex@clusterfs.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/fs/jbd/commit.c     |    6 +++---
 25-akpm/fs/jbd/journal.c    |   25 +++++++++++++++++++++++++
 25-akpm/include/linux/jbd.h |    6 ++++++
 3 files changed, 34 insertions(+), 3 deletions(-)

diff -puN fs/jbd/commit.c~jbd-fix-against-journal-overflow fs/jbd/commit.c
--- 25/fs/jbd/commit.c~jbd-fix-against-journal-overflow	2005-02-23 02:09:24.000000000 -0800
+++ 25-akpm/fs/jbd/commit.c	2005-02-23 02:10:03.000000000 -0800
@@ -103,7 +103,7 @@ void journal_commit_transaction(journal_
 {
 	transaction_t *commit_transaction;
 	struct journal_head *jh, *new_jh, *descriptor;
-	struct buffer_head *wbuf[64];
+	struct buffer_head **wbuf = journal->j_wbuf;
 	int bufs;
 	int flags;
 	int err;
@@ -287,7 +287,7 @@ write_out_data:
 				BUFFER_TRACE(bh, "start journal writeout");
 				get_bh(bh);
 				wbuf[bufs++] = bh;
-				if (bufs == ARRAY_SIZE(wbuf)) {
+				if (bufs == journal->j_wbufsize) {
 					jbd_debug(2, "submit %d writes\n",
 							bufs);
 					spin_unlock(&journal->j_list_lock);
@@ -503,7 +503,7 @@ write_out_data:
 		/* If there's no more to do, or if the descriptor is full,
 		   let the IO rip! */
 
-		if (bufs == ARRAY_SIZE(wbuf) ||
+		if (bufs == journal->j_wbufsize ||
 		    commit_transaction->t_buffers == NULL ||
 		    space_left < sizeof(journal_block_tag_t) + 16) {
 
diff -puN fs/jbd/journal.c~jbd-fix-against-journal-overflow fs/jbd/journal.c
--- 25/fs/jbd/journal.c~jbd-fix-against-journal-overflow	2005-02-23 02:09:24.000000000 -0800
+++ 25-akpm/fs/jbd/journal.c	2005-02-23 02:10:06.000000000 -0800
@@ -721,6 +721,7 @@ journal_t * journal_init_dev(struct bloc
 {
 	journal_t *journal = journal_init_common();
 	struct buffer_head *bh;
+	int n;
 
 	if (!journal)
 		return NULL;
@@ -736,6 +737,17 @@ journal_t * journal_init_dev(struct bloc
 	journal->j_sb_buffer = bh;
 	journal->j_superblock = (journal_superblock_t *)bh->b_data;
 
+	/* journal descriptor can store up to n blocks -bzzz */
+	n = journal->j_blocksize / sizeof(journal_block_tag_t);
+	journal->j_wbufsize = n;
+	journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL);
+	if (!journal->j_wbuf) {
+		printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
+			__FUNCTION__);
+		kfree(journal);
+		journal = NULL;
+	}
+
 	return journal;
 }
  
@@ -752,6 +764,7 @@ journal_t * journal_init_inode (struct i
 	struct buffer_head *bh;
 	journal_t *journal = journal_init_common();
 	int err;
+	int n;
 	unsigned long blocknr;
 
 	if (!journal)
@@ -768,6 +781,17 @@ journal_t * journal_init_inode (struct i
 	journal->j_maxlen = inode->i_size >> inode->i_sb->s_blocksize_bits;
 	journal->j_blocksize = inode->i_sb->s_blocksize;
 
+	/* journal descriptor can store up to n blocks -bzzz */
+	n = journal->j_blocksize / sizeof(journal_block_tag_t);
+	journal->j_wbufsize = n;
+	journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL);
+	if (!journal->j_wbuf) {
+		printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
+			__FUNCTION__);
+		kfree(journal);
+		return NULL;
+	}
+
 	err = journal_bmap(journal, 0, &blocknr);
 	/* If that failed, give up */
 	if (err) {
@@ -1141,6 +1165,7 @@ void journal_destroy(journal_t *journal)
 		iput(journal->j_inode);
 	if (journal->j_revoke)
 		journal_destroy_revoke(journal);
+	kfree(journal->j_wbuf);
 	kfree(journal);
 }
 
diff -puN include/linux/jbd.h~jbd-fix-against-journal-overflow include/linux/jbd.h
--- 25/include/linux/jbd.h~jbd-fix-against-journal-overflow	2005-02-23 02:09:24.000000000 -0800
+++ 25-akpm/include/linux/jbd.h	2005-02-23 02:09:24.000000000 -0800
@@ -789,6 +789,12 @@ struct journal_s
 	struct jbd_revoke_table_s *j_revoke_table[2];
 
 	/*
+	 * array of bhs for journal_commit_transaction
+	 */
+	struct buffer_head	**j_wbuf;
+	int			j_wbufsize;
+
+	/*
 	 * An opaque pointer to fs-private information.  ext3 puts its
 	 * superblock pointer here
 	 */
_