Hi Subrata,
this patch adds eventfd counter overflow test cases.
Michael, there is a small bug in the eventfd() man page. The man page
says that in the select() syscall, exceptfds is set when the counter
overflow occurs. But it is readfds/writefds that is set when the
counter overflows. POLLERR event in poll() is not equivalent to
setting of exceptfds. POLLPRI event in poll() is equivalent to setting
of exceptfds.
Changelog:
* Added eventfd counter overflow test cases.
Signed-off-by: Vijay Kumar <[EMAIL PROTECTED]>
testcases/kernel/syscalls/eventfd/Makefile | 31 ++++++
testcases/kernel/syscalls/eventfd/eventfd01.c | 130 ++++++++++++++++++++++++-
2 files changed, 160 insertions(+), 1 deletions(-)
diff --git a/testcases/kernel/syscalls/eventfd/Makefile
b/testcases/kernel/syscalls/eventfd/Makefile
index e2ebae8..d253431 100644
--- a/testcases/kernel/syscalls/eventfd/Makefile
+++ b/testcases/kernel/syscalls/eventfd/Makefile
@@ -19,10 +19,41 @@
CFLAGS += -I../../../../include -Wall
LDLIBS += -L../../../../lib -lltp
+check_header = $(shell \
+ if echo "\#include <$(1)>" | $(CC) -E - > /dev/null 2>&1 ; \
+ then echo yes ; \
+ else echo no ; fi)
+
+check_aio_eventfd = $(shell \
+ if echo -e \
+ "\#include <libaio.h>\n\
+ int main() \
+ { \
+ io_set_eventfd(NULL, 0); \
+ return 0; \
+ }" | $(CC) -xc -laio - > /dev/null 2>&1 ; \
+ then echo yes ; \
+ else echo no ; fi)
+
+HAS_LIBAIO = $(call check_header,libaio.h)
+HAS_LIBAIO_EVENTFD = $(call check_aio_eventfd)
+
+ifeq ($(HAS_LIBAIO_EVENTFD),yes)
+CFLAGS += -DHAS_AIO_EVENTFD
+LDLIBS += -laio
+endif
+
SRCS = $(wildcard *.c)
TARGETS = $(patsubst %.c, %, $(wildcard *.c))
all: $(TARGETS)
+ifeq ($(HAS_LIBAIO),no)
+ @echo "Note: Libaio is required for testing eventfd overflow testing.";
+else
+ifeq ($(HAS_LIBAIO_EVENTFD),no)
+ @echo "Note: Eventfd support is required in libaio for overflow
testing.";
+endif
+endif
install:
@set -e; for i in $(TARGETS); do ln -f $$i ../../../bin/$$i ; done
diff --git a/testcases/kernel/syscalls/eventfd/eventfd01.c
b/testcases/kernel/syscalls/eventfd/eventfd01.c
index f099248..ea4f8e1 100644
--- a/testcases/kernel/syscalls/eventfd/eventfd01.c
+++ b/testcases/kernel/syscalls/eventfd/eventfd01.c
@@ -53,16 +53,21 @@
#include <errno.h>
#include <string.h>
#include <stdint.h>
+#include <poll.h>
#include <test.h>
#include <usctest.h>
#include <linux_syscall_numbers.h>
+#ifdef HAS_AIO_EVENTFD
+#include <libaio.h>
+#endif
+
static void setup(void);
static void cleanup(void);
char *TCID = "eventfd01";
-int TST_TOTAL = 12;
+int TST_TOTAL = 15;
extern int Tst_count;
static int
@@ -489,6 +494,128 @@ child_inherit_test(int fd)
}
}
+#ifdef HAS_AIO_EVENTFD
+/*
+ * Test whether counter overflow is detected and handled correctly.
+ *
+ * It is not possible to directly overflow the counter using the
+ * write() syscall. Overflows occur when the counter is incremented
+ * from kernel space, in an irq context, when it is not possible to
+ * block the calling thread of execution.
+ *
+ * The AIO subsystem internally uses eventfd mechanism for
+ * notification of completion of read or write requests. In this test
+ * we trigger a counter overflow, by setting the counter value to the
+ * max possible value initially. When the AIO subsystem notifies
+ * through the eventfd counter, the counter overflows.
+ *
+ * NOTE: If the the counter starts from an initial value of 0, it will
+ * take decades for an overflow to occur. But since we set the initial
+ * value to the max possible counter value, we are able to cause it to
+ * overflow with a single increment.
+ *
+ * When the counter overflows, the following are tested
+ * 1. Check whether POLLERR event occurs in poll() for the eventfd.
+ * 2. Check whether readfd_set/writefd_set is set in select() for the
+ eventfd.
+ * 3. The counter value is UINT64_MAX.
+ */
+static void
+counter_overflow_test(int evfd)
+{
+ io_context_t ctx = 0;
+ int fd;
+ int ret;
+ struct iocb iocb;
+ struct iocb *iocbap[1];
+ static char buf[4 * 1024];
+ uint64_t count;
+
+ struct timeval timeout = { 10, 0 };
+ fd_set readfds;
+ struct pollfd pollfd;
+
+ ret = io_setup(16, &ctx);
+ if (ret < 0)
+ tst_resm(TBROK, "io_setup error: %s", strerror(-ret));
+
+ fd = open("testfile", O_RDWR | O_CREAT, 0644);
+ if (fd == -1) {
+ tst_resm(TBROK, "error creating tmp file: %s",
+ strerror(errno));
+ goto err_io_destroy;
+ }
+
+ ret = set_counter(evfd, UINT64_MAX - 1);
+ if (ret == -1)
+ goto err_close_file;
+
+ io_prep_pwrite(&iocb, fd, buf, sizeof(buf), 0);
+ io_set_eventfd(&iocb, evfd);
+
+ iocbap[0] = &iocb;
+ ret = io_submit(ctx, 1, iocbap);
+ if (ret < 0) {
+ tst_resm(TBROK, "error submitting iocb: %s", strerror(-ret));
+ goto err_close_file;
+ }
+
+ FD_ZERO(&readfds);
+ FD_SET(evfd, &readfds);
+ ret = select(evfd + 1, &readfds, NULL, NULL, &timeout);
+ if (ret == -1) {
+ tst_resm(TBROK, "error getting evfd status with select: %s",
+ strerror(errno));
+ goto err_close_file;
+ }
+
+ if (FD_ISSET(evfd, &readfds))
+ tst_resm(TPASS, "read fd set as expected");
+ else
+ tst_resm(TFAIL, "read fd not set");
+
+ pollfd.fd = evfd;
+ pollfd.events = POLLIN;
+ pollfd.revents = 0;
+ ret = poll(&pollfd, 1, 10000);
+ if (ret == -1) {
+ tst_resm(TBROK, "error getting evfd status with poll: %s",
+ strerror(errno));
+ goto err_close_file;
+ }
+ if (pollfd.revents & POLLERR)
+ tst_resm(TPASS, "POLLERR occurred as expected");
+ else
+ tst_resm(TFAIL, "POLLERR did not occur");
+
+ ret = read(evfd, &count, sizeof(count));
+ if (ret == -1) {
+ tst_resm(TBROK, "error reading eventfd: %s", strerror(errno));
+ goto err_close_file;
+ }
+
+ if (count == UINT64_MAX)
+ tst_resm(TPASS, "overflow occurred as expected");
+ else
+ tst_resm(TFAIL, "overflow did not occur");
+
+ err_close_file:
+ close(fd);
+
+ err_io_destroy:
+ io_destroy(ctx);
+}
+#else
+static void
+counter_overflow_test(int evfd)
+{
+ tst_resm(TCONF, "eventfd support is not available in AIO subsystem");
+ tst_resm(TCONF, "eventfd support is not available in AIO subsystem");
+ tst_resm(TCONF, "eventfd support is not available in AIO subsystem");
+ return;
+}
+#endif
+
int
main(int argc, char **argv)
{
@@ -536,6 +663,7 @@ main(int argc, char **argv)
writefd_set_test(fd);
writefd_not_set_test(fd);
child_inherit_test(fd);
+ counter_overflow_test(fd);
close(fd);
}
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list