Imported Upstream version 0.3.112 upstream/0.3.112
authorDongHun Kwak <dh0128.kwak@samsung.com>
Mon, 20 Dec 2021 05:34:02 +0000 (14:34 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Mon, 20 Dec 2021 05:34:02 +0000 (14:34 +0900)
14 files changed:
Makefile
README.md [new file with mode: 0644]
harness/cases/22.t [new file with mode: 0644]
libaio.spec
man/io_getevents.3
src/Makefile
src/aio_ring.h [new file with mode: 0644]
src/io_getevents.c
src/io_pgetevents.c [new file with mode: 0644]
src/libaio.h
src/libaio.map
src/syscall-i386.h
src/syscall-x86_64.h
src/syscall.h

index e9dbdb0..c1fb831 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -14,7 +14,7 @@ all:
        @$(MAKE) -C src
 
 install:
-       @$(MAKE) -C src install prefix=$(prefix) includedir=$(includedir) libdir=$(libdir)
+       @$(MAKE) -C src install prefix=$(DESTDIR)$(prefix) includedir=$(DESTDIR)$(includedir) libdir=$(DESTDIR)$(libdir)
 
 check:
        @$(MAKE) -C harness check
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..692f4a7
--- /dev/null
+++ b/README.md
@@ -0,0 +1,12 @@
+# libaio
+
+The Linux-native asynchronous I/O facility ("async I/O", or "aio") has a
+richer API and capability set than the simple POSIX async I/O facility.
+This library, libaio, provides the Linux-native API for async I/O.
+The POSIX async I/O facility requires this library in order to provide
+kernel-accelerated async I/O capabilities, as do applications which
+require the Linux-native async I/O API.
+
+## Contributing
+
+Patches should be submitted to linux-aio@kvack.org.
diff --git a/harness/cases/22.t b/harness/cases/22.t
new file mode 100644 (file)
index 0000000..c7428a8
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2006-2018 Free Software Foundation, Inc.
+ * Copyright (C) 2018 Christoph Hellwig.
+ * License: LGPLv2.1 or later.
+ *
+ * Description: test aio poll and io_pgetevents signal handling.
+ *
+ * Very roughly based on glibc tst-pselect.c.
+ */
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/poll.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+
+static volatile int handler_called;
+
+static void
+handler(int sig)
+{
+       handler_called = 1;
+}
+
+int test_main(void)
+{
+       struct timespec to = { .tv_sec = 0, .tv_nsec = 500000000 };
+       pid_t parent = getpid(), p;
+       int pipe1[2], pipe2[2];
+       struct sigaction sa = { .sa_flags = 0 };
+       sigset_t sigmask;
+       struct io_context *ctx = NULL;
+       struct io_event ev;
+       struct iocb iocb;
+       struct iocb *iocbs[] = { &iocb };
+       int ret;
+
+       sigemptyset(&sa.sa_mask);
+
+       sa.sa_handler = handler;
+       if (sigaction(SIGUSR1, &sa, NULL) != 0) {
+               printf("sigaction(1) failed\n");
+               return 1;
+       }
+
+       sa.sa_handler = SIG_IGN;
+       if (sigaction(SIGCHLD, &sa, NULL) != 0) {
+               printf("sigaction(2) failed\n");
+               return 1;
+       }
+
+       sigemptyset(&sigmask);
+       sigaddset(&sigmask, SIGUSR1);
+       if (sigprocmask(SIG_BLOCK, &sigmask, NULL) != 0) {
+               printf("sigprocmask failed\n");
+               return 1;
+       }
+
+       if (pipe(pipe1) != 0 || pipe(pipe2) != 0) {
+               printf("pipe failed\n");
+               return 1;
+       }
+
+       sigprocmask(SIG_SETMASK, NULL, &sigmask);
+       sigdelset(&sigmask, SIGUSR1);
+
+       p = fork();
+       switch (p) {
+       case -1:
+               printf("fork failed\n");
+               exit(2);
+       case 0:
+               close(pipe1[1]);
+               close(pipe2[0]);
+
+               ret = io_setup(1, &ctx);
+               if (ret) {
+                       printf("child: io_setup failed\n");
+                       return 1;
+               }
+
+               io_prep_poll(&iocb, pipe1[0], POLLIN);
+               ret = io_submit(ctx, 1, iocbs);
+               if (ret != 1) {
+                       printf("child: io_submit failed\n");
+                       return 1;
+               }
+
+               do {
+                       if (getppid() != parent) {
+                               printf("parent died\n");
+                               exit(2);
+                       }
+                       ret = io_pgetevents(ctx, 1, 1, &ev, &to, &sigmask);
+               } while (ret == 0);
+
+               if (ret != -EINTR) {
+                       printf("child: io_pgetevents did not set errno to EINTR\n");
+                       return 1;
+               }
+
+               do {
+                       errno = 0;
+                       ret = write(pipe2[1], "foo", 3);
+               } while (ret == -1 && errno == EINTR);
+
+               exit(0);
+       default:
+               close(pipe1[0]);
+               close(pipe2[1]);
+
+               io_prep_poll(&iocb, pipe2[0], POLLIN);
+
+               ret = io_setup(1, &ctx);
+               if (ret) {
+                       printf("parent: io_setup failed\n");
+                       return 1;
+               }
+
+               ret = io_submit(ctx, 1, iocbs);
+               if (ret != 1) {
+                       printf("parent: io_submit failed\n");
+                       return 1;
+               }
+
+               kill(p, SIGUSR1);
+
+               ret = io_pgetevents(ctx, 1, 1, &ev, NULL, &sigmask);
+               if (ret < 0) {
+                       printf("parent: io_pgetevents failed\n");
+                       return 1;
+               }
+               if (ret != 1) {
+                       printf("parent: io_pgetevents did not report event\n");
+                       return 1;
+               }
+               if (ev.obj != &iocb) {
+                       printf("parent: io_pgetevents reports wrong fd\n");
+                       return 1;
+               }
+               if ((ev.res & POLLIN) != POLLIN) {
+                       printf("parent: io_pgetevents did not report readable fd\n");
+                       return 1;
+               }
+
+               return 0;
+       }
+}
index 455bb6b..d1fa2cc 100644 (file)
@@ -1,5 +1,5 @@
 Name: libaio
-Version: 0.3.111
+Version: 0.3.112
 Release: 1
 Summary: Linux-native asynchronous I/O access library
 License: LGPL
@@ -36,9 +36,7 @@ make
 %install
 [ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT
 
-make install prefix=$RPM_BUILD_ROOT/usr \
- libdir=$RPM_BUILD_ROOT/%{_libdir} \
- root=$RPM_BUILD_ROOT
+make install DESTDIR=$RPM_BUILD_ROOT prefix=/usr libdir=/%{_libdir}
 
 %clean
 [ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT
@@ -59,6 +57,11 @@ make install prefix=$RPM_BUILD_ROOT/usr \
 %attr(0644,root,root) %{_libdir}/libaio.a
 
 %changelog
+* Mon Oct 22 2018 Jeff Moyer <jmoyer@redhat.com> - 0.3.112-1
+- Add async poll support (Christoph Hellwig)
+- Use canonical DESTDIR= environment variable (Thomas Petazzoni)
+- Add ability to disable building the shared library (Thomas Petazzoni)
+
 * Tue Mar  6 2018 Jeff Moyer <jmoyer@redhat.com> - 0.3.111-1
 - Add two new tests to the test harness (Jeff Moyer)
 - Generic arch dectection for padding defines (Nathan Rossi)
index 8e9ddc8..5062daa 100644 (file)
@@ -18,7 +18,7 @@
 ./"
 .TH io_getevents 2 2002-09-03 "Linux 2.4" "Linux AIO"
 .SH NAME
-io_getevents \- Read resulting events from io requests
+io_getevents, aio_pgetevents \- Read resulting events from io requests
 .SH SYNOPSIS
 .nf
 .B #include <errno.h>
@@ -43,7 +43,7 @@ struct io_event {
 };
 .sp
 .BI "int io_getevents(io_context_t " ctx ",  long " nr ", struct io_event *" events "[], struct timespec *" timeout ");"
-
+.BI "int io_pgetevents(io_context_t " ctx ",  long " nr ", struct io_event *" events "[], struct timespec *" timeout ", sigset_t *" sigmask ");"
 .fi
 .SH DESCRIPTION
 Attempts to read  up to nr events from
@@ -55,6 +55,60 @@ by when has elapsed, where when == NULL specifies an infinite
 timeout.  Note that the timeout pointed to by when is relative and
 will be updated if not NULL and the operation blocks.  Will fail
 with ENOSYS if not implemented.
+.SS io_pgetevents()
+The relationship between
+.BR io_getevents ()
+and
+.BR io_pgetevents ()
+is analogous to the relationship between
+.BR select (2)
+and
+.BR pselect (2):
+similar
+.BR pselect (2),
+.BR pgetevents ()
+allows an application to safely wait until either an aio completion
+events happens or until a signal is caught.
+.PP
+The following
+.BR io_pgetevents ()
+call:
+call:
+.PP
+.in +4n
+.EX
+ret = io_pgetevents(ctx, min_nr, nr, events, timeout, sigmask);
+.EE
+.in
+.PP
+is equivalent to
+.I atomically
+executing the following calls:
+.PP
+.in +4n
+.EX
+sigset_t origmask;
+
+pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
+ret = io_getevents(ctx, min_nr, nr, events, timeout);
+pthread_sigmask(SIG_SETMASK, &origmask, NULL);
+.EE
+.in
+.PP
+See the description of
+.BR pselect (2)
+for an explanation of why
+.BR io_pgetevents ()
+is necessary.
+.PP
+If the
+.I sigmask
+argument is specified as NULL, then no signal mask manipulation is
+performed (and thus
+.BR io_pgetevents ()
+behaves the same as
+.BR io_getevents()
+) .
 .SH ERRORS
 .TP
 .B EINVAL 
@@ -76,4 +130,5 @@ if any of the memory specified to is invalid.
 .BR io_queue_wait(3),
 .BR io_set_callback(3),
 .BR io_submit(3),
-.BR errno(3)
+.BR errno(3),
+.BR pselect(2)
index eadb336..37ae219 100644 (file)
@@ -3,17 +3,22 @@ includedir=$(prefix)/include
 libdir=$(prefix)/lib
 
 CFLAGS ?= -g -fomit-frame-pointer -O2
-CFLAGS += -nostdlib -nostartfiles -Wall -I. -fPIC
+CFLAGS += -Wall -I. -fPIC
 SO_CFLAGS=-shared $(CFLAGS)
 L_CFLAGS=$(CFLAGS)
 LINK_FLAGS=
 LINK_FLAGS+=$(LDFLAGS)
+ENABLE_SHARED ?= 1
 
 soname=libaio.so.1
 minor=0
 micro=1
 libname=$(soname).$(minor).$(micro)
-all_targets += libaio.a $(libname)
+all_targets += libaio.a
+
+ifeq ($(ENABLE_SHARED),1)
+all_targets += $(libname)
+endif
 
 all: $(all_targets)
 
@@ -23,7 +28,7 @@ libaio_srcs += io_queue_wait.c io_queue_run.c
 
 # real syscalls
 libaio_srcs += io_getevents.c io_submit.c io_cancel.c
-libaio_srcs += io_setup.c io_destroy.c
+libaio_srcs += io_setup.c io_destroy.c io_pgetevents.c
 
 # internal functions
 libaio_srcs += raw_syscall.c
@@ -55,9 +60,11 @@ $(libname): $(libaio_sobjs) libaio.map
 install: $(all_targets)
        install -D -m 644 libaio.h $(includedir)/libaio.h
        install -D -m 644 libaio.a $(libdir)/libaio.a
+ifeq ($(ENABLE_SHARED),1)
        install -D -m 755 $(libname) $(libdir)/$(libname)
        ln -sf $(libname) $(libdir)/$(soname)
        ln -sf $(libname) $(libdir)/libaio.so
+endif
 
 $(libaio_objs): libaio.h
 
diff --git a/src/aio_ring.h b/src/aio_ring.h
new file mode 100644 (file)
index 0000000..3842c4b
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+   libaio Linux async I/O interface
+   Copyright 2002 Red Hat, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ */
+#ifndef _AIO_RING_H
+#define _AIO_RING_H
+
+#define AIO_RING_MAGIC                  0xa10a10a1
+
+struct aio_ring {
+       unsigned        id;     /* kernel internal index number */
+       unsigned        nr;     /* number of io_events */
+       unsigned        head;
+       unsigned        tail;
+
+       unsigned        magic;
+       unsigned        compat_features;
+       unsigned        incompat_features;
+       unsigned        header_length;  /* size of aio_ring */
+};
+
+static inline int aio_ring_is_empty(io_context_t ctx, struct timespec *timeout)
+{
+       struct aio_ring *ring = (struct aio_ring *)ctx;
+
+       if (!ring || ring->magic != AIO_RING_MAGIC)
+               return 0;
+       if (!timeout || timeout->tv_sec || timeout->tv_nsec)
+               return 0;
+       if (ring->head != ring->tail)
+               return 0;
+       return 1;
+}
+
+#endif /* _AIO_RING_H */
index 5a05174..90d6081 100644 (file)
 #include <stdlib.h>
 #include <time.h>
 #include "syscall.h"
+#include "aio_ring.h"
 
 io_syscall5(int, __io_getevents_0_4, io_getevents, io_context_t, ctx, long, min_nr, long, nr, struct io_event *, events, struct timespec *, timeout)
 
-#define AIO_RING_MAGIC                  0xa10a10a1
-
-/* Ben will hate me for this */
-struct aio_ring {
-       unsigned        id;     /* kernel internal index number */
-       unsigned        nr;     /* number of io_events */
-       unsigned        head;
-       unsigned        tail;
-       unsigned        magic;
-       unsigned        compat_features;
-       unsigned        incompat_features;
-       unsigned        header_length;  /* size of aio_ring */
-};
-
 int io_getevents_0_4(io_context_t ctx, long min_nr, long nr, struct io_event * events, struct timespec * timeout)
 {
-       struct aio_ring *ring;
-       ring = (struct aio_ring*)ctx;
-       if (ring==NULL || ring->magic != AIO_RING_MAGIC)
-               goto do_syscall;
-       if (timeout!=NULL && timeout->tv_sec == 0 && timeout->tv_nsec == 0) {
-               if (ring->head == ring->tail)
-                       return 0;
-       }
-       
-do_syscall:    
+       if (aio_ring_is_empty(ctx, timeout))
+               return 0;
        return __io_getevents_0_4(ctx, min_nr, nr, events, timeout);
 }
 
diff --git a/src/io_pgetevents.c b/src/io_pgetevents.c
new file mode 100644 (file)
index 0000000..e6b0614
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+   libaio Linux async I/O interface
+   Copyright 2018 Christoph Hellwig.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ */
+#include <libaio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+#include <signal.h>
+#include "syscall.h"
+#include "aio_ring.h"
+
+#ifdef __NR_io_pgetevents
+io_syscall6(int, __io_pgetevents, io_pgetevents, io_context_t, ctx, long,
+               min_nr, long, nr, struct io_event *, events,
+               struct timespec *, timeout, void *, sigmask);
+
+int io_pgetevents(io_context_t ctx, long min_nr, long nr,
+               struct io_event *events, struct timespec *timeout,
+               sigset_t *sigmask)
+{
+       struct {
+               unsigned long ss;
+               unsigned long ss_len;
+       } data;
+
+       if (aio_ring_is_empty(ctx, timeout))
+               return 0;
+
+       data.ss = (unsigned long)sigmask;
+       data.ss_len = _NSIG / 8;
+       return __io_pgetevents(ctx, min_nr, nr, events, timeout, &data);
+}
+#else
+int io_pgetevents(io_context_t ctx, long min_nr, long nr,
+               struct io_event *events, struct timespec *timeout,
+               sigset_t *sigmask)
+
+{
+       return -ENOSYS;
+}
+#endif /* __NR_io_pgetevents */
index 564e680..2bc24e0 100644 (file)
@@ -29,6 +29,7 @@ extern "C" {
 
 #include <sys/types.h>
 #include <string.h>
+#include <signal.h>
 
 struct timespec;
 struct sockaddr;
@@ -43,7 +44,7 @@ typedef enum io_iocb_cmd {
        IO_CMD_FSYNC = 2,
        IO_CMD_FDSYNC = 3,
 
-       IO_CMD_POLL = 5, /* Never implemented in mainline, see io_prep_poll */
+       IO_CMD_POLL = 5,
        IO_CMD_NOOP = 6,
        IO_CMD_PREADV = 7,
        IO_CMD_PWRITEV = 8,
@@ -162,6 +163,9 @@ extern int io_destroy(io_context_t ctx);
 extern int io_submit(io_context_t ctx, long nr, struct iocb *ios[]);
 extern int io_cancel(io_context_t ctx, struct iocb *iocb, struct io_event *evt);
 extern int io_getevents(io_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct timespec *timeout);
+extern int io_pgetevents(io_context_t ctx_id, long min_nr, long nr,
+               struct io_event *events, struct timespec *timeout,
+               sigset_t *sigmask);
 
 
 static inline void io_set_callback(struct iocb *iocb, io_callback_t cb)
@@ -237,8 +241,6 @@ static inline void io_prep_pwritev2(struct iocb *iocb, int fd, const struct iove
        iocb->u.c.offset = offset;
 }
 
-/* Jeff Moyer says this was implemented in Red Hat AS2.1 and RHEL3.
- * AFAICT, it was never in mainline, and should not be used. --RR */
 static inline void io_prep_poll(struct iocb *iocb, int fd, int events)
 {
         memset(iocb, 0, sizeof(*iocb));
index dc37725..ec9d13b 100644 (file)
@@ -20,3 +20,8 @@ LIBAIO_0.4 {
                io_getevents;
                io_queue_wait;
 } LIBAIO_0.1;
+
+LIBAIO_0.5 {
+       global:
+               io_pgetevents;
+} LIBAIO_0.4;
index 266ed93..bc66bb1 100644 (file)
@@ -3,3 +3,4 @@
 #define __NR_io_getevents      247
 #define __NR_io_submit         248
 #define __NR_io_cancel         249
+#define __NR_io_pgetevents     385
index 84b2639..0eccef3 100644 (file)
@@ -3,3 +3,4 @@
 #define __NR_io_getevents      208
 #define __NR_io_submit         209
 #define __NR_io_cancel         210
+#define __NR_io_pgetevents     333
index 9b9e9c1..b53da4c 100644 (file)
@@ -64,3 +64,10 @@ _body_io_syscall(sname, (long)arg1, (long)arg2, (long)arg3, (long)arg4)
 #define io_syscall5(type,fname,sname,type1,arg1,type2,arg2,type3,arg3,type4,arg4, type5,arg5) \
 type fname (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
 _body_io_syscall(sname, (long)arg1, (long)arg2, (long)arg3, (long)arg4, (long)arg5)
+
+#define io_syscall6(type,fname,sname,type1,arg1,type2,arg2,type3,arg3, \
+               type4,arg4,type5,arg5,type6,arg6) \
+type fname (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
+               type6 arg6) \
+_body_io_syscall(sname, (long)arg1, (long)arg2, (long)arg3, (long)arg4, \
+               (long)arg5, (long)arg6)