lkml.org 
[lkml]   [2008]   [Nov]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH V2 4/4] sysipc: use kvmalloc()/kvfree_atomic()

    RCU callback here use vfree()
    use kvmalloc()/kvfree_atomic() make it simple


    Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com>
    ---
    util.c | 116 ++++++++++-------------------------------------------------------
    1 file changed, 19 insertions(+), 97 deletions(-)
    diff --git a/ipc/util.c b/ipc/util.c
    index 49b3ea6..3ecf04d 100644
    --- a/ipc/util.c
    +++ b/ipc/util.c
    @@ -468,51 +468,16 @@ void ipc_free(void* ptr, int size)
    kfree(ptr);
    }

    -/*
    - * rcu allocations:
    - * There are three headers that are prepended to the actual allocation:
    - * - during use: ipc_rcu_hdr.
    - * - during the rcu grace period: ipc_rcu_grace.
    - * - [only if vmalloc]: ipc_rcu_sched.
    - * Their lifetime doesn't overlap, thus the headers share the same memory.
    - * Unlike a normal union, they are right-aligned, thus some container_of
    - * forward/backward casting is necessary:
    - */
    struct ipc_rcu_hdr
    {
    - int refcount;
    - int is_vmalloc;
    - void *data[0];
    -};
    -
    -
    -struct ipc_rcu_grace
    -{
    - struct rcu_head rcu;
    + union {
    + int refcount;
    + struct rcu_head rcu;
    + };
    /* "void *" makes sure alignment of following data is sane. */
    void *data[0];
    };

    -struct ipc_rcu_sched
    -{
    - struct work_struct work;
    - /* "void *" makes sure alignment of following data is sane. */
    - void *data[0];
    -};
    -
    -#define HDRLEN_KMALLOC (sizeof(struct ipc_rcu_grace) > sizeof(struct ipc_rcu_hdr) ? \
    - sizeof(struct ipc_rcu_grace) : sizeof(struct ipc_rcu_hdr))
    -#define HDRLEN_VMALLOC (sizeof(struct ipc_rcu_sched) > HDRLEN_KMALLOC ? \
    - sizeof(struct ipc_rcu_sched) : HDRLEN_KMALLOC)
    -
    -static inline int rcu_use_vmalloc(int size)
    -{
    - /* Too big for a single page? */
    - if (HDRLEN_KMALLOC + size > PAGE_SIZE)
    - return 1;
    - return 0;
    -}
    -
    /**
    * ipc_rcu_alloc - allocate ipc and rcu space
    * @size: size desired
    @@ -522,30 +487,18 @@ static inline int rcu_use_vmalloc(int size)
    * NULL is returned if the allocation fails.
    */

    -void* ipc_rcu_alloc(int size)
    +void *ipc_rcu_alloc(int size)
    {
    - void* out;
    /*
    - * We prepend the allocation with the rcu struct, and
    - * workqueue if necessary (for vmalloc).
    + * We prepend the allocation with the ipc_rcu_hdr
    */
    - if (rcu_use_vmalloc(size)) {
    - out = vmalloc(HDRLEN_VMALLOC + size);
    - if (out) {
    - out += HDRLEN_VMALLOC;
    - container_of(out, struct ipc_rcu_hdr, data)->is_vmalloc = 1;
    - container_of(out, struct ipc_rcu_hdr, data)->refcount = 1;
    - }
    - } else {
    - out = kmalloc(HDRLEN_KMALLOC + size, GFP_KERNEL);
    - if (out) {
    - out += HDRLEN_KMALLOC;
    - container_of(out, struct ipc_rcu_hdr, data)->is_vmalloc = 0;
    - container_of(out, struct ipc_rcu_hdr, data)->refcount = 1;
    - }
    - }
    + struct ipc_rcu_hdr *hdr = kvmalloc(sizeof(struct ipc_rcu_hdr) + size,
    + GFP_KERNEL);
    + if (!hdr)
    + return NULL;

    - return out;
    + hdr->refcount = 1;
    + return hdr->data;
    }

    void ipc_rcu_getref(void *ptr)
    @@ -553,56 +506,25 @@ void ipc_rcu_getref(void *ptr)
    container_of(ptr, struct ipc_rcu_hdr, data)->refcount++;
    }

    -static void ipc_do_vfree(struct work_struct *work)
    -{
    - vfree(container_of(work, struct ipc_rcu_sched, work));
    -}
    -
    /**
    - * ipc_schedule_free - free ipc + rcu space
    + * ipc_free_rcu - free ipc + ipc_rcu_hdr
    * @head: RCU callback structure for queued work
    *
    * Since RCU callback function is called in bh,
    - * we need to defer the vfree to schedule_work().
    - */
    -static void ipc_schedule_free(struct rcu_head *head)
    -{
    - struct ipc_rcu_grace *grace;
    - struct ipc_rcu_sched *sched;
    -
    - grace = container_of(head, struct ipc_rcu_grace, rcu);
    - sched = container_of(&(grace->data[0]), struct ipc_rcu_sched,
    - data[0]);
    -
    - INIT_WORK(&sched->work, ipc_do_vfree);
    - schedule_work(&sched->work);
    -}
    -
    -/**
    - * ipc_immediate_free - free ipc + rcu space
    - * @head: RCU callback structure that contains pointer to be freed
    - *
    - * Free from the RCU callback context.
    + * we need to use kvfree_atomic().
    */
    -static void ipc_immediate_free(struct rcu_head *head)
    +static void ipc_free_rcu(struct rcu_head *head)
    {
    - struct ipc_rcu_grace *free =
    - container_of(head, struct ipc_rcu_grace, rcu);
    - kfree(free);
    + kvfree_atomic(container_of(head, struct ipc_rcu_hdr, rcu));
    }

    void ipc_rcu_putref(void *ptr)
    {
    - if (--container_of(ptr, struct ipc_rcu_hdr, data)->refcount > 0)
    + struct ipc_rcu_hdr *hdr = container_of(ptr, struct ipc_rcu_hdr, data);
    + if (--hdr->refcount > 0)
    return;

    - if (container_of(ptr, struct ipc_rcu_hdr, data)->is_vmalloc) {
    - call_rcu(&container_of(ptr, struct ipc_rcu_grace, data)->rcu,
    - ipc_schedule_free);
    - } else {
    - call_rcu(&container_of(ptr, struct ipc_rcu_grace, data)->rcu,
    - ipc_immediate_free);
    - }
    + call_rcu(&hdr->rcu, ipc_free_rcu);
    }

    /**



    \
     
     \ /
      Last update: 2008-11-18 09:59    [W:0.048 / U:32.744 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site