From: Christoph Hellwig <hch@lst.de>

On Fri, Dec 10, 2004 at 11:04:22AM +1100, Nathan Scott wrote:
> The bug# for the write deadlock I mentioned earlier -- 925836.

I finally found some time to look at it, and this fix is almost trivial.

XFS doesn't need the i_alloc_sem at all, so we should avoid taking it in
direct-io.c completely.  As a side-effect it makes the code a little bit
simpler even.

Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/fs/direct-io.c |   13 +++++++------
 1 files changed, 7 insertions(+), 6 deletions(-)

diff -puN fs/direct-io.c~direct-write-vs-truncate-deadlock fs/direct-io.c
--- 25/fs/direct-io.c~direct-write-vs-truncate-deadlock	2005-01-10 17:29:27.236746304 -0800
+++ 25-akpm/fs/direct-io.c	2005-01-10 17:29:27.240745696 -0800
@@ -215,7 +215,7 @@ static void dio_complete(struct dio *dio
 {
 	if (dio->end_io && dio->result)
 		dio->end_io(dio->inode, offset, bytes, dio->map_bh.b_private);
-	if (dio->lock_type != DIO_NO_LOCKING)
+	if (dio->lock_type == DIO_LOCKING)
 		up_read(&dio->inode->i_alloc_sem);
 }
 
@@ -1201,8 +1201,8 @@ __blockdev_direct_IO(int rw, struct kioc
 	 *	readers need to grab i_sem and i_alloc_sem
 	 *	writers need to grab i_alloc_sem only (i_sem is already held)
 	 * For regular files using DIO_OWN_LOCKING,
-	 *	readers need to grab i_alloc_sem only (i_sem is already held)
-	 *	writers need to grab i_alloc_sem only
+	 *	neither readers nor writers take any locks here
+	 *	(i_sem is already held and release for writers here)
 	 */
 	dio->lock_type = dio_lock_type;
 	if (dio_lock_type != DIO_NO_LOCKING) {
@@ -1219,14 +1219,15 @@ __blockdev_direct_IO(int rw, struct kioc
 				kfree(dio);
 				goto out;
 			}
-			down_read(&inode->i_alloc_sem);
+
 			if (dio_lock_type == DIO_OWN_LOCKING) {
 				up(&inode->i_sem);
 				reader_with_isem = 0;
 			}
-		} else {
-			down_read(&inode->i_alloc_sem);
 		}
+
+		if (dio_lock_type == DIO_LOCKING)
+			down_read(&inode->i_alloc_sem);
 	}
 
 	/*
_