diff -urNp --exclude CVS --exclude BitKeeper --exclude {arch} --exclude .arch-ids x-ref/fs/ext3/inode.c 2.4.23aa3/fs/ext3/inode.c --- x-ref/fs/ext3/inode.c 2004-07-04 02:04:54.250898664 +0200 +++ 2.4.23aa3/fs/ext3/inode.c 2004-07-04 02:05:06.091098680 +0200 @@ -868,22 +868,39 @@ ext3_direct_io_get_block(struct inode *i int ret = 0; lock_kernel(); - if (handle && handle->h_buffer_credits <= EXT3_RESERVE_TRANS_BLOCKS) { + if (!handle) + goto get_block; /* A read */ + + if (handle->h_transaction->t_state == T_LOCKED) { + /* + * Huge direct-io writes can hold off commits for long + * periods of time. Let this commit run. + */ + ext3_journal_stop(handle, inode); + handle = ext3_journal_start(inode, DIO_CREDITS); + if (IS_ERR(handle)) + ret = PTR_ERR(handle); + goto get_block; + } + + if (handle->h_buffer_credits <= EXT3_RESERVE_TRANS_BLOCKS) { /* * Getting low on buffer credits... */ - if (!ext3_journal_extend(handle, DIO_CREDITS)) { + ret = ext3_journal_extend(handle, DIO_CREDITS); + if (ret > 0) { /* - * Couldn't extend the transaction. Start a new one + * Couldn't extend the transaction. Start a new one. */ ret = ext3_journal_restart(handle, DIO_CREDITS); } } + +get_block: if (ret == 0) ret = ext3_get_block_handle(handle, inode, iblock, bh_result, create, 0); - if (ret == 0) - bh_result->b_size = (1 << inode->i_blkbits); + bh_result->b_size = (1 << inode->i_blkbits); unlock_kernel(); return ret; }