diff options
author | K. Y. Srinivasan <kys@microsoft.com> | 2011-10-09 19:42:28 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-10-10 22:50:00 -0600 |
commit | e2bb65378385a10e21612845e33cd5936e0cbadb (patch) | |
tree | efd641a6591d29e5a05da80ce6eb707b0c1c3cde | |
parent | 76e5f8135d63eb784ef44438e46e82cf0329e179 (diff) |
Staging: hv: util: Invoke cn_netlink_send() in a work context
Invoke cn_netlink_send() in a work context as opposed being called
in the context of channel callback. On entry into the channel callback
code the channel inbound spin lock is held and deferring to a work
context avoids having to invoke cn_netlink_send() while holding
the inbound lock. As part of this adjustment, also increase the
timeout value for waiting for the user level component of KVP.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/staging/hv/hv_kvp.c | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/drivers/staging/hv/hv_kvp.c b/drivers/staging/hv/hv_kvp.c index 307aedc08a36..1e9515cc6094 100644 --- a/drivers/staging/hv/hv_kvp.c +++ b/drivers/staging/hv/hv_kvp.c @@ -44,11 +44,12 @@ static struct { bool active; /* transaction status - active or not */ int recv_len; /* number of bytes received. */ + int index; /* current index */ struct vmbus_channel *recv_channel; /* chn we got the request */ u64 recv_req_id; /* request ID. */ } kvp_transaction; -static int kvp_send_key(int index); +static void kvp_send_key(struct work_struct *dummy); #define TIMEOUT_FIRED 1 @@ -57,6 +58,7 @@ static void kvp_work_func(struct work_struct *dummy); static void kvp_register(void); static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func); +static DECLARE_WORK(kvp_sendkey_work, kvp_send_key); static struct cb_id kvp_id = { CN_KVP_IDX, CN_KVP_VAL }; static const char kvp_name[] = "kvp_kernel_module"; @@ -121,10 +123,11 @@ kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) } } -static int -kvp_send_key(int index) +static void +kvp_send_key(struct work_struct *dummy) { struct cn_msg *msg; + int index = kvp_transaction.index; msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC); @@ -136,9 +139,8 @@ kvp_send_key(int index) msg->len = sizeof(struct hv_ku_msg); cn_netlink_send(msg, 0, GFP_ATOMIC); kfree(msg); - return 0; } - return 1; + return; } /* @@ -286,6 +288,7 @@ void hv_kvp_onchannelcallback(void *context) kvp_transaction.recv_channel = channel; kvp_transaction.recv_req_id = requestid; kvp_transaction.active = true; + kvp_transaction.index = kvp_data->index; /* * Get the information from the @@ -296,8 +299,8 @@ void hv_kvp_onchannelcallback(void *context) * Set a timeout to deal with * user-mode not responding. */ - kvp_send_key(kvp_data->index); - schedule_delayed_work(&kvp_work, 100); + schedule_work(&kvp_sendkey_work); + schedule_delayed_work(&kvp_work, 5*HZ); return; @@ -332,4 +335,5 @@ void hv_kvp_deinit(void) { cn_del_callback(&kvp_id); cancel_delayed_work_sync(&kvp_work); + cancel_work_sync(&kvp_sendkey_work); } |