fs/ext3/inode.c           |   12 +++++++-----
 fs/ext3/super.c           |    2 +-
 include/linux/ext3_fs_i.h |    2 +-
 3 files changed, 9 insertions(+), 7 deletions(-)

diff -puN fs/ext3/inode.c~ext3-concurrent-alloc-locking-fix fs/ext3/inode.c
--- 25/fs/ext3/inode.c~ext3-concurrent-alloc-locking-fix	2003-10-03 10:14:53.000000000 -0700
+++ 25-akpm/fs/ext3/inode.c	2003-10-03 10:16:24.000000000 -0700
@@ -812,15 +812,17 @@ out:
 	if (err == -EAGAIN)
 		goto changed;
 
-	if (ext3_find_goal(inode, iblock, chain, partial, &goal) < 0)
+	down(&ei->truncate_sem);
+	if (ext3_find_goal(inode, iblock, chain, partial, &goal) < 0) {
+		up(&ei->truncate_sem);
 		goto changed;
+	}
 
 	left = (chain + depth) - partial;
 
 	/*
 	 * Block out ext3_truncate while we alter the tree
 	 */
-	down_read(&ei->truncate_sem);
 	err = ext3_alloc_branch(handle, inode, left, goal,
 					offsets+(partial-chain), partial);
 
@@ -832,7 +834,7 @@ out:
 	if (!err)
 		err = ext3_splice_branch(handle, inode, iblock, chain,
 					 partial, left);
-	up_read(&ei->truncate_sem);
+	up(&ei->truncate_sem);
 	if (err == -EAGAIN)
 		goto changed;
 	if (err)
@@ -2205,7 +2207,7 @@ void ext3_truncate(struct inode * inode)
 	 * From here we block out all ext3_get_block() callers who want to
 	 * modify the block allocation tree.
 	 */
-	down_write(&ei->truncate_sem);
+	down(&ei->truncate_sem);
 
 	if (n == 1) {		/* direct blocks */
 		ext3_free_data(handle, inode, NULL, i_data+offsets[0],
@@ -2269,7 +2271,7 @@ do_indirects:
 		case EXT3_TIND_BLOCK:
 			;
 	}
-	up_write(&ei->truncate_sem);
+	up(&ei->truncate_sem);
 	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 	ext3_mark_inode_dirty(handle, inode);
 
diff -puN fs/ext3/super.c~ext3-concurrent-alloc-locking-fix fs/ext3/super.c
--- 25/fs/ext3/super.c~ext3-concurrent-alloc-locking-fix	2003-10-03 10:14:53.000000000 -0700
+++ 25-akpm/fs/ext3/super.c	2003-10-03 10:14:53.000000000 -0700
@@ -460,7 +460,7 @@ static void init_once(void * foo, kmem_c
 #ifdef CONFIG_EXT3_FS_XATTR
 		init_rwsem(&ei->xattr_sem);
 #endif
-		init_rwsem(&ei->truncate_sem);
+		init_MUTEX(&ei->truncate_sem);
 		inode_init_once(&ei->vfs_inode);
 	}
 }
diff -puN include/linux/ext3_fs_i.h~ext3-concurrent-alloc-locking-fix include/linux/ext3_fs_i.h
--- 25/include/linux/ext3_fs_i.h~ext3-concurrent-alloc-locking-fix	2003-10-03 10:14:53.000000000 -0700
+++ 25-akpm/include/linux/ext3_fs_i.h	2003-10-03 10:14:53.000000000 -0700
@@ -106,7 +106,7 @@ struct ext3_inode_info {
 	 * during recovery.  Hence we must fix the get_block-vs-truncate race
 	 * by other means, so we have truncate_sem.
 	 */
-	struct rw_semaphore truncate_sem;
+	struct semaphore truncate_sem;
 	struct inode vfs_inode;
 };
 

_