diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2009-06-21 22:25:25 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-06-23 19:36:25 -0400 |
commit | d55d87fdff8252d0e2f7c28c2d443aee17e9d70f (patch) | |
tree | a4bfb0a47525672c690b63e85bf3f47f4ab014f7 /include/net | |
parent | d5fdd6babcfc2b0e6a8da1acf492a69fb54b4c47 (diff) |
net: Move rx skb_orphan call to where needed
In order to get the tun driver to account packets, we need to be
able to receive packets with destructors set. To be on the safe
side, I added an skb_orphan call for all protocols by default since
some of them (IP in particular) cannot handle receiving packets
destructors properly.
Now it seems that at least one protocol (CAN) expects to be able
to pass skb->sk through the rx path without getting clobbered.
So this patch attempts to fix this properly by moving the skb_orphan
call to where it's actually needed. In particular, I've added it
to skb_set_owner_[rw] which is what most users of skb->destructor
call.
This is actually an improvement for tun too since it means that
we only give back the amount charged to the socket when the skb
is passed to another socket that will also be charged accordingly.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Tested-by: Oliver Hartkopp <olver@hartkopp.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net')
-rw-r--r-- | include/net/sctp/sctp.h | 1 | ||||
-rw-r--r-- | include/net/sock.h | 2 |
2 files changed, 3 insertions, 0 deletions
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 9f80a7668289..d16a304cbed4 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h | |||
@@ -448,6 +448,7 @@ static inline void sctp_skb_set_owner_r(struct sk_buff *skb, struct sock *sk) | |||
448 | { | 448 | { |
449 | struct sctp_ulpevent *event = sctp_skb2event(skb); | 449 | struct sctp_ulpevent *event = sctp_skb2event(skb); |
450 | 450 | ||
451 | skb_orphan(skb); | ||
451 | skb->sk = sk; | 452 | skb->sk = sk; |
452 | skb->destructor = sctp_sock_rfree; | 453 | skb->destructor = sctp_sock_rfree; |
453 | atomic_add(event->rmem_len, &sk->sk_rmem_alloc); | 454 | atomic_add(event->rmem_len, &sk->sk_rmem_alloc); |
diff --git a/include/net/sock.h b/include/net/sock.h index 570c7a12b54e..7f5c41cc45a9 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -1250,6 +1250,7 @@ static inline int sk_has_allocations(const struct sock *sk) | |||
1250 | 1250 | ||
1251 | static inline void skb_set_owner_w(struct sk_buff *skb, struct sock *sk) | 1251 | static inline void skb_set_owner_w(struct sk_buff *skb, struct sock *sk) |
1252 | { | 1252 | { |
1253 | skb_orphan(skb); | ||
1253 | skb->sk = sk; | 1254 | skb->sk = sk; |
1254 | skb->destructor = sock_wfree; | 1255 | skb->destructor = sock_wfree; |
1255 | /* | 1256 | /* |
@@ -1262,6 +1263,7 @@ static inline void skb_set_owner_w(struct sk_buff *skb, struct sock *sk) | |||
1262 | 1263 | ||
1263 | static inline void skb_set_owner_r(struct sk_buff *skb, struct sock *sk) | 1264 | static inline void skb_set_owner_r(struct sk_buff *skb, struct sock *sk) |
1264 | { | 1265 | { |
1266 | skb_orphan(skb); | ||
1265 | skb->sk = sk; | 1267 | skb->sk = sk; |
1266 | skb->destructor = sock_rfree; | 1268 | skb->destructor = sock_rfree; |
1267 | atomic_add(skb->truesize, &sk->sk_rmem_alloc); | 1269 | atomic_add(skb->truesize, &sk->sk_rmem_alloc); |