diff options
-rw-r--r-- | INSTALL | 7 | ||||
-rw-r--r-- | TODO | 4 | ||||
-rw-r--r-- | src/Makefile | 48 | ||||
-rw-r--r-- | src/io_cancel.c | 9 | ||||
-rw-r--r-- | src/io_queue_init.c | 16 | ||||
-rw-r--r-- | src/io_queue_run.c | 24 | ||||
-rw-r--r-- | src/io_queue_wait.c | 15 | ||||
-rw-r--r-- | src/io_submit.c | 12 | ||||
-rw-r--r-- | src/lib/src/Makefile | 30 | ||||
-rw-r--r-- | src/lib/src/kso_init.c | 48 | ||||
-rw-r--r-- | src/lib/src/libredhat-kernel.map | 11 | ||||
-rw-r--r-- | src/lib/src/myln.c | 25 | ||||
-rw-r--r-- | src/lib/src/stub.S | 18 | ||||
-rw-r--r-- | src/lib/src/vsysaddr.S | 7 | ||||
-rw-r--r-- | src/libaio.h | 184 | ||||
-rw-r--r-- | src/libaio.map | 10 | ||||
-rw-r--r-- | src/vsys_def.h | 7 |
17 files changed, 475 insertions, 0 deletions
@@ -0,0 +1,7 @@ +To install the library, execute the command: + + make prefix=`pwd`/usr -C src install + +which will install the binaries and header files into the directory +usr. Set prefix=/usr to get them installed into the main system. + @@ -0,0 +1,4 @@ +- Write man pages. +- Make -static links against libaio work. +- Fallback on userspace if the kernel calls return -ENOSYS. + diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..b0bd052 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,48 @@ +prefix=usr +#INCDIR=/home/bcrl/aio/aio-2.4.9-ac18/include +INCDIR=/md0/aio/aio-v2.4.13-ac6/include + +CFLAGS=-nostdlib -nostartfiles -Wall -I. -I$(INCDIR) -g +SO_CFLAGS=-shared $(CFLAGS) +L_CFLAGS=$(CFLAGS) +LINK_FLAGS=-Llib -lredhat-kernel + +soname=libaio.so.1 +all_targets += libaio.a $(soname) + +all: $(all_targets) + + +libaio_srcs := io_queue_init.c io_submit.c io_cancel.c io_queue_wait.c +libaio_srcs += io_queue_run.c + +libaio_objs := $(patsubst %.c,%.ol,$(libaio_srcs)) +libaio_sobjs := $(patsubst %.c,%.os,$(libaio_srcs)) + + +%.os: %.c + $(CC) $(SO_CFLAGS) -c -o $@ $< + +%.ol: %.c + $(CC) $(L_CFLAGS) -c -o $@ $< + + +libaio.a: $(libaio_objs) + rm -f libaio.a + ar r libaio.a $^ + ranlib libaio.a + +$(soname): $(libaio_sobjs) + $(CC) $(SO_CFLAGS) -Wl,--version-script=libaio.map -Wl,-soname=$(soname) -o $@ $^ $(LINK_FLAGS) + +install: $(all_targets) + install -D -m 644 libaio.h $(prefix)/include/libaio.h + install -D -m 644 libaio.a $(prefix)/lib/libaio.a + install -D -m 755 $(soname) $(prefix)/lib/$(soname) + ln -sf $(soname) $(prefix)/lib/libaio.so + +$(libaio_objs): libaio.h + +clean: + rm -f $(all_targets) $(libaio_objs) $(libaio_sobjs) $(soname).new + rm -f *.so *.a *.o diff --git a/src/io_cancel.c b/src/io_cancel.c new file mode 100644 index 0000000..017bf1e --- /dev/null +++ b/src/io_cancel.c @@ -0,0 +1,9 @@ +/* io_cancel.c + */ +#include <libaio.h> +#include "vsys_def.h" + +int io_cancel(io_context_t ctx, struct iocb *iocb) +{ + return vsys_io_cancel(ctx, iocb); +} diff --git a/src/io_queue_init.c b/src/io_queue_init.c new file mode 100644 index 0000000..627331e --- /dev/null +++ b/src/io_queue_init.c @@ -0,0 +1,16 @@ +/* io_queue_init.c + */ +#include <libaio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include "vsys_def.h" + +int io_queue_init(int maxevents, io_context_t *ctxp) +{ + if (maxevents > 0) { + *ctxp = NULL; + return vsys_io_setup(maxevents, ctxp); + } + return -EINVAL; +} diff --git a/src/io_queue_run.c b/src/io_queue_run.c new file mode 100644 index 0000000..7264222 --- /dev/null +++ b/src/io_queue_run.c @@ -0,0 +1,24 @@ +/* io_submit + */ +#include <libaio.h> +#include <errno.h> +#include <stdlib.h> +#include <time.h> +#include "vsys_def.h" + +int io_queue_run(io_context_t ctx) +{ + static struct timespec timeout = { 0, 0 }; + struct io_event event; + int ret; + + /* FIXME: batch requests */ + while (1 == (ret = vsys_io_getevents(ctx, 1, &event, &timeout))) { + io_callback_t cb = (io_callback_t)event.data; + struct iocb *iocb = (struct iocb *)event.obj; + + cb(ctx, iocb, event.res, event.res2); + } + + return ret; +} diff --git a/src/io_queue_wait.c b/src/io_queue_wait.c new file mode 100644 index 0000000..870c2b3 --- /dev/null +++ b/src/io_queue_wait.c @@ -0,0 +1,15 @@ +/* io_submit + */ +#define NO_SYSCALL_ERRNO +#include <linux/types.h> +#include <libaio.h> +#include <errno.h> + +#include "vsys_def.h" + +struct timespec; + +int io_queue_wait(io_context_t ctx, struct timespec *timeout) +{ + return vsys_io_getevents(ctx, 0, NULL, timeout); +} diff --git a/src/io_submit.c b/src/io_submit.c new file mode 100644 index 0000000..6322826 --- /dev/null +++ b/src/io_submit.c @@ -0,0 +1,12 @@ +/* io_submit + */ +#include <errno.h> +#include <libaio.h> +#include "vsys_def.h" + +int io_submit(io_context_t ctx, int nr, struct iocb **iocbs) +{ + if (nr > 0) + return vsys_io_submit(ctx, nr, iocbs); + return -EINVAL; +} diff --git a/src/lib/src/Makefile b/src/lib/src/Makefile new file mode 100644 index 0000000..d92f2a9 --- /dev/null +++ b/src/lib/src/Makefile @@ -0,0 +1,30 @@ +all: libredhat-kernel.so + +ASFLAGS=-D__KERNEL__ -D__ASSEMBLY__ -I../include -nostdlib -nostartfiles +CFLAGS=-D__KERNEL__ -I../include -nostdlib -nostartfiles + +so_objs=vsysaddr.o kso_init.o + +vsysaddr.S: ../System.map stub.S Makefile + rm -f vsysaddr.S + echo '#include "stub.S"' >vsysaddr.S + awk -- "/^bfff.* vsys_/ { print \"dynamic_syscall(\"\$$3 \",0x\" \$$1 \")\"; }" <../System.map >>vsysaddr.S + +vsysaddr.o: vsysaddr.S + +kso_init.o: ../include/linux/compile.h + +libredhat-kernel.so.1: $(so_objs) libredhat-kernel.map + gcc -nostdlib -nostartfiles -shared -Wl,--version-script=libredhat-kernel.map -o $@ $(so_objs) + cp $@ $@.save + strip $@ + +libredhat-kernel.so: libredhat-kernel.so.1 + ln -sf $< $@ + +clean: + rm -f *.o libredhat-kernel.so myln libredhat-kernel.so.1 vsysaddr.S + +# test app +myln: myln.c libredhat-kernel.so Makefile + cc -g -o myln myln.c -L. -lredhat-kernel diff --git a/src/lib/src/kso_init.c b/src/lib/src/kso_init.c new file mode 100644 index 0000000..6015595 --- /dev/null +++ b/src/lib/src/kso_init.c @@ -0,0 +1,48 @@ +#include <linux/compile.h> +#include <linux/types.h> +#include <asm/unistd.h> +#include <asm/fcntl.h> +#include <asm/mman.h> +#include <asm/a.out.h> + +char libredhat_kernel_enosys = 1; /* the asm in stub.S depends on this */ + +long _init(void) +{ + static char unique[] = { LINUX_UNIQUE_BYTES }; + int errno; + long addr; + int fd; + int i; + + _syscall6(int, mmap2, unsigned long, addr, unsigned long, len, + unsigned long, prot, unsigned long, flags, + unsigned long, fd, unsigned long, pgoff) + _syscall2(long, munmap, unsigned long, addr, size_t, len) + _syscall2(int, open, const char *, name, int, flags) + _syscall1(int, close, int, fd) + + if (sizeof(unique) != 16) + return -1; + + fd = open("/dev/vsys", O_RDONLY); + if (-1 == fd) + return -1; + + addr = mmap2(0, VSYSCALL_SIZE, PROT_READ | PROT_EXEC, MAP_SHARED, fd, 0); + if (-1 == addr) + return -1; + + close(fd); + + for (i=0; i<sizeof(unique); i++) + if (unique[i] != ((char *)addr)[i]) { + munmap(addr, VSYSCALL_SIZE); + return -1; + } + + /* okay, all the syscalls we provide are now good */ + libredhat_kernel_enosys = 0; + return 0; +} + diff --git a/src/lib/src/libredhat-kernel.map b/src/lib/src/libredhat-kernel.map new file mode 100644 index 0000000..1b0d390 --- /dev/null +++ b/src/lib/src/libredhat-kernel.map @@ -0,0 +1,11 @@ +REDHAT_0.90 { + global: + vsys_io_setup; + vsys_io_destroy; + vsys_io_submit; + vsys_io_cancel; + vsys_io_wait; + vsys_io_getevents; + local: + *; +}; diff --git a/src/lib/src/myln.c b/src/lib/src/myln.c new file mode 100644 index 0000000..e8b1178 --- /dev/null +++ b/src/lib/src/myln.c @@ -0,0 +1,25 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/mman.h> + +int main () +{ + long ctx = 0; + extern long vsys_io_setup(long, long *); + unsigned char *bob = (void*)&vsys_io_setup; + long ret; + int i; + printf("%p\n", bob); + //printf("%p\n", mmap(0, 65536, PROT_READ | PROT_EXEC, MAP_SHARED, + // open("/dev/vsys", O_RDONLY), 0)); + //for (i=0; i<16; i++) + // printf(" %02x\n", bob[i]); + //printf("\n"); + + ret = vsys_io_setup(100, &ctx); + + printf("ret=%ld, ctx=0x%lx\n", ret, ctx); + return 0; +} diff --git a/src/lib/src/stub.S b/src/lib/src/stub.S new file mode 100644 index 0000000..992b133 --- /dev/null +++ b/src/lib/src/stub.S @@ -0,0 +1,18 @@ +/* stub.S */ +#include <asm/segment.h> +#include <asm/errno.h> + + .text + +#define dynamic_syscall(x,a) \ + .globl x ;\ + .align 16 ;\ + x: ;\ + cmpb $0,libredhat_kernel_enosys ;\ + jne 1f ;\ + ljmp $__USER_CS, $a ;\ + 1: ;\ + movl $-ENOSYS,%eax ;\ + ret ;\ + .size x,.-x + diff --git a/src/lib/src/vsysaddr.S b/src/lib/src/vsysaddr.S new file mode 100644 index 0000000..d9719c1 --- /dev/null +++ b/src/lib/src/vsysaddr.S @@ -0,0 +1,7 @@ +#include "stub.S" +dynamic_syscall(vsys_io_setup,0xbfff0010) +dynamic_syscall(vsys_io_destroy,0xbfff0025) +dynamic_syscall(vsys_io_submit,0xbfff003a) +dynamic_syscall(vsys_io_cancel,0xbfff004f) +dynamic_syscall(vsys_io_wait,0xbfff0064) +dynamic_syscall(vsys_io_getevents,0xbfff0079) diff --git a/src/libaio.h b/src/libaio.h new file mode 100644 index 0000000..d0f9bbe --- /dev/null +++ b/src/libaio.h @@ -0,0 +1,184 @@ +/* /usr/include/libaio.h + * + * Copyright 2000,2001,2002 Red Hat. + * + * Written by Benjamin LaHaise <bcrl@redhat.com> + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, provided that the above copyright + * notice appears in all copies. This software is provided without any + * warranty, express or implied. Red Hat makes no representations about + * the suitability of this software for any purpose. + * + * IN NO EVENT SHALL RED HAT BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + * SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF + * THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF RED HAT HAS BEEN ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * RED HAT DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND + * RED HAT HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + */ +#ifndef __LIBAIO_H +#define __LIBAIO_H +#include <asm/types.h> +#include <string.h> + +struct timespec; +struct sockaddr; +struct iovec; +struct iocb; + +typedef struct io_context *io_context_t; + +typedef enum io_iocb_cmd { + IO_CMD_PREAD = 0, + IO_CMD_PWRITE = 1, + + IO_CMD_FSYNC = 2, + IO_CMD_FDSYNC = 3, + + IO_CMD_POLL = 5, +} io_iocb_cmd_t; + +#if defined(__i386__) /* little endian, 32 bits */ +#define PADDED(x, y) x, y +#define PADDEDptr(x, y) x; unsigned y +#else +#error endian? +#endif + +struct io_iocb_poll { + int PADDED(events, __pad1); +}; /* result code is the set of result flags or -'ve errno */ + +struct io_iocb_sockaddr { + struct sockaddr *addr; + int len; +}; /* result code is the length of the sockaddr, or -'ve errno */ + +struct io_iocb_common { + void *buf; + unsigned __pad1; + long nbytes; + unsigned __pad2; + long long offset; + long long __pad3, __pad4; +}; /* result code is the amount read or -'ve errno */ + +struct io_iocb_vector { + const struct iovec *vec; + int nr; + long long offset; +}; /* result code is the amount read or -'ve errno */ + +struct iocb { + void PADDEDptr(*data, __pad1); /* Return in the io completion event */ + unsigned PADDED(key, __pad2); /* For use in identifying io requests */ + + short aio_lio_opcode; + short aio_reqprio; + int aio_fildes; + + union { + struct io_iocb_common c; + struct io_iocb_vector v; + struct io_iocb_poll poll; + struct io_iocb_sockaddr saddr; + } u; +}; + +struct io_event { + unsigned PADDED(data, __pad1); + unsigned PADDED(obj, __pad2); + unsigned PADDED(res, __pad3); + unsigned PADDED(res2, __pad4); +}; + +#undef PADDED +#undef PADDEDptr + +typedef void (*io_callback_t)(io_context_t ctx, struct iocb *iocb, long res, long res2); + +extern int io_queue_init(int maxevents, io_context_t *ctxp); +extern int io_queue_grow(io_context_t ctx, int new_maxevents); +extern int io_queue_release(io_context_t ctx); +extern int io_queue_wait(io_context_t ctx, struct timespec *timeout); +extern int io_queue_run(io_context_t ctx); +extern int io_submit(io_context_t ctx, int nr, struct iocb *ios[]); +extern int io_cancel(io_context_t ctx, struct iocb *iocb); + +static inline void io_set_callback(struct iocb *iocb, io_callback_t cb) +{ + iocb->data = cb; +} + +static inline void io_prep_pread(struct iocb *iocb, int fd, void *buf, size_t count, long long offset) +{ + iocb->aio_fildes = fd; + iocb->aio_lio_opcode = IO_CMD_PREAD; + iocb->aio_reqprio = 0; + iocb->u.c.buf = buf; + iocb->u.c.nbytes = count; + iocb->u.c.offset = offset; +} + +static inline void io_prep_pwrite(struct iocb *iocb, int fd, void *buf, size_t count, long long offset) +{ + iocb->aio_fildes = fd; + iocb->aio_lio_opcode = IO_CMD_PWRITE; + iocb->aio_reqprio = 0; + iocb->u.c.buf = buf; + iocb->u.c.nbytes = count; + iocb->u.c.offset = offset; +} + +static inline void io_prep_poll(struct iocb *iocb, int fd, int events) +{ + iocb->aio_fildes = fd; + iocb->aio_lio_opcode = IO_CMD_POLL; + iocb->aio_reqprio = 0; + memset(&iocb->u, 0, sizeof(iocb->u)); + iocb->u.poll.events = events; +} + +static inline int io_poll(io_context_t ctx, struct iocb *iocb, io_callback_t cb, int fd, int events) +{ + io_set_callback(iocb, cb); + io_prep_poll(iocb, fd, events); + return io_submit(ctx, 1, &iocb); +} + +static inline void io_prep_fsync(struct iocb *iocb, int fd) +{ + iocb->aio_fildes = fd; + iocb->aio_lio_opcode = IO_CMD_FSYNC; + iocb->aio_reqprio = 0; + memset(&iocb->u, 0, sizeof(iocb->u)); +} + +static inline int io_fsync(io_context_t ctx, struct iocb *iocb, io_callback_t cb, int fd) +{ + io_set_callback(iocb, cb); + io_prep_fsync(iocb, fd); + return io_submit(ctx, 1, &iocb); +} + +static inline void io_prep_fdsync(struct iocb *iocb, int fd) +{ + iocb->aio_fildes = fd; + iocb->aio_lio_opcode = IO_CMD_FDSYNC; + iocb->aio_reqprio = 0; + memset(&iocb->u, 0, sizeof(iocb->u)); +} + +static inline int io_fdsync(io_context_t ctx, struct iocb *iocb, io_callback_t cb, int fd) +{ + io_set_callback(iocb, cb); + io_prep_fdsync(iocb, fd); + return io_submit(ctx, 1, &iocb); +} + +#endif diff --git a/src/libaio.map b/src/libaio.map new file mode 100644 index 0000000..8bd3bc2 --- /dev/null +++ b/src/libaio.map @@ -0,0 +1,10 @@ +LIBAIO_0.1 { + global: + io_queue_init; + io_queue_run; + io_queue_wait; + io_cancel; + io_submit; + local: + *; +}; diff --git a/src/vsys_def.h b/src/vsys_def.h new file mode 100644 index 0000000..e61fa4f --- /dev/null +++ b/src/vsys_def.h @@ -0,0 +1,7 @@ +extern int vsys_io_setup(unsigned nr_reqs, io_context_t *ctxp); +extern int vsys_io_destroy(io_context_t ctx); +extern int vsys_io_submit(io_context_t ctx, long nr, struct iocb *iocbs[]); +extern int vsys_io_cancel(io_context_t ctx, struct iocb *iocb); +extern int vsys_io_wait(io_context_t ctx, struct iocb *iocb, struct timespec *when); +extern int vsys_io_getevents(io_context_t ctx_id, long nr, struct io_event *events, struct timespec *timeout); + |