]> git.neil.brown.name Git - history.git/commitdiff
drivers/net/ppp_deflate.c
authorDavid Woodhouse <dwmw2@infradead.org>
Mon, 4 Mar 2002 13:20:25 +0000 (13:20 +0000)
committerDavid Woodhouse <dwmw2@infradead.org>
Mon, 4 Mar 2002 13:20:25 +0000 (13:20 +0000)
    Use vmalloc for ppp_deflate workspace. It's 400KiB, and kmalloc strangely
    doesn't seem to work very well for that :)

    Use schedule_task to do a delayed cleanup, because the z_comp_free routine
    is called with spinlocks held, hence we can't just call vfree().

    Fix double MOD_DEC_USE_COUNT when allocation fails, for both compression
    and decompression workspaces.

    Change licence text to one that insmod likes.

drivers/net/ppp_deflate.c

index d1b8b3b66260fe75222c533d3aeb28ac5b26254f..c07672f907273b5d26db3495312e6fd68cf9c692 100644 (file)
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 
 #include <linux/ppp_defs.h>
 #include <linux/ppp-comp.h>
 
 #include <linux/zlib.h>
 
+static spinlock_t comp_free_list_lock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(comp_free_list);
+
 /*
  * State for a Deflate (de)compressor.
  */
@@ -52,6 +56,7 @@ struct ppp_deflate_state {
     int                debug;
     z_stream   strm;
     struct compstat stats;
+    struct list_head list;
 };
 
 #define DEFLATE_OVHD   2               /* Deflate overhead/packet */
@@ -76,6 +81,27 @@ static void  z_comp_reset __P((void *state));
 static void    z_decomp_reset __P((void *state));
 static void    z_comp_stats __P((void *state, struct compstat *stats));
 
+static void z_comp_delayedfree(void *arg)
+{
+       struct ppp_deflate_state *state;
+
+       spin_lock_bh(&comp_free_list_lock);
+       while(!list_empty(&comp_free_list)) {
+               state = list_entry(comp_free_list.next, struct ppp_deflate_state, list);
+               list_del(&state->list);
+               spin_unlock_bh(&comp_free_list_lock);
+               if (state->strm.workspace)
+                       vfree(state->strm.workspace);
+               kfree(state);
+               spin_lock_bh(&comp_free_list_lock);
+       }
+       spin_unlock_bh(&comp_free_list_lock);
+}
+
+static struct tq_struct z_comp_task = {
+       routine: z_comp_delayedfree
+};
+
 static void
 z_comp_free(arg)
     void *arg;
@@ -84,9 +110,12 @@ z_comp_free(arg)
 
        if (state) {
                zlib_deflateEnd(&state->strm);
-               if (state->strm.workspace)
-                       kfree(state->strm.workspace);
-               kfree(state);
+
+               spin_lock_bh(&comp_free_list_lock);
+               list_add(&state->list, &comp_free_list);
+               spin_unlock_bh(&comp_free_list_lock);
+
+               schedule_task(&z_comp_task);
                MOD_DEC_USE_COUNT;
        }
 }
@@ -121,8 +150,7 @@ z_comp_alloc(options, opt_len)
        memset (state, 0, sizeof (struct ppp_deflate_state));
        state->strm.next_in   = NULL;
        state->w_size         = w_size;
-       state->strm.workspace = kmalloc(zlib_deflate_workspacesize(),
-                                       GFP_KERNEL);
+       state->strm.workspace = vmalloc(zlib_deflate_workspacesize());
        if (state->strm.workspace == NULL)
                goto out_free;
 
@@ -134,7 +162,6 @@ z_comp_alloc(options, opt_len)
 
 out_free:
        z_comp_free(state);
-       MOD_DEC_USE_COUNT;
        return NULL;
 }
 
@@ -319,7 +346,6 @@ z_decomp_alloc(options, opt_len)
 
 out_free:
        z_decomp_free(state);
-       MOD_DEC_USE_COUNT;
        return NULL;
 }
 
@@ -590,8 +616,10 @@ void __exit deflate_cleanup(void)
 {
        ppp_unregister_compressor(&ppp_deflate);
        ppp_unregister_compressor(&ppp_deflate_draft);
+       /* Ensure that any deflate state pending free is actually freed */
+       flush_scheduled_tasks();
 }
 
 module_init(deflate_init);
 module_exit(deflate_cleanup);
-MODULE_LICENSE("BSD without advertisement clause");
+MODULE_LICENSE("Dual BSD/GPL");