O-direct on ext3 file ssytem
Andrew Morton
akpm at osdl.org
Mon Jul 12 00:51:26 UTC 2004
"Stephen C. Tweedie" <sct at redhat.com> 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 at osdl.org>
---
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
*/
_
More information about the Ext3-users
mailing list