Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 721259bc authored by Lachlan McIlroy's avatar Lachlan McIlroy Committed by David Chatterton
Browse files

[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: default avatarLachlan McIlroy <lachlan@sgi.com>
Signed-off-by: default avatarDavid Chatterton <chatz@sgi.com>
parent 4be536de
Loading
Loading
Loading
Loading
+13 −5
Original line number Original line Diff line number Diff line
@@ -1390,11 +1390,19 @@ xfs_vm_direct_IO(


	iocb->private = xfs_alloc_ioend(inode, IOMAP_UNWRITTEN);
	iocb->private = xfs_alloc_ioend(inode, IOMAP_UNWRITTEN);


	if (rw == WRITE) {
		ret = blockdev_direct_IO_own_locking(rw, iocb, inode,
		ret = blockdev_direct_IO_own_locking(rw, iocb, inode,
			iomap.iomap_target->bt_bdev,
			iomap.iomap_target->bt_bdev,
			iov, offset, nr_segs,
			iov, offset, nr_segs,
			xfs_get_blocks_direct,
			xfs_get_blocks_direct,
			xfs_end_io_direct);
			xfs_end_io_direct);
	} else {
		ret = blockdev_direct_IO_no_locking(rw, iocb, inode,
			iomap.iomap_target->bt_bdev,
			iov, offset, nr_segs,
			xfs_get_blocks_direct,
			xfs_end_io_direct);
	}


	if (unlikely(ret <= 0 && iocb->private))
	if (unlikely(ret <= 0 && iocb->private))
		xfs_destroy_ioend(iocb->private);
		xfs_destroy_ioend(iocb->private);
+6 −5
Original line number Original line Diff line number Diff line
@@ -264,7 +264,9 @@ xfs_read(
					dmflags, &locktype);
					dmflags, &locktype);
		if (ret) {
		if (ret) {
			xfs_iunlock(ip, XFS_IOLOCK_SHARED);
			xfs_iunlock(ip, XFS_IOLOCK_SHARED);
			goto unlock_mutex;
			if (unlikely(ioflags & IO_ISDIRECT))
				mutex_unlock(&inode->i_mutex);
			return ret;
		}
		}
	}
	}


@@ -272,6 +274,9 @@ xfs_read(
		bhv_vop_flushinval_pages(vp, ctooff(offtoct(*offset)),
		bhv_vop_flushinval_pages(vp, ctooff(offtoct(*offset)),
						-1, FI_REMAPF_LOCKED);
						-1, FI_REMAPF_LOCKED);


	if (unlikely(ioflags & IO_ISDIRECT))
		mutex_unlock(&inode->i_mutex);

	xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore,
	xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore,
				(void *)iovp, segs, *offset, ioflags);
				(void *)iovp, segs, *offset, ioflags);
	ret = __generic_file_aio_read(iocb, iovp, segs, offset);
	ret = __generic_file_aio_read(iocb, iovp, segs, offset);
@@ -281,10 +286,6 @@ xfs_read(
		XFS_STATS_ADD(xs_read_bytes, ret);
		XFS_STATS_ADD(xs_read_bytes, ret);


	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
	xfs_iunlock(ip, XFS_IOLOCK_SHARED);

unlock_mutex:
	if (unlikely(ioflags & IO_ISDIRECT))
		mutex_unlock(&inode->i_mutex);
	return ret;
	return ret;
}
}