Don't make an exception for broadcast skb and allocate buffer for it in the same way as for unicast skb. - this makes needless calling of special destructor to free memory under ->head, - ...then, there is no need to reassign this destructor to cloned skb, - ...then, netlink_skb_clone() become equal to generic skb_clone() and can be dropped. Signed-off-by: Jan Dakinevich <jan.dakinevich@xxxxxxxxxxxxx> --- include/linux/netlink.h | 16 ---------------- net/ipv4/fib_frontend.c | 2 +- net/netfilter/nfnetlink.c | 2 +- net/netlink/af_netlink.c | 16 +++------------- 4 files changed, 5 insertions(+), 31 deletions(-) diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 205fa7b..daacffc 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -146,22 +146,6 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb, void netlink_detachskb(struct sock *sk, struct sk_buff *skb); int netlink_sendskb(struct sock *sk, struct sk_buff *skb); -static inline struct sk_buff * -netlink_skb_clone(struct sk_buff *skb, gfp_t gfp_mask) -{ - struct sk_buff *nskb; - - nskb = skb_clone(skb, gfp_mask); - if (!nskb) - return NULL; - - /* This is a large skb, set destructor callback to release head */ - if (is_vmalloc_addr(skb->head)) - nskb->destructor = skb->destructor; - - return nskb; -} - /* * skb should fit one page. This choice is good for headerless malloc. * But we should limit to 8K so that userspace does not have to diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index e8bc939..cbbd75d 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -1371,7 +1371,7 @@ static void nl_fib_input(struct sk_buff *skb) nlmsg_len(nlh) < sizeof(*frn)) return; - skb = netlink_skb_clone(skb, GFP_KERNEL); + skb = skb_clone(skb, GFP_KERNEL); if (!skb) return; nlh = nlmsg_hdr(skb); diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 4abbb45..6ae22c9c 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c @@ -311,7 +311,7 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh, replay: status = 0; - skb = netlink_skb_clone(oskb, GFP_KERNEL); + skb = skb_clone(oskb, GFP_KERNEL); if (!skb) return netlink_ack(oskb, nlh, -ENOMEM, NULL); diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 90b2ab9..04a3457 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -360,13 +360,6 @@ static void netlink_rcv_wake(struct sock *sk) static void netlink_skb_destructor(struct sk_buff *skb) { - if (is_vmalloc_addr(skb->head)) { - if (!skb->cloned || - !atomic_dec_return(&(skb_shinfo(skb)->dataref))) - vfree(skb->head); - - skb->head = NULL; - } if (skb->sk != NULL) sock_rfree(skb); } @@ -1164,13 +1157,12 @@ struct sock *netlink_getsockbyfilp(struct file *filp) return sock; } -static struct sk_buff *netlink_alloc_large_skb(unsigned int size, - int broadcast) +static struct sk_buff *netlink_alloc_large_skb(unsigned int size) { struct sk_buff *skb; void *data; - if (size <= NLMSG_GOODSIZE || broadcast) + if (size <= NLMSG_GOODSIZE) return alloc_skb(size, GFP_KERNEL); size = SKB_DATA_ALIGN(size) + @@ -1183,8 +1175,6 @@ static struct sk_buff *netlink_alloc_large_skb(unsigned int size, skb = __build_skb(data, size); if (skb == NULL) vfree(data); - else - skb->destructor = netlink_skb_destructor; return skb; } @@ -1889,7 +1879,7 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) if (len > sk->sk_sndbuf - 32) goto out; err = -ENOBUFS; - skb = netlink_alloc_large_skb(len, dst_group); + skb = netlink_alloc_large_skb(len); if (skb == NULL) goto out; -- 2.1.4