Message ID | alpine.LNX.2.00.1608161238590.22028@cbobk.fhfr.pm |
---|---|
State | Superseded, archived |
Delegated to: | David Miller |
Headers | show |
On Tue, 16 Aug 2016, Jiri Kosina wrote: > From: Jiri Kosina <jkosina@suse.cz> > > qdisc_match_from_root() is now iterating over per-netdevice qdisc > hashtable instead of going through a linked-list of qdiscs (independently > on the actual underlying netdev), which used to be the case before the > switch to hashtable for qdiscs. > > For singleton qdiscs, there is no underlying netdev associated though, and > therefore dumping a singleton qdisc will panic, as qdisc_dev(root) will > always be NULL. [ ... snip ... ] > @@ -1456,6 +1459,10 @@ static int tc_dump_qdisc_root(struct Qdisc *root, struct sk_buff *skb, > goto done; > q_idx++; > } > + > + if (!qdisc_dev(root)) > + goto done; > + Ok, this will cause default singleton-only devices being missed in the dump. I am now working on creating a automation that'd test as many use cases as possible; will send up a new patch once I have all the known corner cases covered (including the ingress / clsact dump duplication). Please drop this one for now, I'll send up an accumulated followup fixes asap. Thanks,
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index c093d32..83413e7 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -262,6 +262,9 @@ static struct Qdisc *qdisc_match_from_root(struct Qdisc *root, u32 handle) { struct Qdisc *q; + if (!qdisc_dev(root)) + return (root->handle == handle ? root : NULL); + if (!(root->flags & TCQ_F_BUILTIN) && root->handle == handle) return root; @@ -1456,6 +1459,10 @@ static int tc_dump_qdisc_root(struct Qdisc *root, struct sk_buff *skb, goto done; q_idx++; } + + if (!qdisc_dev(root)) + goto done; + hash_for_each(qdisc_dev(root)->qdisc_hash, b, q, hash) { if (q_idx < s_q_idx) { q_idx++; @@ -1781,6 +1788,9 @@ static int tc_dump_tclass_root(struct Qdisc *root, struct sk_buff *skb, if (tc_dump_tclass_qdisc(root, skb, tcm, cb, t_p, s_t) < 0) return -1; + if (!qdisc_dev(root)) + return 0; + hash_for_each(qdisc_dev(root)->qdisc_hash, b, q, hash) { if (tc_dump_tclass_qdisc(q, skb, tcm, cb, t_p, s_t) < 0) return -1;