diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2011-12-15 23:09:45 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-12-16 21:40:33 +0100 |
commit | 869aa41044b04964e27822124b88f799e46f01b9 (patch) | |
tree | 740c289a40c1ffc9ec23d9369cdb9389b1edb8ca /net/sched/sch_gred.c | |
parent | net: fix compilation with !CONFIG_NET (diff) | |
download | linux-869aa41044b04964e27822124b88f799e46f01b9.tar.xz linux-869aa41044b04964e27822124b88f799e46f01b9.zip |
sch_gred: prefer GFP_KERNEL allocations
In control path, its better to use GFP_KERNEL allocations where
possible.
Before taking qdisc spinlock, we preallocate memory just in case we'll
need it in gred_change_vq()
This is a followup to commit 3f1e6d3fd37b (sch_gred: should not use
GFP_KERNEL while holding a spinlock)
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched/sch_gred.c')
-rw-r--r-- | net/sched/sch_gred.c | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 1b5e63126cb3..53204de71c39 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -380,18 +380,19 @@ static inline int gred_change_table_def(struct Qdisc *sch, struct nlattr *dps) static inline int gred_change_vq(struct Qdisc *sch, int dp, struct tc_gred_qopt *ctl, int prio, - u8 *stab, u32 max_P) + u8 *stab, u32 max_P, + struct gred_sched_data **prealloc) { struct gred_sched *table = qdisc_priv(sch); - struct gred_sched_data *q; + struct gred_sched_data *q = table->tab[dp]; - if (table->tab[dp] == NULL) { - table->tab[dp] = kzalloc(sizeof(*q), GFP_ATOMIC); - if (table->tab[dp] == NULL) + if (!q) { + table->tab[dp] = q = *prealloc; + *prealloc = NULL; + if (!q) return -ENOMEM; } - q = table->tab[dp]; q->DP = dp; q->prio = prio; q->limit = ctl->limit; @@ -421,6 +422,7 @@ static int gred_change(struct Qdisc *sch, struct nlattr *opt) int err, prio = GRED_DEF_PRIO; u8 *stab; u32 max_P; + struct gred_sched_data *prealloc; if (opt == NULL) return -EINVAL; @@ -460,9 +462,10 @@ static int gred_change(struct Qdisc *sch, struct nlattr *opt) prio = ctl->prio; } + prealloc = kzalloc(sizeof(*prealloc), GFP_KERNEL); sch_tree_lock(sch); - err = gred_change_vq(sch, ctl->DP, ctl, prio, stab, max_P); + err = gred_change_vq(sch, ctl->DP, ctl, prio, stab, max_P, &prealloc); if (err < 0) goto errout_locked; @@ -476,6 +479,7 @@ static int gred_change(struct Qdisc *sch, struct nlattr *opt) errout_locked: sch_tree_unlock(sch); + kfree(prealloc); errout: return err; } |