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

Reply via email to