18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * fs/eventfd.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org> 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/file.h> 108c2ecf20Sopenharmony_ci#include <linux/poll.h> 118c2ecf20Sopenharmony_ci#include <linux/init.h> 128c2ecf20Sopenharmony_ci#include <linux/fs.h> 138c2ecf20Sopenharmony_ci#include <linux/sched/signal.h> 148c2ecf20Sopenharmony_ci#include <linux/kernel.h> 158c2ecf20Sopenharmony_ci#include <linux/slab.h> 168c2ecf20Sopenharmony_ci#include <linux/list.h> 178c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 188c2ecf20Sopenharmony_ci#include <linux/anon_inodes.h> 198c2ecf20Sopenharmony_ci#include <linux/syscalls.h> 208c2ecf20Sopenharmony_ci#include <linux/export.h> 218c2ecf20Sopenharmony_ci#include <linux/kref.h> 228c2ecf20Sopenharmony_ci#include <linux/eventfd.h> 238c2ecf20Sopenharmony_ci#include <linux/proc_fs.h> 248c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 258c2ecf20Sopenharmony_ci#include <linux/idr.h> 268c2ecf20Sopenharmony_ci#include <linux/uio.h> 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ciDEFINE_PER_CPU(int, eventfd_wake_count); 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistatic DEFINE_IDA(eventfd_ida); 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cistruct eventfd_ctx { 338c2ecf20Sopenharmony_ci struct kref kref; 348c2ecf20Sopenharmony_ci wait_queue_head_t wqh; 358c2ecf20Sopenharmony_ci /* 368c2ecf20Sopenharmony_ci * Every time that a write(2) is performed on an eventfd, the 378c2ecf20Sopenharmony_ci * value of the __u64 being written is added to "count" and a 388c2ecf20Sopenharmony_ci * wakeup is performed on "wqh". A read(2) will return the "count" 398c2ecf20Sopenharmony_ci * value to userspace, and will reset "count" to zero. The kernel 408c2ecf20Sopenharmony_ci * side eventfd_signal() also, adds to the "count" counter and 418c2ecf20Sopenharmony_ci * issue a wakeup. 428c2ecf20Sopenharmony_ci */ 438c2ecf20Sopenharmony_ci __u64 count; 448c2ecf20Sopenharmony_ci unsigned int flags; 458c2ecf20Sopenharmony_ci int id; 468c2ecf20Sopenharmony_ci}; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci__u64 eventfd_signal_mask(struct eventfd_ctx *ctx, __u64 n, unsigned mask) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci unsigned long flags; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci /* 538c2ecf20Sopenharmony_ci * Deadlock or stack overflow issues can happen if we recurse here 548c2ecf20Sopenharmony_ci * through waitqueue wakeup handlers. If the caller users potentially 558c2ecf20Sopenharmony_ci * nested waitqueues with custom wakeup handlers, then it should 568c2ecf20Sopenharmony_ci * check eventfd_signal_count() before calling this function. If 578c2ecf20Sopenharmony_ci * it returns true, the eventfd_signal() call should be deferred to a 588c2ecf20Sopenharmony_ci * safe context. 598c2ecf20Sopenharmony_ci */ 608c2ecf20Sopenharmony_ci if (WARN_ON_ONCE(this_cpu_read(eventfd_wake_count))) 618c2ecf20Sopenharmony_ci return 0; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci spin_lock_irqsave(&ctx->wqh.lock, flags); 648c2ecf20Sopenharmony_ci this_cpu_inc(eventfd_wake_count); 658c2ecf20Sopenharmony_ci if (ULLONG_MAX - ctx->count < n) 668c2ecf20Sopenharmony_ci n = ULLONG_MAX - ctx->count; 678c2ecf20Sopenharmony_ci ctx->count += n; 688c2ecf20Sopenharmony_ci if (waitqueue_active(&ctx->wqh)) 698c2ecf20Sopenharmony_ci wake_up_locked_poll(&ctx->wqh, EPOLLIN | mask); 708c2ecf20Sopenharmony_ci this_cpu_dec(eventfd_wake_count); 718c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ctx->wqh.lock, flags); 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci return n; 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci/** 778c2ecf20Sopenharmony_ci * eventfd_signal - Adds @n to the eventfd counter. 788c2ecf20Sopenharmony_ci * @ctx: [in] Pointer to the eventfd context. 798c2ecf20Sopenharmony_ci * @n: [in] Value of the counter to be added to the eventfd internal counter. 808c2ecf20Sopenharmony_ci * The value cannot be negative. 818c2ecf20Sopenharmony_ci * 828c2ecf20Sopenharmony_ci * This function is supposed to be called by the kernel in paths that do not 838c2ecf20Sopenharmony_ci * allow sleeping. In this function we allow the counter to reach the ULLONG_MAX 848c2ecf20Sopenharmony_ci * value, and we signal this as overflow condition by returning a EPOLLERR 858c2ecf20Sopenharmony_ci * to poll(2). 868c2ecf20Sopenharmony_ci * 878c2ecf20Sopenharmony_ci * Returns the amount by which the counter was incremented. This will be less 888c2ecf20Sopenharmony_ci * than @n if the counter has overflowed. 898c2ecf20Sopenharmony_ci */ 908c2ecf20Sopenharmony_ci__u64 eventfd_signal(struct eventfd_ctx *ctx, __u64 n) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci return eventfd_signal_mask(ctx, n, 0); 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(eventfd_signal); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic void eventfd_free_ctx(struct eventfd_ctx *ctx) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci if (ctx->id >= 0) 998c2ecf20Sopenharmony_ci ida_simple_remove(&eventfd_ida, ctx->id); 1008c2ecf20Sopenharmony_ci kfree(ctx); 1018c2ecf20Sopenharmony_ci} 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_cistatic void eventfd_free(struct kref *kref) 1048c2ecf20Sopenharmony_ci{ 1058c2ecf20Sopenharmony_ci struct eventfd_ctx *ctx = container_of(kref, struct eventfd_ctx, kref); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci eventfd_free_ctx(ctx); 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci/** 1118c2ecf20Sopenharmony_ci * eventfd_ctx_put - Releases a reference to the internal eventfd context. 1128c2ecf20Sopenharmony_ci * @ctx: [in] Pointer to eventfd context. 1138c2ecf20Sopenharmony_ci * 1148c2ecf20Sopenharmony_ci * The eventfd context reference must have been previously acquired either 1158c2ecf20Sopenharmony_ci * with eventfd_ctx_fdget() or eventfd_ctx_fileget(). 1168c2ecf20Sopenharmony_ci */ 1178c2ecf20Sopenharmony_civoid eventfd_ctx_put(struct eventfd_ctx *ctx) 1188c2ecf20Sopenharmony_ci{ 1198c2ecf20Sopenharmony_ci kref_put(&ctx->kref, eventfd_free); 1208c2ecf20Sopenharmony_ci} 1218c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(eventfd_ctx_put); 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistatic int eventfd_release(struct inode *inode, struct file *file) 1248c2ecf20Sopenharmony_ci{ 1258c2ecf20Sopenharmony_ci struct eventfd_ctx *ctx = file->private_data; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci wake_up_poll(&ctx->wqh, EPOLLHUP); 1288c2ecf20Sopenharmony_ci eventfd_ctx_put(ctx); 1298c2ecf20Sopenharmony_ci return 0; 1308c2ecf20Sopenharmony_ci} 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cistatic __poll_t eventfd_poll(struct file *file, poll_table *wait) 1338c2ecf20Sopenharmony_ci{ 1348c2ecf20Sopenharmony_ci struct eventfd_ctx *ctx = file->private_data; 1358c2ecf20Sopenharmony_ci __poll_t events = 0; 1368c2ecf20Sopenharmony_ci u64 count; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci poll_wait(file, &ctx->wqh, wait); 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci /* 1418c2ecf20Sopenharmony_ci * All writes to ctx->count occur within ctx->wqh.lock. This read 1428c2ecf20Sopenharmony_ci * can be done outside ctx->wqh.lock because we know that poll_wait 1438c2ecf20Sopenharmony_ci * takes that lock (through add_wait_queue) if our caller will sleep. 1448c2ecf20Sopenharmony_ci * 1458c2ecf20Sopenharmony_ci * The read _can_ therefore seep into add_wait_queue's critical 1468c2ecf20Sopenharmony_ci * section, but cannot move above it! add_wait_queue's spin_lock acts 1478c2ecf20Sopenharmony_ci * as an acquire barrier and ensures that the read be ordered properly 1488c2ecf20Sopenharmony_ci * against the writes. The following CAN happen and is safe: 1498c2ecf20Sopenharmony_ci * 1508c2ecf20Sopenharmony_ci * poll write 1518c2ecf20Sopenharmony_ci * ----------------- ------------ 1528c2ecf20Sopenharmony_ci * lock ctx->wqh.lock (in poll_wait) 1538c2ecf20Sopenharmony_ci * count = ctx->count 1548c2ecf20Sopenharmony_ci * __add_wait_queue 1558c2ecf20Sopenharmony_ci * unlock ctx->wqh.lock 1568c2ecf20Sopenharmony_ci * lock ctx->qwh.lock 1578c2ecf20Sopenharmony_ci * ctx->count += n 1588c2ecf20Sopenharmony_ci * if (waitqueue_active) 1598c2ecf20Sopenharmony_ci * wake_up_locked_poll 1608c2ecf20Sopenharmony_ci * unlock ctx->qwh.lock 1618c2ecf20Sopenharmony_ci * eventfd_poll returns 0 1628c2ecf20Sopenharmony_ci * 1638c2ecf20Sopenharmony_ci * but the following, which would miss a wakeup, cannot happen: 1648c2ecf20Sopenharmony_ci * 1658c2ecf20Sopenharmony_ci * poll write 1668c2ecf20Sopenharmony_ci * ----------------- ------------ 1678c2ecf20Sopenharmony_ci * count = ctx->count (INVALID!) 1688c2ecf20Sopenharmony_ci * lock ctx->qwh.lock 1698c2ecf20Sopenharmony_ci * ctx->count += n 1708c2ecf20Sopenharmony_ci * **waitqueue_active is false** 1718c2ecf20Sopenharmony_ci * **no wake_up_locked_poll!** 1728c2ecf20Sopenharmony_ci * unlock ctx->qwh.lock 1738c2ecf20Sopenharmony_ci * lock ctx->wqh.lock (in poll_wait) 1748c2ecf20Sopenharmony_ci * __add_wait_queue 1758c2ecf20Sopenharmony_ci * unlock ctx->wqh.lock 1768c2ecf20Sopenharmony_ci * eventfd_poll returns 0 1778c2ecf20Sopenharmony_ci */ 1788c2ecf20Sopenharmony_ci count = READ_ONCE(ctx->count); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci if (count > 0) 1818c2ecf20Sopenharmony_ci events |= EPOLLIN; 1828c2ecf20Sopenharmony_ci if (count == ULLONG_MAX) 1838c2ecf20Sopenharmony_ci events |= EPOLLERR; 1848c2ecf20Sopenharmony_ci if (ULLONG_MAX - 1 > count) 1858c2ecf20Sopenharmony_ci events |= EPOLLOUT; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci return events; 1888c2ecf20Sopenharmony_ci} 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_civoid eventfd_ctx_do_read(struct eventfd_ctx *ctx, __u64 *cnt) 1918c2ecf20Sopenharmony_ci{ 1928c2ecf20Sopenharmony_ci lockdep_assert_held(&ctx->wqh.lock); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci *cnt = ((ctx->flags & EFD_SEMAPHORE) && ctx->count) ? 1 : ctx->count; 1958c2ecf20Sopenharmony_ci ctx->count -= *cnt; 1968c2ecf20Sopenharmony_ci} 1978c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(eventfd_ctx_do_read); 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci/** 2008c2ecf20Sopenharmony_ci * eventfd_ctx_remove_wait_queue - Read the current counter and removes wait queue. 2018c2ecf20Sopenharmony_ci * @ctx: [in] Pointer to eventfd context. 2028c2ecf20Sopenharmony_ci * @wait: [in] Wait queue to be removed. 2038c2ecf20Sopenharmony_ci * @cnt: [out] Pointer to the 64-bit counter value. 2048c2ecf20Sopenharmony_ci * 2058c2ecf20Sopenharmony_ci * Returns %0 if successful, or the following error codes: 2068c2ecf20Sopenharmony_ci * 2078c2ecf20Sopenharmony_ci * -EAGAIN : The operation would have blocked. 2088c2ecf20Sopenharmony_ci * 2098c2ecf20Sopenharmony_ci * This is used to atomically remove a wait queue entry from the eventfd wait 2108c2ecf20Sopenharmony_ci * queue head, and read/reset the counter value. 2118c2ecf20Sopenharmony_ci */ 2128c2ecf20Sopenharmony_ciint eventfd_ctx_remove_wait_queue(struct eventfd_ctx *ctx, wait_queue_entry_t *wait, 2138c2ecf20Sopenharmony_ci __u64 *cnt) 2148c2ecf20Sopenharmony_ci{ 2158c2ecf20Sopenharmony_ci unsigned long flags; 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci spin_lock_irqsave(&ctx->wqh.lock, flags); 2188c2ecf20Sopenharmony_ci eventfd_ctx_do_read(ctx, cnt); 2198c2ecf20Sopenharmony_ci __remove_wait_queue(&ctx->wqh, wait); 2208c2ecf20Sopenharmony_ci if (*cnt != 0 && waitqueue_active(&ctx->wqh)) 2218c2ecf20Sopenharmony_ci wake_up_locked_poll(&ctx->wqh, EPOLLOUT); 2228c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ctx->wqh.lock, flags); 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci return *cnt != 0 ? 0 : -EAGAIN; 2258c2ecf20Sopenharmony_ci} 2268c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(eventfd_ctx_remove_wait_queue); 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_cistatic ssize_t eventfd_read(struct kiocb *iocb, struct iov_iter *to) 2298c2ecf20Sopenharmony_ci{ 2308c2ecf20Sopenharmony_ci struct file *file = iocb->ki_filp; 2318c2ecf20Sopenharmony_ci struct eventfd_ctx *ctx = file->private_data; 2328c2ecf20Sopenharmony_ci __u64 ucnt = 0; 2338c2ecf20Sopenharmony_ci DECLARE_WAITQUEUE(wait, current); 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci if (iov_iter_count(to) < sizeof(ucnt)) 2368c2ecf20Sopenharmony_ci return -EINVAL; 2378c2ecf20Sopenharmony_ci spin_lock_irq(&ctx->wqh.lock); 2388c2ecf20Sopenharmony_ci if (!ctx->count) { 2398c2ecf20Sopenharmony_ci if ((file->f_flags & O_NONBLOCK) || 2408c2ecf20Sopenharmony_ci (iocb->ki_flags & IOCB_NOWAIT)) { 2418c2ecf20Sopenharmony_ci spin_unlock_irq(&ctx->wqh.lock); 2428c2ecf20Sopenharmony_ci return -EAGAIN; 2438c2ecf20Sopenharmony_ci } 2448c2ecf20Sopenharmony_ci __add_wait_queue(&ctx->wqh, &wait); 2458c2ecf20Sopenharmony_ci for (;;) { 2468c2ecf20Sopenharmony_ci set_current_state(TASK_INTERRUPTIBLE); 2478c2ecf20Sopenharmony_ci if (ctx->count) 2488c2ecf20Sopenharmony_ci break; 2498c2ecf20Sopenharmony_ci if (signal_pending(current)) { 2508c2ecf20Sopenharmony_ci __remove_wait_queue(&ctx->wqh, &wait); 2518c2ecf20Sopenharmony_ci __set_current_state(TASK_RUNNING); 2528c2ecf20Sopenharmony_ci spin_unlock_irq(&ctx->wqh.lock); 2538c2ecf20Sopenharmony_ci return -ERESTARTSYS; 2548c2ecf20Sopenharmony_ci } 2558c2ecf20Sopenharmony_ci spin_unlock_irq(&ctx->wqh.lock); 2568c2ecf20Sopenharmony_ci schedule(); 2578c2ecf20Sopenharmony_ci spin_lock_irq(&ctx->wqh.lock); 2588c2ecf20Sopenharmony_ci } 2598c2ecf20Sopenharmony_ci __remove_wait_queue(&ctx->wqh, &wait); 2608c2ecf20Sopenharmony_ci __set_current_state(TASK_RUNNING); 2618c2ecf20Sopenharmony_ci } 2628c2ecf20Sopenharmony_ci eventfd_ctx_do_read(ctx, &ucnt); 2638c2ecf20Sopenharmony_ci if (waitqueue_active(&ctx->wqh)) 2648c2ecf20Sopenharmony_ci wake_up_locked_poll(&ctx->wqh, EPOLLOUT); 2658c2ecf20Sopenharmony_ci spin_unlock_irq(&ctx->wqh.lock); 2668c2ecf20Sopenharmony_ci if (unlikely(copy_to_iter(&ucnt, sizeof(ucnt), to) != sizeof(ucnt))) 2678c2ecf20Sopenharmony_ci return -EFAULT; 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci return sizeof(ucnt); 2708c2ecf20Sopenharmony_ci} 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_cistatic ssize_t eventfd_write(struct file *file, const char __user *buf, size_t count, 2738c2ecf20Sopenharmony_ci loff_t *ppos) 2748c2ecf20Sopenharmony_ci{ 2758c2ecf20Sopenharmony_ci struct eventfd_ctx *ctx = file->private_data; 2768c2ecf20Sopenharmony_ci ssize_t res; 2778c2ecf20Sopenharmony_ci __u64 ucnt; 2788c2ecf20Sopenharmony_ci DECLARE_WAITQUEUE(wait, current); 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci if (count < sizeof(ucnt)) 2818c2ecf20Sopenharmony_ci return -EINVAL; 2828c2ecf20Sopenharmony_ci if (copy_from_user(&ucnt, buf, sizeof(ucnt))) 2838c2ecf20Sopenharmony_ci return -EFAULT; 2848c2ecf20Sopenharmony_ci if (ucnt == ULLONG_MAX) 2858c2ecf20Sopenharmony_ci return -EINVAL; 2868c2ecf20Sopenharmony_ci spin_lock_irq(&ctx->wqh.lock); 2878c2ecf20Sopenharmony_ci res = -EAGAIN; 2888c2ecf20Sopenharmony_ci if (ULLONG_MAX - ctx->count > ucnt) 2898c2ecf20Sopenharmony_ci res = sizeof(ucnt); 2908c2ecf20Sopenharmony_ci else if (!(file->f_flags & O_NONBLOCK)) { 2918c2ecf20Sopenharmony_ci __add_wait_queue(&ctx->wqh, &wait); 2928c2ecf20Sopenharmony_ci for (res = 0;;) { 2938c2ecf20Sopenharmony_ci set_current_state(TASK_INTERRUPTIBLE); 2948c2ecf20Sopenharmony_ci if (ULLONG_MAX - ctx->count > ucnt) { 2958c2ecf20Sopenharmony_ci res = sizeof(ucnt); 2968c2ecf20Sopenharmony_ci break; 2978c2ecf20Sopenharmony_ci } 2988c2ecf20Sopenharmony_ci if (signal_pending(current)) { 2998c2ecf20Sopenharmony_ci res = -ERESTARTSYS; 3008c2ecf20Sopenharmony_ci break; 3018c2ecf20Sopenharmony_ci } 3028c2ecf20Sopenharmony_ci spin_unlock_irq(&ctx->wqh.lock); 3038c2ecf20Sopenharmony_ci schedule(); 3048c2ecf20Sopenharmony_ci spin_lock_irq(&ctx->wqh.lock); 3058c2ecf20Sopenharmony_ci } 3068c2ecf20Sopenharmony_ci __remove_wait_queue(&ctx->wqh, &wait); 3078c2ecf20Sopenharmony_ci __set_current_state(TASK_RUNNING); 3088c2ecf20Sopenharmony_ci } 3098c2ecf20Sopenharmony_ci if (likely(res > 0)) { 3108c2ecf20Sopenharmony_ci ctx->count += ucnt; 3118c2ecf20Sopenharmony_ci if (waitqueue_active(&ctx->wqh)) 3128c2ecf20Sopenharmony_ci wake_up_locked_poll(&ctx->wqh, EPOLLIN); 3138c2ecf20Sopenharmony_ci } 3148c2ecf20Sopenharmony_ci spin_unlock_irq(&ctx->wqh.lock); 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci return res; 3178c2ecf20Sopenharmony_ci} 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_FS 3208c2ecf20Sopenharmony_cistatic void eventfd_show_fdinfo(struct seq_file *m, struct file *f) 3218c2ecf20Sopenharmony_ci{ 3228c2ecf20Sopenharmony_ci struct eventfd_ctx *ctx = f->private_data; 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci spin_lock_irq(&ctx->wqh.lock); 3258c2ecf20Sopenharmony_ci seq_printf(m, "eventfd-count: %16llx\n", 3268c2ecf20Sopenharmony_ci (unsigned long long)ctx->count); 3278c2ecf20Sopenharmony_ci spin_unlock_irq(&ctx->wqh.lock); 3288c2ecf20Sopenharmony_ci seq_printf(m, "eventfd-id: %d\n", ctx->id); 3298c2ecf20Sopenharmony_ci} 3308c2ecf20Sopenharmony_ci#endif 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_cistatic const struct file_operations eventfd_fops = { 3338c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_FS 3348c2ecf20Sopenharmony_ci .show_fdinfo = eventfd_show_fdinfo, 3358c2ecf20Sopenharmony_ci#endif 3368c2ecf20Sopenharmony_ci .release = eventfd_release, 3378c2ecf20Sopenharmony_ci .poll = eventfd_poll, 3388c2ecf20Sopenharmony_ci .read_iter = eventfd_read, 3398c2ecf20Sopenharmony_ci .write = eventfd_write, 3408c2ecf20Sopenharmony_ci .llseek = noop_llseek, 3418c2ecf20Sopenharmony_ci}; 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci/** 3448c2ecf20Sopenharmony_ci * eventfd_fget - Acquire a reference of an eventfd file descriptor. 3458c2ecf20Sopenharmony_ci * @fd: [in] Eventfd file descriptor. 3468c2ecf20Sopenharmony_ci * 3478c2ecf20Sopenharmony_ci * Returns a pointer to the eventfd file structure in case of success, or the 3488c2ecf20Sopenharmony_ci * following error pointer: 3498c2ecf20Sopenharmony_ci * 3508c2ecf20Sopenharmony_ci * -EBADF : Invalid @fd file descriptor. 3518c2ecf20Sopenharmony_ci * -EINVAL : The @fd file descriptor is not an eventfd file. 3528c2ecf20Sopenharmony_ci */ 3538c2ecf20Sopenharmony_cistruct file *eventfd_fget(int fd) 3548c2ecf20Sopenharmony_ci{ 3558c2ecf20Sopenharmony_ci struct file *file; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci file = fget(fd); 3588c2ecf20Sopenharmony_ci if (!file) 3598c2ecf20Sopenharmony_ci return ERR_PTR(-EBADF); 3608c2ecf20Sopenharmony_ci if (file->f_op != &eventfd_fops) { 3618c2ecf20Sopenharmony_ci fput(file); 3628c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 3638c2ecf20Sopenharmony_ci } 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci return file; 3668c2ecf20Sopenharmony_ci} 3678c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(eventfd_fget); 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci/** 3708c2ecf20Sopenharmony_ci * eventfd_ctx_fdget - Acquires a reference to the internal eventfd context. 3718c2ecf20Sopenharmony_ci * @fd: [in] Eventfd file descriptor. 3728c2ecf20Sopenharmony_ci * 3738c2ecf20Sopenharmony_ci * Returns a pointer to the internal eventfd context, otherwise the error 3748c2ecf20Sopenharmony_ci * pointers returned by the following functions: 3758c2ecf20Sopenharmony_ci * 3768c2ecf20Sopenharmony_ci * eventfd_fget 3778c2ecf20Sopenharmony_ci */ 3788c2ecf20Sopenharmony_cistruct eventfd_ctx *eventfd_ctx_fdget(int fd) 3798c2ecf20Sopenharmony_ci{ 3808c2ecf20Sopenharmony_ci struct eventfd_ctx *ctx; 3818c2ecf20Sopenharmony_ci struct fd f = fdget(fd); 3828c2ecf20Sopenharmony_ci if (!f.file) 3838c2ecf20Sopenharmony_ci return ERR_PTR(-EBADF); 3848c2ecf20Sopenharmony_ci ctx = eventfd_ctx_fileget(f.file); 3858c2ecf20Sopenharmony_ci fdput(f); 3868c2ecf20Sopenharmony_ci return ctx; 3878c2ecf20Sopenharmony_ci} 3888c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(eventfd_ctx_fdget); 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci/** 3918c2ecf20Sopenharmony_ci * eventfd_ctx_fileget - Acquires a reference to the internal eventfd context. 3928c2ecf20Sopenharmony_ci * @file: [in] Eventfd file pointer. 3938c2ecf20Sopenharmony_ci * 3948c2ecf20Sopenharmony_ci * Returns a pointer to the internal eventfd context, otherwise the error 3958c2ecf20Sopenharmony_ci * pointer: 3968c2ecf20Sopenharmony_ci * 3978c2ecf20Sopenharmony_ci * -EINVAL : The @fd file descriptor is not an eventfd file. 3988c2ecf20Sopenharmony_ci */ 3998c2ecf20Sopenharmony_cistruct eventfd_ctx *eventfd_ctx_fileget(struct file *file) 4008c2ecf20Sopenharmony_ci{ 4018c2ecf20Sopenharmony_ci struct eventfd_ctx *ctx; 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci if (file->f_op != &eventfd_fops) 4048c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci ctx = file->private_data; 4078c2ecf20Sopenharmony_ci kref_get(&ctx->kref); 4088c2ecf20Sopenharmony_ci return ctx; 4098c2ecf20Sopenharmony_ci} 4108c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(eventfd_ctx_fileget); 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_cistatic int do_eventfd(unsigned int count, int flags) 4138c2ecf20Sopenharmony_ci{ 4148c2ecf20Sopenharmony_ci struct eventfd_ctx *ctx; 4158c2ecf20Sopenharmony_ci struct file *file; 4168c2ecf20Sopenharmony_ci int fd; 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci /* Check the EFD_* constants for consistency. */ 4198c2ecf20Sopenharmony_ci BUILD_BUG_ON(EFD_CLOEXEC != O_CLOEXEC); 4208c2ecf20Sopenharmony_ci BUILD_BUG_ON(EFD_NONBLOCK != O_NONBLOCK); 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci if (flags & ~EFD_FLAGS_SET) 4238c2ecf20Sopenharmony_ci return -EINVAL; 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); 4268c2ecf20Sopenharmony_ci if (!ctx) 4278c2ecf20Sopenharmony_ci return -ENOMEM; 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci kref_init(&ctx->kref); 4308c2ecf20Sopenharmony_ci init_waitqueue_head(&ctx->wqh); 4318c2ecf20Sopenharmony_ci ctx->count = count; 4328c2ecf20Sopenharmony_ci ctx->flags = flags; 4338c2ecf20Sopenharmony_ci ctx->id = ida_simple_get(&eventfd_ida, 0, 0, GFP_KERNEL); 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci flags &= EFD_SHARED_FCNTL_FLAGS; 4368c2ecf20Sopenharmony_ci flags |= O_RDWR; 4378c2ecf20Sopenharmony_ci fd = get_unused_fd_flags(flags); 4388c2ecf20Sopenharmony_ci if (fd < 0) 4398c2ecf20Sopenharmony_ci goto err; 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci file = anon_inode_getfile("[eventfd]", &eventfd_fops, ctx, flags); 4428c2ecf20Sopenharmony_ci if (IS_ERR(file)) { 4438c2ecf20Sopenharmony_ci put_unused_fd(fd); 4448c2ecf20Sopenharmony_ci fd = PTR_ERR(file); 4458c2ecf20Sopenharmony_ci goto err; 4468c2ecf20Sopenharmony_ci } 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci file->f_mode |= FMODE_NOWAIT; 4498c2ecf20Sopenharmony_ci fd_install(fd, file); 4508c2ecf20Sopenharmony_ci return fd; 4518c2ecf20Sopenharmony_cierr: 4528c2ecf20Sopenharmony_ci eventfd_free_ctx(ctx); 4538c2ecf20Sopenharmony_ci return fd; 4548c2ecf20Sopenharmony_ci} 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ciSYSCALL_DEFINE2(eventfd2, unsigned int, count, int, flags) 4578c2ecf20Sopenharmony_ci{ 4588c2ecf20Sopenharmony_ci return do_eventfd(count, flags); 4598c2ecf20Sopenharmony_ci} 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ciSYSCALL_DEFINE1(eventfd, unsigned int, count) 4628c2ecf20Sopenharmony_ci{ 4638c2ecf20Sopenharmony_ci return do_eventfd(count, 0); 4648c2ecf20Sopenharmony_ci} 4658c2ecf20Sopenharmony_ci 466