diff options
Diffstat (limited to 'net/sctp/ulpevent.c')
-rw-r--r-- | net/sctp/ulpevent.c | 24 |
1 files changed, 7 insertions, 17 deletions
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index e049f41faa47..ba97f974f57c 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c | |||
@@ -52,19 +52,6 @@ static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event, | |||
52 | struct sctp_association *asoc); | 52 | struct sctp_association *asoc); |
53 | static void sctp_ulpevent_release_data(struct sctp_ulpevent *event); | 53 | static void sctp_ulpevent_release_data(struct sctp_ulpevent *event); |
54 | 54 | ||
55 | /* Stub skb destructor. */ | ||
56 | static void sctp_stub_rfree(struct sk_buff *skb) | ||
57 | { | ||
58 | /* WARNING: This function is just a warning not to use the | ||
59 | * skb destructor. If the skb is shared, we may get the destructor | ||
60 | * callback on some processor that does not own the sock_lock. This | ||
61 | * was occuring with PACKET socket applications that were monitoring | ||
62 | * our skbs. We can't take the sock_lock, because we can't risk | ||
63 | * recursing if we do really own the sock lock. Instead, do all | ||
64 | * of our rwnd manipulation while we own the sock_lock outright. | ||
65 | */ | ||
66 | } | ||
67 | |||
68 | /* Initialize an ULP event from an given skb. */ | 55 | /* Initialize an ULP event from an given skb. */ |
69 | SCTP_STATIC void sctp_ulpevent_init(struct sctp_ulpevent *event, int msg_flags) | 56 | SCTP_STATIC void sctp_ulpevent_init(struct sctp_ulpevent *event, int msg_flags) |
70 | { | 57 | { |
@@ -111,15 +98,19 @@ static inline void sctp_ulpevent_set_owner(struct sctp_ulpevent *event, | |||
111 | */ | 98 | */ |
112 | sctp_association_hold((struct sctp_association *)asoc); | 99 | sctp_association_hold((struct sctp_association *)asoc); |
113 | skb = sctp_event2skb(event); | 100 | skb = sctp_event2skb(event); |
114 | skb->sk = asoc->base.sk; | ||
115 | event->asoc = (struct sctp_association *)asoc; | 101 | event->asoc = (struct sctp_association *)asoc; |
116 | skb->destructor = sctp_stub_rfree; | 102 | atomic_add(skb->truesize, &event->asoc->rmem_alloc); |
103 | skb_set_owner_r(skb, asoc->base.sk); | ||
117 | } | 104 | } |
118 | 105 | ||
119 | /* A simple destructor to give up the reference to the association. */ | 106 | /* A simple destructor to give up the reference to the association. */ |
120 | static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event) | 107 | static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event) |
121 | { | 108 | { |
122 | sctp_association_put(event->asoc); | 109 | struct sctp_association *asoc = event->asoc; |
110 | struct sk_buff *skb = sctp_event2skb(event); | ||
111 | |||
112 | atomic_sub(skb->truesize, &asoc->rmem_alloc); | ||
113 | sctp_association_put(asoc); | ||
123 | } | 114 | } |
124 | 115 | ||
125 | /* Create and initialize an SCTP_ASSOC_CHANGE event. | 116 | /* Create and initialize an SCTP_ASSOC_CHANGE event. |
@@ -922,7 +913,6 @@ done: | |||
922 | /* Free a ulpevent that has an owner. It includes releasing the reference | 913 | /* Free a ulpevent that has an owner. It includes releasing the reference |
923 | * to the owner, updating the rwnd in case of a DATA event and freeing the | 914 | * to the owner, updating the rwnd in case of a DATA event and freeing the |
924 | * skb. | 915 | * skb. |
925 | * See comments in sctp_stub_rfree(). | ||
926 | */ | 916 | */ |
927 | void sctp_ulpevent_free(struct sctp_ulpevent *event) | 917 | void sctp_ulpevent_free(struct sctp_ulpevent *event) |
928 | { | 918 | { |