Patrick McHardy wrote: > Chris Madden wrote: > >>Ok, I replaced ingress_lock with queue_lock in ing_filter and it died in >>the same place. Trace below (looks to be substantively the same)... >> >>If I am reading tc_ctl_tfilter correctly, we are adding our new >>tcf_proto to the end of the list, and it is getting used before the >>change function is getting executed on it. Locking the ingress_lock in >>qdisc_lock_tree ( in addition to the extant queue_lock )seems to have >>the same effect; I can get a traceback from that if its useful. > > > > The problem is that some classifiers (like basic, fw and route) > implement empty ->init functions, although fw and route properly > deal with it in their classification functions. The ->init function > should allocate and initalize tp->root, which basic fails to do. > If you give me a few hours I'll cook up a patch for this.
Actually its only cls_basic thats broken, in case of route and fw its intentional for backwards-compatibility. Can you try this patch please?
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c index fad08e5..ed788d0 100644 --- a/net/sched/cls_basic.c +++ b/net/sched/cls_basic.c @@ -81,6 +81,13 @@ static void basic_put(struct tcf_proto * static int basic_init(struct tcf_proto *tp) { + struct basic_head *head; + + head = kzalloc(sizeof(*head), GFP_KERNEL); + if (head == NULL) + return -ENOMEM; + INIT_LIST_HEAD(&head->flist); + tp->root = head; return 0; } @@ -175,16 +182,6 @@ static int basic_change(struct tcf_proto return basic_set_parms(tp, f, base, tb, tca[TCA_RATE-1]); } - err = -ENOBUFS; - if (head == NULL) { - head = kzalloc(sizeof(*head), GFP_KERNEL); - if (head == NULL) - goto errout; - - INIT_LIST_HEAD(&head->flist); - tp->root = head; - } - f = kzalloc(sizeof(*f), GFP_KERNEL); if (f == NULL) goto errout;