Skip to content

Commit

Permalink
pkt_sched: Fix gen_estimator locks
Browse files Browse the repository at this point in the history
While passing a qdisc root lock to gen_new_estimator() and
gen_replace_estimator() dev could be deactivated or even before
grafting proper root qdisc as qdisc_sleeping (e.g. qdisc_create), so
using qdisc_root_lock() is not enough. This patch adds
qdisc_root_sleeping_lock() for this, plus additional checks, where
necessary.

Signed-off-by: Jarek Poplawski <jarkao2@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Jarek Poplawski authored and David S. Miller committed Aug 27, 2008
1 parent f7a54c1 commit f6f9b93
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 9 deletions.
8 changes: 8 additions & 0 deletions include/net/sch_generic.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,14 @@ static inline spinlock_t *qdisc_root_lock(struct Qdisc *qdisc)
return qdisc_lock(root);
}

static inline spinlock_t *qdisc_root_sleeping_lock(struct Qdisc *qdisc)
{
struct Qdisc *root = qdisc_root_sleeping(qdisc);

ASSERT_RTNL();
return qdisc_lock(root);
}

static inline struct net_device *qdisc_dev(struct Qdisc *qdisc)
{
return qdisc->dev_queue->dev;
Expand Down
14 changes: 11 additions & 3 deletions net/sched/sch_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -830,9 +830,16 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
sch->stab = stab;
}
if (tca[TCA_RATE]) {
spinlock_t *root_lock;

if ((sch->parent != TC_H_ROOT) &&
!(sch->flags & TCQ_F_INGRESS))
root_lock = qdisc_root_sleeping_lock(sch);
else
root_lock = qdisc_lock(sch);

err = gen_new_estimator(&sch->bstats, &sch->rate_est,
qdisc_root_lock(sch),
tca[TCA_RATE]);
root_lock, tca[TCA_RATE]);
if (err) {
/*
* Any broken qdiscs that would require
Expand Down Expand Up @@ -884,7 +891,8 @@ static int qdisc_change(struct Qdisc *sch, struct nlattr **tca)

if (tca[TCA_RATE])
gen_replace_estimator(&sch->bstats, &sch->rate_est,
qdisc_root_lock(sch), tca[TCA_RATE]);
qdisc_root_sleeping_lock(sch),
tca[TCA_RATE]);
return 0;
}

Expand Down
4 changes: 2 additions & 2 deletions net/sched/sch_cbq.c
Original file line number Diff line number Diff line change
Expand Up @@ -1839,7 +1839,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t

if (tca[TCA_RATE])
gen_replace_estimator(&cl->bstats, &cl->rate_est,
qdisc_root_lock(sch),
qdisc_root_sleeping_lock(sch),
tca[TCA_RATE]);
return 0;
}
Expand Down Expand Up @@ -1930,7 +1930,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t

if (tca[TCA_RATE])
gen_new_estimator(&cl->bstats, &cl->rate_est,
qdisc_root_lock(sch), tca[TCA_RATE]);
qdisc_root_sleeping_lock(sch), tca[TCA_RATE]);

*arg = (unsigned long)cl;
return 0;
Expand Down
4 changes: 2 additions & 2 deletions net/sched/sch_hfsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1045,7 +1045,7 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,

if (tca[TCA_RATE])
gen_replace_estimator(&cl->bstats, &cl->rate_est,
qdisc_root_lock(sch),
qdisc_root_sleeping_lock(sch),
tca[TCA_RATE]);
return 0;
}
Expand Down Expand Up @@ -1104,7 +1104,7 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,

if (tca[TCA_RATE])
gen_new_estimator(&cl->bstats, &cl->rate_est,
qdisc_root_lock(sch), tca[TCA_RATE]);
qdisc_root_sleeping_lock(sch), tca[TCA_RATE]);
*arg = (unsigned long)cl;
return 0;
}
Expand Down
4 changes: 2 additions & 2 deletions net/sched/sch_htb.c
Original file line number Diff line number Diff line change
Expand Up @@ -1372,7 +1372,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
goto failure;

gen_new_estimator(&cl->bstats, &cl->rate_est,
qdisc_root_lock(sch),
qdisc_root_sleeping_lock(sch),
tca[TCA_RATE] ? : &est.nla);
cl->refcnt = 1;
cl->children = 0;
Expand Down Expand Up @@ -1427,7 +1427,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
} else {
if (tca[TCA_RATE])
gen_replace_estimator(&cl->bstats, &cl->rate_est,
qdisc_root_lock(sch),
qdisc_root_sleeping_lock(sch),
tca[TCA_RATE]);
sch_tree_lock(sch);
}
Expand Down

0 comments on commit f6f9b93

Please sign in to comment.