Path: blob/master/tools/testing/selftests/filesystems/eventfd/eventfd_test.c
26305 views
// SPDX-License-Identifier: GPL-2.012#define _GNU_SOURCE3#include <errno.h>4#include <fcntl.h>5#include <asm/unistd.h>6#include <linux/time_types.h>7#include <unistd.h>8#include <assert.h>9#include <signal.h>10#include <pthread.h>11#include <sys/epoll.h>12#include <sys/eventfd.h>13#include "../../kselftest_harness.h"1415#define EVENTFD_TEST_ITERATIONS 100000UL1617struct error {18int code;19char msg[512];20};2122static int error_set(struct error *err, int code, const char *fmt, ...)23{24va_list args;25int r;2627if (code == 0 || !err || err->code != 0)28return code;2930err->code = code;31va_start(args, fmt);32r = vsnprintf(err->msg, sizeof(err->msg), fmt, args);33assert((size_t)r < sizeof(err->msg));34va_end(args);3536return code;37}3839static inline int sys_eventfd2(unsigned int count, int flags)40{41return syscall(__NR_eventfd2, count, flags);42}4344TEST(eventfd_check_flag_rdwr)45{46int fd, flags;4748fd = sys_eventfd2(0, 0);49ASSERT_GE(fd, 0);5051flags = fcntl(fd, F_GETFL);52// The kernel automatically adds the O_RDWR flag.53EXPECT_EQ(flags, O_RDWR);5455close(fd);56}5758TEST(eventfd_check_flag_cloexec)59{60int fd, flags;6162fd = sys_eventfd2(0, EFD_CLOEXEC);63ASSERT_GE(fd, 0);6465flags = fcntl(fd, F_GETFD);66ASSERT_GT(flags, -1);67EXPECT_EQ(flags, FD_CLOEXEC);6869close(fd);70}7172TEST(eventfd_check_flag_nonblock)73{74int fd, flags;7576fd = sys_eventfd2(0, EFD_NONBLOCK);77ASSERT_GE(fd, 0);7879flags = fcntl(fd, F_GETFL);80ASSERT_GT(flags, -1);81EXPECT_EQ(flags & EFD_NONBLOCK, EFD_NONBLOCK);82EXPECT_EQ(flags & O_RDWR, O_RDWR);8384close(fd);85}8687TEST(eventfd_check_flag_cloexec_and_nonblock)88{89int fd, flags;9091fd = sys_eventfd2(0, EFD_CLOEXEC|EFD_NONBLOCK);92ASSERT_GE(fd, 0);9394flags = fcntl(fd, F_GETFL);95ASSERT_GT(flags, -1);96EXPECT_EQ(flags & EFD_NONBLOCK, EFD_NONBLOCK);97EXPECT_EQ(flags & O_RDWR, O_RDWR);9899flags = fcntl(fd, F_GETFD);100ASSERT_GT(flags, -1);101EXPECT_EQ(flags, FD_CLOEXEC);102103close(fd);104}105106static inline void trim_newline(char *str)107{108char *pos = strrchr(str, '\n');109110if (pos)111*pos = '\0';112}113114static int verify_fdinfo(int fd, struct error *err, const char *prefix,115size_t prefix_len, const char *expect, ...)116{117char buffer[512] = {0, };118char path[512] = {0, };119va_list args;120FILE *f;121char *line = NULL;122size_t n = 0;123int found = 0;124int r;125126va_start(args, expect);127r = vsnprintf(buffer, sizeof(buffer), expect, args);128assert((size_t)r < sizeof(buffer));129va_end(args);130131snprintf(path, sizeof(path), "/proc/self/fdinfo/%d", fd);132f = fopen(path, "re");133if (!f)134return error_set(err, -1, "fdinfo open failed for %d", fd);135136while (getline(&line, &n, f) != -1) {137char *val;138139if (strncmp(line, prefix, prefix_len))140continue;141142found = 1;143144val = line + prefix_len;145r = strcmp(val, buffer);146if (r != 0) {147trim_newline(line);148trim_newline(buffer);149error_set(err, -1, "%s '%s' != '%s'",150prefix, val, buffer);151}152break;153}154155free(line);156fclose(f);157158if (found == 0)159return error_set(err, -1, "%s not found for fd %d",160prefix, fd);161162return 0;163}164165TEST(eventfd_check_flag_semaphore)166{167struct error err = {0};168int fd, ret;169170fd = sys_eventfd2(0, EFD_SEMAPHORE);171ASSERT_GE(fd, 0);172173ret = fcntl(fd, F_GETFL);174ASSERT_GT(ret, -1);175EXPECT_EQ(ret & O_RDWR, O_RDWR);176177// The semaphore could only be obtained from fdinfo.178ret = verify_fdinfo(fd, &err, "eventfd-semaphore: ", 19, "1\n");179if (ret != 0)180ksft_print_msg("eventfd semaphore flag check failed: %s\n", err.msg);181EXPECT_EQ(ret, 0);182183close(fd);184}185186/*187* A write(2) fails with the error EINVAL if the size of the supplied buffer188* is less than 8 bytes, or if an attempt is made to write the value189* 0xffffffffffffffff.190*/191TEST(eventfd_check_write)192{193uint64_t value = 1;194ssize_t size;195int fd;196197fd = sys_eventfd2(0, 0);198ASSERT_GE(fd, 0);199200size = write(fd, &value, sizeof(int));201EXPECT_EQ(size, -1);202EXPECT_EQ(errno, EINVAL);203204size = write(fd, &value, sizeof(value));205EXPECT_EQ(size, sizeof(value));206207value = (uint64_t)-1;208size = write(fd, &value, sizeof(value));209EXPECT_EQ(size, -1);210EXPECT_EQ(errno, EINVAL);211212close(fd);213}214215/*216* A read(2) fails with the error EINVAL if the size of the supplied buffer is217* less than 8 bytes.218*/219TEST(eventfd_check_read)220{221uint64_t value;222ssize_t size;223int fd;224225fd = sys_eventfd2(1, 0);226ASSERT_GE(fd, 0);227228size = read(fd, &value, sizeof(int));229EXPECT_EQ(size, -1);230EXPECT_EQ(errno, EINVAL);231232size = read(fd, &value, sizeof(value));233EXPECT_EQ(size, sizeof(value));234EXPECT_EQ(value, 1);235236close(fd);237}238239240/*241* If EFD_SEMAPHORE was not specified and the eventfd counter has a nonzero242* value, then a read(2) returns 8 bytes containing that value, and the243* counter's value is reset to zero.244* If the eventfd counter is zero at the time of the call to read(2), then the245* call fails with the error EAGAIN if the file descriptor has been made nonblocking.246*/247TEST(eventfd_check_read_with_nonsemaphore)248{249uint64_t value;250ssize_t size;251int fd;252int i;253254fd = sys_eventfd2(0, EFD_NONBLOCK);255ASSERT_GE(fd, 0);256257value = 1;258for (i = 0; i < EVENTFD_TEST_ITERATIONS; i++) {259size = write(fd, &value, sizeof(value));260EXPECT_EQ(size, sizeof(value));261}262263size = read(fd, &value, sizeof(value));264EXPECT_EQ(size, sizeof(uint64_t));265EXPECT_EQ(value, EVENTFD_TEST_ITERATIONS);266267size = read(fd, &value, sizeof(value));268EXPECT_EQ(size, -1);269EXPECT_EQ(errno, EAGAIN);270271close(fd);272}273274/*275* If EFD_SEMAPHORE was specified and the eventfd counter has a nonzero value,276* then a read(2) returns 8 bytes containing the value 1, and the counter's277* value is decremented by 1.278* If the eventfd counter is zero at the time of the call to read(2), then the279* call fails with the error EAGAIN if the file descriptor has been made nonblocking.280*/281TEST(eventfd_check_read_with_semaphore)282{283uint64_t value;284ssize_t size;285int fd;286int i;287288fd = sys_eventfd2(0, EFD_SEMAPHORE|EFD_NONBLOCK);289ASSERT_GE(fd, 0);290291value = 1;292for (i = 0; i < EVENTFD_TEST_ITERATIONS; i++) {293size = write(fd, &value, sizeof(value));294EXPECT_EQ(size, sizeof(value));295}296297for (i = 0; i < EVENTFD_TEST_ITERATIONS; i++) {298size = read(fd, &value, sizeof(value));299EXPECT_EQ(size, sizeof(value));300EXPECT_EQ(value, 1);301}302303size = read(fd, &value, sizeof(value));304EXPECT_EQ(size, -1);305EXPECT_EQ(errno, EAGAIN);306307close(fd);308}309310TEST_HARNESS_MAIN311312313