hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
kernel/fs/eventfd.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * fs/eventfd.c
34 *
....@@ -21,8 +22,12 @@
2122 #include <linux/eventfd.h>
2223 #include <linux/proc_fs.h>
2324 #include <linux/seq_file.h>
25
+#include <linux/idr.h>
26
+#include <linux/uio.h>
2427
2528 DEFINE_PER_CPU(int, eventfd_wake_count);
29
+
30
+static DEFINE_IDA(eventfd_ida);
2631
2732 struct eventfd_ctx {
2833 struct kref kref;
....@@ -37,23 +42,10 @@
3742 */
3843 __u64 count;
3944 unsigned int flags;
45
+ int id;
4046 };
4147
42
-/**
43
- * eventfd_signal - Adds @n to the eventfd counter.
44
- * @ctx: [in] Pointer to the eventfd context.
45
- * @n: [in] Value of the counter to be added to the eventfd internal counter.
46
- * The value cannot be negative.
47
- *
48
- * This function is supposed to be called by the kernel in paths that do not
49
- * allow sleeping. In this function we allow the counter to reach the ULLONG_MAX
50
- * value, and we signal this as overflow condition by returning a EPOLLERR
51
- * to poll(2).
52
- *
53
- * Returns the amount by which the counter was incremented. This will be less
54
- * than @n if the counter has overflowed.
55
- */
56
-__u64 eventfd_signal(struct eventfd_ctx *ctx, __u64 n)
48
+__u64 eventfd_signal_mask(struct eventfd_ctx *ctx, __u64 n, unsigned mask)
5749 {
5850 unsigned long flags;
5951
....@@ -74,16 +66,37 @@
7466 n = ULLONG_MAX - ctx->count;
7567 ctx->count += n;
7668 if (waitqueue_active(&ctx->wqh))
77
- wake_up_locked_poll(&ctx->wqh, EPOLLIN);
69
+ wake_up_locked_poll(&ctx->wqh, EPOLLIN | mask);
7870 this_cpu_dec(eventfd_wake_count);
7971 spin_unlock_irqrestore(&ctx->wqh.lock, flags);
8072
8173 return n;
8274 }
75
+
76
+/**
77
+ * eventfd_signal - Adds @n to the eventfd counter.
78
+ * @ctx: [in] Pointer to the eventfd context.
79
+ * @n: [in] Value of the counter to be added to the eventfd internal counter.
80
+ * The value cannot be negative.
81
+ *
82
+ * This function is supposed to be called by the kernel in paths that do not
83
+ * allow sleeping. In this function we allow the counter to reach the ULLONG_MAX
84
+ * value, and we signal this as overflow condition by returning a EPOLLERR
85
+ * to poll(2).
86
+ *
87
+ * Returns the amount by which the counter was incremented. This will be less
88
+ * than @n if the counter has overflowed.
89
+ */
90
+__u64 eventfd_signal(struct eventfd_ctx *ctx, __u64 n)
91
+{
92
+ return eventfd_signal_mask(ctx, n, 0);
93
+}
8394 EXPORT_SYMBOL_GPL(eventfd_signal);
8495
8596 static void eventfd_free_ctx(struct eventfd_ctx *ctx)
8697 {
98
+ if (ctx->id >= 0)
99
+ ida_simple_remove(&eventfd_ida, ctx->id);
87100 kfree(ctx);
88101 }
89102
....@@ -209,32 +222,32 @@
209222 }
210223 EXPORT_SYMBOL_GPL(eventfd_ctx_remove_wait_queue);
211224
212
-static ssize_t eventfd_read(struct file *file, char __user *buf, size_t count,
213
- loff_t *ppos)
225
+static ssize_t eventfd_read(struct kiocb *iocb, struct iov_iter *to)
214226 {
227
+ struct file *file = iocb->ki_filp;
215228 struct eventfd_ctx *ctx = file->private_data;
216
- ssize_t res;
217229 __u64 ucnt = 0;
218230 DECLARE_WAITQUEUE(wait, current);
219231
220
- if (count < sizeof(ucnt))
232
+ if (iov_iter_count(to) < sizeof(ucnt))
221233 return -EINVAL;
222
-
223234 spin_lock_irq(&ctx->wqh.lock);
224
- res = -EAGAIN;
225
- if (ctx->count > 0)
226
- res = sizeof(ucnt);
227
- else if (!(file->f_flags & O_NONBLOCK)) {
235
+ if (!ctx->count) {
236
+ if ((file->f_flags & O_NONBLOCK) ||
237
+ (iocb->ki_flags & IOCB_NOWAIT)) {
238
+ spin_unlock_irq(&ctx->wqh.lock);
239
+ return -EAGAIN;
240
+ }
228241 __add_wait_queue(&ctx->wqh, &wait);
229242 for (;;) {
230243 set_current_state(TASK_INTERRUPTIBLE);
231
- if (ctx->count > 0) {
232
- res = sizeof(ucnt);
244
+ if (ctx->count)
233245 break;
234
- }
235246 if (signal_pending(current)) {
236
- res = -ERESTARTSYS;
237
- break;
247
+ __remove_wait_queue(&ctx->wqh, &wait);
248
+ __set_current_state(TASK_RUNNING);
249
+ spin_unlock_irq(&ctx->wqh.lock);
250
+ return -ERESTARTSYS;
238251 }
239252 spin_unlock_irq(&ctx->wqh.lock);
240253 schedule();
....@@ -243,17 +256,14 @@
243256 __remove_wait_queue(&ctx->wqh, &wait);
244257 __set_current_state(TASK_RUNNING);
245258 }
246
- if (likely(res > 0)) {
247
- eventfd_ctx_do_read(ctx, &ucnt);
248
- if (waitqueue_active(&ctx->wqh))
249
- wake_up_locked_poll(&ctx->wqh, EPOLLOUT);
250
- }
259
+ eventfd_ctx_do_read(ctx, &ucnt);
260
+ if (waitqueue_active(&ctx->wqh))
261
+ wake_up_locked_poll(&ctx->wqh, EPOLLOUT);
251262 spin_unlock_irq(&ctx->wqh.lock);
252
-
253
- if (res > 0 && put_user(ucnt, (__u64 __user *)buf))
263
+ if (unlikely(copy_to_iter(&ucnt, sizeof(ucnt), to) != sizeof(ucnt)))
254264 return -EFAULT;
255265
256
- return res;
266
+ return sizeof(ucnt);
257267 }
258268
259269 static ssize_t eventfd_write(struct file *file, const char __user *buf, size_t count,
....@@ -312,6 +322,7 @@
312322 seq_printf(m, "eventfd-count: %16llx\n",
313323 (unsigned long long)ctx->count);
314324 spin_unlock_irq(&ctx->wqh.lock);
325
+ seq_printf(m, "eventfd-id: %d\n", ctx->id);
315326 }
316327 #endif
317328
....@@ -321,7 +332,7 @@
321332 #endif
322333 .release = eventfd_release,
323334 .poll = eventfd_poll,
324
- .read = eventfd_read,
335
+ .read_iter = eventfd_read,
325336 .write = eventfd_write,
326337 .llseek = noop_llseek,
327338 };
....@@ -398,6 +409,7 @@
398409 static int do_eventfd(unsigned int count, int flags)
399410 {
400411 struct eventfd_ctx *ctx;
412
+ struct file *file;
401413 int fd;
402414
403415 /* Check the EFD_* constants for consistency. */
....@@ -415,12 +427,26 @@
415427 init_waitqueue_head(&ctx->wqh);
416428 ctx->count = count;
417429 ctx->flags = flags;
430
+ ctx->id = ida_simple_get(&eventfd_ida, 0, 0, GFP_KERNEL);
418431
419
- fd = anon_inode_getfd("[eventfd]", &eventfd_fops, ctx,
420
- O_RDWR | (flags & EFD_SHARED_FCNTL_FLAGS));
432
+ flags &= EFD_SHARED_FCNTL_FLAGS;
433
+ flags |= O_RDWR;
434
+ fd = get_unused_fd_flags(flags);
421435 if (fd < 0)
422
- eventfd_free_ctx(ctx);
436
+ goto err;
423437
438
+ file = anon_inode_getfile("[eventfd]", &eventfd_fops, ctx, flags);
439
+ if (IS_ERR(file)) {
440
+ put_unused_fd(fd);
441
+ fd = PTR_ERR(file);
442
+ goto err;
443
+ }
444
+
445
+ file->f_mode |= FMODE_NOWAIT;
446
+ fd_install(fd, file);
447
+ return fd;
448
+err:
449
+ eventfd_free_ctx(ctx);
424450 return fd;
425451 }
426452