Re: [PATCH 2/2] eventfd: simplify eventfd_signal_mask()
From: Sean Christopherson <seanjc@google.com>
Date: 2023-07-13 14:33:13
Also in:
cgroups, dri-devel, intel-gfx, io-uring, kvm, linux-fpga, linux-fsdevel, linux-mm, linux-rdma, linux-s390, linux-usb, lkml, netdev
On Thu, Jul 13, 2023, Christian Brauner wrote:
quoted hunk ↗ jump to hunk
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; }
...
quoted hunk ↗ jump to hunk
@@ -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().