On Thu, 2005-07-07 at 22:19 -0700, David S. Miller wrote:
> I got inspired eariler today, and found that it seemed
> it might be easy to kill off the 'list' member of
> struct sk_buff without changing sk_buff_head at all.
> 
> I got very far.  Nearly every single piece of code was
> easy to change to pass in an explicit SKB list instead
> of skb->list to the SKB queue management functions.
> 
> The big exception was SCTP.  I can't believe after being
> in the kernel for several years it has all of this complicated
> list handling, SKB structure overlaying, and casting all over
> the place.  It was a big downer after a very positive day of
> coding.
> 
> First, it casts "struct sctp_chunk *" pointers to
> "struct sk_buff *" so that it can "borrow" the SKB list
> handling functions.  I just copied over the skb_*() routines
> it used in this way to be sctp_chunk_*(), and used them
> throughout and eliminated the ugly casts.  This can be
> simplified a lot further, since it really doesn't care about
> 'qlen'.  In fact, what it wants is just the most basic list
> handling, ala linux/list.h   So just sticking a list_head
> into sctp_chunk and replacing sctp_chunk_list with a list_head
> as well should do the trick.

I guess we could use the generic lists rather than skb list. But
your sctp_chunk_list looks fine for now except for a minor
bug in __sctp_chunk_dequeue(). You missed resetting result->list
to NULL.

> 
> Some of the rest of the SCTP stuff was transformable with not
> too much effort.
> 
> But then I really got stymied by the reassembly and partial queue
> handling.  These SCTP ulp event things make a layer of abstraction to
> the skb_unlink() point such that you can't know what list the SKB is
> on.  One way to deal with this is to store the list pointer in
> the event struct, and that's likely what will happen at first.  This
> isn't trivial because you have to make sure the assignment is done
> at all of the receive packet list insertion points, some places
> even use sk_buff_head lists on the local stack making this chore
> even more "exciting" :(

Storing list pointer in struct ulpevent seems to be the simplest way
to fix this. But ulpevent is embedded in the cb[40] field of struct
sk_buff and the size of the ulpevent structure is already 34 bytes on
64-bit systems. So adding a pointer increases the size to 42 bytes
and causes it to overflow. I am not sure if you are OK with increasing
cb array to 42 bytes considering that you are trying to reduce the
size of sk_buff.

Anyway, the following patch on top of yours makes SCTP build and work
without skb->list on 32-bit systems.

Thanks
Sridhar

diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -719,6 +719,7 @@ static inline struct sctp_chunk *__sctp_
                next->prev   = prev;
                prev->next   = next;
                result->next = result->prev = NULL;
+               result->list = NULL;
        }
        return result;
 }
diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h
--- a/include/net/sctp/ulpevent.h
+++ b/include/net/sctp/ulpevent.h
@@ -63,6 +63,7 @@ struct sctp_ulpevent {
        __u32 cumtsn;
        int msg_flags;
        int iif;
+       struct sk_buff_head *list;
 };
 
 /* Retrieve the skb this event sits inside of. */
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
--- a/net/sctp/ulpqueue.c
+++ b/net/sctp/ulpqueue.c
@@ -121,6 +121,7 @@ int sctp_ulpq_tail_data(struct sctp_ulpq
                /* Create a temporary list to collect chunks on.  */
                skb_queue_head_init(&temp);
                __skb_queue_tail(&temp, sctp_event2skb(event));
+               event->list = &temp;
 
                event = sctp_ulpq_order(ulpq, event);
        }
@@ -197,10 +198,12 @@ 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);
-       else
+       if (event->list)
+               sctp_skb_list_tail(event->list, queue);
+       else {
                __skb_queue_tail(queue, sctp_event2skb(event));
+               event->list = queue;
+       }
 
        /* Did we just complete partial delivery and need to get
         * rolling again?  Move pending data to the receive
@@ -214,8 +217,8 @@ 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 (event->list)
+               sctp_queue_purge_ulpevents(event->list);
        else
                sctp_ulpevent_free(event);
        return 0;
@@ -237,6 +240,7 @@ static inline void sctp_ulpq_store_reasm
        pos = skb_peek_tail(&ulpq->reasm);
        if (!pos) {
                __skb_queue_tail(&ulpq->reasm, sctp_event2skb(event));
+               event->list = &ulpq->reasm;
                return;
        }
 
@@ -245,6 +249,7 @@ static inline void sctp_ulpq_store_reasm
        ctsn = cevent->tsn;
        if (TSN_lt(ctsn, tsn)) {
                __skb_queue_tail(&ulpq->reasm, sctp_event2skb(event));
+               event->list = &ulpq->reasm;
                return;
        }
 
@@ -259,6 +264,7 @@ static inline void sctp_ulpq_store_reasm
 
        /* Insert before pos. */
        __skb_insert(sctp_event2skb(event), pos->prev, pos, &ulpq->reasm);
+       event->list = &ulpq->reasm;
 
 }
 
@@ -295,6 +301,7 @@ static struct sctp_ulpevent *sctp_make_r
 
        /* Remove the first fragment from the reassembly queue.  */
        __skb_unlink(f_frag, &ulpq->reasm);
+       sctp_skb2event(f_frag)->list = NULL;
        while (pos) {
 
                pnext = pos->next;
@@ -305,6 +312,7 @@ static struct sctp_ulpevent *sctp_make_r
 
                /* Remove the fragment from the reassembly queue.  */
                __skb_unlink(pos, &ulpq->reasm);
+               sctp_skb2event(pos)->list = NULL;
        
                /* Break if we have reached the last fragment.  */
                if (pos == l_frag)
@@ -568,9 +576,11 @@ static inline void sctp_ulpq_retrieve_or
                sctp_ssn_next(in, sid);
 
                __skb_unlink(pos, &ulpq->lobby);
+               sctp_skb2event(pos)->list = NULL;
 
                /* Attach all gathered skbs to the event.  */
-               __skb_queue_tail(sctp_event2skb(event)->list, pos);
+               __skb_queue_tail(event->list, pos);
+               sctp_skb2event(pos)->list = event->list;
        }
 }
 
@@ -586,6 +596,7 @@ static inline void sctp_ulpq_store_order
        pos = skb_peek_tail(&ulpq->lobby);
        if (!pos) {
                __skb_queue_tail(&ulpq->lobby, sctp_event2skb(event));
+               event->list = &ulpq->lobby;
                return;
        }
 
@@ -597,11 +608,13 @@ static inline void sctp_ulpq_store_order
        cssn = cevent->ssn;
        if (sid > csid) {
                __skb_queue_tail(&ulpq->lobby, sctp_event2skb(event));
+               event->list = &ulpq->lobby;
                return;
        }
 
        if ((sid == csid) && SSN_lt(cssn, ssn)) {
                __skb_queue_tail(&ulpq->lobby, sctp_event2skb(event));
+               event->list = &ulpq->lobby;
                return;
        }
 
@@ -622,6 +635,7 @@ static inline void sctp_ulpq_store_order
 
        /* Insert before pos. */
        __skb_insert(sctp_event2skb(event), pos->prev, pos, &ulpq->lobby);
+       event->list = &ulpq->lobby;
 
 }
 
@@ -687,14 +701,17 @@ static inline void sctp_ulpq_reap_ordere
                sctp_ssn_next(in, csid);
 
                __skb_unlink(pos, &ulpq->lobby);
+               sctp_skb2event(pos)->list = NULL;
                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));
+                       event->list = &temp;
                } else {
                        /* Attach all gathered skbs to the event.  */
                        __skb_queue_tail(&temp, pos);
+                       sctp_skb2event(pos)->list = &temp;
                }
        }
 
@@ -855,8 +872,10 @@ void sctp_ulpq_abort_pd(struct sctp_ulpq
                ev = sctp_ulpevent_make_pdapi(ulpq->asoc,
                                              SCTP_PARTIAL_DELIVERY_ABORTED,
                                              gfp);
-       if (ev)
+       if (ev) {
                __skb_queue_tail(&sk->sk_receive_queue, sctp_event2skb(ev));
+               ev->list = &sk->sk_receive_queue;
+       }
 
        /* If there is data waiting, send it up the socket now. */
        if (sctp_ulpq_clear_pd(ulpq) || ev)


-
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