Commit ecf72cc2 authored by David Woodhouse's avatar David Woodhouse

drivers/net/ppp_deflate.c

    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.
parent c39e9205
......@@ -35,12 +35,16 @@
#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");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment