aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/ulpevent.c
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2006-10-10 00:34:04 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-10-12 02:59:44 -0400
commit331c4ee7faa4ee1e1404c872a139784753100498 (patch)
treec5bbae21fd17f7948ab2506cad4d6f2ecba911ee /net/sctp/ulpevent.c
parent6e8c751e07b34d73069e9333f67fbe5ffe31ec3a (diff)
[SCTP]: Fix receive buffer accounting.
When doing receiver buffer accounting, we always used skb->truesize. This is problematic when processing bundled DATA chunks because for every DATA chunk that could be small part of one large skb, we would charge the size of the entire skb. The new approach is to store the size of the DATA chunk we are accounting for in the sctp_ulpevent structure and use that stored value for accounting. Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com> Signed-off-by: Sridhar Samudrala <sri@us.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/ulpevent.c')
-rw-r--r--net/sctp/ulpevent.c25
1 files changed, 15 insertions, 10 deletions
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index ee236784a6bb..a015283a9087 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -55,10 +55,13 @@ static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event);
55 55
56 56
57/* Initialize an ULP event from an given skb. */ 57/* Initialize an ULP event from an given skb. */
58SCTP_STATIC void sctp_ulpevent_init(struct sctp_ulpevent *event, int msg_flags) 58SCTP_STATIC void sctp_ulpevent_init(struct sctp_ulpevent *event,
59 int msg_flags,
60 unsigned int len)
59{ 61{
60 memset(event, 0, sizeof(struct sctp_ulpevent)); 62 memset(event, 0, sizeof(struct sctp_ulpevent));
61 event->msg_flags = msg_flags; 63 event->msg_flags = msg_flags;
64 event->rmem_len = len;
62} 65}
63 66
64/* Create a new sctp_ulpevent. */ 67/* Create a new sctp_ulpevent. */
@@ -73,7 +76,7 @@ SCTP_STATIC struct sctp_ulpevent *sctp_ulpevent_new(int size, int msg_flags,
73 goto fail; 76 goto fail;
74 77
75 event = sctp_skb2event(skb); 78 event = sctp_skb2event(skb);
76 sctp_ulpevent_init(event, msg_flags); 79 sctp_ulpevent_init(event, msg_flags, skb->truesize);
77 80
78 return event; 81 return event;
79 82
@@ -101,17 +104,16 @@ static inline void sctp_ulpevent_set_owner(struct sctp_ulpevent *event,
101 sctp_association_hold((struct sctp_association *)asoc); 104 sctp_association_hold((struct sctp_association *)asoc);
102 skb = sctp_event2skb(event); 105 skb = sctp_event2skb(event);
103 event->asoc = (struct sctp_association *)asoc; 106 event->asoc = (struct sctp_association *)asoc;
104 atomic_add(skb->truesize, &event->asoc->rmem_alloc); 107 atomic_add(event->rmem_len, &event->asoc->rmem_alloc);
105 skb_set_owner_r(skb, asoc->base.sk); 108 sctp_skb_set_owner_r(skb, asoc->base.sk);
106} 109}
107 110
108/* A simple destructor to give up the reference to the association. */ 111/* A simple destructor to give up the reference to the association. */
109static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event) 112static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event)
110{ 113{
111 struct sctp_association *asoc = event->asoc; 114 struct sctp_association *asoc = event->asoc;
112 struct sk_buff *skb = sctp_event2skb(event);
113 115
114 atomic_sub(skb->truesize, &asoc->rmem_alloc); 116 atomic_sub(event->rmem_len, &asoc->rmem_alloc);
115 sctp_association_put(asoc); 117 sctp_association_put(asoc);
116} 118}
117 119
@@ -372,7 +374,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_remote_error(
372 374
373 /* Embed the event fields inside the cloned skb. */ 375 /* Embed the event fields inside the cloned skb. */
374 event = sctp_skb2event(skb); 376 event = sctp_skb2event(skb);
375 sctp_ulpevent_init(event, MSG_NOTIFICATION); 377 sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize);
376 378
377 sre = (struct sctp_remote_error *) 379 sre = (struct sctp_remote_error *)
378 skb_push(skb, sizeof(struct sctp_remote_error)); 380 skb_push(skb, sizeof(struct sctp_remote_error));
@@ -464,7 +466,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
464 466
465 /* Embed the event fields inside the cloned skb. */ 467 /* Embed the event fields inside the cloned skb. */
466 event = sctp_skb2event(skb); 468 event = sctp_skb2event(skb);
467 sctp_ulpevent_init(event, MSG_NOTIFICATION); 469 sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize);
468 470
469 ssf = (struct sctp_send_failed *) 471 ssf = (struct sctp_send_failed *)
470 skb_push(skb, sizeof(struct sctp_send_failed)); 472 skb_push(skb, sizeof(struct sctp_send_failed));
@@ -682,8 +684,11 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
682 /* Embed the event fields inside the cloned skb. */ 684 /* Embed the event fields inside the cloned skb. */
683 event = sctp_skb2event(skb); 685 event = sctp_skb2event(skb);
684 686
685 /* Initialize event with flags 0. */ 687 /* Initialize event with flags 0 and correct length
686 sctp_ulpevent_init(event, 0); 688 * Since this is a clone of the original skb, only account for
689 * the data of this chunk as other chunks will be accounted separately.
690 */
691 sctp_ulpevent_init(event, 0, skb->len + sizeof(struct sk_buff));
687 692
688 sctp_ulpevent_receive_data(event, asoc); 693 sctp_ulpevent_receive_data(event, asoc);
689 694