lkml.org 
[lkml]   [2009]   [Jun]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectRe: [PATCH 3/3] eventfd: add internal reference counting to fix notifier race conditions
    On Sat, 20 Jun 2009, Davide Libenzi wrote:

    > How about the one below?

    Maybe with an interface that can be undone w/out a file* :)


    - Davide


    ---
    fs/eventfd.c | 34 +++++++++++++++++++++++++++++++++-
    include/linux/eventfd.h | 8 ++++++++
    2 files changed, 41 insertions(+), 1 deletion(-)

    Index: linux-2.6.mod/fs/eventfd.c
    ===================================================================
    --- linux-2.6.mod.orig/fs/eventfd.c 2009-06-20 13:08:22.000000000 -0700
    +++ linux-2.6.mod/fs/eventfd.c 2009-06-20 15:07:18.000000000 -0700
    @@ -17,8 +17,10 @@
    #include <linux/eventfd.h>
    #include <linux/syscalls.h>
    #include <linux/module.h>
    +#include <linux/kref.h>

    struct eventfd_ctx {
    + struct kref kref;
    wait_queue_head_t wqh;
    /*
    * Every time that a write(2) is performed on an eventfd, the
    @@ -59,9 +61,19 @@ int eventfd_signal(struct file *file, in
    }
    EXPORT_SYMBOL_GPL(eventfd_signal);

    +static void eventfd_free(struct kref *kref)
    +{
    + struct eventfd_ctx *ctx = container_of(kref, struct eventfd_ctx, kref);
    +
    + kfree(ctx);
    +}
    +
    static int eventfd_release(struct inode *inode, struct file *file)
    {
    - kfree(file->private_data);
    + struct eventfd_ctx *ctx = file->private_data;
    +
    + wake_up_poll(&ctx->wqh, POLLHUP);
    + kref_put(&ctx->kref, eventfd_free);
    return 0;
    }

    @@ -201,6 +213,25 @@ struct file *eventfd_fget(int fd)
    }
    EXPORT_SYMBOL_GPL(eventfd_fget);

    +struct eventfd_kref *eventfd_refget(struct file *file)
    +{
    + struct eventfd_ctx *ctx = file->private_data;
    +
    + if (file->f_op != &eventfd_fops)
    + return ERR_PTR(-EINVAL);
    + kref_get(&ctx->kref);
    + return (struct eventfd_kref *) ctx;
    +}
    +EXPORT_SYMBOL_GPL(eventfd_refget);
    +
    +void eventfd_refput(struct eventfd_kref *ref)
    +{
    + struct eventfd_ctx *ctx = (struct eventfd_ctx *) ref;
    +
    + kref_put(&ctx->kref, eventfd_free);
    +}
    +EXPORT_SYMBOL_GPL(eventfd_refput);
    +
    SYSCALL_DEFINE2(eventfd2, unsigned int, count, int, flags)
    {
    int fd;
    @@ -217,6 +248,7 @@ SYSCALL_DEFINE2(eventfd2, unsigned int,
    if (!ctx)
    return -ENOMEM;

    + kref_init(&ctx->kref);
    init_waitqueue_head(&ctx->wqh);
    ctx->count = count;
    ctx->flags = flags;
    Index: linux-2.6.mod/include/linux/eventfd.h
    ===================================================================
    --- linux-2.6.mod.orig/include/linux/eventfd.h 2009-06-20 13:08:22.000000000 -0700
    +++ linux-2.6.mod/include/linux/eventfd.h 2009-06-20 15:06:03.000000000 -0700
    @@ -8,6 +8,8 @@
    #ifndef _LINUX_EVENTFD_H
    #define _LINUX_EVENTFD_H

    +struct eventfd_kref;
    +
    #ifdef CONFIG_EVENTFD

    /* For O_CLOEXEC and O_NONBLOCK */
    @@ -29,12 +31,18 @@

    struct file *eventfd_fget(int fd);
    int eventfd_signal(struct file *file, int n);
    +struct eventfd_kref *eventfd_refget(struct file *file);
    +void eventfd_refput(struct eventfd_kref *ref);

    #else /* CONFIG_EVENTFD */

    #define eventfd_fget(fd) ERR_PTR(-ENOSYS)
    static inline int eventfd_signal(struct file *file, int n)
    { return 0; }
    +static inline struct eventfd_kref *eventfd_refget(struct file *file)
    +{ return ERR_PTR(-ENOSYS); }
    +static inline void eventfd_refput(struct eventfd_kref *ref)
    +{ }

    #endif /* CONFIG_EVENTFD */


    \
     
     \ /
      Last update: 2009-06-21 00:21    [W:2.518 / U:0.036 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site