Re-enable skb debug destructor, chaining to original when present.

Split skb and node debug flags - one ending in _ref tracks minute changes to reference counts, while the non _ref flag trackes more coarse grained debug events.
Fix a node reference leak before skb_orphan detected by the debug destructor.
Fix debug flag display order for athdebug and 80211debug so that the shorter
name comes first and matches, otherwise only the _ref flags match.


git-svn-id: http://madwifi-project.org/svn/madwifi/trunk@2964 0192ed92-7a03-0410-a25b-9323aeb14dbd
This commit is contained in:
mtaylor 2007-11-25 09:09:24 +00:00
parent 15587c9e84
commit ec5e8e0a11
7 changed files with 38 additions and 20 deletions

View File

@ -446,7 +446,7 @@ enum {
ATH_DEBUG_RECV_DESC = 0x00000008, /* recv descriptors */
ATH_DEBUG_RATE = 0x00000010, /* rate control */
ATH_DEBUG_RESET = 0x00000020, /* reset processing */
/* 0x00000040 was ATH_DEBUG_MODE */
ATH_DEBUG_SKB_REF = 0x00000040, /* sbk references */
ATH_DEBUG_BEACON = 0x00000080, /* beacon handling */
ATH_DEBUG_WATCHDOG = 0x00000100, /* watchdog timeout */
ATH_DEBUG_INTR = 0x00001000, /* ISR */
@ -456,7 +456,6 @@ enum {
ATH_DEBUG_CALIBRATE = 0x00010000, /* periodic calibration */
ATH_DEBUG_KEYCACHE = 0x00020000, /* key cache management */
ATH_DEBUG_STATE = 0x00040000, /* 802.11 state transitions */
ATH_DEBUG_NODE = 0x00080000, /* node management */
ATH_DEBUG_LED = 0x00100000, /* led management */
ATH_DEBUG_FF = 0x00200000, /* fast frames */
ATH_DEBUG_TURBO = 0x00400000, /* turbo/dynamic turbo */
@ -474,7 +473,7 @@ enum {
* to all vaps] */
ATH_DEBUG_FATAL = 0x80000000, /* fatal errors */
ATH_DEBUG_ANY = 0xffffffff,
ATH_DEBUG_GLOBAL = (ATH_DEBUG_SKB)
ATH_DEBUG_GLOBAL = (ATH_DEBUG_SKB|ATH_DEBUG_SKB_REF)
};
#define DPRINTF(sc, _m, _fmt, ...) do { \
if (DFLAG_ISSET(sc, (_m))) { \
@ -5859,6 +5858,8 @@ ath_tx_capture(struct net_device *dev, const struct ath_buf *bf, struct sk_buff
SKB_CB(skb)->ni = ieee80211_ref_node(SKB_CB(skb_orig)->ni);
ieee80211_dev_kfree_skb(&skb_orig);
} else {
if (SKB_CB(skb)->ni != NULL)
ieee80211_unref_node(&SKB_CB(skb)->ni);
skb_orphan(skb);
}

View File

@ -40,6 +40,7 @@
/* Set to true if ANY sc has skb debugging on */
extern int ath_debug_global;
enum {
GLOBAL_DEBUG_SKB_REF = 0x00000040, /* SKB referernce counting */
GLOBAL_DEBUG_SKB = 0x40000000, /* SKB usage/leak debugging,
must match ATH_DEBUG_SKB */
};

View File

@ -392,6 +392,7 @@ struct ieee80211_cb {
#define M_RAW 0x10
#ifdef IEEE80211_DEBUG_REFCNT
int tracked;
void (*next_destructor)(struct sk_buff *skb);
#endif
struct sk_buff *next; /* fast frame sk_buf chain */
};

View File

@ -903,6 +903,7 @@ node_cleanup(struct ieee80211_node *ni)
}
static void node_print_message(
u_int32_t flags,
int show_counter,
int refcnt_adjust,
const struct ieee80211_node *ni,
@ -918,7 +919,7 @@ static void node_print_message(
char node_count[32] = { '\0' };
char expanded_message[1024] = { '\0' };
if (0 == (ni->ni_ic->ic_debug & IEEE80211_MSG_NODE_REF))
if (0 == (ni->ni_ic->ic_debug & flags) && (flags != IEEE80211_MSG_ANY))
return;
if (adjusted_refcount == 0)
@ -1080,7 +1081,8 @@ ieee80211_alloc_node(struct ieee80211vap *vap, const u_int8_t *macaddr)
ni->ni_vap = vap;
ni->ni_ic = ic;
atomic_inc(&ni->ni_ic->ic_node_counter);
node_print_message(1 /* show counter */,
node_print_message(IEEE80211_MSG_NODE|IEEE80211_MSG_NODE_REF,
1 /* show counter */,
0 /* adjust refcount */,
ni,
#ifdef IEEE80211_DEBUG_REFCNT
@ -1629,7 +1631,8 @@ ieee80211_free_node(struct ieee80211_node *ni)
struct ieee80211vap *vap = ni->ni_vap;
atomic_dec(&ni->ni_ic->ic_node_counter);
node_print_message(1 /* show counter */,
node_print_message(IEEE80211_MSG_NODE|IEEE80211_MSG_NODE_REF,
1 /* show counter */,
0 /* adjust refcount */,
ni,
#ifdef IEEE80211_DEBUG_REFCNT
@ -2280,7 +2283,8 @@ ieee80211_ref_node(struct ieee80211_node *ni)
return ni;
}
if (atomic_read(&ni->ni_refcnt) < 1) {
node_print_message(0 /* show counter */,
node_print_message(IEEE80211_MSG_ANY,
0 /* show counter */,
0 /* adjust refcount */,
ni,
#ifdef IEEE80211_DEBUG_REFCNT
@ -2294,7 +2298,8 @@ ieee80211_ref_node(struct ieee80211_node *ni)
return ni;
}
atomic_inc(&ni->ni_refcnt);
node_print_message(0 /* show counter */,
node_print_message(IEEE80211_MSG_NODE_REF,
0 /* show counter */,
0 /* adjust refcount */,
ni,
#ifdef IEEE80211_DEBUG_REFCNT
@ -2330,7 +2335,8 @@ ieee80211_unref_node(struct ieee80211_node **pni)
return;
}
if (atomic_read(&ni->ni_refcnt) < 1) {
node_print_message(0 /* show counter */,
node_print_message(IEEE80211_MSG_ANY,
0 /* show counter */,
0 /* adjust refcount */,
ni,
#ifdef IEEE80211_DEBUG_REFCNT
@ -2344,7 +2350,8 @@ ieee80211_unref_node(struct ieee80211_node **pni)
return;
}
node_print_message(0 /* show counter */,
node_print_message(IEEE80211_MSG_NODE_REF,
0 /* show counter */,
-1 /* adjust refcount */,
ni,
#ifdef IEEE80211_DEBUG_REFCNT

View File

@ -195,11 +195,15 @@ ref_skb(struct sk_buff *skb,
static void skb_destructor(struct sk_buff* skb) {
/* Report any node reference leaks - caused by kernel net device queue
* dropping buffer, rather than passing it to the driver. */
if ((ath_debug_global & GLOBAL_DEBUG_SKB) && SKB_CB(skb)->ni != NULL) {
if (SKB_CB(skb)->ni != NULL) {
printk(KERN_ERR "%s:%d - ERROR: non-NULL node pointer in %p, %p<%s>! "
"Leak Detected!\n",
__func__, __LINE__,
skb, SKB_CB(skb)->ni, ether_sprintf(SKB_CB(skb)->ni->ni_macaddr));
dump_stack();
}
if (SKB_CB(skb)->next_destructor != NULL) {
SKB_CB(skb)->next_destructor(skb);
}
}
EXPORT_SYMBOL(skb_destructor);
@ -232,7 +236,7 @@ static void print_skb_refchange_message(
const char* func2, int line2)
{
char skb_desc[128] = { '\0' };
if (0 == (ath_debug_global & GLOBAL_DEBUG_SKB))
if (0 == (ath_debug_global & GLOBAL_DEBUG_SKB_REF))
return;
get_skb_description(skb_desc, sizeof(skb_desc),
"skb", skb, users_adjustment);
@ -293,8 +297,9 @@ track_skb(struct sk_buff *skb, int users_adjustment,
print_skb_trackchange_message(skb, users_adjustment,
func1, line1, func2, line2,
" is now ** TRACKED **");
/* Always use our debug destructor, when we can... */
if (NULL == skb->destructor) {
/* Install our debug destructor, chaining to the original... */
if (skb->destructor != skb_destructor) {
SKB_CB(skb)->next_destructor = skb->destructor;
skb->destructor = skb_destructor;
}
return skb;
@ -327,6 +332,11 @@ untrack_skb(struct sk_buff *skb, int users_adjustment,
atomic_dec(&skb_total_counter);
atomic_dec(&skb_refs_counter);
SKB_CB(skb)->tracked = 0;
/* Install our debug destructor, chaining to the original... */
if (skb->destructor != skb_destructor) {
SKB_CB(skb)->next_destructor = skb->destructor;
skb->destructor = skb_destructor;
}
print_skb_trackchange_message(skb, users_adjustment,
func1, line1, func2, line2,
" is now ** UNTRACKED **");

View File

@ -89,7 +89,6 @@ static struct {
u_int bit;
const char *desc;
} flags[] = {
{ "node_ref", IEEE80211_MSG_NODE_REF, "node ref counting (affects all devs)" },
{ "debug", IEEE80211_MSG_DEBUG, "IFF_DEBUG equivalent" },
{ "dumppkts", IEEE80211_MSG_DUMPPKTS, "dump packets" },
{ "crypto", IEEE80211_MSG_CRYPTO, "crypto modules" },
@ -97,6 +96,7 @@ static struct {
{ "xrate", IEEE80211_MSG_XRATE, "rate set handling" },
{ "elemid", IEEE80211_MSG_ELEMID, "element id parsing"},
{ "node", IEEE80211_MSG_NODE, "node management" },
{ "node_ref", IEEE80211_MSG_NODE_REF, "node ref counting (affects all devs)" },
{ "assoc", IEEE80211_MSG_ASSOC, "association handling" },
{ "auth", IEEE80211_MSG_AUTH, "authentication handling" },
{ "scan", IEEE80211_MSG_SCAN, "scanning" },

View File

@ -63,7 +63,7 @@ enum {
ATH_DEBUG_RECV_DESC = 0x00000008, /* recv descriptors */
ATH_DEBUG_RATE = 0x00000010, /* rate control */
ATH_DEBUG_RESET = 0x00000020, /* reset processing */
ATH_DEBUG_MODE = 0x00000040, /* mode init/setup */
ATH_DEBUG_SKB_REF = 0x00000040, /* skb ref counting */
ATH_DEBUG_BEACON = 0x00000080, /* beacon handling */
ATH_DEBUG_WATCHDOG = 0x00000100, /* watchdog timeout */
ATH_DEBUG_INTR = 0x00001000, /* ISR */
@ -73,7 +73,6 @@ enum {
ATH_DEBUG_CALIBRATE = 0x00010000, /* periodic calibration */
ATH_DEBUG_KEYCACHE = 0x00020000, /* key cache management */
ATH_DEBUG_STATE = 0x00040000, /* 802.11 state transitions */
ATH_DEBUG_NODE = 0x00080000, /* node management */
ATH_DEBUG_LED = 0x00100000, /* led management */
ATH_DEBUG_FF = 0x00200000, /* fast frames */
ATH_DEBUG_TURBO = 0x00400000, /* turbo/dynamic turbo */
@ -100,7 +99,6 @@ static struct {
{ "recv_desc", ATH_DEBUG_RECV_DESC, "recv descriptors" },
{ "rate", ATH_DEBUG_RATE, "rate control modules" },
{ "reset", ATH_DEBUG_RESET, "reset processing and initialization" },
{ "mode", ATH_DEBUG_MODE, "mode initialization and changes" },
{ "beacon", ATH_DEBUG_BEACON, "beacon handling" },
{ "watchdog", ATH_DEBUG_WATCHDOG, "watchdog timer" },
{ "intr", ATH_DEBUG_INTR, "interrupt processing" },
@ -110,9 +108,9 @@ static struct {
{ "calibrate", ATH_DEBUG_CALIBRATE, "periodic re-calibration" },
{ "keycache", ATH_DEBUG_KEYCACHE, "key cache management" },
{ "state", ATH_DEBUG_STATE, "802.11 state transitions" },
{ "node", ATH_DEBUG_NODE, "node management" },
{ "txbuf", ATH_DEBUG_TXBUF, "ath_buf management" },
{ "skb", ATH_DEBUG_SKB, "skb management (affects all devs)" },
{ "skb_ref", ATH_DEBUG_SKB_REF, "skb ref counting (affects all devs)" },
{ "led", ATH_DEBUG_LED, "led management" },
{ "ff", ATH_DEBUG_FF, "fast frame handling" },
{ "turbo", ATH_DEBUG_TURBO, "dynamic turbo handling" },