Commit bb52c7ac authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

netem: dont call vfree() under spinlock and BH disabled

commit 6373a9a2 (netem: use vmalloc for distribution table) added a
regression, since vfree() is called while holding a spinlock and BH
being disabled.

Fix this by doing the pointers swap in critical section, and freeing
after spinlock release.

Also add __GFP_NOWARN to the kmalloc() try, since we fallback to
vmalloc().
Signed-off-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
Acked-by: default avatarStephen Hemminger <shemminger@vyatta.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5f0a6e2d
...@@ -488,7 +488,7 @@ static int get_dist_table(struct Qdisc *sch, const struct nlattr *attr) ...@@ -488,7 +488,7 @@ static int get_dist_table(struct Qdisc *sch, const struct nlattr *attr)
return -EINVAL; return -EINVAL;
s = sizeof(struct disttable) + n * sizeof(s16); s = sizeof(struct disttable) + n * sizeof(s16);
d = kmalloc(s, GFP_KERNEL); d = kmalloc(s, GFP_KERNEL | __GFP_NOWARN);
if (!d) if (!d)
d = vmalloc(s); d = vmalloc(s);
if (!d) if (!d)
...@@ -501,9 +501,10 @@ static int get_dist_table(struct Qdisc *sch, const struct nlattr *attr) ...@@ -501,9 +501,10 @@ static int get_dist_table(struct Qdisc *sch, const struct nlattr *attr)
root_lock = qdisc_root_sleeping_lock(sch); root_lock = qdisc_root_sleeping_lock(sch);
spin_lock_bh(root_lock); spin_lock_bh(root_lock);
dist_free(q->delay_dist); swap(q->delay_dist, d);
q->delay_dist = d;
spin_unlock_bh(root_lock); spin_unlock_bh(root_lock);
dist_free(d);
return 0; return 0;
} }
......
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