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 | { |
