summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authornetchild <netchild@FreeBSD.org>2006-10-29 14:02:39 +0000
committernetchild <netchild@FreeBSD.org>2006-10-29 14:02:39 +0000
commitb17bbadb52577e26b22d4f282e28dbb0a023669e (patch)
tree777e44600da3571fa21e0cdf85c6aac0b4edbbb9 /sys
parente7bc018a5c33edc8676a9d4799d7f380ebee5c0b (diff)
downloadFreeBSD-src-b17bbadb52577e26b22d4f282e28dbb0a023669e.zip
FreeBSD-src-b17bbadb52577e26b22d4f282e28dbb0a023669e.tar.gz
Backout the linux aio stuff. Several problems where identified and the
dynamic nature (if no native aio code is available, the linux part returns ENOSYS because of missing requisites) should be solved differently than it is. All this will be done in P4. Not included in this commit is a backout of the changes to the native aio code (removing static in some places). Those changes (and some more) will also be needed when the reworked linux aio stuff will reenter the tree. Requested by: rwatson Discussed with: rwatson
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/linux32/linux.h2
-rw-r--r--sys/amd64/linux32/syscalls.master10
-rw-r--r--sys/compat/linux/linux_aio.c1349
-rw-r--r--sys/compat/linux/linux_aio.h98
-rw-r--r--sys/conf/files.amd641
-rw-r--r--sys/conf/files.i3861
-rw-r--r--sys/conf/files.pc981
-rw-r--r--sys/i386/linux/linux.h2
-rw-r--r--sys/i386/linux/syscalls.master10
-rw-r--r--sys/modules/linux/Makefile2
10 files changed, 11 insertions, 1465 deletions
diff --git a/sys/amd64/linux32/linux.h b/sys/amd64/linux32/linux.h
index cf4f471..9c8ed5c 100644
--- a/sys/amd64/linux32/linux.h
+++ b/sys/amd64/linux32/linux.h
@@ -840,6 +840,4 @@ typedef int l_mqd_t;
#define THREADING_FLAGS (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND)
-#include <compat/linux/linux_aio.h>
-
#endif /* !_AMD64_LINUX_LINUX_H_ */
diff --git a/sys/amd64/linux32/syscalls.master b/sys/amd64/linux32/syscalls.master
index 10e9999..c7b84d5 100644
--- a/sys/amd64/linux32/syscalls.master
+++ b/sys/amd64/linux32/syscalls.master
@@ -407,11 +407,11 @@
242 AUE_NULL UNIMPL linux_sched_getaffinity
243 AUE_NULL UNIMPL linux_set_thread_area
244 AUE_NULL UNIMPL linux_get_thread_area
-245 AUE_NULL STD { int linux_io_setup(l_uint nr_reqs, linux_aio_context_t *ctxp); }
-246 AUE_NULL STD { int linux_io_destroy(linux_aio_context_t ctx); }
-247 AUE_NULL STD { int linux_io_getevents(linux_aio_context_t ctx_id, l_long min_nr, l_long nr, struct linux_io_event *events, struct l_timespec *timeout); }
-248 AUE_NULL STD { int linux_io_submit(linux_aio_context_t ctx_id, l_long nr, struct linux_iocb **iocbpp); }
-249 AUE_NULL STD { int linux_io_cancel(linux_aio_context_t ctx_id, struct linux_iocb *iocb, struct linux_io_event *result); }
+245 AUE_NULL UNIMPL linux_io_setup
+246 AUE_NULL UNIMPL linux_io_destroy
+247 AUE_NULL UNIMPL linux_io_getevents
+248 AUE_NULL UNIMPL inux_io_submit
+249 AUE_NULL UNIMPL linux_io_cancel
250 AUE_NULL STD { int linux_fadvise64(void); }
251 AUE_NULL UNIMPL
252 AUE_EXIT STD { int linux_exit_group(int error_code); }
diff --git a/sys/compat/linux/linux_aio.c b/sys/compat/linux/linux_aio.c
deleted file mode 100644
index b6c6674..0000000
--- a/sys/compat/linux/linux_aio.c
+++ /dev/null
@@ -1,1349 +0,0 @@
-/*-
- * Copyright (c) 2006 Li, Xiao <intron@intron.ac>. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "opt_compat.h"
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/sysent.h>
-#include <sys/proc.h>
-#include <sys/errno.h>
-#include <sys/eventhandler.h>
-#include <sys/aio.h>
-#include <sys/mman.h>
-#include <sys/time.h>
-#include <sys/queue.h>
-#include <vm/uma.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/sx.h>
-#include <sys/linker.h>
-#include <sys/sysctl.h>
-#include <sys/syscall.h>
-#include <sys/sysproto.h>
-
-#ifdef COMPAT_LINUX32
-#include <machine/../linux32/linux.h>
-#include <machine/../linux32/linux32_proto.h>
-#else
-#include <machine/../linux/linux.h>
-#include <machine/../linux/linux_proto.h>
-#endif
-
-#define LINUX_AIO_DEBUG
-
-/*
- * Linux Kernel Implementation of Asynchronous I/O
- */
-
-#ifdef LINUX_AIO_DEBUG
-
-/* Print arguments of syscall */
-#define DARGPRINTF(fmt, ...) printf("linux(%ld): %s("fmt")\n", \
- (long)td->td_proc->p_pid, __func__, __VA_ARGS__)
-/* Print message in syscall function */
-#define DPRINTF(fmt, ...) printf(LMSG("%s(): " fmt), \
- __func__, __VA_ARGS__)
-/* Print message in non-syscall function, the one more "P" means "private" */
-#define DPPRINTF(fmt, ...) printf("linux(): %s(): " fmt "\n", \
- __func__, __VA_ARGS__)
-
-#else
-
-#define DARGPRINTF(fmt, ...)
-#define DPRINTF(fmt, ...)
-#define DPPRINTF(fmt, ...)
-
-#endif
-
-/*
- * DATA STRUCTURE HIERARCHY
- *
- * +--------------------+ +--------------------+
- * context_list ---> | context | ---> | context | ---> ...
- * SLIST |(owned by a process)| |(owned by a process)|
- * | | | |
- * | ctx_req | | ctx_req |
- * +----|---------------+ +----|---------------+
- * | STAILQ | STAILQ
- * v v
- * +------------+ +------------+
- * | request | | request |
- * | | | |
- * |.req_pbsd | |.req_pbsd |
- * |.req_porig | |.req_porig |
- * |.req_linux | |.req_linux |
- * | | | |
- * +------------+ +------------+
- * | |
- * v v
- * +------------+ +------------+
- * | request | | request |
- * | | | |
- * |.req_pbsd | |.req_pbsd |
- * |.req_porig | |.req_porig |
- * |.req_linux | |.req_linux |
- * | | | |
- * +------------+ +------------+
- * | |
- * v v
- * ... ...
- */
-
-struct linux_aio_context;
-
-struct linux_aio_request {
- struct aiocb *req_pbsd; /* Userland clone for FreeBSD */
- struct linux_iocb *req_porig; /* Userland original control block */
- struct linux_iocb req_linux; /* Copy of original control block */
- STAILQ_ENTRY(linux_aio_request) req_ctx_entry;
-};
-
-struct linux_aio_context {
- struct sx ctx_sx;
- pid_t ctx_pid;
- struct linux_aio_ring *ctx_pring;
- int ctx_nreq_max; /* Maximum request number */
- int ctx_nreq_cur; /* Current request number */
- STAILQ_HEAD(,linux_aio_request) ctx_req;
- SLIST_ENTRY(linux_aio_context) ctx_list_entry;
-};
-static SLIST_HEAD(,linux_aio_context) linux_aio_context_list;
-
-#define LINUX_AIO_REQ_HOOK(pctx, preq) { \
- STAILQ_INSERT_TAIL(&((pctx)->ctx_req), (preq), req_ctx_entry); \
- (pctx)->ctx_nreq_cur ++; \
-}
-
-#define LINUX_AIO_REQ_UNHOOK(pctx, preq) { \
- STAILQ_REMOVE(&((pctx)->ctx_req), (preq), linux_aio_request, \
- req_ctx_entry); \
- (pctx)->ctx_nreq_cur --; \
-}
-
-#define LINUX_AIO_REQ_FOREACH(pctx, preq) \
- STAILQ_FOREACH((preq), &((pctx)->ctx_req), req_ctx_entry)
-
-#define LINUX_AIO_REQ_FOREACH_SAFE(pctx, preq, ptmpreq) \
- STAILQ_FOREACH_SAFE((preq), &((pctx)->ctx_req), req_ctx_entry, \
- (ptmpreq))
-
-#define LINUX_AIO_CTX_LOCK(pctx) sx_xlock(&((pctx)->ctx_sx))
-
-#define LINUX_AIO_CTX_UNLOCK(pctx) sx_unlock(&((pctx)->ctx_sx))
-
-#define LINUX_AIO_CTX_HOOK(pctx) \
- SLIST_INSERT_HEAD(&linux_aio_context_list, (pctx), ctx_list_entry)
-
-#define LINUX_AIO_CTX_UNHOOK(pctx) \
- SLIST_REMOVE(&linux_aio_context_list, (pctx), \
- linux_aio_context, ctx_list_entry)
-
-#define LINUX_AIO_CTX_FOREACH(pctx) \
- SLIST_FOREACH((pctx), &linux_aio_context_list, ctx_list_entry)
-
-#define LINUX_AIO_CTX_FOREACH_SAFE(pctx, ptmpctx) \
- SLIST_FOREACH_SAFE((pctx), &linux_aio_context_list, \
- ctx_list_entry, (ptmpctx))
-
-#define LINUX_AIO_CTX_MATCH(pctx, ctxid, pid) \
- ((linux_aio_context_t)(pctx)->ctx_pring == (ctxid) \
- && (pctx)->ctx_pid == (pid))
-
-static struct mtx linux_aio_context_list_mtx;
-
-#define LINUX_AIO_CTX_LIST_LOCK() mtx_lock(&linux_aio_context_list_mtx)
-
-#define LINUX_AIO_CTX_LIST_UNLOCK() mtx_unlock(&linux_aio_context_list_mtx)
-
-/*
- * The following two macros are substantially identical to the two macros
- * AIO_(UN)LOCK in /sys/kern/vfs_aio.c. Thus, the mutex much be unlocked
- * before calling functions of FreeBSD native AIO module.
- *
- * XXX
- * I ASSUME the member "kaio_mtx" is the first element of "struct kaioinfo".
- */
-#define LINUX_AIO_LOCK(p) { \
- if ((p)->p_aioinfo == NULL) \
- p_aio_init_aioinfo(p); \
- mtx_lock((struct mtx *)((p)->p_aioinfo)); \
-}
-
-#define LINUX_AIO_UNLOCK(p) { \
- if ((p)->p_aioinfo == NULL) \
- p_aio_init_aioinfo(p); \
- mtx_unlock((struct mtx *)((p)->p_aioinfo)); \
-}
-
-static uma_zone_t linux_aio_context_zone, linux_aio_request_zone;
-
-static eventhandler_tag linux_aio_exit_tag;
-
-/*
- * XXX
- * Calling external function/variable declared with "static" is DANGEROUS !!!
- * Compiler may use register to transfer calling arguments for optimization,
- * which is NOT a normal calling way and can cause kernel crash.
- */
-
-#define NATIVE_AIO_MODULE_NAME "aio"
-static struct mod_depend native_aio_module_depend = {1, 1, 1};
-static linker_file_t native_aio_module_handle = NULL;
-
-/* Mirror of sysctls in /sys/kern/vfs_aio.c */
-#define NATIVE_AIO_SYSCTL_CAPACITY_PROC "vfs.aio.max_aio_queue_per_proc"
-static int native_aio_capacity_proc;
-#define NATIVE_AIO_SYSCTL_CAPACITY_SYS "vfs.aio.max_aio_queue"
-static int native_aio_capacity_sys;
-
-/* For declaration of aio_aqueue(), defined in /sys/kern/vfs_aio.c */
-struct aioliojob;
-
-/* Functions in /sys/kern/vfs_aio.c, XXX defined with "static" */
-#define GET_INTERNAL_FUNC_POINTER(s) { \
- * ((caddr_t *) & p_ ## s) = linker_file_lookup_symbol( \
- native_aio_module_handle, #s, FALSE); \
- if (p_ ## s == NULL) \
- break; \
-}
-static void (*p_aio_init_aioinfo) (struct proc *p);
-static int (*p_aio_aqueue) (struct thread *td, struct aiocb *job,
- struct aioliojob *lio, int type, int osigev);
-
-/* System calls in /sys/kern/vfs_aio.c */
-#define DEFINE_SYSCALL_POINTER_VARIABLE(s) \
- static int (* p_ ## s) (struct thread *, struct s ## _args *)
-#define GET_SYSCALL_POINTER(s) { \
- * ((sy_call_t **) & p_ ## s) = sysent[SYS_ ## s].sy_call; \
- if ((sy_call_t *) p_ ## s == (sy_call_t *)lkmressys) \
- break; \
-}
-DEFINE_SYSCALL_POINTER_VARIABLE(aio_return);
-DEFINE_SYSCALL_POINTER_VARIABLE(aio_suspend);
-DEFINE_SYSCALL_POINTER_VARIABLE(aio_cancel);
-DEFINE_SYSCALL_POINTER_VARIABLE(aio_error);
-
-static int user_mem_rw_verify(void *p, size_t s)
-{
- char buf[256];
- size_t i;
- int nerr = 0;
-
- for (i = 0; i < s; i += sizeof(buf)) {
- /* Verify reading */
- nerr = copyin((char *)p+i, buf, MIN(sizeof(buf), s-i));
- if (nerr != 0)
- break;
-
- /* Verify writing */
- nerr = copyout(buf, (char *)p+i, MIN(sizeof(buf), s-i));
- if (nerr != 0)
- break;
- }
-
- return (nerr);
-}
-
-/* Allocate memory in user space */
-static int user_malloc(struct thread *td, void **pp, size_t s)
-{
- struct mmap_args mmaparg;
- int nerr;
- register_t r;
-
- r = td->td_retval[0];
-
- mmaparg.addr = NULL;
- mmaparg.len = s;
- mmaparg.prot = PROT_READ | PROT_WRITE;
- mmaparg.flags = MAP_PRIVATE | MAP_ANON;
- mmaparg.fd = -1;
- mmaparg.pad = 0;
- mmaparg.pos = 0;
-
- nerr = mmap(td, &mmaparg);
-
- if (nerr == 0) {
- *pp = (void *)td->td_retval[0];
- DPPRINTF("%lu bytes allocated at %p", (unsigned long)s, *pp);
- }
-
- td->td_retval[0] = r;
-
- return (nerr);
-}
-
-/* Free memory in user space */
-static int user_free(struct thread *td, void *p, size_t s)
-{
- struct munmap_args munmaparg;
- int nerr;
- register_t r;
-
- r = td->td_retval[0];
-
- munmaparg.addr = p;
- munmaparg.len = s;
-
- nerr = munmap(td, &munmaparg);
-
- td->td_retval[0] = r;
- DPPRINTF("%lu bytes at %p", (unsigned long)s, p);
-
- return (nerr);
-}
-
-#ifdef LINUX_AIO_DEBUG
-
-static void linux_aio_dump_freebsd_aiocb(struct aiocb *piocb, int isuserland)
-{
- struct aiocb localcb, *pcb;
- int nerr = 0;
-
- if (isuserland) {
- nerr = copyin(piocb, &localcb, sizeof(localcb));
- pcb = &localcb;
- } else
- pcb = piocb;
-
- DPPRINTF("Dump struct aiocb (%p, %s): %s",
- piocb, (isuserland?"userland":"kernel"),
- (nerr?"Failure":""));
- if (!nerr) {
- DPPRINTF("aio_fildes: %d",
- pcb->aio_fildes);
- DPPRINTF("aio_offset: %lu",
- (unsigned long) pcb->aio_offset);
- DPPRINTF("aio_buf: %p",
- pcb->aio_buf);
- DPPRINTF("aio_nbytes: %lu",
- (unsigned long) pcb->aio_nbytes);
- DPPRINTF("aio_lio_opcode: %d",
- pcb->aio_lio_opcode);
- DPPRINTF("aio_reqprio: %d",
- pcb->aio_reqprio);
- DPPRINTF("aio_sigevent.sigev_notify: %d",
- pcb->aio_sigevent.sigev_notify);
- DPPRINTF("aio_sigevent.sigev_signo: %d",
- pcb->aio_sigevent.sigev_signo);
- }
-}
-
-#define DUMP_FREEBSD_AIOCB(p, isu) linux_aio_dump_freebsd_aiocb((p), (isu));
-
-#define DUMP_TIMESPEC(f, t ,a) \
- DPRINTF("%s%ld second + %ld nanosecond%s", \
- (f), (long)(t)->tv_sec, (long)(t)->tv_nsec, (a));
-
-#else /* ! LINUX_AIO_DEBUG */
-
-#define DUMP_FREEBSD_AIOCB(p, isu)
-#define DUMP_TIMESPEC(f, t, a)
-
-#endif /* LINUX_AIO_DEBUG */
-
-static int iocb_reformat(struct linux_iocb *plnx, struct aiocb *pbsd)
-{
- int nerr = 0;
-
- bzero(pbsd, sizeof(*pbsd));
-
- pbsd->aio_fildes = plnx->aio_fildes; /* File descriptor */
- pbsd->aio_offset = plnx->aio_offset; /* File offset for I/O */
- pbsd->aio_buf = (void *)(unsigned long) plnx->aio_buf; /*
- * User space
- * I/O buffer
- */
- pbsd->aio_nbytes = plnx->aio_nbytes; /* Number of bytes for I/O */
- switch (plnx->aio_lio_opcode) { /* LIO opcode */
- case LINUX_IOCB_CMD_PREAD:
- pbsd->aio_lio_opcode = LIO_READ;
- break;
- case LINUX_IOCB_CMD_PWRITE:
- pbsd->aio_lio_opcode = LIO_WRITE;
- break;
- case LINUX_IOCB_CMD_FSYNC:
- case LINUX_IOCB_CMD_FDSYNC:
- pbsd->aio_lio_opcode = LIO_SYNC;
- break;
-#if 0
- case LINUX_IOCB_CMD_PREADX:
- break;
- case LINUX_IOCB_CMD_POLL:
- break;
-#endif
- case LINUX_IOCB_CMD_NOOP:
- pbsd->aio_lio_opcode = LIO_NOP;
- break;
- default:
- nerr = EINVAL;
- break;
- }
- if (nerr != 0) {
- DPPRINTF("Unsupported aio_lio_opcode: %u",
- (unsigned)plnx->aio_lio_opcode);
- return (nerr);
- }
- pbsd->aio_reqprio = plnx->aio_reqprio; /* Request priority */
- pbsd->aio_sigevent.sigev_notify = SIGEV_NONE; /* No signal to deliver */
- pbsd->aio_sigevent.sigev_signo = 0; /* No signal to deliver */
-
- return (nerr);
-}
-
-static int link_to_native_aio_module(struct thread *td)
-{
- int nerr;
-
- if (native_aio_module_handle != NULL) {
- /* Linking has been done successfully. */
- return (0);
- }
-
- nerr = linker_reference_module(NATIVE_AIO_MODULE_NAME,
- &native_aio_module_depend, &native_aio_module_handle);
- if (nerr)
- return (nerr);
-
- do {
- nerr = EINVAL;
-
- /* Kernel internal functions */
- GET_INTERNAL_FUNC_POINTER(aio_init_aioinfo);
- GET_INTERNAL_FUNC_POINTER(aio_aqueue);
-
- /* System calls */
- GET_SYSCALL_POINTER(aio_return);
- GET_SYSCALL_POINTER(aio_suspend);
- GET_SYSCALL_POINTER(aio_cancel);
- GET_SYSCALL_POINTER(aio_error);
-
- nerr = 0;
- } while (0);
-
- if (nerr) {
- linker_release_module(NULL, NULL, native_aio_module_handle);
- native_aio_module_handle = NULL;
-
- printf(LMSG("Unable to link to the native module \""
- NATIVE_AIO_MODULE_NAME "\"."));
-
- return (nerr);
- }
-
- return (0);
-}
-
-#define LINK_TO_NATIVE_AIO_MODULE() \
- if (link_to_native_aio_module(td)) { \
- printf(LMSG("Please load the module \"" \
- NATIVE_AIO_MODULE_NAME "\"" \
- "to provide FreeBSD " \
- "native Asynchronous I/O support.")); \
- return (ENOSYS); \
-}
-
-static int mirror_native_aio_sysctl(struct thread *td)
-{
- int nerr = 0;
- size_t l;
-
- l = sizeof(native_aio_capacity_proc);
- nerr = kernel_sysctlbyname(td, NATIVE_AIO_SYSCTL_CAPACITY_PROC,
- &native_aio_capacity_proc, &l, NULL, 0,
- NULL ,0);
- if (nerr)
- return (nerr);
-
- l = sizeof(native_aio_capacity_sys);
- nerr = kernel_sysctlbyname(td, NATIVE_AIO_SYSCTL_CAPACITY_SYS,
- &native_aio_capacity_sys, &l, NULL, 0,
- NULL ,0);
- if (nerr)
- return (nerr);
-
- DPRINTF(NATIVE_AIO_SYSCTL_CAPACITY_PROC "=%d, "
- NATIVE_AIO_SYSCTL_CAPACITY_SYS "=%d",
- native_aio_capacity_proc,
- native_aio_capacity_sys);
-
- return (nerr);
-}
-
-/* Linux system call io_setup(2) */
-int linux_io_setup(struct thread *td, struct linux_io_setup_args *args)
-{
- struct proc *p;
- struct linux_aio_ring *pring, ring;
- struct linux_aio_context *pctx = NULL, *ptmpctx;
- linux_aio_context_t ctx_id;
- int nerr = 0, nr, nrall, nq, arg_nr_reqs;
-
- DARGPRINTF("%u, %p", args->nr_reqs, args->ctxp);
- LINK_TO_NATIVE_AIO_MODULE();
- nerr = mirror_native_aio_sysctl(td);
- if (nerr) {
- printf(LMSG("linux_io_setup(): Unable to query sysctls "
- NATIVE_AIO_SYSCTL_CAPACITY_PROC
- " and/or " NATIVE_AIO_SYSCTL_CAPACITY_SYS
- " ."));
- return (nerr);
- }
-
- /* Signed integer is a little safer than unsigned */
- arg_nr_reqs = args->nr_reqs;
- if (arg_nr_reqs <= 0)
- return (EINVAL);
-
- if (arg_nr_reqs > native_aio_capacity_proc
- || arg_nr_reqs > native_aio_capacity_sys) {
- printf(LMSG("linux_io_setup(): Please increase sysctls "
- NATIVE_AIO_SYSCTL_CAPACITY_PROC
- " and/or " NATIVE_AIO_SYSCTL_CAPACITY_SYS
- " ."));
- return (ENOMEM);
- }
-
- nerr = user_mem_rw_verify(args->ctxp, sizeof(*(args->ctxp)));
- if (nerr != 0)
- return (nerr);
-
- copyin(args->ctxp, &ctx_id, sizeof(ctx_id));
- if (ctx_id != 0) /* "Not initialized", described by io_setup(2) */
- return (EINVAL);
-
- p = td->td_proc;
-
- /* Get a new "ring" */
- nerr = user_malloc(td, (void **)&pring, sizeof(*pring));
- if (nerr != 0)
- return (nerr);
-
- /* Get a new context */
- pctx = uma_zalloc(linux_aio_context_zone, M_WAITOK);
-
- LINUX_AIO_CTX_LIST_LOCK();
-
- /* Count request capacity of all contexts belonging to this process */
- nr = 0;
- nrall = 0;
- nq = 0;
- LINUX_AIO_CTX_FOREACH(ptmpctx) {
- if (ptmpctx->ctx_pid == p->p_pid) {
- nr += ptmpctx->ctx_nreq_max;
- nq ++;
- }
- nrall += ptmpctx->ctx_nreq_max;
- }
- DPRINTF("%d queues of %d requests totally allocated for this process, "
- "%d requests' total capacity for the whole system",
- nq, nr, nrall);
-
- /* Check whether there are enough resources for requested queue */
- if (arg_nr_reqs > native_aio_capacity_proc - nr
- || arg_nr_reqs > native_aio_capacity_sys - nrall) {
- printf(LMSG("linux_io_setup(): "
- "Please increase sysctls "
- NATIVE_AIO_SYSCTL_CAPACITY_PROC
- " and/or " NATIVE_AIO_SYSCTL_CAPACITY_SYS " ."
- "Besides %d queues of %d requests totally "
- "for this process, and %d requests' queues "
- "totally for the whole system, "
- "this Linux application needs one more "
- "AIO queue of %d requests' capacity."),
- nq, nr, nrall, arg_nr_reqs);
- LINUX_AIO_CTX_LIST_UNLOCK();
- DPRINTF("Free context %p", pctx);
- uma_zfree(linux_aio_context_zone, pctx);
- user_free(td, pring, sizeof(*pring));
- return (ENOMEM);
- }
-
- /* Initialize the new context */
- sx_init(&(pctx->ctx_sx), "linux_aio_context");
- pctx->ctx_pid = p->p_pid;
- pctx->ctx_pring = pring;
- pctx->ctx_nreq_max = arg_nr_reqs;
- pctx->ctx_nreq_cur = 0;
- STAILQ_INIT(&(pctx->ctx_req));
-
- /* Hook the new context to global context list */
- LINUX_AIO_CTX_HOOK(pctx);
-
- LINUX_AIO_CTX_LIST_UNLOCK();
-
- /* Initialize the new "ring" */
- DPRINTF("initialize the \"ring\" %p", pring);
- bzero(&ring, sizeof(ring));
- ring.ring_id = 1;
- ring.ring_nr = arg_nr_reqs;
- ring.ring_head = 0;
- ring.ring_tail = 1;
- ring.ring_magic = LINUX_AIO_RING_MAGIC;
- ring.ring_compat_features = LINUX_AIO_RING_COMPAT_FEATURES;
- ring.ring_incompat_features = LINUX_AIO_RING_INCOMPAT_FEATURES;
- ring.ring_header_length = sizeof(ring);
- copyout(&ring, pring, sizeof(ring)); /* It has been hooked before */
-
- /* Substantial return value */
- ctx_id = (linux_aio_context_t)pctx->ctx_pring;
- copyout(&ctx_id, args->ctxp, sizeof(ctx_id));
- DPRINTF("returned context: %lx -> %p", (unsigned long)ctx_id, pctx);
-
- return (nerr);
-}
-
-/* Linux system call io_destroy(2) */
-int linux_io_destroy(struct thread *td, struct linux_io_destroy_args *args)
-{
- int nerr = 0;
- struct proc *p;
- struct linux_aio_context *pctx;
- struct linux_aio_request *preq, *ptmpreq;
- struct aio_cancel_args cancelargs;
- struct aio_return_args aioretargs;
-
- DARGPRINTF("%lx", (unsigned long)args->ctx);
- LINK_TO_NATIVE_AIO_MODULE();
-
- p = td->td_proc;
-
- /*
- * Locking:
- *
- * LINUX_AIO_LOCK(p); <----------------+
- * ... |
- * LINUX_AIO_CTX_LIST_LOCK(); <--+ |
- * ... | |
- * LINUX_AIO_CTX_LIST_UNLOCK(); <--+ |
- * ... |
- * LINUX_AIO_CTX_LOCK(pctx); <---------|---+
- * LINUX_AIO_UNLOCK(p); <----------------+ |
- * ... |
- * LINUX_AIO_CTX_UNLOCK(pctx); <-------------+
- */
-
- LINUX_AIO_LOCK(p);
-
- /* Find the context in context list */
- LINUX_AIO_CTX_LIST_LOCK();
- LINUX_AIO_CTX_FOREACH(pctx) {
- if (LINUX_AIO_CTX_MATCH(pctx, args->ctx, p->p_pid))
- break;
- }
- LINUX_AIO_CTX_LIST_UNLOCK();
-
- /* Unable to find the context */
- if (pctx == NULL) {
- LINUX_AIO_UNLOCK(p);
- return (EINVAL);
- }
-
- DPRINTF("Found the context: %lx -> %p", (unsigned long)args->ctx, pctx);
-
- /* Unhook the context from context list */
- DPRINTF("Unhook context %p", pctx);
- LINUX_AIO_CTX_UNHOOK(pctx);
-
- LINUX_AIO_CTX_LOCK(pctx); /* XXX Interlaced, seamless */
- LINUX_AIO_UNLOCK(p); /* XXX Interlaced, seamless */
-
- /* Real cleanup */
- LINUX_AIO_REQ_FOREACH_SAFE(pctx, preq, ptmpreq) {
- DPRINTF("Cancel request (Linux: %p, FreeBSD: %p)",
- preq->req_porig, preq->req_pbsd);
-
- /* Cancel FreeBSD native clone */
- cancelargs.fd = preq->req_linux.aio_fildes;
- cancelargs.aiocbp = preq->req_pbsd;
- p_aio_cancel(td, &cancelargs);
- DPRINTF("aio_cancel() returned %ld", (long)td->td_retval[0]);
- if (td->td_retval[0] == AIO_NOTCANCELED)
- printf(LMSG("linux_io_destroy(): Asynchronous IO "
- "request (Linux: %p, FreeBSD: %p) "
- "cannot be cancelled. "
- "***** Both User Space "
- "and Kernel Memory Leaked! *****"),
- preq->req_porig, preq->req_pbsd);
-
- LINUX_AIO_REQ_UNHOOK(pctx, preq);
-
- if (td->td_retval[0] == AIO_ALLDONE) {
- aioretargs.aiocbp = preq->req_pbsd;
- p_aio_return(td, &aioretargs);
- DPRINTF("aio_return(%p) returned %ld",
- aioretargs.aiocbp,
- (long)td->td_retval[0]);
-
- td->td_retval[0] = AIO_ALLDONE;
- }
-
- /* Free user space clone of the request */
- if (td->td_retval[0] != AIO_NOTCANCELED) /*
- * XXX How to avoid
- * memory leak here?
- */
- user_free(td, preq->req_pbsd,
- sizeof(*(preq->req_pbsd)));
-
- /* Free kernel structure of the request */
- uma_zfree(linux_aio_request_zone, preq);
-
- td->td_retval[0] = 0;
- }
-
- LINUX_AIO_CTX_UNLOCK(pctx);
-
- sx_destroy(&(pctx->ctx_sx));
-
- /* Free the "ring" */
- DPRINTF("free the \"ring\" %p", pctx->ctx_pring);
- user_free(td, pctx->ctx_pring, sizeof(*pctx->ctx_pring));
-
- /* Free destroyed context */
- uma_zfree(linux_aio_context_zone, pctx);
-
- return (nerr);
-}
-
-/* Linux system call io_getevents(2) */
-int linux_io_getevents(struct thread *td, struct linux_io_getevents_args *args)
-{
- int i, j, nerr = 0;
- struct proc *p;
- struct l_timespec l_timeout;
- struct timespec timeout, *u_ptimeout, t1, t2;
- struct linux_aio_context *pctx;
- struct linux_aio_request *preq, *ptmpreq;
- struct linux_io_event evt;
- struct aio_return_args aioretargs;
- struct aio_error_args aioerrargs;
- register_t aio_ret, aio_err;
- struct aiocb ** u_aiocbp;
- struct aio_suspend_args aiosusargs;
-
- DARGPRINTF("%lx, %ld, %ld, %p, %p",
- (unsigned long) args->ctx_id,
- (long)args->min_nr, (long)args->nr,
- args->events, args->timeout);
- LINK_TO_NATIVE_AIO_MODULE();
-
- if (args->nr <= 0)
- return (EINVAL);
-
- if (args->min_nr < 0)
- return (EINVAL);
-
- nerr = user_mem_rw_verify(args->events,
- sizeof(*(args->events)) * args->nr);
- if (nerr != 0)
- return (nerr);
-
- if (args->timeout != NULL) {
- nerr = copyin(args->timeout, &l_timeout, sizeof(l_timeout));
- if (nerr != 0)
- return (nerr);
- timeout.tv_sec = l_timeout.tv_sec;
- timeout.tv_nsec = l_timeout.tv_nsec;
- DUMP_TIMESPEC("User specified timeout: ", &timeout, "");
- }
-
- p = td->td_proc;
-
- /*
- * Locking:
- *
- * LINUX_AIO_LOCK(p); <----------------+
- * ... |
- * LINUX_AIO_CTX_LIST_LOCK(); <--+ |
- * ... | |
- * LINUX_AIO_CTX_LIST_UNLOCK(); <--+ |
- * ... |
- * LINUX_AIO_CTX_LOCK(pctx); <---------|---+
- * LINUX_AIO_UNLOCK(p); <----------------+ |
- * ... |
- * LINUX_AIO_CTX_UNLOCK(pctx); <-------------+
- */
-
- LINUX_AIO_LOCK(p);
-
- /* Find the context in context list */
- LINUX_AIO_CTX_LIST_LOCK();
- LINUX_AIO_CTX_FOREACH(pctx) {
- if (LINUX_AIO_CTX_MATCH(pctx, args->ctx_id, p->p_pid))
- break;
- }
- LINUX_AIO_CTX_LIST_UNLOCK();
-
- /* Unable to find the context */
- if (pctx == NULL) {
- LINUX_AIO_UNLOCK(p);
- return (EINVAL);
- }
-
- DPRINTF("Found the context: %lx -> %p", (unsigned long)args->ctx_id, pctx);
-
- LINUX_AIO_CTX_LOCK(pctx); /* XXX Interlaced, seamless */
- LINUX_AIO_UNLOCK(p); /* XXX Interlaced, seamless */
-
- if (STAILQ_EMPTY(&(pctx->ctx_req))) {
- td->td_retval[0] = 0; /* No queued request */
- DPRINTF("No request in queue (context: %p) at all, "
- "return directly", pctx);
- } else { /* Deal with the request queue */
- i = 0; /*
- * This variable's value will be the return value
- * of linux_io_getevents()
- */
-
- nerr = user_malloc(td, (void **)&u_aiocbp,
- sizeof(*u_aiocbp) * pctx->ctx_nreq_max);
- if (nerr != 0)
- goto skip_substantial_0;
-
- nerr = user_malloc(td, (void **)&u_ptimeout,
- sizeof(*u_ptimeout));
- if (nerr != 0)
- goto skip_substantial_1;
-
- for (i = 0;i < args->nr;) {
-
- /* Collecting finished requests and waiting for queued requests */
-
- LINUX_AIO_REQ_FOREACH_SAFE(pctx, preq, ptmpreq) {
-
- /* Collect all finished requests */
-
- if (i >= args->nr) /* Full */
- break;
-
- aioerrargs.aiocbp = preq->req_pbsd;
- p_aio_error(td, &aioerrargs);
- aio_ret = td->td_retval[0];
- td->td_retval[0] = 0;
-
- DPRINTF("aio_error(%p) (Linux: %p) "
- "returned %ld%s",
- aioerrargs.aiocbp,
- preq->req_porig,
- (long)aio_ret,
- aio_ret == EINPROGRESS ?
- "(EINPROGRESS)" : "" );
-
- if (aio_ret == EINPROGRESS)
- continue;
-
- /* Done */
- LINUX_AIO_REQ_UNHOOK(pctx, preq);
-
- aioretargs.aiocbp = preq->req_pbsd;
- aio_err = p_aio_return(td, &aioretargs);
- aio_ret = td->td_retval[0];
- td->td_retval[0] = 0;
-
- DPRINTF("aio_return(%p) (Linux: %p) "
- "returned %ld, errno=%ld",
- aioretargs.aiocbp,
- preq->req_porig,
- (long)aio_ret,
- (long)aio_err);
-
- evt.data = preq->req_linux.aio_data;
- evt.obj = (uint64_t)(unsigned long)
- preq->req_porig;
- if (aio_ret >= 0) {
- /* Normal return (success) */
- evt.res = aio_ret;
- } else { /* Error code (failure) */
- /*
- * Translate FreeBSD error code
- * to Linux's
- */
- evt.res =
- p->p_sysent->sv_errtbl[aio_err];
- }
- DPRINTF("context %p (Linux: %p): "
- "io_event.res=%lld",
- preq->req_pbsd,
- preq->req_porig,
- (long long)evt.res);
- evt.res2 = 0;
-
- copyout(&evt, &(args->events[i]), sizeof(evt));
-
- uma_zfree(linux_aio_request_zone, preq);
-
- i ++;
- } /* End of collecting all finished requests */
-
- if (STAILQ_EMPTY(&(pctx->ctx_req))) {
- /* No request remained in this context */
- DPRINTF("returning(context %p): "
- "request queue is empty",
- pctx);
- break;
- }
-
- if (i >= args->nr) { /* Full */
- DPRINTF("returning(context %p): user space "
- "event array is full",
- pctx);
- break;
- }
-
- if (i >= args->min_nr) {
- /* Met the minimum requirement */
- DPRINTF("returning(context %p): "
- "met the minimum requirement",
- pctx);
- break;
- }
-
- if (args->timeout != NULL) {
- if (! timespecisset(&timeout)) { /* Timed out */
- DPRINTF("returning(context %p): "
- "no time remaining",
- pctx);
- break;
- }
- }
-
- if (args->timeout != NULL) {
- nanouptime(&t1); /* Time before aio_suspend() */
- DUMP_TIMESPEC("T1: ", &t1,
- " (uptime before calling aio_suspend())");
- }
-
- /* Prepare arguments for aio_suspend() */
- j = 0;
- LINUX_AIO_REQ_FOREACH(pctx, preq) {
- copyout(&(preq->req_pbsd), &(u_aiocbp[j]),
- sizeof(preq->req_pbsd));
- j++;
- }
- MPASS(j == pctx->ctx_nreq_cur);
- aiosusargs.aiocbp = u_aiocbp;
- aiosusargs.nent = j;
-
- if (args->timeout != NULL) {
- copyout(&timeout, u_ptimeout, sizeof(timeout));
- aiosusargs.timeout = u_ptimeout;
- DUMP_TIMESPEC("Time remained: ", &timeout, "");
- } else {
- aiosusargs.timeout = NULL;
- }
-
- aio_err = p_aio_suspend(td, &aiosusargs);
- DPRINTF("aio_suspend(%p, %d, %p) returned %ld",
- aiosusargs.aiocbp, aiosusargs.nent,
- aiosusargs.timeout, (long)aio_err);
-
- if (args->timeout != NULL) {
- nanouptime(&t2); /* Time after aio_suspend() */
- DUMP_TIMESPEC("T2: ", &t2,
- " (uptime after calling aio_suspend())");
- timespecsub(&t2, &t1); /*
- * Time spent by
- * aio_suspend()
- */
- DUMP_TIMESPEC("T_delta: ", &t2,
- " (time spent by calling aio_suspend())");
- if (timespeccmp(&t2, &timeout, >=)) {
- timespecclear(&timeout); /* Timed out */
- } else {
- timespecsub(&timeout, &t2);
- /* Time remaining */
- }
- DUMP_TIMESPEC("Time remained: ", &timeout, "");
- }
-
- if (aio_err == EAGAIN) { /* Timed out */
- DPRINTF("returning(context %p): "
- "timed out after calling aio_suspend()",
- pctx);
- break;
- }
- } /*
- * End of collecting finished requests
- * and waiting for queued requests
- */
-
- l_timeout.tv_sec = timeout.tv_sec;
- l_timeout.tv_nsec = timeout.tv_nsec;
- copyout(&l_timeout, args->timeout, sizeof(l_timeout));
- /* No matter whether successfully or not */
-
- nerr = user_free(td, u_ptimeout, sizeof(*u_ptimeout));
-skip_substantial_1:
- nerr = user_free(td, u_aiocbp,
- sizeof(*u_aiocbp) * pctx->ctx_nreq_max);
-skip_substantial_0:
- td->td_retval[0] = i;
- /* user_free() resets td->td_retval[0] to 0 */
- DPRINTF("%d requests are unhooked from the context %p", i, pctx);
- } /* End of dealing with request queue */
-
- LINUX_AIO_CTX_UNLOCK(pctx);
-
- return (nerr);
-}
-
-/* Linux system call io_submit(2) */
-int linux_io_submit(struct thread *td, struct linux_io_submit_args *args)
-{
- int i, nerr = 0;
- struct proc *p;
- struct linux_aio_context *pctx;
- struct linux_aio_request req, *preq;
- struct linux_iocb *porig;
- struct aiocb iocb, *piocb;
-
- DARGPRINTF("%lx, %ld, %p", (unsigned long)args->ctx_id,
- (long)args->nr, args->iocbpp);
- LINK_TO_NATIVE_AIO_MODULE();
-
- if (args->nr <= 0)
- return (EINVAL);
-
- p = td->td_proc;
-
- /*
- * Locking:
- *
- * LINUX_AIO_LOCK(p); <----------------+
- * ... |
- * LINUX_AIO_CTX_LIST_LOCK(); <--+ |
- * ... | |
- * LINUX_AIO_CTX_LIST_UNLOCK(); <--+ |
- * ... |
- * LINUX_AIO_CTX_LOCK(pctx); <---------|---+
- * LINUX_AIO_UNLOCK(p); <----------------+ |
- * ... |
- * LINUX_AIO_CTX_UNLOCK(pctx); <-------------+
- */
-
- LINUX_AIO_LOCK(p);
-
- /* Find the context in context list */
- LINUX_AIO_CTX_LIST_LOCK();
- LINUX_AIO_CTX_FOREACH(pctx) {
- if (LINUX_AIO_CTX_MATCH(pctx, args->ctx_id, p->p_pid))
- break;
- }
- LINUX_AIO_CTX_LIST_UNLOCK();
-
- /* Unable to find the context */
- if (pctx == NULL) {
- LINUX_AIO_UNLOCK(p);
- return (EINVAL);
- }
-
- DPRINTF("Found the context: %lx -> %p", (unsigned long)args->ctx_id, pctx);
-
- LINUX_AIO_CTX_LOCK(pctx); /* XXX Interlaced, seamless */
- LINUX_AIO_UNLOCK(p); /* XXX Interlaced, seamless */
-
- for (i = 0; pctx->ctx_nreq_cur < pctx->ctx_nreq_max && i < args->nr;
- i++) {
- /* Get user space Linux control block */
- nerr = copyin(&(args->iocbpp[i]), &porig, sizeof(porig));
- if (nerr != 0)
- break;
- nerr = copyin(porig, &(req.req_linux), sizeof(req.req_linux));
- if (nerr != 0)
- break;
-
- /* Create user space FreeBSD control block clone */
- nerr = iocb_reformat(&(req.req_linux), &iocb);
- if (nerr != 0)
- break;
- nerr = user_malloc(td, (void **)&piocb, sizeof(*piocb));
- if (nerr != 0)
- break;
- nerr = copyout(&iocb, piocb, sizeof(iocb));
- if (nerr != 0)
- break;
- DUMP_FREEBSD_AIOCB(piocb, 1);
-
- /* Submit user space control block */
- nerr = p_aio_aqueue(td, piocb, NULL, iocb.aio_lio_opcode, 0);
- if (nerr != 0) {
- user_free(td, piocb, sizeof(*piocb));
- break;
- }
-
- req.req_porig = porig;
- req.req_pbsd = piocb;
-
- /* Hook request to the context */
- preq = uma_zalloc(linux_aio_request_zone, M_WAITOK);
- memcpy(preq, &req, sizeof(req));
- DPRINTF("Linux IOCB %p (aio_lio_opcode=%u, aio_fildes=%u), "
- "FreeBSD IOCB %p",
- preq->req_porig,
- (unsigned)preq->req_linux.aio_lio_opcode,
- (unsigned)preq->req_linux.aio_fildes,
- preq->req_pbsd);
- LINUX_AIO_REQ_HOOK(pctx, preq);
- }
-
- LINUX_AIO_CTX_UNLOCK(pctx);
-
- if (i > 0) {
- td->td_retval[0] = i;
- nerr = 0;
- }
-
- if (i == 0 && nerr == 0)
- nerr = EAGAIN; /* No request is successfully submitted */
-
- return (nerr);
-}
-
-/* Linux system call io_cancel(2) */
-int linux_io_cancel(struct thread *td, struct linux_io_cancel_args *args)
-{
- int nerr = 0;
- struct proc *p;
- struct linux_iocb lcb;
- struct linux_aio_context *pctx;
- struct linux_aio_request *preq;
- struct linux_io_event evt;
- struct aio_cancel_args aiocnclargs;
-
- DARGPRINTF("%lx, %p, %p", (unsigned long)args->ctx_id,
- args->iocb, args->result);
- LINK_TO_NATIVE_AIO_MODULE();
-
- nerr = copyin(args->iocb, &lcb, sizeof(lcb));
- if (nerr != 0)
- return (nerr);
-
- nerr = user_mem_rw_verify(args->result, sizeof(*(args->result)));
- if (nerr != 0)
- return (nerr);
-
- p = td->td_proc;
-
- /*
- * Locking:
- *
- * LINUX_AIO_LOCK(p); <----------------+
- * ... |
- * LINUX_AIO_CTX_LIST_LOCK(); <--+ |
- * ... | |
- * LINUX_AIO_CTX_LIST_UNLOCK(); <--+ |
- * ... |
- * LINUX_AIO_CTX_LOCK(pctx); <---------|---+
- * LINUX_AIO_UNLOCK(p); <----------------+ |
- * ... |
- * LINUX_AIO_CTX_UNLOCK(pctx); <-------------+
- */
-
- LINUX_AIO_LOCK(p);
-
- /* Find the context in context list */
- LINUX_AIO_CTX_LIST_LOCK();
- LINUX_AIO_CTX_FOREACH(pctx) {
- if (LINUX_AIO_CTX_MATCH(pctx, args->ctx_id, p->p_pid))
- break;
- }
- LINUX_AIO_CTX_LIST_UNLOCK();
-
- /* Unable to find the context */
- if (pctx == NULL) {
- LINUX_AIO_UNLOCK(p);
- return (EINVAL);
- }
-
- DPRINTF("Found the context: %lx -> %p", (unsigned long)args->ctx_id, pctx);
-
- LINUX_AIO_CTX_LOCK(pctx); /* XXX Interlaced, seamless */
- LINUX_AIO_UNLOCK(p); /* XXX Interlaced, seamless */
-
- LINUX_AIO_REQ_FOREACH(pctx, preq) {
- if (preq->req_porig == args->iocb
- && preq->req_linux.aio_key == lcb.aio_key)
- break;
- }
-
- if (preq == NULL) {
- DPRINTF("Unable to find IO control block %p", args->iocb);
- nerr = EINVAL;
- } else { /* Found the request in context */
- DPRINTF("Cancel request (Linux: %p, FreeBSD: %p)",
- preq->req_porig, preq->req_pbsd);
-
- /* Cancel FreeBSD native clone */
- aiocnclargs.fd = preq->req_linux.aio_fildes;
- aiocnclargs.aiocbp = preq->req_pbsd;
- p_aio_cancel(td, &aiocnclargs);
- DPRINTF("aio_cancel() returned %ld", (long)td->td_retval[0]);
-
- if (td->td_retval[0] == AIO_CANCELED) {
- /* Cancellation succeeded */
- LINUX_AIO_REQ_UNHOOK(pctx, preq);
-
- evt.data = preq->req_linux.aio_data;
- evt.obj = (uint64_t)(unsigned long) preq->req_porig;
- evt.res = p->p_sysent->sv_errtbl[ECANCELED];
- evt.res2 = 0;
-
- /* Fill in user space structure linux_io_event */
- copyout(&evt, args->result, sizeof(evt));
-
- /* Free user space clone of the request */
- user_free(td, preq->req_pbsd,
- sizeof(*(preq->req_pbsd)));
-
- /* Free kernel structure of the request */
- uma_zfree(linux_aio_request_zone, preq);
- } else if (td->td_retval[0] == AIO_ALLDONE) {
- nerr = EINVAL; /*
- * This value of Linux 2.6.15
- * is really confusing !!!
- */
- } else { /* AIO_NOTCANCELED */
- nerr = EAGAIN;
- }
-
- td->td_retval[0] = 0;
- }
-
- LINUX_AIO_CTX_UNLOCK(pctx);
-
- return (nerr);
-}
-
-static void linux_aio_proc_rundown(void *arg, struct proc *p)
-{
- struct linux_aio_context *pctx, *ptmpctx;
- struct linux_aio_request *preq, *ptmpreq;
-
- /*
- * FreeBSD module "aio" can do more essential native cleanup
- * (i.e. cancelling all queued requests) itself.
- */
-
- LINUX_AIO_CTX_LIST_LOCK();
-
- LINUX_AIO_CTX_FOREACH_SAFE(pctx, ptmpctx) {
- if (pctx->ctx_pid == p->p_pid) {
- LINUX_AIO_REQ_FOREACH_SAFE(pctx, preq, ptmpreq) {
- DPPRINTF("Free request %p from context %p "
- "(ring: %p)",
- preq, pctx, pctx->ctx_pring);
- LINUX_AIO_REQ_UNHOOK(pctx, preq);
- uma_zfree(linux_aio_request_zone, preq);
- }
-
- DPPRINTF("Free context %p (ring: %p)",
- pctx, pctx->ctx_pring);
-
- /* Unhook it from context list */
- LINUX_AIO_CTX_UNHOOK(pctx);
-
- /* Free it really */
- sx_destroy(&(pctx->ctx_sx));
- uma_zfree(linux_aio_context_zone, pctx);
-
- DPPRINTF("The remaining context list is %s",
- (SLIST_EMPTY(&linux_aio_context_list) ?
- "empty":"not empty"));
- }
- }
-
- LINUX_AIO_CTX_LIST_UNLOCK();
-}
-
-/*
- * Module constructor/destructor
- */
-static int
-linux_aio_modload(struct module *module, int cmd, void *arg)
-{
- int nerr = 0;
-
- switch (cmd) {
- case MOD_LOAD:
- linux_aio_context_zone = uma_zcreate("LINUXAIOCTX",
- sizeof(struct linux_aio_context),
- NULL, NULL, NULL, NULL,
- UMA_ALIGN_PTR, 0);
- linux_aio_request_zone = uma_zcreate("LINUXAIOREQ",
- sizeof(struct linux_aio_request),
- NULL, NULL, NULL, NULL,
- UMA_ALIGN_PTR, 0);
- mtx_init(&linux_aio_context_list_mtx,
- "linux_aio_context_list", NULL, MTX_DEF);
- SLIST_INIT(&linux_aio_context_list);
- linux_aio_exit_tag = EVENTHANDLER_REGISTER(process_exit,
- linux_aio_proc_rundown,
- NULL, EVENTHANDLER_PRI_ANY);
- break;
- case MOD_UNLOAD:
- LINUX_AIO_CTX_LIST_LOCK();
- if (!SLIST_EMPTY(&linux_aio_context_list)) {
- nerr = EBUSY;
- LINUX_AIO_CTX_LIST_UNLOCK();
- break;
- }
- EVENTHANDLER_DEREGISTER(process_exit, linux_aio_exit_tag);
- LINUX_AIO_CTX_LIST_UNLOCK();
- mtx_destroy(&linux_aio_context_list_mtx);
- uma_zdestroy(linux_aio_request_zone);
- uma_zdestroy(linux_aio_context_zone);
- if (native_aio_module_handle != NULL) {
- /*
- * linker_release_module() cannot be used here.
- * It tries to hold "kld_sx", conflicting against
- * module_unload().
- */
- linker_file_unload(native_aio_module_handle,
- LINKER_UNLOAD_NORMAL);
- }
- break;
- case MOD_SHUTDOWN:
- break;
- default:
- nerr = EINVAL;
- break;
- }
- return (nerr);
-}
-
-static moduledata_t linux_aio_mod = {
- "linuxaio",
- &linux_aio_modload,
- NULL
-};
-
-DECLARE_MODULE(linuxaio, linux_aio_mod, SI_SUB_VFS, SI_ORDER_ANY);
diff --git a/sys/compat/linux/linux_aio.h b/sys/compat/linux/linux_aio.h
deleted file mode 100644
index 96028a8..0000000
--- a/sys/compat/linux/linux_aio.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*-
- * Copyright (c) 2006 Li, Xiao <intron@intron.ac>. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-/*
- * Linux Kernel Implementation of Asynchronous I/O
- */
-
-#ifndef _LINUX_AIO_H_
-#define _LINUX_AIO_H_
-
-typedef unsigned long linux_aio_context_t;
-
-enum {
- LINUX_IOCB_CMD_PREAD = 0,
- LINUX_IOCB_CMD_PWRITE = 1,
- LINUX_IOCB_CMD_FSYNC = 2,
- LINUX_IOCB_CMD_FDSYNC = 3,
-#if 0
- LINUX_IOCB_CMD_PREADX = 4,
- LINUX_IOCB_CMD_POLL = 5,
-#endif
- LINUX_IOCB_CMD_NOOP = 6,
-};
-
-struct linux_io_event {
- uint64_t data;
- uint64_t obj;
- int64_t res;
- int64_t res2;
-};
-
-#if _BYTE_ORDER == _LITTLE_ENDIAN
-#define LINUX_AIO_PADDED(x,y) x,y
-#elif _BYTE_ORDER == _BIG_ENDIAN
-#define LINUX_AIO_PADDED(x,y) y,x
-#else
-#error Unidentified byte order !!!
-#endif
-
-struct linux_iocb {
- uint64_t aio_data;
- uint32_t LINUX_AIO_PADDED(aio_key, aio_reserved1);
-
- uint16_t aio_lio_opcode;
- int16_t aio_reqprio;
- uint32_t aio_fildes;
-
- uint64_t aio_buf;
- uint64_t aio_nbytes;
- int64_t aio_offset;
-
- uint64_t aio_reserved2; /* TODO: use this for a (struct sigevent *) */
- uint64_t aio_reserved3;
-
-};
-
-/* User space context information structure */
-struct linux_aio_ring {
- l_uint ring_id;
- l_uint ring_nr;
- l_uint ring_head;
- l_uint ring_tail;
-#define LINUX_AIO_RING_MAGIC 0xa10a10a1
- l_uint ring_magic;
-#define LINUX_AIO_RING_COMPAT_FEATURES 1
- l_uint ring_compat_features;
-#define LINUX_AIO_RING_INCOMPAT_FEATURES 0
- l_uint ring_incompat_features;
- l_uint ring_header_length; /* Size of this structure */
-
- struct linux_io_event ring_io_events[0];
-};
-
-#endif /* !_LINUX_AIO_H_ */
diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
index 692362f..3d3bc8c 100644
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -232,7 +232,6 @@ amd64/linux32/linux32_locore.s optional compat_linux32 \
amd64/linux32/linux32_machdep.c optional compat_linux32
amd64/linux32/linux32_sysent.c optional compat_linux32
amd64/linux32/linux32_sysvec.c optional compat_linux32
-compat/linux/linux_aio.c optional compat_linux32
compat/linux/linux_emul.c optional compat_linux32
compat/linux/linux_file.c optional compat_linux32
compat/linux/linux_futex.c optional compat_linux32
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index a0d0835..09fc1b1 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -85,7 +85,6 @@ rr232x_lib.o optional rr232x \
#
compat/linprocfs/linprocfs.c optional linprocfs
compat/linsysfs/linsysfs.c optional linsysfs
-compat/linux/linux_aio.c optional compat_linux
compat/linux/linux_emul.c optional compat_linux
compat/linux/linux_file.c optional compat_linux
compat/linux/linux_futex.c optional compat_linux
diff --git a/sys/conf/files.pc98 b/sys/conf/files.pc98
index 7b1702f..c538a6a 100644
--- a/sys/conf/files.pc98
+++ b/sys/conf/files.pc98
@@ -55,7 +55,6 @@ opt_ah.h optional ath_hal \
#
compat/linprocfs/linprocfs.c optional linprocfs
compat/linsysfs/linsysfs.c optional linsysfs
-compat/linux/linux_aio.c optional compat_linux
compat/linux/linux_emul.c optional compat_linux
compat/linux/linux_file.c optional compat_linux
compat/linux/linux_futex.c optional compat_linux
diff --git a/sys/i386/linux/linux.h b/sys/i386/linux/linux.h
index 1ca7381..9ad9353 100644
--- a/sys/i386/linux/linux.h
+++ b/sys/i386/linux/linux.h
@@ -803,6 +803,4 @@ typedef int l_mqd_t;
#define THREADING_FLAGS (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND)
-#include <compat/linux/linux_aio.h>
-
#endif /* !_I386_LINUX_LINUX_H_ */
diff --git a/sys/i386/linux/syscalls.master b/sys/i386/linux/syscalls.master
index 24c98be..0cf274c 100644
--- a/sys/i386/linux/syscalls.master
+++ b/sys/i386/linux/syscalls.master
@@ -410,11 +410,11 @@
242 AUE_NULL UNIMPL linux_sched_getaffinity
243 AUE_NULL STD { int linux_set_thread_area(struct l_user_desc *desc); }
244 AUE_NULL STD { int linux_get_thread_area(struct l_user_desc *desc); }
-245 AUE_NULL STD { int linux_io_setup(l_uint nr_reqs, linux_aio_context_t *ctxp); }
-246 AUE_NULL STD { int linux_io_destroy(linux_aio_context_t ctx); }
-247 AUE_NULL STD { int linux_io_getevents(linux_aio_context_t ctx_id, l_long min_nr, l_long nr, struct linux_io_event *events, struct l_timespec *timeout); }
-248 AUE_NULL STD { int linux_io_submit(linux_aio_context_t ctx_id, l_long nr, struct linux_iocb **iocbpp); }
-249 AUE_NULL STD { int linux_io_cancel(linux_aio_context_t ctx_id, struct linux_iocb *iocb, struct linux_io_event *result); }
+245 AUE_NULL UNIMPL linux_io_setup
+246 AUE_NULL UNIMPL linux_io_destroy
+247 AUE_NULL UNIMPL linux_io_getevents
+248 AUE_NULL UNIMPL linux_io_submit
+249 AUE_NULL UNIMPL linux_io_cancel
250 AUE_NULL STD { int linux_fadvise64(void); }
251 AUE_NULL UNIMPL
252 AUE_EXIT STD { int linux_exit_group(int error_code); }
diff --git a/sys/modules/linux/Makefile b/sys/modules/linux/Makefile
index ca6b467..1230470 100644
--- a/sys/modules/linux/Makefile
+++ b/sys/modules/linux/Makefile
@@ -8,7 +8,7 @@ CFLAGS+=-DCOMPAT_IA32 -DCOMPAT_LINUX32
.PATH: ${.CURDIR}/../../compat/linux ${.CURDIR}/../../${MACHINE_ARCH}/linux${SFX}
KMOD= linux
-SRCS= linux_aio.c linux${SFX}_dummy.c linux_emul.c linux_file.c \
+SRCS= linux${SFX}_dummy.c linux_emul.c linux_file.c \
linux_futex.c linux_getcwd.c linux_ioctl.c linux_ipc.c \
linux${SFX}_machdep.c linux_mib.c linux_misc.c linux_signal.c \
linux_socket.c linux_stats.c linux_sysctl.c linux${SFX}_sysent.c \
OpenPOWER on IntegriCloud