[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <4922820D.4000802@cn.fujitsu.com>
Date: Tue, 18 Nov 2008 16:51:25 +0800
From: Lai Jiangshan <laijs@...fujitsu.com>
To: Andrew Morton <akpm@...ux-foundation.org>
CC: Johannes Weiner <hannes@...xchg.org>,
David Miller <davem@...emloft.net>,
Dave Airlie <airlied@...il.com>,
Paul Menage <menage@...gle.com>,
kamezawa.hiroyu@...fujitsu.com,
Balbir Singh <balbir@...ux.vnet.ibm.com>,
Arjan van de Ven <arjan@...radead.org>,
Jan Kara <jack@...e.cz>, Jes Sorensen <jes@....com>,
KOSAKI Motohiro <kosaki.motohiro@...fujitsu.com>,
dada1@...mosbay.com, Alexey Dobriyan <adobriyan@...il.com>,
Jens Axboe <jens.axboe@...cle.com>,
Linux Kernel Mailing List <linux-kernel@...r.kernel.org>,
"Paul E. McKenney" <paulmck@...ux.vnet.ibm.com>,
Nick Piggin <npiggin@...e.de>,
Al Viro <viro@...iv.linux.org.uk>,
Rik van Riel <riel@...hat.com>,
Pekka Enberg <penberg@...helsinki.fi>
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@...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);
}
/**
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists