Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netlink: Eliminate kmalloc in netlink dump operation.

Following patch stores struct netlink_callback in netlink_sock
to avoid allocating and freeing it on every netlink dump msg.
Only one dump operation is allowed for a given socket at a time
therefore we can safely convert cb pointer to cb struct inside
netlink_sock.

Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Pravin B Shelar and committed by
David S. Miller
16b304f3 de98ac5e

+47 -59
+45 -58
net/netlink/af_netlink.c
··· 595 595 * for dumps is performed here. A dump is allowed to continue 596 596 * if at least half the ring is unused. 597 597 */ 598 - while (nlk->cb != NULL && netlink_dump_space(nlk)) { 598 + while (nlk->cb_running && netlink_dump_space(nlk)) { 599 599 err = netlink_dump(sk); 600 600 if (err < 0) { 601 601 sk->sk_err = err; ··· 802 802 #define netlink_mmap_sendmsg(sk, msg, dst_portid, dst_group, siocb) 0 803 803 #endif /* CONFIG_NETLINK_MMAP */ 804 804 805 - static void netlink_destroy_callback(struct netlink_callback *cb) 806 - { 807 - kfree_skb(cb->skb); 808 - kfree(cb); 809 - } 810 - 811 - static void netlink_consume_callback(struct netlink_callback *cb) 812 - { 813 - consume_skb(cb->skb); 814 - kfree(cb); 815 - } 816 - 817 805 static void netlink_skb_destructor(struct sk_buff *skb) 818 806 { 819 807 #ifdef CONFIG_NETLINK_MMAP ··· 860 872 { 861 873 struct netlink_sock *nlk = nlk_sk(sk); 862 874 863 - if (nlk->cb) { 864 - if (nlk->cb->done) 865 - nlk->cb->done(nlk->cb); 875 + if (nlk->cb_running) { 876 + if (nlk->cb.done) 877 + nlk->cb.done(&nlk->cb); 866 878 867 - module_put(nlk->cb->module); 868 - netlink_destroy_callback(nlk->cb); 879 + module_put(nlk->cb.module); 880 + kfree_skb(nlk->cb.skb); 869 881 } 870 882 871 883 skb_queue_purge(&sk->sk_receive_queue); ··· 2338 2350 2339 2351 skb_free_datagram(sk, skb); 2340 2352 2341 - if (nlk->cb && atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2) { 2353 + if (nlk->cb_running && 2354 + atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2) { 2342 2355 ret = netlink_dump(sk); 2343 2356 if (ret) { 2344 2357 sk->sk_err = ret; ··· 2555 2566 int alloc_size; 2556 2567 2557 2568 mutex_lock(nlk->cb_mutex); 2558 - 2559 - cb = nlk->cb; 2560 - if (cb == NULL) { 2569 + if (!nlk->cb_running) { 2561 2570 err = -EINVAL; 2562 2571 goto errout_skb; 2563 2572 } 2564 2573 2574 + cb = &nlk->cb; 2565 2575 alloc_size = max_t(int, cb->min_dump_alloc, NLMSG_GOODSIZE); 2566 2576 2567 2577 if (!netlink_rx_is_mmaped(sk) && ··· 2598 2610 2599 2611 if (cb->done) 2600 2612 cb->done(cb); 2601 - nlk->cb = NULL; 2602 - mutex_unlock(nlk->cb_mutex); 2603 2613 2614 + nlk->cb_running = false; 2615 + mutex_unlock(nlk->cb_mutex); 2604 2616 module_put(cb->module); 2605 - netlink_consume_callback(cb); 2617 + consume_skb(cb->skb); 2606 2618 return 0; 2607 2619 2608 2620 errout_skb: ··· 2620 2632 struct netlink_sock *nlk; 2621 2633 int ret; 2622 2634 2623 - cb = kzalloc(sizeof(*cb), GFP_KERNEL); 2624 - if (cb == NULL) 2625 - return -ENOBUFS; 2626 - 2627 2635 /* Memory mapped dump requests need to be copied to avoid looping 2628 2636 * on the pending state in netlink_mmap_sendmsg() while the CB hold 2629 2637 * a reference to the skb. 2630 2638 */ 2631 2639 if (netlink_skb_is_mmaped(skb)) { 2632 2640 skb = skb_copy(skb, GFP_KERNEL); 2633 - if (skb == NULL) { 2634 - kfree(cb); 2641 + if (skb == NULL) 2635 2642 return -ENOBUFS; 2636 - } 2637 2643 } else 2638 2644 atomic_inc(&skb->users); 2639 2645 2646 + sk = netlink_lookup(sock_net(ssk), ssk->sk_protocol, NETLINK_CB(skb).portid); 2647 + if (sk == NULL) { 2648 + ret = -ECONNREFUSED; 2649 + goto error_free; 2650 + } 2651 + 2652 + nlk = nlk_sk(sk); 2653 + mutex_lock(nlk->cb_mutex); 2654 + /* A dump is in progress... */ 2655 + if (nlk->cb_running) { 2656 + ret = -EBUSY; 2657 + goto error_unlock; 2658 + } 2659 + /* add reference of module which cb->dump belongs to */ 2660 + if (!try_module_get(control->module)) { 2661 + ret = -EPROTONOSUPPORT; 2662 + goto error_unlock; 2663 + } 2664 + 2665 + cb = &nlk->cb; 2666 + memset(cb, 0, sizeof(*cb)); 2640 2667 cb->dump = control->dump; 2641 2668 cb->done = control->done; 2642 2669 cb->nlh = nlh; ··· 2660 2657 cb->min_dump_alloc = control->min_dump_alloc; 2661 2658 cb->skb = skb; 2662 2659 2663 - sk = netlink_lookup(sock_net(ssk), ssk->sk_protocol, NETLINK_CB(skb).portid); 2664 - if (sk == NULL) { 2665 - netlink_destroy_callback(cb); 2666 - return -ECONNREFUSED; 2667 - } 2668 - nlk = nlk_sk(sk); 2660 + nlk->cb_running = true; 2669 2661 2670 - mutex_lock(nlk->cb_mutex); 2671 - /* A dump is in progress... */ 2672 - if (nlk->cb) { 2673 - mutex_unlock(nlk->cb_mutex); 2674 - netlink_destroy_callback(cb); 2675 - ret = -EBUSY; 2676 - goto out; 2677 - } 2678 - /* add reference of module which cb->dump belongs to */ 2679 - if (!try_module_get(cb->module)) { 2680 - mutex_unlock(nlk->cb_mutex); 2681 - netlink_destroy_callback(cb); 2682 - ret = -EPROTONOSUPPORT; 2683 - goto out; 2684 - } 2685 - 2686 - nlk->cb = cb; 2687 2662 mutex_unlock(nlk->cb_mutex); 2688 2663 2689 2664 ret = netlink_dump(sk); 2690 - out: 2691 2665 sock_put(sk); 2692 2666 2693 2667 if (ret) ··· 2674 2694 * signal not to send ACK even if it was requested. 2675 2695 */ 2676 2696 return -EINTR; 2697 + 2698 + error_unlock: 2699 + sock_put(sk); 2700 + mutex_unlock(nlk->cb_mutex); 2701 + error_free: 2702 + kfree_skb(skb); 2703 + return ret; 2677 2704 } 2678 2705 EXPORT_SYMBOL(__netlink_dump_start); 2679 2706 ··· 2903 2916 struct sock *s = v; 2904 2917 struct netlink_sock *nlk = nlk_sk(s); 2905 2918 2906 - seq_printf(seq, "%pK %-3d %-6u %08x %-8d %-8d %pK %-8d %-8d %-8lu\n", 2919 + seq_printf(seq, "%pK %-3d %-6u %08x %-8d %-8d %d %-8d %-8d %-8lu\n", 2907 2920 s, 2908 2921 s->sk_protocol, 2909 2922 nlk->portid, 2910 2923 nlk->groups ? (u32)nlk->groups[0] : 0, 2911 2924 sk_rmem_alloc_get(s), 2912 2925 sk_wmem_alloc_get(s), 2913 - nlk->cb, 2926 + nlk->cb_running, 2914 2927 atomic_read(&s->sk_refcnt), 2915 2928 atomic_read(&s->sk_drops), 2916 2929 sock_i_ino(s)
+2 -1
net/netlink/af_netlink.h
··· 32 32 unsigned long *groups; 33 33 unsigned long state; 34 34 wait_queue_head_t wait; 35 - struct netlink_callback *cb; 35 + bool cb_running; 36 + struct netlink_callback cb; 36 37 struct mutex *cb_mutex; 37 38 struct mutex cb_def_mutex; 38 39 void (*netlink_rcv)(struct sk_buff *skb);