Skip to content

Commit 0463d4a

Browse files
kaberDavid S. Miller
authored andcommitted
[NET_SCHED]: Eliminate qdisc_tree_lock
Since we're now holding the rtnl during the entire dump operation, we can remove qdisc_tree_lock, whose only purpose is to protect dump callbacks from concurrent changes to the qdisc tree. Signed-off-by: Patrick McHardy <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent ffa4d72 commit 0463d4a

File tree

4 files changed

+10
-45
lines changed

4 files changed

+10
-45
lines changed

include/net/pkt_sched.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ struct qdisc_walker
1313
int (*fn)(struct Qdisc *, unsigned long cl, struct qdisc_walker *);
1414
};
1515

16-
extern rwlock_t qdisc_tree_lock;
17-
1816
#define QDISC_ALIGNTO 32
1917
#define QDISC_ALIGN(len) (((len) + QDISC_ALIGNTO-1) & ~(QDISC_ALIGNTO-1))
2018

net/sched/cls_api.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,6 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
400400
if ((dev = dev_get_by_index(tcm->tcm_ifindex)) == NULL)
401401
return skb->len;
402402

403-
read_lock(&qdisc_tree_lock);
404403
if (!tcm->tcm_parent)
405404
q = dev->qdisc_sleeping;
406405
else
@@ -457,7 +456,6 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
457456
if (cl)
458457
cops->put(q, cl);
459458
out:
460-
read_unlock(&qdisc_tree_lock);
461459
dev_put(dev);
462460
return skb->len;
463461
}

net/sched/sch_api.c

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ int unregister_qdisc(struct Qdisc_ops *qops)
191191
(root qdisc, all its children, children of children etc.)
192192
*/
193193

194-
static struct Qdisc *__qdisc_lookup(struct net_device *dev, u32 handle)
194+
struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle)
195195
{
196196
struct Qdisc *q;
197197

@@ -202,16 +202,6 @@ static struct Qdisc *__qdisc_lookup(struct net_device *dev, u32 handle)
202202
return NULL;
203203
}
204204

205-
struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle)
206-
{
207-
struct Qdisc *q;
208-
209-
read_lock(&qdisc_tree_lock);
210-
q = __qdisc_lookup(dev, handle);
211-
read_unlock(&qdisc_tree_lock);
212-
return q;
213-
}
214-
215205
static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid)
216206
{
217207
unsigned long cl;
@@ -405,7 +395,7 @@ void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n)
405395
if (n == 0)
406396
return;
407397
while ((parentid = sch->parent)) {
408-
sch = __qdisc_lookup(sch->dev, TC_H_MAJ(parentid));
398+
sch = qdisc_lookup(sch->dev, TC_H_MAJ(parentid));
409399
cops = sch->ops->cl_ops;
410400
if (cops->qlen_notify) {
411401
cl = cops->get(sch, parentid);
@@ -905,21 +895,17 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
905895
continue;
906896
if (idx > s_idx)
907897
s_q_idx = 0;
908-
read_lock(&qdisc_tree_lock);
909898
q_idx = 0;
910899
list_for_each_entry(q, &dev->qdisc_list, list) {
911900
if (q_idx < s_q_idx) {
912901
q_idx++;
913902
continue;
914903
}
915904
if (tc_fill_qdisc(skb, q, q->parent, NETLINK_CB(cb->skb).pid,
916-
cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) {
917-
read_unlock(&qdisc_tree_lock);
905+
cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0)
918906
goto done;
919-
}
920907
q_idx++;
921908
}
922-
read_unlock(&qdisc_tree_lock);
923909
}
924910

925911
done:
@@ -1142,7 +1128,6 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
11421128
s_t = cb->args[0];
11431129
t = 0;
11441130

1145-
read_lock(&qdisc_tree_lock);
11461131
list_for_each_entry(q, &dev->qdisc_list, list) {
11471132
if (t < s_t || !q->ops->cl_ops ||
11481133
(tcm->tcm_parent &&
@@ -1164,7 +1149,6 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
11641149
break;
11651150
t++;
11661151
}
1167-
read_unlock(&qdisc_tree_lock);
11681152

11691153
cb->args[0] = t;
11701154

net/sched/sch_generic.c

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -36,34 +36,23 @@
3636

3737
/* Main transmission queue. */
3838

39-
/* Main qdisc structure lock.
40-
41-
However, modifications
42-
to data, participating in scheduling must be additionally
43-
protected with dev->queue_lock spinlock.
44-
45-
The idea is the following:
46-
- enqueue, dequeue are serialized via top level device
47-
spinlock dev->queue_lock.
48-
- tree walking is protected by read_lock(qdisc_tree_lock)
49-
and this lock is used only in process context.
50-
- updates to tree are made only under rtnl semaphore,
51-
hence this lock may be made without local bh disabling.
52-
53-
qdisc_tree_lock must be grabbed BEFORE dev->queue_lock!
39+
/* Modifications to data participating in scheduling must be protected with
40+
* dev->queue_lock spinlock.
41+
*
42+
* The idea is the following:
43+
* - enqueue, dequeue are serialized via top level device
44+
* spinlock dev->queue_lock.
45+
* - updates to tree and tree walking are only done under the rtnl mutex.
5446
*/
55-
DEFINE_RWLOCK(qdisc_tree_lock);
5647

5748
void qdisc_lock_tree(struct net_device *dev)
5849
{
59-
write_lock(&qdisc_tree_lock);
6050
spin_lock_bh(&dev->queue_lock);
6151
}
6252

6353
void qdisc_unlock_tree(struct net_device *dev)
6454
{
6555
spin_unlock_bh(&dev->queue_lock);
66-
write_unlock(&qdisc_tree_lock);
6756
}
6857

6958
/*
@@ -528,15 +517,11 @@ void dev_activate(struct net_device *dev)
528517
printk(KERN_INFO "%s: activation failed\n", dev->name);
529518
return;
530519
}
531-
write_lock(&qdisc_tree_lock);
532520
list_add_tail(&qdisc->list, &dev->qdisc_list);
533-
write_unlock(&qdisc_tree_lock);
534521
} else {
535522
qdisc = &noqueue_qdisc;
536523
}
537-
write_lock(&qdisc_tree_lock);
538524
dev->qdisc_sleeping = qdisc;
539-
write_unlock(&qdisc_tree_lock);
540525
}
541526

542527
if (!netif_carrier_ok(dev))

0 commit comments

Comments
 (0)