Hi Viaj On Tue, Aug 12, 2008 at 7:57 PM, Vijay Kumar <[EMAIL PROTECTED]> wrote: > 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.
( http://www.kernel.org/doc/man-pages/online/pages/man2/eventfd.2.html ) Thanks for spotting that. I'm not sure why I wrote the text they way I did. But now that you point it out, I consider the behavior a design error. If I'd correctly described the behavior at the start, I would have seen that, and suggested to Davide to change the interface so that it uses POLLPRI, not POLLERR, (and thus select() exceptfds) to notify the overflow condition. The problem with the current behavior is that using select() it is impossible to distinguish the overflow condition from the normal case where the eventfd has some non-zero value (and is thus both readable and writable). For ABI stability reasons, I guess we probably can't fix this now. Maybe Davide has some thoughts to offer. Cheers, Michael > * 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); > } > -- Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ man-pages online: http://www.kernel.org/doc/man-pages/online_pages.html Found a bug? http://www.kernel.org/doc/man-pages/reporting_bugs.html ------------------------------------------------------------------------- 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
