summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2004-09-28 00:44:58 -0700
committerDavid S. Miller <davem@nuts.davemloft.net>2004-09-28 00:44:58 -0700
commit2eff7ad471c23d0aa074fc738c41658269abce30 (patch)
treedc3df3d21923c716d6440553203f36d2242abeca
parent6ad5331ee3c59d40eb8a52078823a0921c83dfa8 (diff)
[NETLINK]: Trim SKBs at netlink_{unicast,broadcast}() time.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/netlink/af_netlink.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 671071666d09..8bcf3f30f306 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -536,12 +536,25 @@ void netlink_detachskb(struct sock *sk, struct sk_buff *skb)
sock_put(sk);
}
+static inline void netlink_trim(struct sk_buff *skb, int allocation)
+{
+ int delta = skb->end - skb->tail;
+
+ if (delta * 2 < skb->truesize)
+ return;
+ if (pskb_expand_head(skb, 0, -delta, allocation))
+ return;
+ skb->truesize -= delta;
+}
+
int netlink_unicast(struct sock *ssk, struct sk_buff *skb, u32 pid, int nonblock)
{
struct sock *sk;
int err;
long timeo;
+ netlink_trim(skb, gfp_any());
+
timeo = sock_sndtimeo(ssk, nonblock);
retry:
sk = netlink_getsockbypid(ssk, pid);
@@ -588,6 +601,8 @@ int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid,
int protocol = ssk->sk_protocol;
int failure = 0, delivered = 0;
+ netlink_trim(skb, allocation);
+
/* While we sleep in clone, do not allow to change socket list */
netlink_lock_table();