make netlink user -> kernel interface synchronious
Subsystems (9)
PATCH 5/5 make netlink user -> kernel interface synchronious
This patch make processing netlink user -> kernel messages synchronious. This change was inspired by the talk with Alexey Kuznetsov about current netlink messages processing. He says that he was badly wrong when introduced asynchronious user -> kernel communication.
The call netlink_unicast is the only path to send message to the kernel netlink socket. But, unfortunately, it is also used to send data to the user.
Before this change the user message has been attached to the socket queue and sk->sk_data_ready was called. The process has been blocked until all pending messages were processed. The bad thing is that this processing may occur in the arbitrary process context.
This patch changes nlk->data_ready callback to get 1 skb and force packet processing right in the netlink_unicast.
Kernel -> user path in netlink_unicast remains untouched.
EINTR processing for in netlink_run_queue was changed. It forces rtnl_lock drop, but the process remains in the cycle until the message will be fully processed. So, there is no need to use this kludges now.
drivers/connector/connector.c renamed from drivers/connector/connector.c.nlk6 +1 -13
@@ -235,18 +235,6 @@ out: }/* -* Netlink socket input callback - dequeues the skbs and calls the -* main netlink receiving function. -*/ -static void cn_input (struct sock *sk,int len) -{ -struct sk_buff *skb; - -while ((skb =skb_dequeue (&sk->sk_receive_queue)) !=NULL ) -cn_rx_skb (skb); -} - -/* * Notification routing. * * Gets id and checks if there are notification request for it's idx
@@ -442,7 +430,7 @@ static int __devinit cn_init(void)struct cn_dev *dev = &cdev;int err; - dev->input = cn_input; + dev->input = cn_rx_skb; dev->id.idx = cn_idx; dev->id.val = cn_val;
drivers/scsi/scsi_netlink.c renamed from drivers/scsi/scsi_netlink.c.nlk6 +2 -23
@@ -64,7 +64,7 @@ scsi_nl_rcv_msg(struct sk_buff *skb)if (nlh->nlmsg_type !=SCSI_TRANSPORT_MSG ) { err = -EBADMSG ; - goto next_msg; +return ; } hdr =NLMSG_DATA (nlh);
@@ -99,27 +99,6 @@ next_msg:/** -* scsi_nl_rcv_msg - -* Receive handler for a socket. Extracts a received message buffer from -* the socket, and starts message processing. -* -* @sk: socket -* @len: unused -* -**/ -static void -scsi_nl_rcv (struct sock *sk,int len) -{ -struct sk_buff *skb; - -while ((skb =skb_dequeue (&sk->sk_receive_queue))) { -scsi_nl_rcv_msg (skb); -kfree_skb (skb); - } -} - - -/** * scsi_nl_rcv_event - * Event handler for a netlink socket. *
@@ -168,7 +147,7 @@ scsi_netlink_init(void) } scsi_nl_sock =netlink_kernel_create (&init_net,NETLINK_SCSITRANSPORT , -SCSI_NL_GRP_CNT , scsi_nl_rcv,NULL , +SCSI_NL_GRP_CNT , scsi_nl_rcv_msg,NULL ,THIS_MODULE );if (!scsi_nl_sock) { printk(KERN_ERR "%s: register of recieve handler failed\n",
drivers/scsi/scsi_transport_iscsi.c renamed from drivers/scsi/scsi_transport_iscsi.c.nlk6 +36 -48
97 lines not on this page · raw message
fs/ecryptfs/netlink.c renamed from fs/ecryptfs/netlink.c.nlk6 +1 -13
@@ -165,22 +165,10 @@ static int ecryptfs_process_nl_quit(stru* it to its desired netlink context element and wake up the process * that is waiting for a response. */ -static void ecryptfs_receive_nl_message (struct sock *sk,int len) +static void ecryptfs_receive_nl_message (struct sk_buff *skb) { -struct sk_buff *skb;struct nlmsghdr *nlh; -int rc =0 ;/* skb_recv_datagram requires this */ -receive: - skb =skb_recv_datagram (sk,0 ,0 , &rc); -if (rc == -EINTR ) - goto receive; -else if (rc <0 ) { -ecryptfs_printk (KERN_ERR ,"Error occurred while " -"receiving eCryptfs netlink message; " -"rc = [%d]\n" , rc); -return ; - } nlh =nlmsg_hdr (skb);if (!NLMSG_OK (nlh, skb->len)) { ecryptfs_printk(KERN_ERR, "Received corrupt netlink "
include/linux/connector.h renamed from include/linux/connector.h.nlk6 +1 -1
@@ -153,7 +153,7 @@ struct cn_dev {u32 seq, groups;struct sock *nls; -void (*input) (struct sock * sk,int len); +void (*input) (struct sk_buff *skb);struct cn_queue_dev *cbdev; };
include/linux/netlink.h renamed from include/linux/netlink.h.nlk6 +1 -1
@@ -175,7 +175,7 @@ struct netlink_skb_parmsextern struct sock *netlink_kernel_create (struct net *net,int unit,unsigned int groups, -void (*input)(struct sock *sk,int len), +void (*input)(struct sk_buff *skb),struct mutex *cb_mutex,struct module *module);extern int netlink_change_ngroups (struct sock *sk,unsigned int groups);
include/net/netlink.h renamed from include/net/netlink.h.nlk6 +3 -3
@@ -220,9 +220,9 @@ struct nl_info {u32 pid; }; -extern unsigned int netlink_run_queue (struct sock *sk,unsigned int qlen, -int (*cb)(struct sk_buff *, -struct nlmsghdr *)); +extern int netlink_rcv_skb (struct sk_buff *skb, +int (*cb)(struct sk_buff *, +struct nlmsghdr *));extern int nlmsg_notify (struct sock *sk,struct sk_buff *skb,u32 pid,unsigned int group,int report,gfp_t flags);
kernel/audit.c renamed from kernel/audit.c.nlk6 +2 -10
@@ -847,18 +847,10 @@ static void audit_receive_skb(struct sk_ }/* Receive messages from netlink socket. */ -static void audit_receive (struct sock *sk,int length) +static void audit_receive (struct sk_buff *skb) { -struct sk_buff *skb; -unsigned int qlen; -mutex_lock (&audit_cmd_mutex); - -for (qlen =skb_queue_len (&sk->sk_receive_queue); qlen; qlen--) { - skb =skb_dequeue (&sk->sk_receive_queue); -audit_receive_skb (skb); -kfree_skb (skb); - } +audit_receive_skb (skb);mutex_unlock (&audit_cmd_mutex); }
net/core/rtnetlink.c renamed from net/core/rtnetlink.c.nlk6 +4 -8
@@ -1312,15 +1312,11 @@ static int rtnetlink_rcv_msg(struct sk_breturn doit (skb, nlh, (void *)&rta_buf[0 ]); } -static void rtnetlink_rcv (struct sock *sk,int len) +static void rtnetlink_rcv (struct sk_buff *skb) { -unsigned int qlen =0 ; - -do { -rtnl_lock (); - qlen =netlink_run_queue (sk, qlen, &rtnetlink_rcv_msg); -rtnl_unlock (); - }while (qlen); +rtnl_lock (); +netlink_rcv_skb (skb, &rtnetlink_rcv_msg); +rtnl_unlock (); }static int rtnetlink_event (struct notifier_block *this,unsigned long event,void *ptr)
net/decnet/netfilter/dn_rtmsg.c renamed from net/decnet/netfilter/dn_rtmsg.c.nlk6 +2 -12
@@ -115,17 +115,6 @@ static inline void dnrmg_receive_user_skRCV_SKB_FAIL (-EINVAL ); } -static void dnrmg_receive_user_sk (struct sock *sk,int len) -{ -struct sk_buff *skb; -unsigned int qlen =skb_queue_len (&sk->sk_receive_queue); - -for (; qlen && (skb =skb_dequeue (&sk->sk_receive_queue)); qlen--) { -dnrmg_receive_user_skb (skb); -kfree_skb (skb); - } -} -static struct nf_hook_ops dnrmg_ops = { .hook = dnrmg_hook, .pf = PF_DECnet,
@@ -139,7 +128,8 @@ static int __init dn_rtmsg_init(void) dnrmg =netlink_kernel_create (&init_net,NETLINK_DNRTMSG ,DNRNG_NLGRP_MAX , - dnrmg_receive_user_sk,NULL ,THIS_MODULE ); + dnrmg_receive_user_skb, +NULL ,THIS_MODULE );if (dnrmg ==NULL ) {printk (KERN_ERR "dn_rtmsg: Cannot create netlink socket" );return -ENOMEM ;
net/ipv4/fib_frontend.c renamed from net/ipv4/fib_frontend.c.nlk6 +6 -3
@@ -62,6 +62,9 @@ static struct hlist_head fib_table_hash[#define FIB_TABLE_HASHSZ 256static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ ]; +static struct sock *fibnl =NULL ; + +struct fib_table *fib_new_table (u32 id) {struct fib_table *tb;
@@ -806,13 +809,13 @@ static void nl_fib_input(struct sk_buff pid =NETLINK_CB (skb).pid;/* pid of sending process */ NETLINK_CB (skb).pid =0 ;/* from kernel */ NETLINK_CB (skb).dst_group =0 ;/* unicast */ -netlink_unicast (sk, skb, pid,MSG_DONTWAIT ); +netlink_unicast (fibnl, skb, pid,MSG_DONTWAIT ); }static void nl_fib_lookup_init (void ) { -netlink_kernel_create (&init_net,NETLINK_FIB_LOOKUP ,0 , nl_fib_input, -NULL ,THIS_MODULE ); + fibnl =netlink_kernel_create (&init_net,NETLINK_FIB_LOOKUP ,0 , + nl_fib_input,NULL ,THIS_MODULE ); }static void fib_disable_ip (struct net_device *dev,int force)
net/ipv4/inet_diag.c renamed from net/ipv4/inet_diag.c.nlk6 +4 -8
@@ -839,15 +839,11 @@ static int inet_diag_rcv_msg(struct sk_bstatic DEFINE_MUTEX (inet_diag_mutex); -static void inet_diag_rcv (struct sock *sk,int len) +static void inet_diag_rcv (struct sk_buff *skb) { -unsigned int qlen =0 ; - -do { -mutex_lock (&inet_diag_mutex); - qlen =netlink_run_queue (sk, qlen, &inet_diag_rcv_msg); -mutex_unlock (&inet_diag_mutex); - }while (qlen); +mutex_lock (&inet_diag_mutex); +netlink_rcv_skb (skb, &inet_diag_rcv_msg); +mutex_unlock (&inet_diag_mutex); }static DEFINE_SPINLOCK (inet_diag_register_lock);
net/ipv4/netfilter/ip_queue.c renamed from net/ipv4/netfilter/ip_queue.c.nlk6 +4 -13
@@ -475,7 +475,7 @@ ipq_dev_drop(int ifindex)#define RCV_SKB_FAIL (err) do { netlink_ack(skb, nlh, (err)); return; } while (0)static inline void -ipq_rcv_skb (struct sk_buff *skb) +__ipq_rcv_skb (struct sk_buff *skb) {int status, type, pid, flags, nlmsglen, skblen;struct nlmsghdr *nlh;
@@ -533,19 +533,10 @@ ipq_rcv_skb(struct sk_buff *skb) }static void -ipq_rcv_sk (struct sock *sk,int len) +ipq_rcv_skb (struct sk_buff *skb) { -struct sk_buff *skb; -unsigned int qlen; -mutex_lock (&ipqnl_mutex); - -for (qlen =skb_queue_len (&sk->sk_receive_queue); qlen; qlen--) { - skb =skb_dequeue (&sk->sk_receive_queue); -ipq_rcv_skb (skb); -kfree_skb (skb); - } - +__ipq_rcv_skb (skb);mutex_unlock (&ipqnl_mutex); }
@@ -670,7 +661,7 @@ static int __init ip_queue_init(void)netlink_register_notifier (&ipq_nl_notifier); ipqnl =netlink_kernel_create (&init_net,NETLINK_FIREWALL ,0 , - ipq_rcv_sk,NULL ,THIS_MODULE ); + ipq_rcv_skb,NULL ,THIS_MODULE );if (ipqnl ==NULL ) {printk (KERN_ERR "ip_queue: failed to create netlink socket\n" ); goto cleanup_netlink_notifier;
net/ipv6/netfilter/ip6_queue.c renamed from net/ipv6/netfilter/ip6_queue.c.nlk6 +5 -14
@@ -464,7 +464,7 @@ ipq_dev_drop(int ifindex)#define RCV_SKB_FAIL (err) do { netlink_ack(skb, nlh, (err)); return; } while (0)static inline void -ipq_rcv_skb (struct sk_buff *skb) +__ipq_rcv_skb (struct sk_buff *skb) {int status, type, pid, flags, nlmsglen, skblen;struct nlmsghdr *nlh;
@@ -522,19 +522,10 @@ ipq_rcv_skb(struct sk_buff *skb) }static void -ipq_rcv_sk (struct sock *sk,int len) +ipq_rcv_skb (struct sk_buff *skb) { -struct sk_buff *skb; -unsigned int qlen; -mutex_lock (&ipqnl_mutex); - -for (qlen =skb_queue_len (&sk->sk_receive_queue); qlen; qlen--) { - skb =skb_dequeue (&sk->sk_receive_queue); -ipq_rcv_skb (skb); -kfree_skb (skb); - } - +__ipq_rcv_skb (skb);mutex_unlock (&ipqnl_mutex); }
@@ -658,8 +649,8 @@ static int __init ip6_queue_init(void)struct proc_dir_entry *proc;netlink_register_notifier (&ipq_nl_notifier); - ipqnl =netlink_kernel_create (&init_net,NETLINK_IP6_FW ,0 , ipq_rcv_sk, -NULL ,THIS_MODULE ); + ipqnl =netlink_kernel_create (&init_net,NETLINK_IP6_FW ,0 , + ipq_rcv_skb,NULL ,THIS_MODULE );if (ipqnl ==NULL ) {printk (KERN_ERR "ip6_queue: failed to create netlink socket\n" ); goto cleanup_netlink_notifier;
net/netfilter/nfnetlink.c renamed from net/netfilter/nfnetlink.c.nlk6 +4 -8
@@ -169,15 +169,11 @@ static int nfnetlink_rcv_msg(struct sk_b } } -static void nfnetlink_rcv (struct sock *sk,int len) +static void nfnetlink_rcv (struct sk_buff *skb) { -unsigned int qlen =0 ; - -do { -nfnl_lock (); - qlen =netlink_run_queue (sk, qlen, nfnetlink_rcv_msg); -nfnl_unlock (); - }while (qlen); +nfnl_lock (); +netlink_rcv_skb (skb, &nfnetlink_rcv_msg); +nfnl_unlock (); } static void __exit nfnetlink_exit(void)
net/netlink/af_netlink.c renamed from net/netlink/af_netlink.c.nlk6 +47 -105
254 lines not on this page · raw message
net/netlink/genetlink.c renamed from net/netlink/genetlink.c.nlk6 +4 -8
@@ -470,15 +470,11 @@ static int genl_rcv_msg(struct sk_buff *return ops->doit (skb, &info); } -static void genl_rcv (struct sock *sk,int len) +static void genl_rcv (struct sk_buff *skb) { -unsigned int qlen =0 ; - -do { -genl_lock (); - qlen =netlink_run_queue (sk, qlen, genl_rcv_msg); -genl_unlock (); - }while (qlen && genl_sock && genl_sock->sk_receive_queue.qlen); +genl_lock (); +netlink_rcv_skb (skb, &genl_rcv_msg); +genl_unlock (); }/**************************************************************************
net/xfrm/xfrm_user.c renamed from net/xfrm/xfrm_user.c.nlk6 +4 -9
@@ -1881,16 +1881,11 @@ static int xfrm_user_rcv_msg(struct sk_breturn link->doit (skb, nlh, attrs); } -static void xfrm_netlink_rcv (struct sock *sk,int len) +static void xfrm_netlink_rcv (struct sk_buff *skb) { -unsigned int qlen =0 ; - -do { -mutex_lock (&xfrm_cfg_mutex); - qlen =netlink_run_queue (sk, qlen, &xfrm_user_rcv_msg); -mutex_unlock (&xfrm_cfg_mutex); - - }while (qlen); +mutex_lock (&xfrm_cfg_mutex); +netlink_rcv_skb (skb, &xfrm_user_rcv_msg); +mutex_unlock (&xfrm_cfg_mutex); }static inline size_t xfrm_expire_msgsize (void )
Quoted 9 lines · Denis V. Lunev
This patch make processing netlink user -> kernel messages synchronious. This change was inspired by the talk with Alexey Kuznetsov about current netlink messages processing. He says that he was badly wrong when introduced asynchronious user -> kernel communication.
The call
netlink_unicastis the only path to send message to the kernel netlink socket. But, unfortunately, it is also used to send data to the user.
Quoted 7 lines
Before this change the user message has been attached to the socket queue and
sk->sk_data_readywas called. The process has been blocked until all pending messages were processed. The bad thing is that this processing may occur in the arbitrary process context.This patch changes
nlk->data_readycallback to get 1 skb and force packet processing right in thenetlink_unicast.
I guess the process credential stuff in netlink_skb_params can now be removed as well.
Quoted 15 lines · Patrick McHardy
Quoted 14 lines · Denis V. Lunev
This patch make processing netlink user -> kernel messages synchronious. This change was inspired by the talk with Alexey Kuznetsov about current netlink messages processing. He says that he was badly wrong when introduced asynchronious user -> kernel communication.
The call
netlink_unicastis the only path to send message to the kernel netlink socket. But, unfortunately, it is also used to send data to the user.Before this change the user message has been attached to the socket queue and
sk->sk_data_readywas called. The process has been blocked until all pending messages were processed. The bad thing is that this processing may occur in the arbitrary process context.
Quoted 6 lines
Quoted 2 lines
This patch changes
nlk->data_readycallback to get 1 skb and force packet processing right in thenetlink_unicast.I guess the process credential stuff in
netlink_skb_paramscan now be removed as well.
Yes, but I think the patch should be tested by more people before.
Regards,
Den
From: "Denis V. Lunev" <[email protected]>
Date: Fri, 5 Oct 2007 18:48:44 +0400
Quoted 17 lines
This patch make processing netlink user -> kernel messages synchronious. This change was inspired by the talk with Alexey Kuznetsov about current netlink messages processing. He says that he was badly wrong when introduced asynchronious user -> kernel communication.
The call
netlink_unicastis the only path to send message to the kernel netlink socket. But, unfortunately, it is also used to send data to the user.Before this change the user message has been attached to the socket queue and
sk->sk_data_readywas called. The process has been blocked until all pending messages were processed. The bad thing is that this processing may occur in the arbitrary process context.This patch changes
nlk->data_readycallback to get 1 skb and force packet processing right in thenetlink_unicast.
Quoted 8 lines
Kernel -> user path in
netlink_unicastremains untouched.EINTR processing for in
netlink_run_queuewas changed. It forcesrtnl_lockdrop, but the process remains in the cycle until the message will be fully processed. So, there is no need to use this kludges now.Signed-off-by Denis V. Lunev <[email protected]>Acked-by Alexey Kuznetsov <[email protected]>
Applied.