Patch from Anton Blanchard <anton@samba.org>




 arch/ppc64/kernel/misc.S      |   10 ++--
 arch/ppc64/kernel/sys_ppc32.c |   93 ++++++++++++++++++++++++++++++++++++++++++
 fs/aio.c                      |    6 +-
 3 files changed, 101 insertions(+), 8 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-03-15 18:42:26.000000000 -0800
+++ 25-akpm/arch/ppc64/kernel/misc.S	2003-03-15 18:42:26.000000000 -0800
@@ -729,11 +729,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-03-15 18:42:26.000000000 -0800
+++ 25-akpm/arch/ppc64/kernel/sys_ppc32.c	2003-03-15 18:42:26.000000000 -0800
@@ -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>
@@ -2975,6 +2976,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.
diff -puN fs/aio.c~ppc64-aio-32bit-emulation fs/aio.c
--- 25/fs/aio.c~ppc64-aio-32bit-emulation	2003-03-15 18:42:26.000000000 -0800
+++ 25-akpm/fs/aio.c	2003-03-15 18:42:26.000000000 -0800
@@ -522,7 +522,7 @@ int aio_put_req(struct kiocb *req)
 /*	Lookup an ioctx id.  ioctx_list is lockless for reads.
  *	FIXME: this is O(n) and is only suitable for development.
  */
-static struct kioctx *lookup_ioctx(unsigned long ctx_id)
+struct kioctx *lookup_ioctx(unsigned long ctx_id)
 {
 	struct kioctx *ioctx;
 	struct mm_struct *mm;
@@ -984,9 +984,9 @@ asmlinkage long sys_io_destroy(aio_conte
 	return -EINVAL;
 }
 
-static int FASTCALL(io_submit_one(struct kioctx *ctx, struct iocb *user_iocb,
+int FASTCALL(io_submit_one(struct kioctx *ctx, struct iocb *user_iocb,
 				  struct iocb *iocb));
-static int io_submit_one(struct kioctx *ctx, struct iocb *user_iocb,
+int io_submit_one(struct kioctx *ctx, struct iocb *user_iocb,
 			 struct iocb *iocb)
 {
 	struct kiocb *req;

_