On 09/20/2018 06:43 AM, Eric Dumazet wrote:
>
> And lastly this patch looks way too complicated to me.
> You probably can write something much simpler.
Something like :
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index
930d17fa906c9ebf1cf7b6031ce0a22f9f66c0e4..e0a81beb4f37751421dbbe794ccf3d5a46bdf900
100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -278,22 +278,26 @@ static bool netlink_filter_tap(const struct sk_buff *skb)
return false;
}
-static int __netlink_deliver_tap_skb(struct sk_buff *skb,
+static int __netlink_deliver_tap_skb(struct sk_buff **pskb,
struct net_device *dev)
{
- struct sk_buff *nskb;
+ struct sk_buff *nskb, *skb = *pskb;
struct sock *sk = skb->sk;
int ret = -ENOMEM;
if (!net_eq(dev_net(dev), sock_net(sk)))
return 0;
- dev_hold(dev);
-
- if (is_vmalloc_addr(skb->head))
+ if (is_vmalloc_addr(skb->head)) {
nskb = netlink_to_full_skb(skb, GFP_ATOMIC);
- else
- nskb = skb_clone(skb, GFP_ATOMIC);
+ if (!nskb)
+ return -ENOMEM;
+ consume_skb(skb);
+ skb = nskb;
+ *pskb = skb;
+ }
+ dev_hold(dev);
+ nskb = skb_clone(skb, GFP_ATOMIC);
if (nskb) {
nskb->dev = dev;
nskb->protocol = htons((u16) sk->sk_protocol);
@@ -318,7 +322,7 @@ static void __netlink_deliver_tap(struct sk_buff *skb,
struct netlink_tap_net *n
return;
list_for_each_entry_rcu(tmp, &nn->netlink_tap_all, list) {
- ret = __netlink_deliver_tap_skb(skb, tmp->dev);
+ ret = __netlink_deliver_tap_skb(&skb, tmp->dev);
if (unlikely(ret))
break;
}