Ok, this almost fully kills of skb->list.  The thing that is missing
is that a couple ugly ATM drivers need to have their skb_unlink()
calls fixed to pass in the list head pointer as the second arg.  I
gave it a quick shot, but I was unsuccessful.  I can't even compile
one of them on my workstation (nicstar.c) because it casts pointers to
"u32" and stuff like that :-/

Sridhar, I resolved the remaining SCTP issues by taking advantage of
the fact that when we are collecting onto a list, the SKB of the
"event" we use is the first member of that on-stack temp list we
are using.  Thus, "(struct sk_buff_head *) sctp_event2skb(event)->prev"
gets us the list head pointer we need, and if the 'prev' pointer is
NULL then it wasn't on a list.

It is not the prettiest solution in the world, but for now it works.
We should really do serious cleanups in this area in the future to
flesh all of this out more nicely.

But anyways, let me know if SCTP still passes your tests with this
change installed.  Thanks.

Please, if anyone has the stomache to try and fix the ATM drivers
(I think the two that need fixing is nicstar.c and zatm.c, grep
for skb_unlink() calls using only one argument), I would _seriously_
appreciate it, thanks.

diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c
--- a/drivers/bluetooth/bfusb.c
+++ b/drivers/bluetooth/bfusb.c
@@ -158,7 +158,7 @@ static int bfusb_send_bulk(struct bfusb 
        if (err) {
                BT_ERR("%s bulk tx submit failed urb %p err %d", 
                                        bfusb->hdev->name, urb, err);
-               skb_unlink(skb);
+               skb_unlink(skb, &bfusb->pending_q);
                usb_free_urb(urb);
        } else
                atomic_inc(&bfusb->pending_tx);
@@ -212,7 +212,7 @@ static void bfusb_tx_complete(struct urb
 
        read_lock(&bfusb->lock);
 
-       skb_unlink(skb);
+       skb_unlink(skb, &bfusb->pending_q);
        skb_queue_tail(&bfusb->completed_q, skb);
 
        bfusb_tx_wakeup(bfusb);
@@ -253,7 +253,7 @@ static int bfusb_rx_submit(struct bfusb 
        if (err) {
                BT_ERR("%s bulk rx submit failed urb %p err %d",
                                        bfusb->hdev->name, urb, err);
-               skb_unlink(skb);
+               skb_unlink(skb, &bfusb->pending_q);
                kfree_skb(skb);
                usb_free_urb(urb);
        }
@@ -398,7 +398,7 @@ static void bfusb_rx_complete(struct urb
                buf   += len;
        }
 
-       skb_unlink(skb);
+       skb_unlink(skb, &bfusb->pending_q);
        kfree_skb(skb);
 
        bfusb_rx_submit(bfusb, urb);
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -681,7 +681,7 @@ static void handle_packet_response(struc
                 return;
         }
 
-       __skb_unlink(skb, skb->list);
+       __skb_unlink(skb, &host->pending_packet_queue);
 
        if (packet->state == hpsb_queued) {
                packet->sendtime = jiffies;
@@ -989,7 +989,7 @@ void abort_timedouts(unsigned long __opa
                packet = (struct hpsb_packet *)skb->data;
 
                if (time_before(packet->sendtime + expire, jiffies)) {
-                       __skb_unlink(skb, skb->list);
+                       __skb_unlink(skb, &host->pending_packet_queue);
                        packet->state = hpsb_complete;
                        packet->ack_code = ACKX_TIMEOUT;
                        queue_packet_complete(packet);
diff --git a/drivers/isdn/act2000/capi.c b/drivers/isdn/act2000/capi.c
--- a/drivers/isdn/act2000/capi.c
+++ b/drivers/isdn/act2000/capi.c
@@ -606,7 +606,7 @@ handle_ack(act2000_card *card, act2000_c
                 if ((((m->msg.data_b3_req.fakencci >> 8) & 0xff) == 
chan->ncci) &&
                    (m->msg.data_b3_req.blocknr == blocknr)) {
                        /* found corresponding DATA_B3_REQ */
-                        skb_unlink(tmp);
+                        skb_unlink(tmp, &card->ackq);
                        chan->queued -= m->msg.data_b3_req.datalen;
                        if (m->msg.data_b3_req.flags)
                                ret = m->msg.data_b3_req.datalen;
diff --git a/drivers/net/shaper.c b/drivers/net/shaper.c
--- a/drivers/net/shaper.c
+++ b/drivers/net/shaper.c
@@ -156,52 +156,6 @@ static int shaper_start_xmit(struct sk_b
         
        SHAPERCB(skb)->shapelen= shaper_clocks(shaper,skb);
        
-#ifdef SHAPER_COMPLEX /* and broken.. */
-
-       while(ptr && ptr!=(struct sk_buff *)&shaper->sendq)
-       {
-               if(ptr->pri<skb->pri 
-                       && jiffies - SHAPERCB(ptr)->shapeclock < SHAPER_MAXSLIP)
-               {
-                       struct sk_buff *tmp=ptr->prev;
-
-                       /*
-                        *      It goes before us therefore we slip the length
-                        *      of the new frame.
-                        */
-
-                       SHAPERCB(ptr)->shapeclock+=SHAPERCB(skb)->shapelen;
-                       SHAPERCB(ptr)->shapelatency+=SHAPERCB(skb)->shapelen;
-
-                       /*
-                        *      The packet may have slipped so far back it
-                        *      fell off.
-                        */
-                       if(SHAPERCB(ptr)->shapelatency > SHAPER_LATENCY)
-                       {
-                               skb_unlink(ptr);
-                               dev_kfree_skb(ptr);
-                       }
-                       ptr=tmp;
-               }
-               else
-                       break;
-       }
-       if(ptr==NULL || ptr==(struct sk_buff *)&shaper->sendq)
-               skb_queue_head(&shaper->sendq,skb);
-       else
-       {
-               struct sk_buff *tmp;
-               /*
-                *      Set the packet clock out time according to the
-                *      frames ahead. Im sure a bit of thought could drop
-                *      this loop.
-                */
-               for(tmp=skb_peek(&shaper->sendq); tmp!=NULL && tmp!=ptr; 
tmp=tmp->next)
-                       SHAPERCB(skb)->shapeclock+=tmp->shapelen;
-               skb_append(ptr,skb);
-       }
-#else
        {
                struct sk_buff *tmp;
                /*
@@ -220,7 +174,7 @@ static int shaper_start_xmit(struct sk_b
                } else
                        skb_queue_tail(&shaper->sendq, skb);
        }
-#endif         
+
        if(sh_debug)
                printk("Frame queued.\n");
        if(skb_queue_len(&shaper->sendq)>SHAPER_QLEN)
@@ -302,7 +256,7 @@ static void shaper_kick(struct shaper *s
                         *      Pull the frame and get interrupts back on.
                         */
                         
-                       skb_unlink(skb);
+                       skb_unlink(skb, &shaper->sendq);
                        if (shaper->recovery < 
                            SHAPERCB(skb)->shapeclock + SHAPERCB(skb)->shapelen)
                                shaper->recovery = SHAPERCB(skb)->shapeclock + 
SHAPERCB(skb)->shapelen;
diff --git a/drivers/net/wan/sdla_fr.c b/drivers/net/wan/sdla_fr.c
--- a/drivers/net/wan/sdla_fr.c
+++ b/drivers/net/wan/sdla_fr.c
@@ -444,7 +444,7 @@ void        s508_s514_unlock(sdla_t *card, uns
 void   s508_s514_lock(sdla_t *card, unsigned long *smp_flags);
 
 unsigned short calc_checksum (char *, int);
-static int setup_fr_header(struct sk_buff** skb,
+static int setup_fr_header(struct sk_buff *skb,
                           struct net_device* dev, char op_mode);
 
 
@@ -1371,7 +1371,7 @@ static int if_send(struct sk_buff* skb, 
        /* Move the if_header() code to here. By inserting frame
         * relay header in if_header() we would break the
         * tcpdump and other packet sniffers */
-       chan->fr_header_len = setup_fr_header(&skb,dev,chan->common.usedby);
+       chan->fr_header_len = setup_fr_header(skb,dev,chan->common.usedby);
        if (chan->fr_header_len < 0 ){
                ++chan->ifstats.tx_dropped;
                ++card->wandev.stats.tx_dropped;
@@ -1596,8 +1596,6 @@ static int setup_for_delayed_transmit(st
                return 1;
        }
 
-       skb_unlink(skb);
-       
         chan->transmit_length = len;
        chan->delay_skb = skb;
         
@@ -4870,18 +4868,15 @@ static void unconfig_fr (sdla_t *card)
        }
 }
 
-static int setup_fr_header(struct sk_buff **skb_orig, struct net_device* dev,
+static int setup_fr_header(struct sk_buff *skb, struct net_device* dev,
                           char op_mode)
 {
-       struct sk_buff *skb = *skb_orig;
        fr_channel_t *chan=dev->priv;
 
-       if (op_mode == WANPIPE){
-
+       if (op_mode == WANPIPE) {
                chan->fr_header[0]=Q922_UI;
                
                switch (htons(skb->protocol)){
-                       
                case ETH_P_IP:
                        chan->fr_header[1]=NLPID_IP;
                        break;
@@ -4893,16 +4888,14 @@ static int setup_fr_header(struct sk_buf
        }
 
        /* If we are in bridging mode, we must apply
-        * an Ethernet header */
-       if (op_mode == BRIDGE || op_mode == BRIDGE_NODE){
-
-
+        * an Ethernet header
+        */
+       if (op_mode == BRIDGE || op_mode == BRIDGE_NODE) {
                /* Encapsulate the packet as a bridged Ethernet frame. */
 #ifdef DEBUG
                printk(KERN_INFO "%s: encapsulating skb for frame relay\n", 
                        dev->name);
 #endif
-               
                chan->fr_header[0] = 0x03;
                chan->fr_header[1] = 0x00;
                chan->fr_header[2] = 0x80;
@@ -4915,7 +4908,6 @@ static int setup_fr_header(struct sk_buf
                /* Yuck. */
                skb->protocol = ETH_P_802_3;
                return 8;
-
        }
                
        return 0;
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -2903,19 +2903,18 @@ static struct net_device_stats *usbnet_g
  * completion callbacks.  2.5 should have fixed those bugs...
  */
 
-static void defer_bh (struct usbnet *dev, struct sk_buff *skb)
+static void defer_bh(struct usbnet *dev, struct sk_buff *skb, struct 
sk_buff_head *list)
 {
-       struct sk_buff_head     *list = skb->list;
        unsigned long           flags;
 
-       spin_lock_irqsave (&list->lock, flags);
-       __skb_unlink (skb, list);
-       spin_unlock (&list->lock);
-       spin_lock (&dev->done.lock);
-       __skb_queue_tail (&dev->done, skb);
+       spin_lock_irqsave(&list->lock, flags);
+       __skb_unlink(skb, list);
+       spin_unlock(&list->lock);
+       spin_lock(&dev->done.lock);
+       __skb_queue_tail(&dev->done, skb);
        if (dev->done.qlen == 1)
-               tasklet_schedule (&dev->bh);
-       spin_unlock_irqrestore (&dev->done.lock, flags);
+               tasklet_schedule(&dev->bh);
+       spin_unlock_irqrestore(&dev->done.lock, flags);
 }
 
 /* some work can't be done in tasklets, so we use keventd
@@ -3120,7 +3119,7 @@ block:
                break;
        }
 
-       defer_bh (dev, skb);
+       defer_bh(dev, skb, &dev->rxq);
 
        if (urb) {
                if (netif_running (dev->net)
@@ -3490,7 +3489,7 @@ static void tx_complete (struct urb *urb
 
        urb->dev = NULL;
        entry->state = tx_done;
-       defer_bh (dev, skb);
+       defer_bh(dev, skb, &dev->txq);
 }
 
 /*-------------------------------------------------------------------------*/
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -205,7 +205,6 @@ struct sk_buff {
        struct sk_buff          *next;
        struct sk_buff          *prev;
 
-       struct sk_buff_head     *list;
        struct sock             *sk;
        struct timeval          stamp;
        struct net_device       *dev;
@@ -596,7 +595,6 @@ static inline void __skb_queue_head(stru
 {
        struct sk_buff *prev, *next;
 
-       newsk->list = list;
        list->qlen++;
        prev = (struct sk_buff *)list;
        next = prev->next;
@@ -621,7 +619,6 @@ static inline void __skb_queue_tail(stru
 {
        struct sk_buff *prev, *next;
 
-       newsk->list = list;
        list->qlen++;
        next = (struct sk_buff *)list;
        prev = next->prev;
@@ -654,7 +651,6 @@ static inline struct sk_buff *__skb_dequ
                next->prev   = prev;
                prev->next   = next;
                result->next = result->prev = NULL;
-               result->list = NULL;
        }
        return result;
 }
@@ -663,7 +659,7 @@ static inline struct sk_buff *__skb_dequ
 /*
  *     Insert a packet on a list.
  */
-extern void        skb_insert(struct sk_buff *old, struct sk_buff *newsk);
+extern void        skb_insert(struct sk_buff *old, struct sk_buff *newsk, 
struct sk_buff_head *list);
 static inline void __skb_insert(struct sk_buff *newsk,
                                struct sk_buff *prev, struct sk_buff *next,
                                struct sk_buff_head *list)
@@ -671,24 +667,23 @@ static inline void __skb_insert(struct s
        newsk->next = next;
        newsk->prev = prev;
        next->prev  = prev->next = newsk;
-       newsk->list = list;
        list->qlen++;
 }
 
 /*
  *     Place a packet after a given packet in a list.
  */
-extern void       skb_append(struct sk_buff *old, struct sk_buff *newsk);
-static inline void __skb_append(struct sk_buff *old, struct sk_buff *newsk)
+extern void       skb_append(struct sk_buff *old, struct sk_buff *newsk, 
struct sk_buff_head *list);
+static inline void __skb_append(struct sk_buff *old, struct sk_buff *newsk, 
struct sk_buff_head *list)
 {
-       __skb_insert(newsk, old, old->next, old->list);
+       __skb_insert(newsk, old, old->next, list);
 }
 
 /*
  * remove sk_buff from list. _Must_ be called atomically, and with
  * the list known..
  */
-extern void       skb_unlink(struct sk_buff *skb);
+extern void       skb_unlink(struct sk_buff *skb, struct sk_buff_head *list);
 static inline void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list)
 {
        struct sk_buff *next, *prev;
@@ -697,7 +692,6 @@ static inline void __skb_unlink(struct s
        next       = skb->next;
        prev       = skb->prev;
        skb->next  = skb->prev = NULL;
-       skb->list  = NULL;
        next->prev = prev;
        prev->next = next;
 }
diff --git a/net/atm/ipcommon.c b/net/atm/ipcommon.c
--- a/net/atm/ipcommon.c
+++ b/net/atm/ipcommon.c
@@ -34,7 +34,6 @@
 
 void skb_migrate(struct sk_buff_head *from,struct sk_buff_head *to)
 {
-       struct sk_buff *skb;
        unsigned long flags;
        struct sk_buff *skb_from = (struct sk_buff *) from;
        struct sk_buff *skb_to = (struct sk_buff *) to;
@@ -47,8 +46,6 @@ void skb_migrate(struct sk_buff_head *fr
        prev->next = skb_to;
        to->prev->next = from->next;
        to->prev = from->prev;
-       for (skb = from->next; skb != skb_to; skb = skb->next)
-               skb->list = to;
        to->qlen += from->qlen;
        spin_unlock(&to->lock);
        from->prev = skb_from;
diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c
--- a/net/ax25/ax25_subr.c
+++ b/net/ax25/ax25_subr.c
@@ -76,7 +76,7 @@ void ax25_requeue_frames(ax25_cb *ax25)
                if (skb_prev == NULL)
                        skb_queue_head(&ax25->write_queue, skb);
                else
-                       skb_append(skb_prev, skb);
+                       skb_append(skb_prev, skb, &ax25->write_queue);
                skb_prev = skb;
        }
 }
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -281,8 +281,6 @@ void kfree_skbmem(struct sk_buff *skb)
 
 void __kfree_skb(struct sk_buff *skb)
 {
-       BUG_ON(skb->list != NULL);
-
        dst_release(skb->dst);
 #ifdef CONFIG_XFRM
        secpath_put(skb->sp);
@@ -333,7 +331,6 @@ struct sk_buff *skb_clone(struct sk_buff
 #define C(x) n->x = skb->x
 
        n->next = n->prev = NULL;
-       n->list = NULL;
        n->sk = NULL;
        C(stamp);
        C(dev);
@@ -404,7 +401,6 @@ static void copy_skb_header(struct sk_bu
         */
        unsigned long offset = new->data - old->data;
 
-       new->list       = NULL;
        new->sk         = NULL;
        new->dev        = old->dev;
        new->real_dev   = old->real_dev;
@@ -1344,50 +1340,43 @@ void skb_queue_tail(struct sk_buff_head 
        __skb_queue_tail(list, newsk);
        spin_unlock_irqrestore(&list->lock, flags);
 }
+
 /**
  *     skb_unlink      -       remove a buffer from a list
  *     @skb: buffer to remove
+ *     @list: list to use
  *
- *     Place a packet after a given packet in a list. The list locks are taken
- *     and this function is atomic with respect to other list locked calls
+ *     Remove a packet from a list. The list locks are taken and this
+ *     function is atomic with respect to other list locked calls
  *
- *     Works even without knowing the list it is sitting on, which can be
- *     handy at times. It also means that THE LIST MUST EXIST when you
- *     unlink. Thus a list must have its contents unlinked before it is
- *     destroyed.
+ *     You must know what list the SKB is on.
  */
-void skb_unlink(struct sk_buff *skb)
+void skb_unlink(struct sk_buff *skb, struct sk_buff_head *list)
 {
-       struct sk_buff_head *list = skb->list;
-
-       if (list) {
-               unsigned long flags;
+       unsigned long flags;
 
-               spin_lock_irqsave(&list->lock, flags);
-               if (skb->list == list)
-                       __skb_unlink(skb, skb->list);
-               spin_unlock_irqrestore(&list->lock, flags);
-       }
+       spin_lock_irqsave(&list->lock, flags);
+       __skb_unlink(skb, list);
+       spin_unlock_irqrestore(&list->lock, flags);
 }
 
-
 /**
  *     skb_append      -       append a buffer
  *     @old: buffer to insert after
  *     @newsk: buffer to insert
+ *     @list: list to use
  *
  *     Place a packet after a given packet in a list. The list locks are taken
  *     and this function is atomic with respect to other list locked calls.
  *     A buffer cannot be placed on two lists at the same time.
  */
-
-void skb_append(struct sk_buff *old, struct sk_buff *newsk)
+void skb_append(struct sk_buff *old, struct sk_buff *newsk, struct 
sk_buff_head *list)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&old->list->lock, flags);
-       __skb_append(old, newsk);
-       spin_unlock_irqrestore(&old->list->lock, flags);
+       spin_lock_irqsave(&list->lock, flags);
+       __skb_append(old, newsk, list);
+       spin_unlock_irqrestore(&list->lock, flags);
 }
 
 
@@ -1395,19 +1384,21 @@ void skb_append(struct sk_buff *old, str
  *     skb_insert      -       insert a buffer
  *     @old: buffer to insert before
  *     @newsk: buffer to insert
+ *     @list: list to use
+ *
+ *     Place a packet before a given packet in a list. The list locks are
+ *     taken and this function is atomic with respect to other list locked
+ *     calls.
  *
- *     Place a packet before a given packet in a list. The list locks are taken
- *     and this function is atomic with respect to other list locked calls
  *     A buffer cannot be placed on two lists at the same time.
  */
-
-void skb_insert(struct sk_buff *old, struct sk_buff *newsk)
+void skb_insert(struct sk_buff *old, struct sk_buff *newsk, struct 
sk_buff_head *list)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&old->list->lock, flags);
-       __skb_insert(newsk, old->prev, old, old->list);
-       spin_unlock_irqrestore(&old->list->lock, flags);
+       spin_lock_irqsave(&list->lock, flags);
+       __skb_insert(newsk, old->prev, old, list);
+       spin_unlock_irqrestore(&list->lock, flags);
 }
 
 #if 0
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -1763,7 +1763,7 @@ static int dn_recvmsg(struct kiocb *iocb
                nskb = skb->next;
 
                if (skb->len == 0) {
-                       skb_unlink(skb);
+                       skb_unlink(skb, queue);
                        kfree_skb(skb);
                        /* 
                         * N.B. Don't refer to skb or cb after this point
diff --git a/net/decnet/dn_nsp_out.c b/net/decnet/dn_nsp_out.c
--- a/net/decnet/dn_nsp_out.c
+++ b/net/decnet/dn_nsp_out.c
@@ -479,7 +479,7 @@ int dn_nsp_check_xmit_queue(struct sock 
                xmit_count = cb2->xmit_count;
                segnum = cb2->segnum;
                /* Remove and drop ack'ed packet */
-               skb_unlink(ack);
+               skb_unlink(ack, list);
                kfree_skb(ack);
                ack = NULL;
 
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
--- a/net/econet/af_econet.c
+++ b/net/econet/af_econet.c
@@ -869,7 +869,7 @@ static void aun_tx_ack(unsigned long seq
 
 foundit:
        tx_result(skb->sk, eb->cookie, result);
-       skb_unlink(skb);
+       skb_unlink(skb, &aun_queue);
        spin_unlock_irqrestore(&aun_queue_lock, flags);
        kfree_skb(skb);
 }
@@ -947,7 +947,7 @@ static void ab_cleanup(unsigned long h)
                {
                        tx_result(skb->sk, eb->cookie, 
                                  ECTYPE_TRANSMIT_NOT_PRESENT);
-                       skb_unlink(skb);
+                       skb_unlink(skb, &aun_queue);
                        kfree_skb(skb);
                }
                skb = newskb;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -975,7 +975,7 @@ do_fault:
        if (!skb->len) {
                if (sk->sk_send_head == skb)
                        sk->sk_send_head = NULL;
-               __skb_unlink(skb, skb->list);
+               __skb_unlink(skb, &sk->sk_write_queue);
                sk_stream_free_skb(sk, skb);
        }
 
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -2085,7 +2085,7 @@ static int tcp_clean_rtx_queue(struct so
                        seq_rtt = now - scb->when;
                tcp_dec_pcount_approx(&tp->fackets_out, skb);
                tcp_packets_out_dec(tp, skb);
-               __skb_unlink(skb, skb->list);
+               __skb_unlink(skb, &sk->sk_write_queue);
                sk_stream_free_skb(sk, skb);
        }
 
@@ -2853,7 +2853,7 @@ static void tcp_ofo_queue(struct sock *s
 
                if (!after(TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt)) {
                        SOCK_DEBUG(sk, "ofo packet was already received \n");
-                       __skb_unlink(skb, skb->list);
+                       __skb_unlink(skb, &tp->out_of_order_queue);
                        __kfree_skb(skb);
                        continue;
                }
@@ -2861,7 +2861,7 @@ static void tcp_ofo_queue(struct sock *s
                           tp->rcv_nxt, TCP_SKB_CB(skb)->seq,
                           TCP_SKB_CB(skb)->end_seq);
 
-               __skb_unlink(skb, skb->list);
+               __skb_unlink(skb, &tp->out_of_order_queue);
                __skb_queue_tail(&sk->sk_receive_queue, skb);
                tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
                if(skb->h.th->fin)
@@ -3027,7 +3027,7 @@ drop:
                u32 end_seq = TCP_SKB_CB(skb)->end_seq;
 
                if (seq == TCP_SKB_CB(skb1)->end_seq) {
-                       __skb_append(skb1, skb);
+                       __skb_append(skb1, skb, &tp->out_of_order_queue);
 
                        if (!tp->rx_opt.num_sacks ||
                            tp->selective_acks[0].end_seq != seq)
@@ -3071,7 +3071,7 @@ drop:
                               tcp_dsack_extend(tp, TCP_SKB_CB(skb1)->seq, 
end_seq);
                               break;
                       }
-                      __skb_unlink(skb1, skb1->list);
+                      __skb_unlink(skb1, &tp->out_of_order_queue);
                       tcp_dsack_extend(tp, TCP_SKB_CB(skb1)->seq, 
TCP_SKB_CB(skb1)->end_seq);
                       __kfree_skb(skb1);
                }
@@ -3088,8 +3088,9 @@ add_sack:
  * simplifies code)
  */
 static void
-tcp_collapse(struct sock *sk, struct sk_buff *head,
-            struct sk_buff *tail, u32 start, u32 end)
+tcp_collapse(struct sock *sk, struct sk_buff_head *list,
+            struct sk_buff *head, struct sk_buff *tail,
+            u32 start, u32 end)
 {
        struct sk_buff *skb;
 
@@ -3099,7 +3100,7 @@ tcp_collapse(struct sock *sk, struct sk_
                /* No new bits? It is possible on ofo queue. */
                if (!before(start, TCP_SKB_CB(skb)->end_seq)) {
                        struct sk_buff *next = skb->next;
-                       __skb_unlink(skb, skb->list);
+                       __skb_unlink(skb, list);
                        __kfree_skb(skb);
                        NET_INC_STATS_BH(LINUX_MIB_TCPRCVCOLLAPSED);
                        skb = next;
@@ -3145,7 +3146,7 @@ tcp_collapse(struct sock *sk, struct sk_
                nskb->mac.raw = nskb->head + (skb->mac.raw-skb->head);
                memcpy(nskb->cb, skb->cb, sizeof(skb->cb));
                TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(nskb)->end_seq = start;
-               __skb_insert(nskb, skb->prev, skb, skb->list);
+               __skb_insert(nskb, skb->prev, skb, list);
                sk_stream_set_owner_r(nskb, sk);
 
                /* Copy data, releasing collapsed skbs. */
@@ -3164,7 +3165,7 @@ tcp_collapse(struct sock *sk, struct sk_
                        }
                        if (!before(start, TCP_SKB_CB(skb)->end_seq)) {
                                struct sk_buff *next = skb->next;
-                               __skb_unlink(skb, skb->list);
+                               __skb_unlink(skb, list);
                                __kfree_skb(skb);
                                NET_INC_STATS_BH(LINUX_MIB_TCPRCVCOLLAPSED);
                                skb = next;
@@ -3200,7 +3201,8 @@ static void tcp_collapse_ofo_queue(struc
                if (skb == (struct sk_buff *)&tp->out_of_order_queue ||
                    after(TCP_SKB_CB(skb)->seq, end) ||
                    before(TCP_SKB_CB(skb)->end_seq, start)) {
-                       tcp_collapse(sk, head, skb, start, end);
+                       tcp_collapse(sk, &tp->out_of_order_queue,
+                                    head, skb, start, end);
                        head = skb;
                        if (skb == (struct sk_buff *)&tp->out_of_order_queue)
                                break;
@@ -3237,7 +3239,8 @@ static int tcp_prune_queue(struct sock *
                tp->rcv_ssthresh = min(tp->rcv_ssthresh, 4U * tp->advmss);
 
        tcp_collapse_ofo_queue(sk);
-       tcp_collapse(sk, sk->sk_receive_queue.next,
+       tcp_collapse(sk, &sk->sk_receive_queue,
+                    sk->sk_receive_queue.next,
                     (struct sk_buff*)&sk->sk_receive_queue,
                     tp->copied_seq, tp->rcv_nxt);
        sk_stream_mem_reclaim(sk);
@@ -3462,7 +3465,7 @@ static void tcp_check_urg(struct sock * 
                struct sk_buff *skb = skb_peek(&sk->sk_receive_queue);
                tp->copied_seq++;
                if (skb && !before(tp->copied_seq, TCP_SKB_CB(skb)->end_seq)) {
-                       __skb_unlink(skb, skb->list);
+                       __skb_unlink(skb, &sk->sk_receive_queue);
                        __kfree_skb(skb);
                }
        }
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -507,7 +507,7 @@ static int tcp_fragment(struct sock *sk,
 
        /* Link BUFF into the send queue. */
        skb_header_release(buff);
-       __skb_append(skb, buff);
+       __skb_append(skb, buff, &sk->sk_write_queue);
 
        return 0;
 }
@@ -892,7 +892,7 @@ static int tso_fragment(struct sock *sk,
 
        /* Link BUFF into the send queue. */
        skb_header_release(buff);
-       __skb_append(skb, buff);
+       __skb_append(skb, buff, &sk->sk_write_queue);
 
        return 0;
 }
@@ -1257,7 +1257,7 @@ static void tcp_retrans_try_collapse(str
                       tcp_skb_pcount(next_skb) != 1);
 
                /* Ok.  We will be able to collapse the packet. */
-               __skb_unlink(next_skb, next_skb->list);
+               __skb_unlink(next_skb, &sk->sk_write_queue);
 
                memcpy(skb_put(skb, next_skb_size), next_skb->data, 
next_skb_size);
 
diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c
--- a/net/irda/irlap_frame.c
+++ b/net/irda/irlap_frame.c
@@ -988,9 +988,6 @@ void irlap_resend_rejected_frames(struct
                        IRDA_DEBUG(0, "%s(), unable to copy\n", __FUNCTION__);
                        return;
                }
-               /* Unlink tx_skb from list */
-               tx_skb->next = tx_skb->prev = NULL;
-               tx_skb->list = NULL;
 
                /* Clear old Nr field + poll bit */
                tx_skb->data[1] &= 0x0f;
@@ -1063,9 +1060,6 @@ void irlap_resend_rejected_frame(struct 
                        IRDA_DEBUG(0, "%s(), unable to copy\n", __FUNCTION__);
                        return;
                }
-               /* Unlink tx_skb from list */
-               tx_skb->next = tx_skb->prev = NULL;
-               tx_skb->list = NULL;
 
                /* Clear old Nr field + poll bit */
                tx_skb->data[1] &= 0x0f;
diff --git a/net/lapb/lapb_subr.c b/net/lapb/lapb_subr.c
--- a/net/lapb/lapb_subr.c
+++ b/net/lapb/lapb_subr.c
@@ -78,7 +78,7 @@ void lapb_requeue_frames(struct lapb_cb 
                if (!skb_prev)
                        skb_queue_head(&lapb->write_queue, skb);
                else
-                       skb_append(skb_prev, skb);
+                       skb_append(skb_prev, skb, &lapb->write_queue);
                skb_prev = skb;
        }
 }
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -714,7 +714,7 @@ static int llc_ui_recvmsg(struct kiocb *
        if (uaddr)
                memcpy(uaddr, llc_ui_skb_cb(skb), sizeof(*uaddr));
        msg->msg_namelen = sizeof(*uaddr);
-       if (!skb->list) {
+       if (!skb->next) {
 dgram_free:
                kfree_skb(skb);
        }
diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c
--- a/net/llc/llc_conn.c
+++ b/net/llc/llc_conn.c
@@ -71,7 +71,11 @@ int llc_conn_state_process(struct sock *
 
        if (!ev->ind_prim && !ev->cfm_prim) {
                /* indicate or confirm not required */
-               if (!skb->list)
+               /* XXX this is not very pretty, perhaps we should store
+                * XXX indicate/confirm-needed state in the llc_conn_state_ev
+                * XXX control block of the SKB instead? -DaveM
+                */
+               if (!skb->next)
                        goto out_kfree_skb;
                goto out_skb_put;
        }
diff --git a/net/netrom/nr_subr.c b/net/netrom/nr_subr.c
--- a/net/netrom/nr_subr.c
+++ b/net/netrom/nr_subr.c
@@ -77,7 +77,7 @@ void nr_requeue_frames(struct sock *sk)
                if (skb_prev == NULL)
                        skb_queue_head(&sk->sk_write_queue, skb);
                else
-                       skb_append(skb_prev, skb);
+                       skb_append(skb_prev, skb, &sk->sk_write_queue);
                skb_prev = skb;
        }
 }
diff --git a/net/rose/rose_subr.c b/net/rose/rose_subr.c
--- a/net/rose/rose_subr.c
+++ b/net/rose/rose_subr.c
@@ -74,7 +74,7 @@ void rose_requeue_frames(struct sock *sk
                if (skb_prev == NULL)
                        skb_queue_head(&sk->sk_write_queue, skb);
                else
-                       skb_append(skb_prev, skb);
+                       skb_append(skb_prev, skb, &sk->sk_write_queue);
                skb_prev = skb;
        }
 }
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4892,7 +4892,7 @@ static void sctp_sock_migrate(struct soc
        sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) {
                event = sctp_skb2event(skb);
                if (event->asoc == assoc) {
-                       __skb_unlink(skb, skb->list);
+                       __skb_unlink(skb, &oldsk->sk_receive_queue);
                        __skb_queue_tail(&newsk->sk_receive_queue, skb);
                }
        }
@@ -4921,7 +4921,7 @@ static void sctp_sock_migrate(struct soc
                sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) {
                        event = sctp_skb2event(skb);
                        if (event->asoc == assoc) {
-                               __skb_unlink(skb, skb->list);
+                               __skb_unlink(skb, &oldsp->pd_lobby);
                                __skb_queue_tail(queue, skb);
                        }
                }
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
--- a/net/sctp/ulpqueue.c
+++ b/net/sctp/ulpqueue.c
@@ -50,9 +50,9 @@
 
 /* Forward declarations for internal helpers.  */
 static struct sctp_ulpevent * sctp_ulpq_reasm(struct sctp_ulpq *ulpq,
-                                               struct sctp_ulpevent *);
+                                             struct sctp_ulpevent *);
 static struct sctp_ulpevent * sctp_ulpq_order(struct sctp_ulpq *,
-                                               struct sctp_ulpevent *);
+                                             struct sctp_ulpevent *);
 
 /* 1st Level Abstractions */
 
@@ -125,7 +125,9 @@ int sctp_ulpq_tail_data(struct sctp_ulpq
                event = sctp_ulpq_order(ulpq, event);
        }
 
-       /* Send event to the ULP.  */
+       /* Send event to the ULP.  'event' is the sctp_ulpevent for
+        * very first SKB on the 'temp' list.
+        */
        if (event)
                sctp_ulpq_tail_event(ulpq, event);
 
@@ -158,14 +160,18 @@ static int sctp_ulpq_clear_pd(struct sct
        return sctp_clear_pd(ulpq->asoc->base.sk);
 }
 
-
-
+/* If the SKB of 'event' is on a list, it is the first such member
+ * of that list.
+ */
 int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event)
 {
        struct sock *sk = ulpq->asoc->base.sk;
-       struct sk_buff_head *queue;
+       struct sk_buff_head *queue, *skb_list;
+       struct sk_buff *skb = sctp_event2skb(event);
        int clear_pd = 0;
 
+       skb_list = (struct sk_buff_head *) skb->prev;
+
        /* If the socket is just going to throw this away, do not
         * even try to deliver it.
         */
@@ -197,10 +203,10 @@ int sctp_ulpq_tail_event(struct sctp_ulp
        /* If we are harvesting multiple skbs they will be
         * collected on a list.
         */
-       if (sctp_event2skb(event)->list)
-               sctp_skb_list_tail(sctp_event2skb(event)->list, queue);
+       if (skb_list)
+               sctp_skb_list_tail(skb_list, queue);
        else
-               __skb_queue_tail(queue, sctp_event2skb(event));
+               __skb_queue_tail(queue, skb);
 
        /* Did we just complete partial delivery and need to get
         * rolling again?  Move pending data to the receive
@@ -214,10 +220,11 @@ int sctp_ulpq_tail_event(struct sctp_ulp
        return 1;
 
 out_free:
-       if (sctp_event2skb(event)->list)
-               sctp_queue_purge_ulpevents(sctp_event2skb(event)->list);
+       if (skb_list)
+               sctp_queue_purge_ulpevents(skb_list);
        else
                sctp_ulpevent_free(event);
+
        return 0;
 }
 
@@ -269,7 +276,7 @@ static inline void sctp_ulpq_store_reasm
  * payload was fragmented on the way and ip had to reassemble them.
  * We add the rest of skb's to the first skb's fraglist.
  */
-static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff 
*f_frag, struct sk_buff *l_frag)
+static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head 
*queue, struct sk_buff *f_frag, struct sk_buff *l_frag)
 {
        struct sk_buff *pos;
        struct sctp_ulpevent *event;
@@ -294,7 +301,7 @@ static struct sctp_ulpevent *sctp_make_r
                skb_shinfo(f_frag)->frag_list = pos;
 
        /* Remove the first fragment from the reassembly queue.  */
-       __skb_unlink(f_frag, f_frag->list);
+       __skb_unlink(f_frag, queue);
        while (pos) {
 
                pnext = pos->next;
@@ -304,7 +311,7 @@ static struct sctp_ulpevent *sctp_make_r
                f_frag->data_len += pos->len;
 
                /* Remove the fragment from the reassembly queue.  */
-               __skb_unlink(pos, pos->list);
+               __skb_unlink(pos, queue);
        
                /* Break if we have reached the last fragment.  */
                if (pos == l_frag)
@@ -375,7 +382,7 @@ static inline struct sctp_ulpevent *sctp
 done:
        return retval;
 found:
-       retval = sctp_make_reassembled_event(first_frag, pos);
+       retval = sctp_make_reassembled_event(&ulpq->reasm, first_frag, pos);
        if (retval)
                retval->msg_flags |= MSG_EOR;
        goto done;
@@ -435,7 +442,7 @@ static inline struct sctp_ulpevent *sctp
         * further.
         */
 done:
-       retval = sctp_make_reassembled_event(first_frag, last_frag);
+       retval = sctp_make_reassembled_event(&ulpq->reasm, first_frag, 
last_frag);
        if (retval && is_last)
                retval->msg_flags |= MSG_EOR;
 
@@ -527,7 +534,7 @@ static inline struct sctp_ulpevent *sctp
         * further.
         */
 done:
-       retval = sctp_make_reassembled_event(first_frag, last_frag);
+       retval = sctp_make_reassembled_event(&ulpq->reasm, first_frag, 
last_frag);
        return retval;
 }
 
@@ -537,6 +544,7 @@ done:
 static inline void sctp_ulpq_retrieve_ordered(struct sctp_ulpq *ulpq,
                                              struct sctp_ulpevent *event)
 {
+       struct sk_buff_head *event_list;
        struct sk_buff *pos, *tmp;
        struct sctp_ulpevent *cevent;
        struct sctp_stream *in;
@@ -547,6 +555,8 @@ static inline void sctp_ulpq_retrieve_or
        ssn = event->ssn;
        in  = &ulpq->asoc->ssnmap->in;
 
+       event_list = (struct sk_buff_head *) sctp_event2skb(event)->prev;
+
        /* We are holding the chunks by stream, by SSN.  */
        sctp_skb_for_each(pos, &ulpq->lobby, tmp) {
                cevent = (struct sctp_ulpevent *) pos->cb;
@@ -567,10 +577,10 @@ static inline void sctp_ulpq_retrieve_or
                /* Found it, so mark in the ssnmap. */
                sctp_ssn_next(in, sid);
 
-               __skb_unlink(pos, pos->list);
+               __skb_unlink(pos, &ulpq->lobby);
 
                /* Attach all gathered skbs to the event.  */
-               __skb_queue_tail(sctp_event2skb(event)->list, pos);
+               __skb_queue_tail(event_list, pos);
        }
 }
 
@@ -626,7 +636,7 @@ static inline void sctp_ulpq_store_order
 }
 
 static struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *ulpq,
-                                               struct sctp_ulpevent *event)
+                                            struct sctp_ulpevent *event)
 {
        __u16 sid, ssn;
        struct sctp_stream *in;
@@ -667,7 +677,7 @@ static inline void sctp_ulpq_reap_ordere
 {
        struct sk_buff *pos, *tmp;
        struct sctp_ulpevent *cevent;
-       struct sctp_ulpevent *event = NULL;
+       struct sctp_ulpevent *event;
        struct sctp_stream *in;
        struct sk_buff_head temp;
        __u16 csid, cssn;
@@ -675,6 +685,8 @@ static inline void sctp_ulpq_reap_ordere
        in  = &ulpq->asoc->ssnmap->in;
 
        /* We are holding the chunks by stream, by SSN.  */
+       skb_queue_head_init(&temp);
+       event = NULL;
        sctp_skb_for_each(pos, &ulpq->lobby, tmp) {
                cevent = (struct sctp_ulpevent *) pos->cb;
                csid = cevent->stream;
@@ -686,19 +698,20 @@ static inline void sctp_ulpq_reap_ordere
                /* Found it, so mark in the ssnmap. */         
                sctp_ssn_next(in, csid);
 
-               __skb_unlink(pos, pos->list);
+               __skb_unlink(pos, &ulpq->lobby);
                if (!event) {                                           
                        /* Create a temporary list to collect chunks on.  */
                        event = sctp_skb2event(pos);
-                       skb_queue_head_init(&temp);
                        __skb_queue_tail(&temp, sctp_event2skb(event));
                } else {
                        /* Attach all gathered skbs to the event.  */
-                       __skb_queue_tail(sctp_event2skb(event)->list, pos);
+                       __skb_queue_tail(&temp, pos);
                }
        }
 
-       /* Send event to the ULP.  */
+       /* Send event to the ULP.  'event' is the sctp_ulpevent for
+        * very first SKB on the 'temp' list.
+        */
        if (event)
                sctp_ulpq_tail_event(ulpq, event);
 }
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -286,16 +286,16 @@ void unix_gc(void)
                        skb = skb_peek(&s->sk_receive_queue);
                        while (skb &&
                               skb != (struct sk_buff *)&s->sk_receive_queue) {
-                               nextsk=skb->next;
+                               nextsk = skb->next;
                                /*
                                 *      Do we have file descriptors ?
                                 */
-                               if(UNIXCB(skb).fp)
-                               {
-                                       __skb_unlink(skb, skb->list);
-                                       __skb_queue_tail(&hitlist,skb);
+                               if (UNIXCB(skb).fp) {
+                                       __skb_unlink(skb,
+                                                    &s->sk_receive_queue);
+                                       __skb_queue_tail(&hitlist, skb);
                                }
-                               skb=nextsk;
+                               skb = nextsk;
                        }
                        spin_unlock(&s->sk_receive_queue.lock);
                }
diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c
--- a/net/x25/x25_subr.c
+++ b/net/x25/x25_subr.c
@@ -80,7 +80,7 @@ void x25_requeue_frames(struct sock *sk)
                if (!skb_prev)
                        skb_queue_head(&sk->sk_write_queue, skb);
                else
-                       skb_append(skb_prev, skb);
+                       skb_append(skb_prev, skb, &sk->sk_write_queue);
                skb_prev = skb;
        }
 }
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to