[SCTP]: Rewrite of sctp buffer management code
[linux-3.10.git] / net / sctp / ulpevent.c
index 661ea2d..5dc094b 100644 (file)
@@ -141,11 +141,6 @@ struct sctp_ulpevent  *sctp_ulpevent_make_assoc_change(
         * an ABORT, so we need to include it in the sac_info.
         */
        if (chunk) {
-               /* sctp_inqu_pop() has allready pulled off the chunk
-                * header.  We need to put it back temporarily
-                */
-               skb_push(chunk->skb, sizeof(sctp_chunkhdr_t));
-
                /* Copy the chunk data to a new skb and reserve enough
                 * head room to use as notification.
                 */
@@ -155,9 +150,6 @@ struct sctp_ulpevent  *sctp_ulpevent_make_assoc_change(
                if (!skb)
                        goto fail;
 
-               /* put back the chunk header now that we have a copy */
-               skb_pull(chunk->skb, sizeof(sctp_chunkhdr_t));
-
                /* Embed the event fields inside the cloned skb.  */
                event = sctp_skb2event(skb);
                sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize);
@@ -168,7 +160,8 @@ struct sctp_ulpevent  *sctp_ulpevent_make_assoc_change(
 
                /* Trim the buffer to the right length.  */
                skb_trim(skb, sizeof(struct sctp_assoc_change) +
-                        ntohs(chunk->chunk_hdr->length));
+                        ntohs(chunk->chunk_hdr->length) -
+                        sizeof(sctp_chunkhdr_t));
        } else {
                event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change),
                                  MSG_NOTIFICATION, gfp);
@@ -692,6 +685,24 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
        struct sctp_ulpevent *event = NULL;
        struct sk_buff *skb;
        size_t padding, len;
+       int rx_count;
+
+       /*
+        * check to see if we need to make space for this
+        * new skb, expand the rcvbuffer if needed, or drop
+        * the frame
+        */
+       if (asoc->ep->rcvbuf_policy)
+               rx_count = atomic_read(&asoc->rmem_alloc);
+       else
+               rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc);
+
+       if (rx_count >= asoc->base.sk->sk_rcvbuf) {
+
+               if ((asoc->base.sk->sk_userlocks & SOCK_RCVBUF_LOCK) ||
+                  (!sk_stream_rmem_schedule(asoc->base.sk, chunk->skb)))
+                       goto fail;
+       }
 
        /* Clone the original skb, sharing the data.  */
        skb = skb_clone(chunk->skb, gfp);