2023-07-13 10:14:58

by Christian Brauner

[permalink] [raw]
Subject: [PATCH 0/2] eventfd: simplify signal helpers

Hey everyone,

This simplifies the eventfd_signal() and eventfd_signal_mask() helpers
by removing the count argument which is effectively unused.

---



---
base-commit: 6be357f00aad4189130147fdc6f568cf776a4909
change-id: 20230713-vfs-eventfd-signal-0b0d167ad6ec



2023-07-13 10:51:14

by Christian Brauner

[permalink] [raw]
Subject: [PATCH 2/2] eventfd: simplify eventfd_signal_mask()

The eventfd_signal_mask() helper was introduced for io_uring and similar
to eventfd_signal() it always passed 1 for @n. So don't bother with that
argument at all.

Signed-off-by: Christian Brauner <[email protected]>
---
drivers/gpu/drm/i915/gvt/interrupt.c | 2 +-
fs/eventfd.c | 9 +++++----
include/linux/eventfd.h | 9 ++++-----
io_uring/io_uring.c | 4 ++--
4 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/interrupt.c b/drivers/gpu/drm/i915/gvt/interrupt.c
index 3d9e09c2add4..31aff6f733d4 100644
--- a/drivers/gpu/drm/i915/gvt/interrupt.c
+++ b/drivers/gpu/drm/i915/gvt/interrupt.c
@@ -435,7 +435,7 @@ static int inject_virtual_interrupt(struct intel_vgpu *vgpu)
*/
if (!test_bit(INTEL_VGPU_STATUS_ATTACHED, vgpu->status))
return -ESRCH;
- if (vgpu->msi_trigger && eventfd_signal(vgpu->msi_trigger) != 1)
+ if (vgpu->msi_trigger && !eventfd_signal(vgpu->msi_trigger))
return -EFAULT;
return 0;
}
diff --git a/fs/eventfd.c b/fs/eventfd.c
index dc9e01053235..077be5da72bd 100644
--- a/fs/eventfd.c
+++ b/fs/eventfd.c
@@ -43,9 +43,10 @@ struct eventfd_ctx {
int id;
};

-__u64 eventfd_signal_mask(struct eventfd_ctx *ctx, __u64 n, __poll_t mask)
+bool eventfd_signal_mask(struct eventfd_ctx *ctx, __poll_t mask)
{
unsigned long flags;
+ __u64 n = 1;

/*
* Deadlock or stack overflow issues can happen if we recurse here
@@ -68,7 +69,7 @@ __u64 eventfd_signal_mask(struct eventfd_ctx *ctx, __u64 n, __poll_t mask)
current->in_eventfd = 0;
spin_unlock_irqrestore(&ctx->wqh.lock, flags);

- return n;
+ return n == 1;
}

/**
@@ -82,9 +83,9 @@ __u64 eventfd_signal_mask(struct eventfd_ctx *ctx, __u64 n, __poll_t mask)
*
* Returns the amount by which the counter was incremented.
*/
-__u64 eventfd_signal(struct eventfd_ctx *ctx)
+bool eventfd_signal(struct eventfd_ctx *ctx)
{
- return eventfd_signal_mask(ctx, 1, 0);
+ return eventfd_signal_mask(ctx, 0);
}
EXPORT_SYMBOL_GPL(eventfd_signal);

diff --git a/include/linux/eventfd.h b/include/linux/eventfd.h
index 562089431551..0155ee25f7c8 100644
--- a/include/linux/eventfd.h
+++ b/include/linux/eventfd.h
@@ -35,8 +35,8 @@ void eventfd_ctx_put(struct eventfd_ctx *ctx);
struct file *eventfd_fget(int fd);
struct eventfd_ctx *eventfd_ctx_fdget(int fd);
struct eventfd_ctx *eventfd_ctx_fileget(struct file *file);
-__u64 eventfd_signal(struct eventfd_ctx *ctx);
-__u64 eventfd_signal_mask(struct eventfd_ctx *ctx, __u64 n, __poll_t mask);
+bool eventfd_signal(struct eventfd_ctx *ctx);
+bool eventfd_signal_mask(struct eventfd_ctx *ctx, __poll_t mask);
int eventfd_ctx_remove_wait_queue(struct eventfd_ctx *ctx, wait_queue_entry_t *wait,
__u64 *cnt);
void eventfd_ctx_do_read(struct eventfd_ctx *ctx, __u64 *cnt);
@@ -58,13 +58,12 @@ static inline struct eventfd_ctx *eventfd_ctx_fdget(int fd)
return ERR_PTR(-ENOSYS);
}

-static inline int eventfd_signal(struct eventfd_ctx *ctx)
+static inline bool eventfd_signal(struct eventfd_ctx *ctx)
{
return -ENOSYS;
}

-static inline int eventfd_signal_mask(struct eventfd_ctx *ctx, __u64 n,
- unsigned mask)
+static inline bool eventfd_signal_mask(struct eventfd_ctx *ctx, unsigned mask)
{
return -ENOSYS;
}
diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
index e8096d502a7c..a9359ef73935 100644
--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -537,7 +537,7 @@ static void io_eventfd_ops(struct rcu_head *rcu)
int ops = atomic_xchg(&ev_fd->ops, 0);

if (ops & BIT(IO_EVENTFD_OP_SIGNAL_BIT))
- eventfd_signal_mask(ev_fd->cq_ev_fd, 1, EPOLL_URING_WAKE);
+ eventfd_signal_mask(ev_fd->cq_ev_fd, EPOLL_URING_WAKE);

/* IO_EVENTFD_OP_FREE_BIT may not be set here depending on callback
* ordering in a race but if references are 0 we know we have to free
@@ -573,7 +573,7 @@ static void io_eventfd_signal(struct io_ring_ctx *ctx)
goto out;

if (likely(eventfd_signal_allowed())) {
- eventfd_signal_mask(ev_fd->cq_ev_fd, 1, EPOLL_URING_WAKE);
+ eventfd_signal_mask(ev_fd->cq_ev_fd, EPOLL_URING_WAKE);
} else {
atomic_inc(&ev_fd->refs);
if (!atomic_fetch_or(BIT(IO_EVENTFD_OP_SIGNAL_BIT), &ev_fd->ops))

--
2.34.1


2023-07-13 12:15:05

by Petr Machata

[permalink] [raw]
Subject: Re: [PATCH 2/2] eventfd: simplify eventfd_signal_mask()


Christian Brauner <[email protected]> writes:

> @@ -82,9 +83,9 @@ __u64 eventfd_signal_mask(struct eventfd_ctx *ctx, __u64 n, __poll_t mask)
> *
> * Returns the amount by which the counter was incremented.

This should be reworded to reflect the fact that the function now
returns a bool.

> */
> -__u64 eventfd_signal(struct eventfd_ctx *ctx)
> +bool eventfd_signal(struct eventfd_ctx *ctx)
> {
> - return eventfd_signal_mask(ctx, 1, 0);
> + return eventfd_signal_mask(ctx, 0);
> }
> EXPORT_SYMBOL_GPL(eventfd_signal);
>

2023-07-13 14:12:03

by Christian Brauner

[permalink] [raw]
Subject: Re: [PATCH 2/2] eventfd: simplify eventfd_signal_mask()

On Thu, Jul 13, 2023 at 01:59:01PM +0200, Petr Machata wrote:
>
> Christian Brauner <[email protected]> writes:
>
> > @@ -82,9 +83,9 @@ __u64 eventfd_signal_mask(struct eventfd_ctx *ctx, __u64 n, __poll_t mask)
> > *
> > * Returns the amount by which the counter was incremented.
>
> This should be reworded to reflect the fact that the function now
> returns a bool.

Thanks, I'll update that in-tree to avoid respamming everyone.

2023-07-13 14:51:48

by Sean Christopherson

[permalink] [raw]
Subject: Re: [PATCH 2/2] eventfd: simplify eventfd_signal_mask()

On Thu, Jul 13, 2023, Christian Brauner wrote:
> diff --git a/fs/eventfd.c b/fs/eventfd.c
> index dc9e01053235..077be5da72bd 100644
> --- a/fs/eventfd.c
> +++ b/fs/eventfd.c
> @@ -43,9 +43,10 @@ struct eventfd_ctx {
> int id;
> };
>
> -__u64 eventfd_signal_mask(struct eventfd_ctx *ctx, __u64 n, __poll_t mask)
> +bool eventfd_signal_mask(struct eventfd_ctx *ctx, __poll_t mask)
> {
> unsigned long flags;
> + __u64 n = 1;
>
> /*
> * Deadlock or stack overflow issues can happen if we recurse here
> @@ -68,7 +69,7 @@ __u64 eventfd_signal_mask(struct eventfd_ctx *ctx, __u64 n, __poll_t mask)
> current->in_eventfd = 0;
> spin_unlock_irqrestore(&ctx->wqh.lock, flags);
>
> - return n;
> + return n == 1;
> }

...

> @@ -58,13 +58,12 @@ static inline struct eventfd_ctx *eventfd_ctx_fdget(int fd)
> return ERR_PTR(-ENOSYS);
> }
>
> -static inline int eventfd_signal(struct eventfd_ctx *ctx)
> +static inline bool eventfd_signal(struct eventfd_ctx *ctx)
> {
> return -ENOSYS;
> }
>
> -static inline int eventfd_signal_mask(struct eventfd_ctx *ctx, __u64 n,
> - unsigned mask)
> +static inline bool eventfd_signal_mask(struct eventfd_ctx *ctx, unsigned mask)
> {
> return -ENOSYS;

This will morph to "true" for what should be an error case. One option would be
to have eventfd_signal_mask() return 0/-errno instead of the count, but looking
at all the callers, nothing ever actually consumes the result.

KVMGT morphs failure into -EFAULT

if (vgpu->msi_trigger && eventfd_signal(vgpu->msi_trigger, 1) != 1)
return -EFAULT;

but the only caller of that user ignores the return value.

if (vgpu_vreg(vgpu, i915_mmio_reg_offset(GEN8_MASTER_IRQ))
& ~GEN8_MASTER_IRQ_CONTROL)
inject_virtual_interrupt(vgpu);

The sample driver in samples/vfio-mdev/mtty.c uses a similar pattern: prints an
error but otherwise ignores the result.

So why not return nothing? That will simplify eventfd_signal_mask() a wee bit
more, and eliminate that bizarre return value confusion for the ugly stubs, e.g.

void eventfd_signal_mask(struct eventfd_ctx *ctx, unsigned mask)
{
unsigned long flags;

/*
* Deadlock or stack overflow issues can happen if we recurse here
* through waitqueue wakeup handlers. If the caller users potentially
* nested waitqueues with custom wakeup handlers, then it should
* check eventfd_signal_allowed() before calling this function. If
* it returns false, the eventfd_signal() call should be deferred to a
* safe context.
*/
if (WARN_ON_ONCE(current->in_eventfd))
return;

spin_lock_irqsave(&ctx->wqh.lock, flags);
current->in_eventfd = 1;
if (ctx->count < ULLONG_MAX)
ctx->count++;
if (waitqueue_active(&ctx->wqh))
wake_up_locked_poll(&ctx->wqh, EPOLLIN | mask);
current->in_eventfd = 0;
spin_unlock_irqrestore(&ctx->wqh.lock, flags);
}

You could even go further and unify the real and stub versions of eventfd_signal().

2023-07-13 15:05:24

by Christian Brauner

[permalink] [raw]
Subject: Re: [PATCH 2/2] eventfd: simplify eventfd_signal_mask()

On Thu, Jul 13, 2023 at 07:33:05AM -0700, Sean Christopherson wrote:
> On Thu, Jul 13, 2023, Christian Brauner wrote:
> > diff --git a/fs/eventfd.c b/fs/eventfd.c
> > index dc9e01053235..077be5da72bd 100644
> > --- a/fs/eventfd.c
> > +++ b/fs/eventfd.c
> > @@ -43,9 +43,10 @@ struct eventfd_ctx {
> > int id;
> > };
> >
> > -__u64 eventfd_signal_mask(struct eventfd_ctx *ctx, __u64 n, __poll_t mask)
> > +bool eventfd_signal_mask(struct eventfd_ctx *ctx, __poll_t mask)
> > {
> > unsigned long flags;
> > + __u64 n = 1;
> >
> > /*
> > * Deadlock or stack overflow issues can happen if we recurse here
> > @@ -68,7 +69,7 @@ __u64 eventfd_signal_mask(struct eventfd_ctx *ctx, __u64 n, __poll_t mask)
> > current->in_eventfd = 0;
> > spin_unlock_irqrestore(&ctx->wqh.lock, flags);
> >
> > - return n;
> > + return n == 1;
> > }
>
> ...
>
> > @@ -58,13 +58,12 @@ static inline struct eventfd_ctx *eventfd_ctx_fdget(int fd)
> > return ERR_PTR(-ENOSYS);
> > }
> >
> > -static inline int eventfd_signal(struct eventfd_ctx *ctx)
> > +static inline bool eventfd_signal(struct eventfd_ctx *ctx)
> > {
> > return -ENOSYS;
> > }
> >
> > -static inline int eventfd_signal_mask(struct eventfd_ctx *ctx, __u64 n,
> > - unsigned mask)
> > +static inline bool eventfd_signal_mask(struct eventfd_ctx *ctx, unsigned mask)
> > {
> > return -ENOSYS;
>
> This will morph to "true" for what should be an error case. One option would be

Ewww, that means it did return -ENOSYS before any of this.

> to have eventfd_signal_mask() return 0/-errno instead of the count, but looking
> at all the callers, nothing ever actually consumes the result.
>
> KVMGT morphs failure into -EFAULT
>
> if (vgpu->msi_trigger && eventfd_signal(vgpu->msi_trigger, 1) != 1)
> return -EFAULT;
>
> but the only caller of that user ignores the return value.
>
> if (vgpu_vreg(vgpu, i915_mmio_reg_offset(GEN8_MASTER_IRQ))
> & ~GEN8_MASTER_IRQ_CONTROL)
> inject_virtual_interrupt(vgpu);
>
> The sample driver in samples/vfio-mdev/mtty.c uses a similar pattern: prints an
> error but otherwise ignores the result.
>
> So why not return nothing? That will simplify eventfd_signal_mask() a wee bit
> more, and eliminate that bizarre return value confusion for the ugly stubs, e.g.

Yeah, it used to return an int in the non-eventfd and a __u64 in the
eventfd case.

>
> void eventfd_signal_mask(struct eventfd_ctx *ctx, unsigned mask)
> {
> unsigned long flags;
>
> /*
> * Deadlock or stack overflow issues can happen if we recurse here
> * through waitqueue wakeup handlers. If the caller users potentially
> * nested waitqueues with custom wakeup handlers, then it should
> * check eventfd_signal_allowed() before calling this function. If
> * it returns false, the eventfd_signal() call should be deferred to a
> * safe context.
> */
> if (WARN_ON_ONCE(current->in_eventfd))
> return;
>
> spin_lock_irqsave(&ctx->wqh.lock, flags);
> current->in_eventfd = 1;
> if (ctx->count < ULLONG_MAX)
> ctx->count++;
> if (waitqueue_active(&ctx->wqh))
> wake_up_locked_poll(&ctx->wqh, EPOLLIN | mask);
> current->in_eventfd = 0;
> spin_unlock_irqrestore(&ctx->wqh.lock, flags);
> }
>
> You could even go further and unify the real and stub versions of eventfd_signal().

The reason I didn't make eventfd_signal_mask() return void was that it
was called from eventfd_signal() which did, I didn't realize the caller
didn't actually consume the return value.

If we can let both return void it gets simpler.

Thanks for that.

2023-07-13 17:34:16

by Alex Williamson

[permalink] [raw]
Subject: Re: [PATCH 0/2] eventfd: simplify signal helpers

On Thu, 13 Jul 2023 12:05:36 +0200
Christian Brauner <[email protected]> wrote:

> Hey everyone,
>
> This simplifies the eventfd_signal() and eventfd_signal_mask() helpers
> by removing the count argument which is effectively unused.

We have a patch under review which does in fact make use of the
signaling value:

https://lore.kernel.org/all/[email protected]/

Thanks,
Alex