VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   35 Branches   59 Tags
457c899653991 (Thomas Gleixner   2019-05-19 13:08:55 +0100   1) // SPDX-License-Identifier: GPL-2.0-only
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700   2) /*
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700   3)  *  fs/eventfd.c
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700   4)  *
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700   5)  *  Copyright (C) 2007  Davide Libenzi <davidel@xmailserver.org>
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700   6)  *
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700   7)  */
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700   8) 
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700   9) #include <linux/file.h>
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  10) #include <linux/poll.h>
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  11) #include <linux/init.h>
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  12) #include <linux/fs.h>
174cd4b1e5fbd (Ingo Molnar       2017-02-02 19:15:33 +0100  13) #include <linux/sched/signal.h>
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  14) #include <linux/kernel.h>
5a0e3ad6af866 (Tejun Heo         2010-03-24 17:04:11 +0900  15) #include <linux/slab.h>
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  16) #include <linux/list.h>
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  17) #include <linux/spinlock.h>
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  18) #include <linux/anon_inodes.h>
7747cdb2f8302 (Adrian Bunk       2008-02-06 01:36:49 -0800  19) #include <linux/syscalls.h>
630d9c47274aa (Paul Gortmaker    2011-11-16 23:57:37 -0500  20) #include <linux/export.h>
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700  21) #include <linux/kref.h>
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700  22) #include <linux/eventfd.h>
cbac5542d4812 (Cyrill Gorcunov   2012-12-17 16:04:57 -0800  23) #include <linux/proc_fs.h>
cbac5542d4812 (Cyrill Gorcunov   2012-12-17 16:04:57 -0800  24) #include <linux/seq_file.h>
b556db17b0e7c (Masatake YAMATO   2019-05-14 15:45:19 -0700  25) #include <linux/idr.h>
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600  26) #include <linux/uio.h>
b556db17b0e7c (Masatake YAMATO   2019-05-14 15:45:19 -0700  27) 
b5e683d5cab8c (Jens Axboe        2020-02-02 08:23:03 -0700  28) DEFINE_PER_CPU(int, eventfd_wake_count);
b5e683d5cab8c (Jens Axboe        2020-02-02 08:23:03 -0700  29) 
ce528c4c20f94 (YueHaibing        2019-05-14 15:45:22 -0700  30) static DEFINE_IDA(eventfd_ida);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  31) 
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  32) struct eventfd_ctx {
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700  33) 	struct kref kref;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  34) 	wait_queue_head_t wqh;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  35) 	/*
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  36) 	 * Every time that a write(2) is performed on an eventfd, the
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  37) 	 * value of the __u64 being written is added to "count" and a
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  38) 	 * wakeup is performed on "wqh". A read(2) will return the "count"
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  39) 	 * value to userspace, and will reset "count" to zero. The kernel
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700  40) 	 * side eventfd_signal() also, adds to the "count" counter and
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  41) 	 * issue a wakeup.
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  42) 	 */
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  43) 	__u64 count;
bcd0b235bf380 (Davide Libenzi    2009-03-31 15:24:18 -0700  44) 	unsigned int flags;
b556db17b0e7c (Masatake YAMATO   2019-05-14 15:45:19 -0700  45) 	int id;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  46) };
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  47) 
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700  48) /**
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700  49)  * eventfd_signal - Adds @n to the eventfd counter.
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700  50)  * @ctx: [in] Pointer to the eventfd context.
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700  51)  * @n: [in] Value of the counter to be added to the eventfd internal counter.
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700  52)  *          The value cannot be negative.
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700  53)  *
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700  54)  * This function is supposed to be called by the kernel in paths that do not
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700  55)  * allow sleeping. In this function we allow the counter to reach the ULLONG_MAX
a9a08845e9acb (Linus Torvalds    2018-02-11 14:34:03 -0800  56)  * value, and we signal this as overflow condition by returning a EPOLLERR
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700  57)  * to poll(2).
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700  58)  *
20d5a865e1f1d (Masanari Iida     2015-09-22 12:04:17 +0900  59)  * Returns the amount by which the counter was incremented.  This will be less
ee62c6b2dc93c (Sha Zhengju       2012-05-31 16:26:41 -0700  60)  * than @n if the counter has overflowed.
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  61)  */
ee62c6b2dc93c (Sha Zhengju       2012-05-31 16:26:41 -0700  62) __u64 eventfd_signal(struct eventfd_ctx *ctx, __u64 n)
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  63) {
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  64) 	unsigned long flags;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  65) 
b5e683d5cab8c (Jens Axboe        2020-02-02 08:23:03 -0700  66) 	/*
b5e683d5cab8c (Jens Axboe        2020-02-02 08:23:03 -0700  67) 	 * Deadlock or stack overflow issues can happen if we recurse here
b5e683d5cab8c (Jens Axboe        2020-02-02 08:23:03 -0700  68) 	 * through waitqueue wakeup handlers. If the caller users potentially
b5e683d5cab8c (Jens Axboe        2020-02-02 08:23:03 -0700  69) 	 * nested waitqueues with custom wakeup handlers, then it should
b5e683d5cab8c (Jens Axboe        2020-02-02 08:23:03 -0700  70) 	 * check eventfd_signal_count() before calling this function. If
b5e683d5cab8c (Jens Axboe        2020-02-02 08:23:03 -0700  71) 	 * it returns true, the eventfd_signal() call should be deferred to a
b5e683d5cab8c (Jens Axboe        2020-02-02 08:23:03 -0700  72) 	 * safe context.
b5e683d5cab8c (Jens Axboe        2020-02-02 08:23:03 -0700  73) 	 */
b5e683d5cab8c (Jens Axboe        2020-02-02 08:23:03 -0700  74) 	if (WARN_ON_ONCE(this_cpu_read(eventfd_wake_count)))
b5e683d5cab8c (Jens Axboe        2020-02-02 08:23:03 -0700  75) 		return 0;
b5e683d5cab8c (Jens Axboe        2020-02-02 08:23:03 -0700  76) 
d48eb23315952 (Davide Libenzi    2007-05-18 12:02:33 -0700  77) 	spin_lock_irqsave(&ctx->wqh.lock, flags);
b5e683d5cab8c (Jens Axboe        2020-02-02 08:23:03 -0700  78) 	this_cpu_inc(eventfd_wake_count);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  79) 	if (ULLONG_MAX - ctx->count < n)
ee62c6b2dc93c (Sha Zhengju       2012-05-31 16:26:41 -0700  80) 		n = ULLONG_MAX - ctx->count;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  81) 	ctx->count += n;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  82) 	if (waitqueue_active(&ctx->wqh))
a9a08845e9acb (Linus Torvalds    2018-02-11 14:34:03 -0800  83) 		wake_up_locked_poll(&ctx->wqh, EPOLLIN);
b5e683d5cab8c (Jens Axboe        2020-02-02 08:23:03 -0700  84) 	this_cpu_dec(eventfd_wake_count);
d48eb23315952 (Davide Libenzi    2007-05-18 12:02:33 -0700  85) 	spin_unlock_irqrestore(&ctx->wqh.lock, flags);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  86) 
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  87) 	return n;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  88) }
5718607bb670c (Rusty Russell     2009-06-12 22:27:09 -0600  89) EXPORT_SYMBOL_GPL(eventfd_signal);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700  90) 
562787a5c32cc (Davide Libenzi    2009-09-22 16:43:57 -0700  91) static void eventfd_free_ctx(struct eventfd_ctx *ctx)
562787a5c32cc (Davide Libenzi    2009-09-22 16:43:57 -0700  92) {
b556db17b0e7c (Masatake YAMATO   2019-05-14 15:45:19 -0700  93) 	if (ctx->id >= 0)
b556db17b0e7c (Masatake YAMATO   2019-05-14 15:45:19 -0700  94) 		ida_simple_remove(&eventfd_ida, ctx->id);
562787a5c32cc (Davide Libenzi    2009-09-22 16:43:57 -0700  95) 	kfree(ctx);
562787a5c32cc (Davide Libenzi    2009-09-22 16:43:57 -0700  96) }
562787a5c32cc (Davide Libenzi    2009-09-22 16:43:57 -0700  97) 
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700  98) static void eventfd_free(struct kref *kref)
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700  99) {
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 100) 	struct eventfd_ctx *ctx = container_of(kref, struct eventfd_ctx, kref);
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 101) 
562787a5c32cc (Davide Libenzi    2009-09-22 16:43:57 -0700 102) 	eventfd_free_ctx(ctx);
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 103) }
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 104) 
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 105) /**
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 106)  * eventfd_ctx_put - Releases a reference to the internal eventfd context.
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 107)  * @ctx: [in] Pointer to eventfd context.
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 108)  *
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 109)  * The eventfd context reference must have been previously acquired either
105f2b7096075 (Eric Biggers      2018-01-06 09:45:44 -0800 110)  * with eventfd_ctx_fdget() or eventfd_ctx_fileget().
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 111)  */
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 112) void eventfd_ctx_put(struct eventfd_ctx *ctx)
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 113) {
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 114) 	kref_put(&ctx->kref, eventfd_free);
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 115) }
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 116) EXPORT_SYMBOL_GPL(eventfd_ctx_put);
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 117) 
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 118) static int eventfd_release(struct inode *inode, struct file *file)
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 119) {
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 120) 	struct eventfd_ctx *ctx = file->private_data;
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 121) 
a9a08845e9acb (Linus Torvalds    2018-02-11 14:34:03 -0800 122) 	wake_up_poll(&ctx->wqh, EPOLLHUP);
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 123) 	eventfd_ctx_put(ctx);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 124) 	return 0;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 125) }
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 126) 
a11e1d432b51f (Linus Torvalds    2018-06-28 09:43:44 -0700 127) static __poll_t eventfd_poll(struct file *file, poll_table *wait)
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 128) {
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 129) 	struct eventfd_ctx *ctx = file->private_data;
076ccb76e1a6c (Al Viro           2017-07-03 01:02:18 -0400 130) 	__poll_t events = 0;
e22553e2a25ed (Chris Mason       2015-02-17 13:46:07 -0800 131) 	u64 count;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 132) 
a11e1d432b51f (Linus Torvalds    2018-06-28 09:43:44 -0700 133) 	poll_wait(file, &ctx->wqh, wait);
a11e1d432b51f (Linus Torvalds    2018-06-28 09:43:44 -0700 134) 
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 135) 	/*
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 136) 	 * All writes to ctx->count occur within ctx->wqh.lock.  This read
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 137) 	 * can be done outside ctx->wqh.lock because we know that poll_wait
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 138) 	 * takes that lock (through add_wait_queue) if our caller will sleep.
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 139) 	 *
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 140) 	 * The read _can_ therefore seep into add_wait_queue's critical
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 141) 	 * section, but cannot move above it!  add_wait_queue's spin_lock acts
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 142) 	 * as an acquire barrier and ensures that the read be ordered properly
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 143) 	 * against the writes.  The following CAN happen and is safe:
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 144) 	 *
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 145) 	 *     poll                               write
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 146) 	 *     -----------------                  ------------
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 147) 	 *     lock ctx->wqh.lock (in poll_wait)
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 148) 	 *     count = ctx->count
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 149) 	 *     __add_wait_queue
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 150) 	 *     unlock ctx->wqh.lock
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 151) 	 *                                        lock ctx->qwh.lock
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 152) 	 *                                        ctx->count += n
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 153) 	 *                                        if (waitqueue_active)
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 154) 	 *                                          wake_up_locked_poll
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 155) 	 *                                        unlock ctx->qwh.lock
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 156) 	 *     eventfd_poll returns 0
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 157) 	 *
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 158) 	 * but the following, which would miss a wakeup, cannot happen:
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 159) 	 *
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 160) 	 *     poll                               write
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 161) 	 *     -----------------                  ------------
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 162) 	 *     count = ctx->count (INVALID!)
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 163) 	 *                                        lock ctx->qwh.lock
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 164) 	 *                                        ctx->count += n
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 165) 	 *                                        **waitqueue_active is false**
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 166) 	 *                                        **no wake_up_locked_poll!**
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 167) 	 *                                        unlock ctx->qwh.lock
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 168) 	 *     lock ctx->wqh.lock (in poll_wait)
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 169) 	 *     __add_wait_queue
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 170) 	 *     unlock ctx->wqh.lock
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 171) 	 *     eventfd_poll returns 0
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 172) 	 */
a484c3dd9426e (Paolo Bonzini     2016-03-22 14:27:14 -0700 173) 	count = READ_ONCE(ctx->count);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 174) 
e22553e2a25ed (Chris Mason       2015-02-17 13:46:07 -0800 175) 	if (count > 0)
a11e1d432b51f (Linus Torvalds    2018-06-28 09:43:44 -0700 176) 		events |= EPOLLIN;
e22553e2a25ed (Chris Mason       2015-02-17 13:46:07 -0800 177) 	if (count == ULLONG_MAX)
a9a08845e9acb (Linus Torvalds    2018-02-11 14:34:03 -0800 178) 		events |= EPOLLERR;
e22553e2a25ed (Chris Mason       2015-02-17 13:46:07 -0800 179) 	if (ULLONG_MAX - 1 > count)
a11e1d432b51f (Linus Torvalds    2018-06-28 09:43:44 -0700 180) 		events |= EPOLLOUT;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 181) 
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 182) 	return events;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 183) }
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 184) 
28f1326710555 (David Woodhouse   2020-10-27 13:55:21 +0000 185) void eventfd_ctx_do_read(struct eventfd_ctx *ctx, __u64 *cnt)
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 186) {
28f1326710555 (David Woodhouse   2020-10-27 13:55:21 +0000 187) 	lockdep_assert_held(&ctx->wqh.lock);
28f1326710555 (David Woodhouse   2020-10-27 13:55:21 +0000 188) 
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 189) 	*cnt = (ctx->flags & EFD_SEMAPHORE) ? 1 : ctx->count;
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 190) 	ctx->count -= *cnt;
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 191) }
28f1326710555 (David Woodhouse   2020-10-27 13:55:21 +0000 192) EXPORT_SYMBOL_GPL(eventfd_ctx_do_read);
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 193) 
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 194) /**
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 195)  * eventfd_ctx_remove_wait_queue - Read the current counter and removes wait queue.
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 196)  * @ctx: [in] Pointer to eventfd context.
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 197)  * @wait: [in] Wait queue to be removed.
361821854b71f (Randy Dunlap      2011-02-20 20:08:35 -0800 198)  * @cnt: [out] Pointer to the 64-bit counter value.
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 199)  *
361821854b71f (Randy Dunlap      2011-02-20 20:08:35 -0800 200)  * Returns %0 if successful, or the following error codes:
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 201)  *
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 202)  * -EAGAIN      : The operation would have blocked.
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 203)  *
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 204)  * This is used to atomically remove a wait queue entry from the eventfd wait
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 205)  * queue head, and read/reset the counter value.
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 206)  */
ac6424b981bce (Ingo Molnar       2017-06-20 12:06:13 +0200 207) int eventfd_ctx_remove_wait_queue(struct eventfd_ctx *ctx, wait_queue_entry_t *wait,
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 208) 				  __u64 *cnt)
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 209) {
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 210) 	unsigned long flags;
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 211) 
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 212) 	spin_lock_irqsave(&ctx->wqh.lock, flags);
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 213) 	eventfd_ctx_do_read(ctx, cnt);
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 214) 	__remove_wait_queue(&ctx->wqh, wait);
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 215) 	if (*cnt != 0 && waitqueue_active(&ctx->wqh))
a9a08845e9acb (Linus Torvalds    2018-02-11 14:34:03 -0800 216) 		wake_up_locked_poll(&ctx->wqh, EPOLLOUT);
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 217) 	spin_unlock_irqrestore(&ctx->wqh.lock, flags);
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 218) 
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 219) 	return *cnt != 0 ? 0 : -EAGAIN;
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 220) }
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 221) EXPORT_SYMBOL_GPL(eventfd_ctx_remove_wait_queue);
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 222) 
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 223) static ssize_t eventfd_read(struct kiocb *iocb, struct iov_iter *to)
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 224) {
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 225) 	struct file *file = iocb->ki_filp;
b6364572d641c (Eric Biggers      2018-01-06 09:45:43 -0800 226) 	struct eventfd_ctx *ctx = file->private_data;
b6364572d641c (Eric Biggers      2018-01-06 09:45:43 -0800 227) 	__u64 ucnt = 0;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 228) 	DECLARE_WAITQUEUE(wait, current);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 229) 
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 230) 	if (iov_iter_count(to) < sizeof(ucnt))
b6364572d641c (Eric Biggers      2018-01-06 09:45:43 -0800 231) 		return -EINVAL;
d48eb23315952 (Davide Libenzi    2007-05-18 12:02:33 -0700 232) 	spin_lock_irq(&ctx->wqh.lock);
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 233) 	if (!ctx->count) {
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 234) 		if ((file->f_flags & O_NONBLOCK) ||
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 235) 		    (iocb->ki_flags & IOCB_NOWAIT)) {
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 236) 			spin_unlock_irq(&ctx->wqh.lock);
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 237) 			return -EAGAIN;
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 238) 		}
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 239) 		__add_wait_queue(&ctx->wqh, &wait);
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 240) 		for (;;) {
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 241) 			set_current_state(TASK_INTERRUPTIBLE);
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 242) 			if (ctx->count)
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 243) 				break;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 244) 			if (signal_pending(current)) {
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 245) 				__remove_wait_queue(&ctx->wqh, &wait);
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 246) 				__set_current_state(TASK_RUNNING);
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 247) 				spin_unlock_irq(&ctx->wqh.lock);
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 248) 				return -ERESTARTSYS;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 249) 			}
d48eb23315952 (Davide Libenzi    2007-05-18 12:02:33 -0700 250) 			spin_unlock_irq(&ctx->wqh.lock);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 251) 			schedule();
d48eb23315952 (Davide Libenzi    2007-05-18 12:02:33 -0700 252) 			spin_lock_irq(&ctx->wqh.lock);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 253) 		}
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 254) 		__remove_wait_queue(&ctx->wqh, &wait);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 255) 		__set_current_state(TASK_RUNNING);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 256) 	}
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 257) 	eventfd_ctx_do_read(ctx, &ucnt);
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 258) 	if (waitqueue_active(&ctx->wqh))
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 259) 		wake_up_locked_poll(&ctx->wqh, EPOLLOUT);
d48eb23315952 (Davide Libenzi    2007-05-18 12:02:33 -0700 260) 	spin_unlock_irq(&ctx->wqh.lock);
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 261) 	if (unlikely(copy_to_iter(&ucnt, sizeof(ucnt), to) != sizeof(ucnt)))
b6364572d641c (Eric Biggers      2018-01-06 09:45:43 -0800 262) 		return -EFAULT;
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 263) 
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 264) 	return sizeof(ucnt);
cb289d6244a37 (Davide Libenzi    2010-01-13 09:34:36 -0800 265) }
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 266) 
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 267) static ssize_t eventfd_write(struct file *file, const char __user *buf, size_t count,
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 268) 			     loff_t *ppos)
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 269) {
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 270) 	struct eventfd_ctx *ctx = file->private_data;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 271) 	ssize_t res;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 272) 	__u64 ucnt;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 273) 	DECLARE_WAITQUEUE(wait, current);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 274) 
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 275) 	if (count < sizeof(ucnt))
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 276) 		return -EINVAL;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 277) 	if (copy_from_user(&ucnt, buf, sizeof(ucnt)))
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 278) 		return -EFAULT;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 279) 	if (ucnt == ULLONG_MAX)
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 280) 		return -EINVAL;
d48eb23315952 (Davide Libenzi    2007-05-18 12:02:33 -0700 281) 	spin_lock_irq(&ctx->wqh.lock);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 282) 	res = -EAGAIN;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 283) 	if (ULLONG_MAX - ctx->count > ucnt)
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 284) 		res = sizeof(ucnt);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 285) 	else if (!(file->f_flags & O_NONBLOCK)) {
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 286) 		__add_wait_queue(&ctx->wqh, &wait);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 287) 		for (res = 0;;) {
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 288) 			set_current_state(TASK_INTERRUPTIBLE);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 289) 			if (ULLONG_MAX - ctx->count > ucnt) {
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 290) 				res = sizeof(ucnt);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 291) 				break;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 292) 			}
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 293) 			if (signal_pending(current)) {
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 294) 				res = -ERESTARTSYS;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 295) 				break;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 296) 			}
d48eb23315952 (Davide Libenzi    2007-05-18 12:02:33 -0700 297) 			spin_unlock_irq(&ctx->wqh.lock);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 298) 			schedule();
d48eb23315952 (Davide Libenzi    2007-05-18 12:02:33 -0700 299) 			spin_lock_irq(&ctx->wqh.lock);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 300) 		}
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 301) 		__remove_wait_queue(&ctx->wqh, &wait);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 302) 		__set_current_state(TASK_RUNNING);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 303) 	}
bcd0b235bf380 (Davide Libenzi    2009-03-31 15:24:18 -0700 304) 	if (likely(res > 0)) {
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 305) 		ctx->count += ucnt;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 306) 		if (waitqueue_active(&ctx->wqh))
a9a08845e9acb (Linus Torvalds    2018-02-11 14:34:03 -0800 307) 			wake_up_locked_poll(&ctx->wqh, EPOLLIN);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 308) 	}
d48eb23315952 (Davide Libenzi    2007-05-18 12:02:33 -0700 309) 	spin_unlock_irq(&ctx->wqh.lock);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 310) 
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 311) 	return res;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 312) }
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 313) 
cbac5542d4812 (Cyrill Gorcunov   2012-12-17 16:04:57 -0800 314) #ifdef CONFIG_PROC_FS
a3816ab0e8fe5 (Joe Perches       2014-09-29 16:08:25 -0700 315) static void eventfd_show_fdinfo(struct seq_file *m, struct file *f)
cbac5542d4812 (Cyrill Gorcunov   2012-12-17 16:04:57 -0800 316) {
cbac5542d4812 (Cyrill Gorcunov   2012-12-17 16:04:57 -0800 317) 	struct eventfd_ctx *ctx = f->private_data;
cbac5542d4812 (Cyrill Gorcunov   2012-12-17 16:04:57 -0800 318) 
cbac5542d4812 (Cyrill Gorcunov   2012-12-17 16:04:57 -0800 319) 	spin_lock_irq(&ctx->wqh.lock);
a3816ab0e8fe5 (Joe Perches       2014-09-29 16:08:25 -0700 320) 	seq_printf(m, "eventfd-count: %16llx\n",
a3816ab0e8fe5 (Joe Perches       2014-09-29 16:08:25 -0700 321) 		   (unsigned long long)ctx->count);
cbac5542d4812 (Cyrill Gorcunov   2012-12-17 16:04:57 -0800 322) 	spin_unlock_irq(&ctx->wqh.lock);
b556db17b0e7c (Masatake YAMATO   2019-05-14 15:45:19 -0700 323) 	seq_printf(m, "eventfd-id: %d\n", ctx->id);
cbac5542d4812 (Cyrill Gorcunov   2012-12-17 16:04:57 -0800 324) }
cbac5542d4812 (Cyrill Gorcunov   2012-12-17 16:04:57 -0800 325) #endif
cbac5542d4812 (Cyrill Gorcunov   2012-12-17 16:04:57 -0800 326) 
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 327) static const struct file_operations eventfd_fops = {
cbac5542d4812 (Cyrill Gorcunov   2012-12-17 16:04:57 -0800 328) #ifdef CONFIG_PROC_FS
cbac5542d4812 (Cyrill Gorcunov   2012-12-17 16:04:57 -0800 329) 	.show_fdinfo	= eventfd_show_fdinfo,
cbac5542d4812 (Cyrill Gorcunov   2012-12-17 16:04:57 -0800 330) #endif
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 331) 	.release	= eventfd_release,
a11e1d432b51f (Linus Torvalds    2018-06-28 09:43:44 -0700 332) 	.poll		= eventfd_poll,
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 333) 	.read_iter	= eventfd_read,
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 334) 	.write		= eventfd_write,
6038f373a3dc1 (Arnd Bergmann     2010-08-15 18:52:59 +0200 335) 	.llseek		= noop_llseek,
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 336) };
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 337) 
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 338) /**
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 339)  * eventfd_fget - Acquire a reference of an eventfd file descriptor.
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 340)  * @fd: [in] Eventfd file descriptor.
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 341)  *
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 342)  * Returns a pointer to the eventfd file structure in case of success, or the
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 343)  * following error pointer:
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 344)  *
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 345)  * -EBADF    : Invalid @fd file descriptor.
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 346)  * -EINVAL   : The @fd file descriptor is not an eventfd file.
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 347)  */
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 348) struct file *eventfd_fget(int fd)
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 349) {
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 350) 	struct file *file;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 351) 
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 352) 	file = fget(fd);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 353) 	if (!file)
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 354) 		return ERR_PTR(-EBADF);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 355) 	if (file->f_op != &eventfd_fops) {
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 356) 		fput(file);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 357) 		return ERR_PTR(-EINVAL);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 358) 	}
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 359) 
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 360) 	return file;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 361) }
5718607bb670c (Rusty Russell     2009-06-12 22:27:09 -0600 362) EXPORT_SYMBOL_GPL(eventfd_fget);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 363) 
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 364) /**
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 365)  * eventfd_ctx_fdget - Acquires a reference to the internal eventfd context.
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 366)  * @fd: [in] Eventfd file descriptor.
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 367)  *
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 368)  * Returns a pointer to the internal eventfd context, otherwise the error
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 369)  * pointers returned by the following functions:
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 370)  *
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 371)  * eventfd_fget
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 372)  */
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 373) struct eventfd_ctx *eventfd_ctx_fdget(int fd)
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 374) {
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 375) 	struct eventfd_ctx *ctx;
36a7411724b1c (Al Viro           2013-12-23 16:51:33 -0500 376) 	struct fd f = fdget(fd);
36a7411724b1c (Al Viro           2013-12-23 16:51:33 -0500 377) 	if (!f.file)
36a7411724b1c (Al Viro           2013-12-23 16:51:33 -0500 378) 		return ERR_PTR(-EBADF);
36a7411724b1c (Al Viro           2013-12-23 16:51:33 -0500 379) 	ctx = eventfd_ctx_fileget(f.file);
36a7411724b1c (Al Viro           2013-12-23 16:51:33 -0500 380) 	fdput(f);
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 381) 	return ctx;
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 382) }
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 383) EXPORT_SYMBOL_GPL(eventfd_ctx_fdget);
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 384) 
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 385) /**
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 386)  * eventfd_ctx_fileget - Acquires a reference to the internal eventfd context.
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 387)  * @file: [in] Eventfd file pointer.
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 388)  *
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 389)  * Returns a pointer to the internal eventfd context, otherwise the error
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 390)  * pointer:
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 391)  *
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 392)  * -EINVAL   : The @fd file descriptor is not an eventfd file.
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 393)  */
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 394) struct eventfd_ctx *eventfd_ctx_fileget(struct file *file)
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 395) {
105f2b7096075 (Eric Biggers      2018-01-06 09:45:44 -0800 396) 	struct eventfd_ctx *ctx;
105f2b7096075 (Eric Biggers      2018-01-06 09:45:44 -0800 397) 
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 398) 	if (file->f_op != &eventfd_fops)
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 399) 		return ERR_PTR(-EINVAL);
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 400) 
105f2b7096075 (Eric Biggers      2018-01-06 09:45:44 -0800 401) 	ctx = file->private_data;
105f2b7096075 (Eric Biggers      2018-01-06 09:45:44 -0800 402) 	kref_get(&ctx->kref);
105f2b7096075 (Eric Biggers      2018-01-06 09:45:44 -0800 403) 	return ctx;
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 404) }
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 405) EXPORT_SYMBOL_GPL(eventfd_ctx_fileget);
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 406) 
2fc96f8331ba7 (Dominik Brodowski 2018-03-11 11:34:37 +0100 407) static int do_eventfd(unsigned int count, int flags)
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 408) {
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 409) 	struct eventfd_ctx *ctx;
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 410) 	struct file *file;
7d815165c1a64 (Eric Biggers      2018-01-06 09:45:42 -0800 411) 	int fd;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 412) 
e38b36f325153 (Ulrich Drepper    2008-07-23 21:29:42 -0700 413) 	/* Check the EFD_* constants for consistency.  */
e38b36f325153 (Ulrich Drepper    2008-07-23 21:29:42 -0700 414) 	BUILD_BUG_ON(EFD_CLOEXEC != O_CLOEXEC);
e38b36f325153 (Ulrich Drepper    2008-07-23 21:29:42 -0700 415) 	BUILD_BUG_ON(EFD_NONBLOCK != O_NONBLOCK);
e38b36f325153 (Ulrich Drepper    2008-07-23 21:29:42 -0700 416) 
bcd0b235bf380 (Davide Libenzi    2009-03-31 15:24:18 -0700 417) 	if (flags & ~EFD_FLAGS_SET)
7d815165c1a64 (Eric Biggers      2018-01-06 09:45:42 -0800 418) 		return -EINVAL;
b087498eb5605 (Ulrich Drepper    2008-07-23 21:29:25 -0700 419) 
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 420) 	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 421) 	if (!ctx)
7d815165c1a64 (Eric Biggers      2018-01-06 09:45:42 -0800 422) 		return -ENOMEM;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 423) 
133890103b9de (Davide Libenzi    2009-06-30 11:41:11 -0700 424) 	kref_init(&ctx->kref);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 425) 	init_waitqueue_head(&ctx->wqh);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 426) 	ctx->count = count;
bcd0b235bf380 (Davide Libenzi    2009-03-31 15:24:18 -0700 427) 	ctx->flags = flags;
b556db17b0e7c (Masatake YAMATO   2019-05-14 15:45:19 -0700 428) 	ctx->id = ida_simple_get(&eventfd_ida, 0, 0, GFP_KERNEL);
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 429) 
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 430) 	flags &= EFD_SHARED_FCNTL_FLAGS;
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 431) 	flags |= O_RDWR;
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 432) 	fd = get_unused_fd_flags(flags);
7d815165c1a64 (Eric Biggers      2018-01-06 09:45:42 -0800 433) 	if (fd < 0)
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 434) 		goto err;
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 435) 
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 436) 	file = anon_inode_getfile("[eventfd]", &eventfd_fops, ctx, flags);
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 437) 	if (IS_ERR(file)) {
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 438) 		put_unused_fd(fd);
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 439) 		fd = PTR_ERR(file);
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 440) 		goto err;
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 441) 	}
562787a5c32cc (Davide Libenzi    2009-09-22 16:43:57 -0700 442) 
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 443) 	file->f_mode |= FMODE_NOWAIT;
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 444) 	fd_install(fd, file);
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 445) 	return fd;
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 446) err:
12aceb89b0bce (Jens Axboe        2020-05-01 13:11:09 -0600 447) 	eventfd_free_ctx(ctx);
2030a42cecd4d (Al Viro           2008-02-23 06:46:49 -0500 448) 	return fd;
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 449) }
e1ad7468c77dd (Davide Libenzi    2007-05-10 22:23:19 -0700 450) 
2fc96f8331ba7 (Dominik Brodowski 2018-03-11 11:34:37 +0100 451) SYSCALL_DEFINE2(eventfd2, unsigned int, count, int, flags)
2fc96f8331ba7 (Dominik Brodowski 2018-03-11 11:34:37 +0100 452) {
2fc96f8331ba7 (Dominik Brodowski 2018-03-11 11:34:37 +0100 453) 	return do_eventfd(count, flags);
2fc96f8331ba7 (Dominik Brodowski 2018-03-11 11:34:37 +0100 454) }
2fc96f8331ba7 (Dominik Brodowski 2018-03-11 11:34:37 +0100 455) 
d4e82042c4cfa (Heiko Carstens    2009-01-14 14:14:34 +0100 456) SYSCALL_DEFINE1(eventfd, unsigned int, count)
b087498eb5605 (Ulrich Drepper    2008-07-23 21:29:25 -0700 457) {
2fc96f8331ba7 (Dominik Brodowski 2018-03-11 11:34:37 +0100 458) 	return do_eventfd(count, 0);
b087498eb5605 (Ulrich Drepper    2008-07-23 21:29:25 -0700 459) }
bcd0b235bf380 (Davide Libenzi    2009-03-31 15:24:18 -0700 460)