.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
#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>
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.