Patch from Anton Blanchard <anton@samba.org>




 arch/ppc64/kernel/misc.S      |   10 ++--
 arch/ppc64/kernel/sys_ppc32.c |   93 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 98 insertions(+), 5 deletions(-)

diff -puN arch/ppc64/kernel/misc.S~ppc64-aio-32bit-emulation arch/ppc64/kernel/misc.S
--- 25/arch/ppc64/kernel/misc.S~ppc64-aio-32bit-emulation	2003-05-22 01:16:06.000000000 -0700
+++ 25-akpm/arch/ppc64/kernel/misc.S	2003-05-22 01:16:06.000000000 -0700
@@ -735,11 +735,11 @@ _GLOBAL(sys_call_table32)
 	.llong .sys_ni_syscall
 	.llong .sys_ni_syscall		/* 225 - reserved for tux */
 	.llong .sys32_sendfile64
-	.llong .sys_ni_syscall		/* reserved for sys_io_setup */
-	.llong .sys_ni_syscall		/* reserved for sys_io_destroy */
-	.llong .sys_ni_syscall		/* reserved for sys_io_getevents */
-	.llong .sys_ni_syscall		/* 230 - reserved for sys_io_submit */
-	.llong .sys_ni_syscall		/* reserved for sys_io_cancel */
+	.llong .sys32_io_setup
+	.llong .sys_io_destroy
+	.llong .sys32_io_getevents
+	.llong .sys32_io_submit
+	.llong .sys_io_cancel
 	.llong .sys_set_tid_address
 	.llong .ppc32_fadvise64
 	.llong .sys_exit_group
diff -puN arch/ppc64/kernel/sys_ppc32.c~ppc64-aio-32bit-emulation arch/ppc64/kernel/sys_ppc32.c
--- 25/arch/ppc64/kernel/sys_ppc32.c~ppc64-aio-32bit-emulation	2003-05-22 01:16:06.000000000 -0700
+++ 25-akpm/arch/ppc64/kernel/sys_ppc32.c	2003-05-22 01:16:06.000000000 -0700
@@ -58,6 +58,7 @@
 #include <linux/security.h>
 #include <linux/compat.h>
 #include <linux/ptrace.h>
+#include <linux/aio_abi.h>
 
 #include <asm/types.h>
 #include <asm/ipc.h>
@@ -2643,6 +2644,98 @@ unsigned long sys32_mmap2(unsigned long 
 	return sys_mmap(addr, len, prot, flags, fd, pgoff << 12);
 }
 
+extern long sys_io_setup(unsigned nr_reqs, aio_context_t *ctx);
+
+long sys32_io_setup(unsigned nr_reqs, u32 *ctx32p)
+{
+	long ret;
+	aio_context_t ctx64;
+	mm_segment_t oldfs = get_fs();
+
+	if (get_user((u32)ctx64, ctx32p))
+		return -EFAULT;
+
+	set_fs(KERNEL_DS);
+	ret = sys_io_setup(nr_reqs, &ctx64);
+	set_fs(oldfs);
+
+	/* truncating is ok because it's a user address */
+	if (!ret)
+		ret = put_user((u32)ctx64, ctx32p);
+
+	return ret;
+}
+
+long sys_io_getevents(aio_context_t ctx_id, long min_nr, long nr,
+		      struct io_event *events, struct timespec *timeout);
+
+long sys32_io_getevents(aio_context_t ctx_id, u32 min_nr, u32 nr,
+			struct io_event *events, struct compat_timespec *t32)
+{
+	struct timespec t;
+	long ret;
+	mm_segment_t oldfs = get_fs();
+
+	if (t32) {
+		if (get_user(t.tv_sec, &t32->tv_sec) ||
+		    __get_user(t.tv_nsec, &t32->tv_nsec))
+			return -EFAULT;
+	}
+
+	if (verify_area(VERIFY_WRITE, events, nr * sizeof(*events)))
+		return -EFAULT;
+
+	set_fs(KERNEL_DS);
+	/* sign extend min_nr and nr */
+	ret = sys_io_getevents(ctx_id, (int)min_nr, (int)nr, events,
+			       t32 ? &t : NULL);
+	set_fs(oldfs);
+
+	return ret;
+}
+
+long sys32_io_submit(aio_context_t ctx_id, u32 number, u32 *iocbpp)
+{
+	struct kioctx *ctx;
+	long ret = 0;
+	int i;
+	int nr = (int)number;	/* sign extend */
+
+	if (unlikely(nr < 0))
+		return -EINVAL;
+
+	if (unlikely(!access_ok(VERIFY_READ, iocbpp, (nr*sizeof(u32)))))
+		return -EFAULT;
+
+	ctx = lookup_ioctx(ctx_id);
+	if (unlikely(!ctx)) {
+		pr_debug("EINVAL: io_submit: invalid context id\n");
+		return -EINVAL;
+	}
+
+	for (i=0; i<nr; i++) {
+		struct iocb tmp;
+		u32 *user_iocb;
+
+		if (unlikely(__get_user(user_iocb, iocbpp + i))) {
+			ret = -EFAULT;
+			break;
+		}
+
+		if (unlikely(copy_from_user(&tmp, user_iocb, sizeof(tmp)))) {
+			ret = -EFAULT;
+			break;
+		}
+
+		ret = io_submit_one(ctx, user_iocb, &tmp);
+		if (ret)
+			break;
+	}
+
+	put_ioctx(ctx);
+	return i ? i : ret;
+}
+
 /* 
  * long long munging:
  * The 32 bit ABI passes long longs in an odd even register pair.

_