Add kernel API specification for the epoll_ctl() system call. Signed-off-by: Sasha Levin <sas...@kernel.org> --- fs/eventpoll.c | 203 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+)
diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 50adea7ba43d1..409a0c440f112 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -2647,6 +2647,209 @@ int do_epoll_ctl(int epfd, int op, int fd, struct epoll_event *epds, * the eventpoll file that enables the insertion/removal/change of * file descriptors inside the interest set. */ + +/* Valid values for epoll_ctl op parameter */ +static const s64 epoll_ctl_valid_ops[] = { + EPOLL_CTL_ADD, + EPOLL_CTL_DEL, + EPOLL_CTL_MOD, +}; + +DEFINE_KERNEL_API_SPEC(sys_epoll_ctl) + KAPI_DESCRIPTION("Control interface for an epoll file descriptor") + KAPI_LONG_DESC("Performs control operations on the epoll instance referred to by epfd. " + "It requests that the operation op be performed for the target file " + "descriptor fd. Valid operations are adding, modifying, or deleting " + "file descriptors from the interest set.") + KAPI_CONTEXT(KAPI_CTX_PROCESS | KAPI_CTX_SLEEPABLE) + + KAPI_PARAM(0, "epfd", "int", "File descriptor referring to the epoll instance") + KAPI_PARAM_FLAGS(KAPI_PARAM_IN) + .type = KAPI_TYPE_FD, + .constraint_type = KAPI_CONSTRAINT_NONE, + KAPI_PARAM_END + + KAPI_PARAM(1, "op", "int", "Operation to be performed") + KAPI_PARAM_FLAGS(KAPI_PARAM_IN) + .type = KAPI_TYPE_INT, + .constraint_type = KAPI_CONSTRAINT_ENUM, + .enum_values = epoll_ctl_valid_ops, + .enum_count = ARRAY_SIZE(epoll_ctl_valid_ops), + .constraints = "Must be EPOLL_CTL_ADD, EPOLL_CTL_DEL, or EPOLL_CTL_MOD", + KAPI_PARAM_END + + KAPI_PARAM(2, "fd", "int", "File descriptor to be monitored") + KAPI_PARAM_FLAGS(KAPI_PARAM_IN) + .type = KAPI_TYPE_FD, + .constraint_type = KAPI_CONSTRAINT_NONE, + .constraints = "Must refer to a file that supports poll operations", + KAPI_PARAM_END + + KAPI_PARAM(3, "event", "struct epoll_event __user *", "Settings for the file descriptor") + KAPI_PARAM_FLAGS(KAPI_PARAM_IN | KAPI_PARAM_USER | KAPI_PARAM_OPTIONAL) + .type = KAPI_TYPE_USER_PTR, + KAPI_PARAM_SIZE(sizeof(struct epoll_event)) + .constraints = "Required for ADD and MOD operations, ignored for DEL", + KAPI_PARAM_END + + KAPI_RETURN("long", "0 on success, negative error code on failure") + .type = KAPI_TYPE_INT, + .check_type = KAPI_RETURN_EXACT, + KAPI_RETURN_SUCCESS(0) + KAPI_RETURN_END + + KAPI_ERROR(0, -EBADF, "EBADF", "epfd or fd is not a valid file descriptor", + "One of the file descriptors is invalid or has been closed.") + KAPI_ERROR(1, -EEXIST, "EEXIST", "op is EPOLL_CTL_ADD and fd is already registered", + "The file descriptor is already present in the epoll instance.") + KAPI_ERROR(2, -EINVAL, "EINVAL", "Invalid operation or parameters", + "epfd is not an epoll file descriptor, epfd == fd, op is not valid, " + "or EPOLLEXCLUSIVE was specified with invalid events.") + KAPI_ERROR(3, -ENOENT, "ENOENT", "op is EPOLL_CTL_MOD or EPOLL_CTL_DEL and fd is not registered", + "The file descriptor is not registered with this epoll instance.") + KAPI_ERROR(4, -ENOMEM, "ENOMEM", "Insufficient kernel memory", + "There was insufficient memory to handle the requested operation.") + KAPI_ERROR(5, -EPERM, "EPERM", "Target file does not support epoll", + "The target file fd does not support poll operations.") + KAPI_ERROR(6, -ELOOP, "ELOOP", "Circular monitoring detected", + "fd refers to an epoll instance and this operation would result " + "in a circular loop of epoll instances monitoring one another.") + KAPI_ERROR(7, -EFAULT, "EFAULT", "event points outside accessible address space", + "The memory area pointed to by event is not accessible with write permissions.") + KAPI_ERROR(8, -EAGAIN, "EAGAIN", "Nonblocking mode and lock not available", + "The operation was called in nonblocking mode and could not acquire necessary locks.") + KAPI_ERROR(9, -ENOSPC, "ENOSPC", "User epoll watch limit exceeded", + "The limit on the total number of epoll watches was exceeded. " + "See /proc/sys/fs/epoll/max_user_watches.") + KAPI_ERROR(10, -EINTR, "EINTR", "Interrupted by signal", + "The system call was interrupted by a signal before completion.") + + .error_count = 11, + .param_count = 4, + .since_version = "2.6", + + /* Locking specifications */ + KAPI_LOCK(0, "ep->mtx", KAPI_LOCK_MUTEX) + KAPI_LOCK_ACQUIRED + KAPI_LOCK_RELEASED + KAPI_LOCK_DESC("Protects the epoll instance during control operations") + KAPI_LOCK_END + + KAPI_LOCK(1, "epnested_mutex", KAPI_LOCK_MUTEX) + KAPI_LOCK_DESC("Global mutex to prevent circular epoll structures (acquired for nested epoll)") + KAPI_LOCK_END + + .lock_count = 2, + + /* Side effects */ + KAPI_SIDE_EFFECT(0, KAPI_EFFECT_MODIFY_STATE | KAPI_EFFECT_ALLOC_MEMORY, + "epoll interest list", + "Adds new epitem structure to the epoll interest list") + KAPI_EFFECT_CONDITION("When op is EPOLL_CTL_ADD") + KAPI_EFFECT_REVERSIBLE + KAPI_SIDE_EFFECT_END + + KAPI_SIDE_EFFECT(1, KAPI_EFFECT_MODIFY_STATE | KAPI_EFFECT_FREE_MEMORY, + "epoll interest list", + "Removes epitem structure from the epoll interest list") + KAPI_EFFECT_CONDITION("When op is EPOLL_CTL_DEL") + KAPI_EFFECT_REVERSIBLE + KAPI_SIDE_EFFECT_END + + KAPI_SIDE_EFFECT(2, KAPI_EFFECT_MODIFY_STATE, + "epoll event mask", + "Modifies the event mask for an existing epitem") + KAPI_EFFECT_CONDITION("When op is EPOLL_CTL_MOD") + KAPI_EFFECT_REVERSIBLE + KAPI_SIDE_EFFECT_END + + KAPI_SIDE_EFFECT(3, KAPI_EFFECT_MODIFY_STATE, + "file reference count", + "Increases reference count on the monitored file") + KAPI_EFFECT_CONDITION("When op is EPOLL_CTL_ADD") + KAPI_EFFECT_REVERSIBLE + KAPI_SIDE_EFFECT_END + + KAPI_SIDE_EFFECT(4, KAPI_EFFECT_MODIFY_STATE, + "file reference count", + "Decreases reference count on the monitored file") + KAPI_EFFECT_CONDITION("When op is EPOLL_CTL_DEL") + KAPI_EFFECT_REVERSIBLE + KAPI_SIDE_EFFECT_END + + KAPI_SIDE_EFFECT(5, KAPI_EFFECT_SCHEDULE, + "process state", + "May wake up processes waiting on the epoll instance if events become available") + KAPI_EFFECT_CONDITION("When adding or modifying entries that match current events") + KAPI_SIDE_EFFECT_END + + KAPI_SIDE_EFFECT_COUNT(6) + + /* State transitions */ + KAPI_STATE_TRANS(0, "epoll entry", "non-existent", "monitored", + "File descriptor is added to epoll interest list") + KAPI_STATE_TRANS_COND("When op is EPOLL_CTL_ADD") + KAPI_STATE_TRANS_END + + KAPI_STATE_TRANS(1, "epoll entry", "monitored", "non-existent", + "File descriptor is removed from epoll interest list") + KAPI_STATE_TRANS_COND("When op is EPOLL_CTL_DEL") + KAPI_STATE_TRANS_END + + KAPI_STATE_TRANS(2, "epoll entry", "monitored with events A", "monitored with events B", + "Event mask for file descriptor is modified") + KAPI_STATE_TRANS_COND("When op is EPOLL_CTL_MOD") + KAPI_STATE_TRANS_END + + KAPI_STATE_TRANS(3, "epoll ready list", "empty or partial", "contains new events", + "Ready list may be updated if new/modified entry has pending events") + KAPI_STATE_TRANS_COND("When monitored fd has events matching the mask") + KAPI_STATE_TRANS_END + + KAPI_STATE_TRANS_COUNT(4) + + /* Signal specifications */ + KAPI_SIGNAL(0, SIGINT, "SIGINT", KAPI_SIGNAL_RECEIVE, KAPI_SIGNAL_ACTION_RETURN) + KAPI_SIGNAL_CONDITION("During mutex acquisition or memory allocation") + KAPI_SIGNAL_DESC("Returns -EINTR if interrupted before completing the operation") + KAPI_SIGNAL_RESTARTABLE + KAPI_SIGNAL_END + + KAPI_SIGNAL(1, SIGTERM, "SIGTERM", KAPI_SIGNAL_RECEIVE, KAPI_SIGNAL_ACTION_RETURN) + KAPI_SIGNAL_CONDITION("During mutex acquisition or memory allocation") + KAPI_SIGNAL_DESC("Returns -EINTR if interrupted before completing the operation") + KAPI_SIGNAL_RESTARTABLE + KAPI_SIGNAL_END + + KAPI_SIGNAL(2, SIGKILL, "SIGKILL", KAPI_SIGNAL_RECEIVE, KAPI_SIGNAL_ACTION_TERMINATE) + KAPI_SIGNAL_CONDITION("At any point during the syscall") + KAPI_SIGNAL_DESC("Process is terminated immediately, operation may be partially completed") + KAPI_SIGNAL_END + + KAPI_SIGNAL(3, SIGHUP, "SIGHUP", KAPI_SIGNAL_RECEIVE, KAPI_SIGNAL_ACTION_RETURN) + KAPI_SIGNAL_CONDITION("During blocking operations") + KAPI_SIGNAL_DESC("Returns -EINTR if terminal hangup occurs") + KAPI_SIGNAL_RESTARTABLE + KAPI_SIGNAL_END + + KAPI_SIGNAL(4, SIGURG, "SIGURG", KAPI_SIGNAL_IGNORE, KAPI_SIGNAL_ACTION_DEFAULT) + KAPI_SIGNAL_CONDITION("May be generated by monitored sockets") + KAPI_SIGNAL_DESC("Urgent data signals from monitored sockets do not affect epoll_ctl") + KAPI_SIGNAL_END + + .signal_count = 5, + + .examples = "struct epoll_event ev;\n" + "ev.events = EPOLLIN | EPOLLOUT;\n" + "ev.data.fd = fd;\n" + "if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1)\n" + " handle_error();\n", + .notes = "EPOLL_CTL_DEL ignores the event parameter (can be NULL). " + "EPOLLEXCLUSIVE flag has restrictions and cannot be used with EPOLL_CTL_MOD. " + "The epoll instance maintains a reference to registered files until they are " + "explicitly removed with EPOLL_CTL_DEL or the epoll instance is closed.", +KAPI_END_SPEC; + SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, struct epoll_event __user *, event) { -- 2.39.5