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