fs/ext3/balloc.c |  150 ++++++++++++++++++++++++++-----------------------------
 1 files changed, 71 insertions(+), 79 deletions(-)

diff -puN fs/ext3/balloc.c~ext3-block-allocation-speedup fs/ext3/balloc.c
--- 25/fs/ext3/balloc.c~ext3-block-allocation-speedup	2003-07-06 23:36:09.000000000 -0700
+++ 25-akpm/fs/ext3/balloc.c	2003-07-07 00:57:12.000000000 -0700
@@ -279,7 +279,8 @@ error_return:
 	return;
 }
 
-/* For ext3 allocations, we must not reuse any blocks which are
+/*
+ * For ext3 allocations, we must not reuse any blocks which are
  * allocated in the bitmap buffer's "last committed data" copy.  This
  * prevents deletes from freeing up the page for reuse until we have
  * committed the delete transaction.
@@ -294,14 +295,21 @@ error_return:
  * data-writes at some point, and disable it for metadata allocations or
  * sync-data inodes.
  */
-static inline int ext3_test_allocatable(int nr, struct buffer_head *bh,
-					int have_access)
+static inline int ext3_test_allocatable(int nr, struct buffer_head *bh)
 {
+	int ret;
+	struct journal_head *jh = bh2jh(bh);
+
 	if (ext3_test_bit(nr, bh->b_data))
 		return 0;
-	if (!have_access || !buffer_jbd(bh) || !bh2jh(bh)->b_committed_data)
-		return 1;
-	return !ext3_test_bit(nr, bh2jh(bh)->b_committed_data);
+
+	jbd_lock_bh_state(bh);
+	if (!jh->b_committed_data)
+		ret = 1;
+	else
+		ret = !ext3_test_bit(nr, jh->b_committed_data);
+	jbd_unlock_bh_state(bh);
+	return ret;
 }
 
 /*
@@ -311,11 +319,12 @@ static inline int ext3_test_allocatable(
  * the initial goal; then for a free byte somewhere in the bitmap; then
  * for any free bit in the bitmap.
  */
-static int find_next_usable_block(int start, struct buffer_head *bh,
-				int maxblocks, int have_access)
+static int
+find_next_usable_block(int start, struct buffer_head *bh, int maxblocks)
 {
 	int here, next;
 	char *p, *r;
+	struct journal_head *jh = bh2jh(bh);
 
 	if (start > 0) {
 		/*
@@ -328,48 +337,38 @@ static int find_next_usable_block(int st
 		 */
 		int end_goal = (start + 63) & ~63;
 		here = ext3_find_next_zero_bit(bh->b_data, end_goal, start);
-		if (here < end_goal &&
-			ext3_test_allocatable(here, bh, have_access))
+		if (here < end_goal && ext3_test_allocatable(here, bh))
 			return here;
-	
-		ext3_debug ("Bit not found near goal\n");
+		ext3_debug("Bit not found near goal\n");
 	}
 
 	here = start;
 	if (here < 0)
 		here = 0;
 
-	/*
-	 * There has been no free block found in the near vicinity of
-	 * the goal: do a search forward through the block groups,
-	 * searching in each group first for an entire free byte in the
-	 * bitmap and then for any free bit.
-	 * 
-	 * Search first in the remainder of the current group 
-	 */
-	p = ((char *) bh->b_data) + (here >> 3);
+	p = ((char *)bh->b_data) + (here >> 3);
 	r = memscan(p, 0, (maxblocks - here + 7) >> 3);
-	next = (r - ((char *) bh->b_data)) << 3;
+	next = (r - ((char *)bh->b_data)) << 3;
 
-	if (next < maxblocks && ext3_test_allocatable(next, bh, have_access))
+	if (next < maxblocks && ext3_test_allocatable(next, bh))
 		return next;
 
-	/* The bitmap search --- search forward alternately
-	 * through the actual bitmap and the last-committed copy
-	 * until we find a bit free in both. */
-
+	/*
+	 * The bitmap search --- search forward alternately through the actual
+	 * bitmap and the last-committed copy until we find a bit free in
+	 * both
+	 */
 	while (here < maxblocks) {
-		next  = ext3_find_next_zero_bit ((unsigned long *) bh->b_data, 
-						 maxblocks, here);
+		next = ext3_find_next_zero_bit(bh->b_data, maxblocks, here);
 		if (next >= maxblocks)
 			return -1;
-		if (ext3_test_allocatable(next, bh, have_access))
+		if (ext3_test_allocatable(next, bh))
 			return next;
-
-		if (have_access)
-			here = ext3_find_next_zero_bit
-				((unsigned long *) bh2jh(bh)->b_committed_data, 
-			 	maxblocks, next);
+		jbd_lock_bh_state(bh);
+		if (jh->b_committed_data)
+			here = ext3_find_next_zero_bit(jh->b_committed_data,
+						 	maxblocks, next);
+		jbd_unlock_bh_state(bh);
 	}
 	return -1;
 }
@@ -384,14 +383,20 @@ static int find_next_usable_block(int st
 static inline int
 claim_block(spinlock_t *lock, int block, struct buffer_head *bh)
 {
+	struct journal_head *jh = bh2jh(bh);
+	int ret;
+
 	if (ext3_set_bit_atomic(lock, block, bh->b_data))
 		return 0;
-	if (buffer_jbd(bh) && bh2jh(bh)->b_committed_data &&
-			ext3_test_bit(block, bh2jh(bh)->b_committed_data)) {
+	jbd_lock_bh_state(bh);
+	if (jh->b_committed_data && ext3_test_bit(block,jh->b_committed_data)) {
 		ext3_clear_bit_atomic(lock, block, bh->b_data);
-		return 0;
+		ret = 0;
+	} else {
+		ret = 1;
 	}
-	return 1;
+	jbd_unlock_bh_state(bh);
+	return ret;
 }
 
 /*
@@ -403,43 +408,34 @@ static int
 ext3_try_to_allocate(struct super_block *sb, handle_t *handle, int group,
 		struct buffer_head *bitmap_bh, int goal, int *errp)
 {
-	int i, fatal = 0;
-	int have_access = 0;
+	int i;
+	int fatal;
 	int credits = 0;
 
 	*errp = 0;
 
-	if (goal >= 0 && ext3_test_allocatable(goal, bitmap_bh, 0))
-		goto got;
-
-repeat:
-	goal = find_next_usable_block(goal, bitmap_bh,
-				EXT3_BLOCKS_PER_GROUP(sb), have_access);
-	if (goal < 0)
+	/*
+	 * Make sure we use undo access for the bitmap, because it is critical
+	 * that we do the frozen_data COW on bitmap buffers in all cases even
+	 * if the buffer is in BJ_Forget state in the committing transaction.
+	 */
+	BUFFER_TRACE(bitmap_bh, "get undo access for new block");
+	fatal = ext3_journal_get_undo_access(handle, bitmap_bh, &credits);
+	if (fatal) {
+		*errp = fatal;
 		goto fail;
+	}
 
-	for (i = 0;
-		i < 7 && goal > 0 && 
-			ext3_test_allocatable(goal - 1, bitmap_bh, have_access);
-		i++, goal--);
-
-got:
-	if (!have_access) {
-		/*
-		 * Make sure we use undo access for the bitmap, because it is
-	 	 * critical that we do the frozen_data COW on bitmap buffers in
-	 	 * all cases even if the buffer is in BJ_Forget state in the
-	 	 * committing transaction.
-		 */
-		BUFFER_TRACE(bitmap_bh, "get undo access for new block");
-		fatal = ext3_journal_get_undo_access(handle, bitmap_bh,
-							&credits);
-		if (fatal) {
-			*errp = fatal;
-			goto fail;
-		}
-		jbd_lock_bh_state(bitmap_bh);
-		have_access = 1;
+repeat:
+	if (goal < 0 || !ext3_test_allocatable(goal, bitmap_bh)) {
+		goal = find_next_usable_block(goal, bitmap_bh,
+					EXT3_BLOCKS_PER_GROUP(sb));
+		if (goal < 0)
+			goto fail_access;
+
+		for (i = 0; i < 7 && goal > 0 &&
+				ext3_test_allocatable(goal - 1, bitmap_bh);
+			i++, goal--);
 	}
 
 	if (!claim_block(sb_bgl_lock(EXT3_SB(sb), group), goal, bitmap_bh)) {
@@ -449,29 +445,25 @@ got:
 		 */
 		goal++;
 		if (goal >= EXT3_BLOCKS_PER_GROUP(sb))
-			goto fail;
+			goto fail_access;
 		goto repeat;
 	}
 
 	BUFFER_TRACE(bitmap_bh, "journal_dirty_metadata for bitmap block");
-	jbd_unlock_bh_state(bitmap_bh);
 	fatal = ext3_journal_dirty_metadata(handle, bitmap_bh);
 	if (fatal) {
 		*errp = fatal;
 		goto fail;
 	}
-
 	return goal;
+
+fail_access:
+	BUFFER_TRACE(bitmap_bh, "journal_release_buffer");
+	ext3_journal_release_buffer(handle, bitmap_bh, credits);
 fail:
-	if (have_access) {
-		BUFFER_TRACE(bitmap_bh, "journal_release_buffer");
-		jbd_unlock_bh_state(bitmap_bh);
-		ext3_journal_release_buffer(handle, bitmap_bh, credits);
-	}
 	return -1;
 }
 
-
 /*
  * ext3_new_block uses a goal block to assist allocation.  If the goal is
  * free, or there is a free block within 32 blocks of the goal, that block

_