On 2020/9/3 15:24, Eric Dumazet wrote: > > > On 9/2/20 6:14 PM, Yunsheng Lin wrote: > >> >> It seems semantics for some_qdisc_is_busy() is changed, which does not only >> do >> the checking, but also do the reseting? > > Yes, obviously, we would have to rename to a better name. > >> >> Also, qdisc_reset() could be called multi times for the same qdisc if >> some_qdisc_is_busy() >> return true multi times? > > This should not matter, qdisc_reset() can be called multiple times, > as we also call it from qdisc_destroy() anyway.
How about the below patch, which does not need to change the semantics for some_qdisc_is_busy() and avoid calling qdisc_reset() multi times? diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 265a61d..ce9031c 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -1131,24 +1131,7 @@ EXPORT_SYMBOL(dev_activate); static void qdisc_deactivate(struct Qdisc *qdisc) { - bool nolock = qdisc->flags & TCQ_F_NOLOCK; - - if (qdisc->flags & TCQ_F_BUILTIN) - return; - if (test_bit(__QDISC_STATE_DEACTIVATED, &qdisc->state)) - return; - - if (nolock) - spin_lock_bh(&qdisc->seqlock); - spin_lock_bh(qdisc_lock(qdisc)); - set_bit(__QDISC_STATE_DEACTIVATED, &qdisc->state); - - qdisc_reset(qdisc); - - spin_unlock_bh(qdisc_lock(qdisc)); - if (nolock) - spin_unlock_bh(&qdisc->seqlock); } static void dev_deactivate_queue(struct net_device *dev, @@ -1165,6 +1148,33 @@ static void dev_deactivate_queue(struct net_device *dev, } } +static void dev_reset_qdisc(struct net_device *dev) +{ + unsigned int i; + + for (i = 0; i < dev->num_tx_queues; i++) { + struct netdev_queue *dev_queue; + struct Qdisc *q; + bool nolock; + + dev_queue = netdev_get_tx_queue(dev, i); + q = dev_queue->qdisc_sleeping; + nolock = q->flags & TCQ_F_NOLOCK; + + if (nolock) + spin_lock_bh(&q->seqlock); + + spin_lock_bh(qdisc_lock(q)); + + qdisc_reset(q); + + spin_unlock_bh(qdisc_lock(q)); + + if (nolock) + spin_unlock_bh(&q->seqlock); + } +} + static bool some_qdisc_is_busy(struct net_device *dev) { unsigned int i; @@ -1219,6 +1229,9 @@ void dev_deactivate_many(struct list_head *head) */ synchronize_net(); + list_for_each_entry(dev, head, close_list) + dev_reset_qdisc(dev); + /* Wait for outstanding qdisc_run calls. */ list_for_each_entry(dev, head, close_list) { while (some_qdisc_is_busy(dev)) { > >