[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20080816085536.GA1737@ami.dom.local>
Date: Sat, 16 Aug 2008 10:55:37 +0200
From: Jarek Poplawski <jarkao2@...il.com>
To: Denys Fedoryshchenko <denys@...p.net.lb>
Cc: netdev@...r.kernel.org
Subject: Re: panic 2.6.27-rc3-git2, qdisc_dequeue_head
On Fri, Aug 15, 2008 at 11:54:24PM +0300, Denys Fedoryshchenko wrote:
> Btw, it can happen on deletion also. At that moment there was 600 sessions
> established(and non-stop logging in/off), and it is difficult to tell, what
> was happening at that moment...
Alas I can't find the reason, so here is some debugging patch (not tested!).
Jarek P.
---
include/linux/skbuff.h | 43 +++++++++++++++++++++++++++++++------------
net/sched/sch_generic.c | 1 +
2 files changed, 32 insertions(+), 12 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 358661c..c46b1bd 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -120,6 +120,7 @@ struct sk_buff_head {
__u32 qlen;
spinlock_t lock;
+ spinlock_t lock_debug;
};
struct sk_buff;
@@ -657,6 +658,7 @@ static inline __u32 skb_queue_len(const struct sk_buff_head *list_)
static inline void skb_queue_head_init(struct sk_buff_head *list)
{
spin_lock_init(&list->lock);
+ spin_lock_init(&list->lock_debug);
list->prev = list->next = (struct sk_buff *)list;
list->qlen = 0;
}
@@ -679,10 +681,15 @@ static inline void __skb_insert(struct sk_buff *newsk,
struct sk_buff *prev, struct sk_buff *next,
struct sk_buff_head *list)
{
- newsk->next = next;
- newsk->prev = prev;
- next->prev = prev->next = newsk;
- list->qlen++;
+ if (spin_trylock(&list->lock_debug)) {
+ newsk->next = next;
+ newsk->prev = prev;
+ next->prev = prev->next = newsk;
+ list->qlen++;
+ spin_unlock(&list->lock_debug);
+ } else {
+ WARN_ON(1);
+ }
}
/**
@@ -775,10 +782,16 @@ static inline void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list)
extern struct sk_buff *skb_dequeue(struct sk_buff_head *list);
static inline struct sk_buff *__skb_dequeue(struct sk_buff_head *list)
{
- struct sk_buff *skb = skb_peek(list);
- if (skb)
- __skb_unlink(skb, list);
- return skb;
+ if (spin_trylock(&list->lock_debug)) {
+ struct sk_buff *skb = skb_peek(list);
+ if (skb)
+ __skb_unlink(skb, list);
+ spin_unlock(&list->lock_debug);
+ return skb;
+ } else {
+ WARN_ON(1);
+ return NULL;
+ }
}
/**
@@ -792,10 +805,16 @@ static inline struct sk_buff *__skb_dequeue(struct sk_buff_head *list)
extern struct sk_buff *skb_dequeue_tail(struct sk_buff_head *list);
static inline struct sk_buff *__skb_dequeue_tail(struct sk_buff_head *list)
{
- struct sk_buff *skb = skb_peek_tail(list);
- if (skb)
- __skb_unlink(skb, list);
- return skb;
+ if (spin_trylock(&list->lock_debug)) {
+ struct sk_buff *skb = skb_peek_tail(list);
+ if (skb)
+ __skb_unlink(skb, list);
+ spin_unlock(&list->lock_debug);
+ return skb;
+ } else {
+ WARN_ON(1);
+ return NULL;
+ }
}
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 4685746..bffe6cb 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -540,6 +540,7 @@ static void __qdisc_destroy(struct rcu_head *head)
kfree_skb(qdisc->gso_skb);
+ memset(qdisc, 0xf0 , sizeof(*qdisc));
kfree((char *) qdisc - qdisc->padded);
}
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists