OSDN Git Service

MAINTAINERS: update cxgb4vf maintainer to Vishal
[tomoyo/tomoyo-test1.git] / fs / eventfd.c
index 8aa0ea8..78e41c7 100644 (file)
@@ -24,6 +24,8 @@
 #include <linux/seq_file.h>
 #include <linux/idr.h>
 
+DEFINE_PER_CPU(int, eventfd_wake_count);
+
 static DEFINE_IDA(eventfd_ida);
 
 struct eventfd_ctx {
@@ -60,12 +62,25 @@ __u64 eventfd_signal(struct eventfd_ctx *ctx, __u64 n)
 {
        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_count() before calling this function. If
+        * it returns true, the eventfd_signal() call should be deferred to a
+        * safe context.
+        */
+       if (WARN_ON_ONCE(this_cpu_read(eventfd_wake_count)))
+               return 0;
+
        spin_lock_irqsave(&ctx->wqh.lock, flags);
+       this_cpu_inc(eventfd_wake_count);
        if (ULLONG_MAX - ctx->count < n)
                n = ULLONG_MAX - ctx->count;
        ctx->count += n;
        if (waitqueue_active(&ctx->wqh))
                wake_up_locked_poll(&ctx->wqh, EPOLLIN);
+       this_cpu_dec(eventfd_wake_count);
        spin_unlock_irqrestore(&ctx->wqh.lock, flags);
 
        return n;