Skip to content

Commit fd44de7

Browse files
kaberDavid S. Miller
authored andcommitted
[NET_SCHED]: ingress: switch back to using ingress_lock
Switch ingress queueing back to use ingress_lock. qdisc_lock_tree now locks both the ingress and egress qdiscs on the device. All changes to data that might be used on both ingress and egress needs to be protected by using qdisc_lock_tree instead of manually taking dev->queue_lock. Additionally the qdisc stats_lock needs to be initialized to ingress_lock for ingress qdiscs. Signed-off-by: Patrick McHardy <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 0463d4a commit fd44de7

File tree

5 files changed

+26
-23
lines changed

5 files changed

+26
-23
lines changed

net/core/dev.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1747,10 +1747,10 @@ static int ing_filter(struct sk_buff *skb)
17471747

17481748
skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_INGRESS);
17491749

1750-
spin_lock(&dev->queue_lock);
1750+
spin_lock(&dev->ingress_lock);
17511751
if ((q = dev->qdisc_ingress) != NULL)
17521752
result = q->enqueue(skb, q);
1753-
spin_unlock(&dev->queue_lock);
1753+
spin_unlock(&dev->ingress_lock);
17541754

17551755
}
17561756

net/sched/cls_route.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@ static __inline__ int route4_fastmap_hash(u32 id, int iif)
8989
static inline
9090
void route4_reset_fastmap(struct net_device *dev, struct route4_head *head, u32 id)
9191
{
92-
spin_lock_bh(&dev->queue_lock);
92+
qdisc_lock_tree(dev);
9393
memset(head->fastmap, 0, sizeof(head->fastmap));
94-
spin_unlock_bh(&dev->queue_lock);
94+
qdisc_unlock_tree(dev);
9595
}
9696

9797
static inline void

net/sched/sch_api.c

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -500,12 +500,16 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp)
500500

501501
if (handle == TC_H_INGRESS) {
502502
sch->flags |= TCQ_F_INGRESS;
503+
sch->stats_lock = &dev->ingress_lock;
503504
handle = TC_H_MAKE(TC_H_INGRESS, 0);
504-
} else if (handle == 0) {
505-
handle = qdisc_alloc_handle(dev);
506-
err = -ENOMEM;
507-
if (handle == 0)
508-
goto err_out3;
505+
} else {
506+
sch->stats_lock = &dev->queue_lock;
507+
if (handle == 0) {
508+
handle = qdisc_alloc_handle(dev);
509+
err = -ENOMEM;
510+
if (handle == 0)
511+
goto err_out3;
512+
}
509513
}
510514

511515
sch->handle = handle;
@@ -654,9 +658,9 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
654658
return err;
655659
if (q) {
656660
qdisc_notify(skb, n, clid, q, NULL);
657-
spin_lock_bh(&dev->queue_lock);
661+
qdisc_lock_tree(dev);
658662
qdisc_destroy(q);
659-
spin_unlock_bh(&dev->queue_lock);
663+
qdisc_unlock_tree(dev);
660664
}
661665
} else {
662666
qdisc_notify(skb, n, clid, NULL, q);
@@ -789,17 +793,17 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
789793
err = qdisc_graft(dev, p, clid, q, &old_q);
790794
if (err) {
791795
if (q) {
792-
spin_lock_bh(&dev->queue_lock);
796+
qdisc_lock_tree(dev);
793797
qdisc_destroy(q);
794-
spin_unlock_bh(&dev->queue_lock);
798+
qdisc_unlock_tree(dev);
795799
}
796800
return err;
797801
}
798802
qdisc_notify(skb, n, clid, old_q, q);
799803
if (old_q) {
800-
spin_lock_bh(&dev->queue_lock);
804+
qdisc_lock_tree(dev);
801805
qdisc_destroy(old_q);
802-
spin_unlock_bh(&dev->queue_lock);
806+
qdisc_unlock_tree(dev);
803807
}
804808
}
805809
return 0;

net/sched/sch_generic.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,20 @@
4242
* The idea is the following:
4343
* - enqueue, dequeue are serialized via top level device
4444
* spinlock dev->queue_lock.
45+
* - ingress filtering is serialized via top level device
46+
* spinlock dev->ingress_lock.
4547
* - updates to tree and tree walking are only done under the rtnl mutex.
4648
*/
4749

4850
void qdisc_lock_tree(struct net_device *dev)
4951
{
5052
spin_lock_bh(&dev->queue_lock);
53+
spin_lock(&dev->ingress_lock);
5154
}
5255

5356
void qdisc_unlock_tree(struct net_device *dev)
5457
{
58+
spin_unlock(&dev->ingress_lock);
5559
spin_unlock_bh(&dev->queue_lock);
5660
}
5761

@@ -431,7 +435,6 @@ struct Qdisc *qdisc_alloc(struct net_device *dev, struct Qdisc_ops *ops)
431435
sch->dequeue = ops->dequeue;
432436
sch->dev = dev;
433437
dev_hold(dev);
434-
sch->stats_lock = &dev->queue_lock;
435438
atomic_set(&sch->refcnt, 1);
436439

437440
return sch;
@@ -447,6 +450,7 @@ struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops,
447450
sch = qdisc_alloc(dev, ops);
448451
if (IS_ERR(sch))
449452
goto errout;
453+
sch->stats_lock = &dev->queue_lock;
450454
sch->parent = parentid;
451455

452456
if (!ops->init || ops->init(sch, NULL) == 0)

net/sched/sch_ingress.c

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -248,16 +248,11 @@ ing_hook(unsigned int hook, struct sk_buff **pskb,
248248
skb->dev ? (*pskb)->dev->name : "(no dev)",
249249
skb->len);
250250

251-
/*
252-
revisit later: Use a private since lock dev->queue_lock is also
253-
used on the egress (might slow things for an iota)
254-
*/
255-
256251
if (dev->qdisc_ingress) {
257-
spin_lock(&dev->queue_lock);
252+
spin_lock(&dev->ingress_lock);
258253
if ((q = dev->qdisc_ingress) != NULL)
259254
fwres = q->enqueue(skb, q);
260-
spin_unlock(&dev->queue_lock);
255+
spin_unlock(&dev->ingress_lock);
261256
}
262257

263258
return fwres;

0 commit comments

Comments
 (0)