net: qdisc: use rcu prefix and silence sparse warnings
Add __rcu notation to qdisc handling by doing this we can make smatch output more legible. And anyways some of the cases should be using rcu_dereference() see qdisc_all_tx_empty(), qdisc_tx_chainging(), and so on. Also *wake_queue() API is commonly called from driver timer routines without rcu lock or rtnl lock. So I added rcu_read_lock() blocks around netif_wake_subqueue and netif_tx_wake_queue. Signed-off-by: John Fastabend <john.r.fastabend@intel.com> Acked-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
d1015645dd
commit
46e5da40ae
@@ -259,7 +259,9 @@ static inline spinlock_t *qdisc_lock(struct Qdisc *qdisc)
|
||||
|
||||
static inline struct Qdisc *qdisc_root(const struct Qdisc *qdisc)
|
||||
{
|
||||
return qdisc->dev_queue->qdisc;
|
||||
struct Qdisc *q = rcu_dereference_rtnl(qdisc->dev_queue->qdisc);
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
static inline struct Qdisc *qdisc_root_sleeping(const struct Qdisc *qdisc)
|
||||
@@ -384,7 +386,7 @@ static inline void qdisc_reset_all_tx_gt(struct net_device *dev, unsigned int i)
|
||||
struct Qdisc *qdisc;
|
||||
|
||||
for (; i < dev->num_tx_queues; i++) {
|
||||
qdisc = netdev_get_tx_queue(dev, i)->qdisc;
|
||||
qdisc = rtnl_dereference(netdev_get_tx_queue(dev, i)->qdisc);
|
||||
if (qdisc) {
|
||||
spin_lock_bh(qdisc_lock(qdisc));
|
||||
qdisc_reset(qdisc);
|
||||
@@ -402,13 +404,18 @@ static inline void qdisc_reset_all_tx(struct net_device *dev)
|
||||
static inline bool qdisc_all_tx_empty(const struct net_device *dev)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
rcu_read_lock();
|
||||
for (i = 0; i < dev->num_tx_queues; i++) {
|
||||
struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
|
||||
const struct Qdisc *q = txq->qdisc;
|
||||
const struct Qdisc *q = rcu_dereference(txq->qdisc);
|
||||
|
||||
if (q->q.qlen)
|
||||
if (q->q.qlen) {
|
||||
rcu_read_unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -416,9 +423,10 @@ static inline bool qdisc_all_tx_empty(const struct net_device *dev)
|
||||
static inline bool qdisc_tx_changing(const struct net_device *dev)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < dev->num_tx_queues; i++) {
|
||||
struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
|
||||
if (txq->qdisc != txq->qdisc_sleeping)
|
||||
if (rcu_access_pointer(txq->qdisc) != txq->qdisc_sleeping)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -428,9 +436,10 @@ static inline bool qdisc_tx_changing(const struct net_device *dev)
|
||||
static inline bool qdisc_tx_is_noop(const struct net_device *dev)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < dev->num_tx_queues; i++) {
|
||||
struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
|
||||
if (txq->qdisc != &noop_qdisc)
|
||||
if (rcu_access_pointer(txq->qdisc) != &noop_qdisc)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
Reference in New Issue
Block a user