From: Patrick McHardy <kaber@trash.net>
To: Stephen Hemminger <shemminger@osdl.org>
Cc: "David S. Miller" <davem@redhat.com>, netdev@oss.sgi.com
Subject: Re: [PATCH 2.6 3/5]: Use double-linked list for dev->qdisc_list
Date: Tue, 03 Aug 2004 21:22:45 +0200 [thread overview]
Message-ID: <410FE605.8070606@trash.net> (raw)
In-Reply-To: <20040803083540.13675d64@dell_ss3.pdx.osdl.net>
Stephen Hemminger wrote:
>Since qdisc lists are using rcu for deletion, you should use the
>_rcu flavors of list stuff.
>
>
RCU is used for dev->qdisc, but not for dev->qdisc_list.
>replace BUG_TRAP(dev->qdisc_list == NULL);
>with BUG_TRAP(list_empty(&dev->qdisc_list));
>
>I tried a similar patch but was finding the bug_trap() was showing up on
>deletion so did not trust it.
>
>
The BUG_TRAP is no longer valid with RCU. The qdiscs aren't destroyed
immediately, so they are still in the list.
Regards
Patrick
>This is what I was experimenting with.
>
>------------
>diff -Nru a/include/linux/netdevice.h b/include/linux/netdevice.h
>--- a/include/linux/netdevice.h 2004-07-28 15:14:27 -07:00
>+++ b/include/linux/netdevice.h 2004-07-28 15:14:27 -07:00
>@@ -362,7 +362,7 @@
>
> struct Qdisc *qdisc;
> struct Qdisc *qdisc_sleeping;
>- struct Qdisc *qdisc_list;
>+ struct list_head qdisc_list;
> struct Qdisc *qdisc_ingress;
> unsigned long tx_queue_len; /* Max frames per queue allowed */
>
>diff -Nru a/include/net/pkt_sched.h b/include/net/pkt_sched.h
>--- a/include/net/pkt_sched.h 2004-07-28 15:14:27 -07:00
>+++ b/include/net/pkt_sched.h 2004-07-28 15:14:27 -07:00
>@@ -79,7 +79,7 @@
> #define TCQ_F_INGRES 4
> int padded;
> struct Qdisc_ops *ops;
>- struct Qdisc *next;
>+ struct list_head list;
> u32 handle;
> atomic_t refcnt;
> struct sk_buff_head q;
>diff -Nru a/net/sched/sch_api.c b/net/sched/sch_api.c
>--- a/net/sched/sch_api.c 2004-07-28 15:14:27 -07:00
>+++ b/net/sched/sch_api.c 2004-07-28 15:14:27 -07:00
>@@ -195,7 +195,7 @@
> {
> struct Qdisc *q;
>
>- for (q = dev->qdisc_list; q; q = q->next) {
>+ list_for_each_entry_rcu(q, &dev->qdisc_list, list) {
> if (q->handle == handle)
> return q;
> }
>@@ -453,8 +453,7 @@
> smp_wmb();
> if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) {
> qdisc_lock_tree(dev);
>- sch->next = dev->qdisc_list;
>- dev->qdisc_list = sch;
>+ list_add_rcu(&sch->list, &dev->qdisc_list);
> qdisc_unlock_tree(dev);
>
> #ifdef CONFIG_NET_ESTIMATOR
>@@ -812,18 +811,20 @@
> continue;
> if (idx > s_idx)
> s_q_idx = 0;
>- read_lock(&qdisc_tree_lock);
>- for (q = dev->qdisc_list, q_idx = 0; q;
>- q = q->next, q_idx++) {
>- if (q_idx < s_q_idx)
>+
>+ rcu_read_lock();
>+
>+ q_idx = 0;
>+ list_for_each_entry_rcu(q, &dev->qdisc_list, list) {
>+ if (q_idx++ < s_q_idx)
> continue;
> if (tc_fill_qdisc(skb, q, 0, NETLINK_CB(cb->skb).pid,
> cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) {
>- read_unlock(&qdisc_tree_lock);
>+ rcu_read_unlock();
> goto done;
> }
> }
>- read_unlock(&qdisc_tree_lock);
>+ rcu_read_unlock();
> }
>
> done:
>@@ -1033,9 +1034,10 @@
>
> s_t = cb->args[0];
>
>- read_lock(&qdisc_tree_lock);
>- for (q=dev->qdisc_list, t=0; q; q = q->next, t++) {
>- if (t < s_t) continue;
>+ rcu_read_lock();
>+ t = 0;
>+ list_for_each_entry_rcu(q, &dev->qdisc_list, list) {
>+ if (t++ < s_t) continue;
> if (!q->ops->cl_ops) continue;
> if (tcm->tcm_parent && TC_H_MAJ(tcm->tcm_parent) != q->handle)
> continue;
>@@ -1052,7 +1054,7 @@
> if (arg.w.stop)
> break;
> }
>- read_unlock(&qdisc_tree_lock);
>+ rcu_read_unlock();
>
> cb->args[0] = t;
>
>diff -Nru a/net/sched/sch_generic.c b/net/sched/sch_generic.c
>--- a/net/sched/sch_generic.c 2004-07-28 15:14:27 -07:00
>+++ b/net/sched/sch_generic.c 2004-07-28 15:14:27 -07:00
>@@ -405,6 +405,8 @@
> sch->dev = dev;
> sch->stats_lock = &dev->queue_lock;
> atomic_set(&sch->refcnt, 1);
>+ INIT_LIST_HEAD(&sch->list);
>+
> /* enqueue is accessed locklessly - make sure it's visible
> * before we set a netdevice's qdisc pointer to sch */
> smp_wmb();
>@@ -450,23 +452,12 @@
>
> void qdisc_destroy(struct Qdisc *qdisc)
> {
>- struct net_device *dev = qdisc->dev;
>-
> if (!atomic_dec_and_test(&qdisc->refcnt))
> return;
>
>- if (dev) {
>- struct Qdisc *q, **qp;
>- for (qp = &qdisc->dev->qdisc_list; (q=*qp) != NULL; qp = &q->next) {
>- if (q == qdisc) {
>- *qp = q->next;
>- break;
>- }
>- }
>- }
>-
>+ if (qdisc->dev)
>+ list_del_rcu(&qdisc->list);
> call_rcu(&qdisc->q_rcu, __qdisc_destroy);
>-
> }
>
>
>@@ -488,8 +479,7 @@
> }
>
> write_lock(&qdisc_tree_lock);
>- qdisc->next = dev->qdisc_list;
>- dev->qdisc_list = qdisc;
>+ list_add_rcu(&qdisc->list, &dev->qdisc_list);
> write_unlock(&qdisc_tree_lock);
>
> } else {
>@@ -533,7 +523,7 @@
> qdisc_lock_tree(dev);
> dev->qdisc = &noop_qdisc;
> dev->qdisc_sleeping = &noop_qdisc;
>- dev->qdisc_list = NULL;
>+ INIT_LIST_HEAD(&dev->qdisc_list);
> qdisc_unlock_tree(dev);
>
> dev_watchdog_init(dev);
>@@ -554,9 +544,9 @@
> qdisc_destroy(qdisc);
> }
> #endif
>- BUG_TRAP(dev->qdisc_list == NULL);
>+ BUG_TRAP(!list_empty(&dev->qdisc_list));
> BUG_TRAP(!timer_pending(&dev->watchdog_timer));
>- dev->qdisc_list = NULL;
>+
> qdisc_unlock_tree(dev);
> }
>
>
>
>
next prev parent reply other threads:[~2004-08-03 19:22 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-08-03 15:24 [PATCH 2.6 3/5]: Use double-linked list for dev->qdisc_list Patrick McHardy
2004-08-03 15:35 ` Stephen Hemminger
2004-08-03 19:22 ` Patrick McHardy [this message]
2004-08-03 15:38 ` [PATCH 2.6] cache align qdisc data Stephen Hemminger
2004-08-03 19:17 ` Patrick McHardy
2004-08-03 20:31 ` Stephen Hemminger
2004-08-03 20:42 ` Patrick McHardy
2004-08-03 21:05 ` Stephen Hemminger
2004-08-04 16:51 ` David S. Miller
2004-08-04 16:43 ` [PATCH 2.6 3/5]: Use double-linked list for dev->qdisc_list David S. Miller
2004-08-04 19:55 ` Patrick McHardy
2004-08-04 20:43 ` David S. Miller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=410FE605.8070606@trash.net \
--to=kaber@trash.net \
--cc=davem@redhat.com \
--cc=netdev@oss.sgi.com \
--cc=shemminger@osdl.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.