diff options
author | Lachlan McIlroy <lachlan@sgi.com> | 2006-09-07 00:27:05 -0400 |
---|---|---|
committer | David Chatterton <chatz@sgi.com> | 2006-09-07 00:27:05 -0400 |
commit | 721259bce2851893155c6cb88a3f8ecb106b348c (patch) | |
tree | 0db37f80a7ef0b701b313e9ba28f8c0d3950e533 /fs/xfs/linux-2.6/xfs_aops.c | |
parent | 4be536debe3f7b0c62283e77fd6bd8bdb9f83c6f (diff) |
[XFS] Fix ABBA deadlock between i_mutex and iolock. Avoid calling
__blockdev_direct_IO for the DIO_OWN_LOCKING case for direct I/O reads
since it drops and reacquires the i_mutex while holding the iolock and
this violates the locking order.
SGI-PV: 955696
SGI-Modid: xfs-linux-melb:xfs-kern:26898a
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
Signed-off-by: David Chatterton <chatz@sgi.com>
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_aops.c')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_aops.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index c40f81ba9b13..34dcb43a7837 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
@@ -1390,11 +1390,19 @@ xfs_vm_direct_IO( | |||
1390 | 1390 | ||
1391 | iocb->private = xfs_alloc_ioend(inode, IOMAP_UNWRITTEN); | 1391 | iocb->private = xfs_alloc_ioend(inode, IOMAP_UNWRITTEN); |
1392 | 1392 | ||
1393 | ret = blockdev_direct_IO_own_locking(rw, iocb, inode, | 1393 | if (rw == WRITE) { |
1394 | iomap.iomap_target->bt_bdev, | 1394 | ret = blockdev_direct_IO_own_locking(rw, iocb, inode, |
1395 | iov, offset, nr_segs, | 1395 | iomap.iomap_target->bt_bdev, |
1396 | xfs_get_blocks_direct, | 1396 | iov, offset, nr_segs, |
1397 | xfs_end_io_direct); | 1397 | xfs_get_blocks_direct, |
1398 | xfs_end_io_direct); | ||
1399 | } else { | ||
1400 | ret = blockdev_direct_IO_no_locking(rw, iocb, inode, | ||
1401 | iomap.iomap_target->bt_bdev, | ||
1402 | iov, offset, nr_segs, | ||
1403 | xfs_get_blocks_direct, | ||
1404 | xfs_end_io_direct); | ||
1405 | } | ||
1398 | 1406 | ||
1399 | if (unlikely(ret <= 0 && iocb->private)) | 1407 | if (unlikely(ret <= 0 && iocb->private)) |
1400 | xfs_destroy_ioend(iocb->private); | 1408 | xfs_destroy_ioend(iocb->private); |