<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">

Signed-off-by: Andrew Morton &lt;akpm@osdl.org&gt;
---

 25-akpm/fs/ext3/inode.c |   34 ++++++++++++++++++++++------------
 1 files changed, 22 insertions(+), 12 deletions(-)

diff -puN fs/ext3/inode.c~ext3-remove-unnecessary-race-then-retry-in-ext3_get_block-leak-fix fs/ext3/inode.c
--- 25/fs/ext3/inode.c~ext3-remove-unnecessary-race-then-retry-in-ext3_get_block-leak-fix	2005-04-07 04:27:06.000000000 -0700
+++ 25-akpm/fs/ext3/inode.c	2005-04-07 04:27:47.000000000 -0700
@@ -699,8 +699,9 @@ ext3_get_block_handle(handle_t *handle, 
 		goto cleanup;
 
 	down(&amp;ei-&gt;truncate_sem);
+
 	/*
-	 * if the indirect block is missing while we are reading
+	 * If the indirect block is missing while we are reading
 	 * the chain(ext3_get_branch() returns -EAGAIN err), or
 	 * if the chain has been changed after we grab the semaphore,
 	 * (either because another process truncated this branch, or
@@ -711,7 +712,11 @@ ext3_get_block_handle(handle_t *handle, 
 	 * at this point, we will have the current copy of the chain when we
 	 * splice the branch into the tree.
 	 */
-	if ((err = -EAGAIN) || !verify_chain(chain, partial)) {
+	if (err == -EAGAIN || !verify_chain(chain, partial)) {
+		while (partial &gt; chain) {
+			brelse(partial-&gt;bh);
+			partial--;
+		}
 		partial = ext3_get_branch(inode, depth, offsets, chain, &amp;err);
 		if (!partial) {
 			up(&amp;ei-&gt;truncate_sem);
@@ -722,11 +727,12 @@ ext3_get_block_handle(handle_t *handle, 
 		}
 	}
 
-	/* Okey, we need to do block allocation */
-	/* lazy initialize the block allocation info here if necessary */
-	if (S_ISREG(inode-&gt;i_mode) &amp;&amp; (!ei-&gt;i_block_alloc_info)) {
+	/*
+	 * Okay, we need to do block allocation.  Lazily initialize the block
+	 * allocation info here if necessary
+	*/
+	if (S_ISREG(inode-&gt;i_mode) &amp;&amp; (!ei-&gt;i_block_alloc_info))
 		ext3_init_block_alloc_info(inode);
-	}
 
 	goal = ext3_find_goal(inode, iblock, chain, partial);
 
@@ -736,19 +742,23 @@ ext3_get_block_handle(handle_t *handle, 
 	 * Block out ext3_truncate while we alter the tree
 	 */
 	err = ext3_alloc_branch(handle, inode, left, goal,
-					offsets+(partial-chain), partial);
+				offsets + (partial - chain), partial);
 
-	/* The ext3_splice_branch call will free and forget any buffers
+	/*
+	 * The ext3_splice_branch call will free and forget any buffers
 	 * on the new chain if there is a failure, but that risks using
 	 * up transaction credits, especially for bitmaps where the
 	 * credits cannot be returned.  Can we handle this somehow?  We
-	 * may need to return -EAGAIN upwards in the worst case.  --sct */
+	 * may need to return -EAGAIN upwards in the worst case.  --sct
+	 */
 	if (!err)
 		err = ext3_splice_branch(handle, inode, iblock, chain,
 					 partial, left);
-	/* i_disksize growing is protected by truncate_sem
-	 * don't forget to protect it if you're about to implement
-	 * concurrent ext3_get_block() -bzzz */
+	/*
+	 * i_disksize growing is protected by truncate_sem.  Don't forget to
+	 * protect it if you're about to implement concurrent
+	 * ext3_get_block() -bzzz
+	*/
 	if (!err &amp;&amp; extend_disksize &amp;&amp; inode-&gt;i_size &gt; ei-&gt;i_disksize)
 		ei-&gt;i_disksize = inode-&gt;i_size;
 	up(&amp;ei-&gt;truncate_sem);
_
</pre></body></html>