[XFS] Disable the combination of XFS direct IO and AIO until the IO completion
handling for unwritten extents can be moved out of interrupt context.

SGI Modid: xfs-linux:xfs-kern:22343a

Signed-off-by: Nathan Scott <nathans@sgi.com>
Signed-off-by: Christoph Hellwig <hch@sgi.com>
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index 9f057a4..d0d412a 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -515,10 +515,49 @@
 }
 #endif /* HAVE_FOP_OPEN_EXEC */
 
+/*
+ * Temporary workaround to the AIO direct IO write problem.
+ * This code can go and we can revert to do_sync_write once
+ * the writepage(s) rework is merged.
+ */
+STATIC ssize_t
+linvfs_write(
+	struct file	*filp,
+	const char	__user *buf,
+	size_t		len,
+	loff_t		*ppos)
+{
+	struct kiocb	kiocb;
+	ssize_t		ret;
+
+	init_sync_kiocb(&kiocb, filp);
+	kiocb.ki_pos = *ppos;
+	ret = __linvfs_write(&kiocb, buf, 0, len, kiocb.ki_pos);
+	*ppos = kiocb.ki_pos;
+	return ret;
+}
+STATIC ssize_t
+linvfs_write_invis(
+	struct file	*filp,
+	const char	__user *buf,
+	size_t		len,
+	loff_t		*ppos)
+{
+	struct kiocb	kiocb;
+	ssize_t		ret;
+
+	init_sync_kiocb(&kiocb, filp);
+	kiocb.ki_pos = *ppos;
+	ret = __linvfs_write(&kiocb, buf, IO_INVIS, len, kiocb.ki_pos);
+	*ppos = kiocb.ki_pos;
+	return ret;
+}
+
+
 struct file_operations linvfs_file_operations = {
 	.llseek		= generic_file_llseek,
 	.read		= do_sync_read,
-	.write		= do_sync_write,
+	.write		= linvfs_write,
 	.readv		= linvfs_readv,
 	.writev		= linvfs_writev,
 	.aio_read	= linvfs_aio_read,
@@ -540,7 +579,7 @@
 struct file_operations linvfs_invis_file_operations = {
 	.llseek		= generic_file_llseek,
 	.read		= do_sync_read,
-	.write		= do_sync_write,
+	.write		= linvfs_write_invis,
 	.readv		= linvfs_readv_invis,
 	.writev		= linvfs_writev_invis,
 	.aio_read	= linvfs_aio_read_invis,
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index ff145fd..aa9daae 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -683,6 +683,9 @@
 			(xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
 				mp->m_rtdev_targp : mp->m_ddev_targp;
 
+		if (ioflags & IO_ISAIO)
+			return XFS_ERROR(-ENOSYS);
+
 		if ((pos & target->pbr_smask) || (count & target->pbr_smask))
 			return XFS_ERROR(-EINVAL);