On Mon, Dec 18, 2017 at 7:58 PM, John Fastabend <john.fastab...@gmail.com> wrote: > On 12/18/2017 06:20 PM, Cong Wang wrote: >> On Mon, Dec 18, 2017 at 5:25 PM, John Fastabend >> <john.fastab...@gmail.com> wrote: >>> On 12/18/2017 02:34 PM, Cong Wang wrote: >>>> First, the check of &q->ring.queue against NULL is wrong, it >>>> is always false. We should check the value rather than the address. >>>> >>> >>> Thanks. >>> >>>> Secondly, we need the same check in pfifo_fast_reset() too, >>>> as both ->reset() and ->destroy() are called in qdisc_destroy(). >>>> >>> >>> not that it hurts to have the check here, but if init fails >>> in qdisc_create it seems only ->destroy() is called without >>> a ->reset(). >>> >>> Is there another path for init() to fail that I'm missing. >> >> Pretty sure ->reset() is called in qdisc_destroy() and also before >> ->destroy(): >> > > Except, the failed init path does not call qdisc_destroy. > > static struct Qdisc *qdisc_create(struct net_device *dev, > [...] > > if (ops->init) { > err = ops->init(sch, tca[TCA_OPTIONS]); > if (err != 0) > goto err_out5; > } > [...] > > err_out5: > /* ops->init() failed, we call ->destroy() like qdisc_create_dflt() */ > if (ops->destroy) > ops->destroy(sch);
Didn't I say qdisc_destroy() rather than ->destroy()? :-) struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue, const struct Qdisc_ops *ops, unsigned int parentid) { struct Qdisc *sch; if (!try_module_get(ops->owner)) return NULL; sch = qdisc_alloc(dev_queue, ops); if (IS_ERR(sch)) { module_put(ops->owner); return NULL; } sch->parent = parentid; if (!ops->init || ops->init(sch, NULL) == 0) return sch; qdisc_destroy(sch); return NULL; }