From: Alex Tomas Dynamically allocate the holding array for kjournald write patching rather than allocating it on the stack. Signed-off-by: Alex Tomas Signed-off-by: Andrew Morton --- 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 */ _