]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] ppc64: 32/64bit emulation for aio
authorAndrew Morton <akpm@digeo.com>
Sun, 25 May 2003 08:08:03 +0000 (01:08 -0700)
committerLinus Torvalds <torvalds@home.transmeta.com>
Sun, 25 May 2003 08:08:03 +0000 (01:08 -0700)
From: Anton Blanchard <anton@samba.org>

PPC64 32/64-bit emulation for AIO.

arch/ppc64/kernel/misc.S
arch/ppc64/kernel/sys_ppc32.c

index 19573605448c017fffc900e7cf4f31e244629fa9..720fc3f5a4bba9fe93804c59d72b197823e3621d 100644 (file)
@@ -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
index 63a9bc173b3a4e7e5d452c146e95a20b62bb0fa1..64cc96968e28638d602f17c36735f512e1b18abc 100644 (file)
@@ -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 addr, size_t len,
        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.