"Stephen C. Tweedie" <sct@xxxxxxxxxx> wrote: > > Hi, > > On Fri, 2004-07-09 at 13:22, Marc-Christian Petersen wrote: > > > ext3 supports direct i/o, but not in 2.4 mainline. It was added in 2.6. > > > > my system is running : > > > Red Hat Enterprise Linux AS release 3 (Taroon Update > > > 2) > > > Kernel 2.4.21-15.ELsmp on an i686 > > > > 2.4-aa, 2.4-suse, 2.4-wolk tree and some others have it, 2.4-rh kernels do not > > have it. > > 2.4 RHL kernels did not; RHEL 3 does, so 2.4.21-15.EL will have it. > oop, nobody told me that. You might need to add this fix: ext3_direct_io_get_blocks() is misinterpreting the return value from ext3_journal_extend(), and is consequently running out of buffer credits and going BUG on tremendously large direct-io writes. Fix that up. Also, I note that the really large direct-io writes can hold a transaction open for the entire duration, which can be minutes. This violates ext3's attempt to commit data at regular intervals. Fix that up by looking at the transaction state: if it's T_LOCKED, shut off the current handle so the pending commit can complete. Signed-off-by: Andrew Morton <akpm@xxxxxxxx> --- 25-akpm/fs/ext3/inode.c | 28 ++++++++++++++++++++++------ 1 files changed, 22 insertions(+), 6 deletions(-) diff -puN fs/ext3/inode.c~ext3-direct-io-credits-overflow-fix fs/ext3/inode.c --- 25/fs/ext3/inode.c~ext3-direct-io-credits-overflow-fix 2004-06-27 00:19:37.609592016 -0700 +++ 25-akpm/fs/ext3/inode.c 2004-06-27 00:19:37.616590952 -0700 @@ -881,26 +881,42 @@ ext3_direct_io_get_blocks(struct inode * handle_t *handle = journal_current_handle(); int ret = 0; - 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); + 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); return ret; } - /* * `handle' can be NULL if create is zero */ _ _______________________________________________ Ext3-users@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/ext3-users