summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--INSTALL7
-rw-r--r--TODO4
-rw-r--r--src/Makefile48
-rw-r--r--src/io_cancel.c9
-rw-r--r--src/io_queue_init.c16
-rw-r--r--src/io_queue_run.c24
-rw-r--r--src/io_queue_wait.c15
-rw-r--r--src/io_submit.c12
-rw-r--r--src/lib/src/Makefile30
-rw-r--r--src/lib/src/kso_init.c48
-rw-r--r--src/lib/src/libredhat-kernel.map11
-rw-r--r--src/lib/src/myln.c25
-rw-r--r--src/lib/src/stub.S18
-rw-r--r--src/lib/src/vsysaddr.S7
-rw-r--r--src/libaio.h184
-rw-r--r--src/libaio.map10
-rw-r--r--src/vsys_def.h7
17 files changed, 475 insertions, 0 deletions
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..62340b6
--- /dev/null
+++ b/INSTALL
@@ -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.
+
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..0a9ac15
--- /dev/null
+++ b/TODO
@@ -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);
+