fault-injection: add ability to export fault_attr in arbitrary directory
[linux-2.6.git] / mm / mempool.c
index 65f2957..1a3bc3d 100644 (file)
@@ -46,9 +46,9 @@ static void free_pool(mempool_t *pool)
  * @pool_data: optional private data available to the user-defined functions.
  *
  * this function creates and allocates a guaranteed size, preallocated
- * memory pool. The pool can be used from the mempool_alloc and mempool_free
+ * memory pool. The pool can be used from the mempool_alloc() and mempool_free()
  * functions. This function might sleep. Both the alloc_fn() and the free_fn()
- * functions might sleep - as long as the mempool_alloc function is not called
+ * functions might sleep - as long as the mempool_alloc() function is not called
  * from IRQ contexts.
  */
 mempool_t *mempool_create(int min_nr, mempool_alloc_t *alloc_fn,
@@ -62,10 +62,9 @@ mempool_t *mempool_create_node(int min_nr, mempool_alloc_t *alloc_fn,
                        mempool_free_t *free_fn, void *pool_data, int node_id)
 {
        mempool_t *pool;
-       pool = kmalloc_node(sizeof(*pool), GFP_KERNEL, node_id);
+       pool = kmalloc_node(sizeof(*pool), GFP_KERNEL | __GFP_ZERO, node_id);
        if (!pool)
                return NULL;
-       memset(pool, 0, sizeof(*pool));
        pool->elements = kmalloc_node(min_nr * sizeof(void *),
                                        GFP_KERNEL, node_id);
        if (!pool->elements) {
@@ -112,7 +111,7 @@ EXPORT_SYMBOL(mempool_create_node);
  * while this function is running. mempool_alloc() & mempool_free()
  * might be called (eg. from IRQ contexts) while this function executes.
  */
-int mempool_resize(mempool_t *pool, int new_min_nr, unsigned int __nocast gfp_mask)
+int mempool_resize(mempool_t *pool, int new_min_nr, gfp_t gfp_mask)
 {
        void *element;
        void **new_elements;
@@ -183,8 +182,8 @@ EXPORT_SYMBOL(mempool_resize);
  */
 void mempool_destroy(mempool_t *pool)
 {
-       if (pool->curr_nr != pool->min_nr)
-               BUG();          /* There were outstanding elements */
+       /* Check for outstanding elements */
+       BUG_ON(pool->curr_nr != pool->min_nr);
        free_pool(pool);
 }
 EXPORT_SYMBOL(mempool_destroy);
@@ -195,17 +194,17 @@ EXPORT_SYMBOL(mempool_destroy);
  *             mempool_create().
  * @gfp_mask:  the usual allocation bitmask.
  *
- * this function only sleeps if the alloc_fn function sleeps or
+ * this function only sleeps if the alloc_fn() function sleeps or
  * returns NULL. Note that due to preallocation, this function
  * *never* fails when called from process contexts. (it might
  * fail if called from an IRQ context.)
  */
-void * mempool_alloc(mempool_t *pool, unsigned int __nocast gfp_mask)
+void * mempool_alloc(mempool_t *pool, gfp_t gfp_mask)
 {
        void *element;
        unsigned long flags;
        wait_queue_t wait;
-       unsigned int gfp_temp;
+       gfp_t gfp_temp;
 
        might_sleep_if(gfp_mask & __GFP_WAIT);
 
@@ -238,8 +237,13 @@ repeat_alloc:
        init_wait(&wait);
        prepare_to_wait(&pool->wait, &wait, TASK_UNINTERRUPTIBLE);
        smp_mb();
-       if (!pool->curr_nr)
-               io_schedule();
+       if (!pool->curr_nr) {
+               /*
+                * FIXME: this should be io_schedule().  The timeout is there
+                * as a workaround for some DM problems in 2.6.18.
+                */
+               io_schedule_timeout(5*HZ);
+       }
        finish_wait(&pool->wait, &wait);
 
        goto repeat_alloc;
@@ -258,6 +262,9 @@ void mempool_free(void *element, mempool_t *pool)
 {
        unsigned long flags;
 
+       if (unlikely(element == NULL))
+               return;
+
        smp_mb();
        if (pool->curr_nr < pool->min_nr) {
                spin_lock_irqsave(&pool->lock, flags);
@@ -276,16 +283,51 @@ EXPORT_SYMBOL(mempool_free);
 /*
  * A commonly used alloc and free fn.
  */
-void *mempool_alloc_slab(unsigned int __nocast gfp_mask, void *pool_data)
+void *mempool_alloc_slab(gfp_t gfp_mask, void *pool_data)
 {
-       kmem_cache_t *mem = (kmem_cache_t *) pool_data;
+       struct kmem_cache *mem = pool_data;
        return kmem_cache_alloc(mem, gfp_mask);
 }
 EXPORT_SYMBOL(mempool_alloc_slab);
 
 void mempool_free_slab(void *element, void *pool_data)
 {
-       kmem_cache_t *mem = (kmem_cache_t *) pool_data;
+       struct kmem_cache *mem = pool_data;
        kmem_cache_free(mem, element);
 }
 EXPORT_SYMBOL(mempool_free_slab);
+
+/*
+ * A commonly used alloc and free fn that kmalloc/kfrees the amount of memory
+ * specified by pool_data
+ */
+void *mempool_kmalloc(gfp_t gfp_mask, void *pool_data)
+{
+       size_t size = (size_t)pool_data;
+       return kmalloc(size, gfp_mask);
+}
+EXPORT_SYMBOL(mempool_kmalloc);
+
+void mempool_kfree(void *element, void *pool_data)
+{
+       kfree(element);
+}
+EXPORT_SYMBOL(mempool_kfree);
+
+/*
+ * A simple mempool-backed page allocator that allocates pages
+ * of the order specified by pool_data.
+ */
+void *mempool_alloc_pages(gfp_t gfp_mask, void *pool_data)
+{
+       int order = (int)(long)pool_data;
+       return alloc_pages(gfp_mask, order);
+}
+EXPORT_SYMBOL(mempool_alloc_pages);
+
+void mempool_free_pages(void *element, void *pool_data)
+{
+       int order = (int)(long)pool_data;
+       __free_pages(element, order);
+}
+EXPORT_SYMBOL(mempool_free_pages);