From c2e5df616e1ae6c2a074cb241ebb65a318ebaf7c Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 21 Sep 2017 20:58:49 -0700 Subject: vmbus: add per-channel sysfs info This extends existing vmbus related sysfs structure to provide per-channel state information. This is useful when diagnosing issues with multiple queues in networking and storage. The existing sysfs only displayed information about the primary channel. The one place it reported multiple channels was the channel_vp_mapping file which violated the sysfs convention of one value per file. Signed-off-by: Stephen Hemminger Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- include/linux/hyperv.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include/linux/hyperv.h') diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index c458d7b7ad19..ef16ee039850 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -828,6 +828,11 @@ struct vmbus_channel { */ struct rcu_head rcu; + /* + * For sysfs per-channel properties. + */ + struct kobject kobj; + /* * For performance critical channels (storage, networking * etc,), Hyper-V has a mechanism to enhance the throughput @@ -1089,6 +1094,7 @@ struct hv_device { struct device device; struct vmbus_channel *channel; + struct kset *channels_kset; }; -- cgit v1.2.3 From 6981fbf3780366093858c5d2dcdaadcd1fbb04be Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sun, 29 Oct 2017 11:33:40 -0700 Subject: Drivers: hv: vmbus: Expose per-channel interrupts and events counters When investigating performance, it is useful to be able to look at the number of host and guest events per-channel. This is equivalent to per-device interrupt statistics. Signed-off-by: Stephen Hemminger Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/stable/sysfs-bus-vmbus | 26 ++++++++++++++++++++------ drivers/hv/connection.c | 2 ++ drivers/hv/vmbus_drv.c | 16 ++++++++++++++++ include/linux/hyperv.h | 4 ++++ 4 files changed, 42 insertions(+), 6 deletions(-) (limited to 'include/linux/hyperv.h') diff --git a/Documentation/ABI/stable/sysfs-bus-vmbus b/Documentation/ABI/stable/sysfs-bus-vmbus index 0ebd8a1537a0..d4077cc60d55 100644 --- a/Documentation/ABI/stable/sysfs-bus-vmbus +++ b/Documentation/ABI/stable/sysfs-bus-vmbus @@ -61,39 +61,53 @@ Date: September. 2017 KernelVersion: 4.14 Contact: Stephen Hemminger Description: Inbound channel signaling state -Users: Debuggig tools +Users: Debugging tools What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/latency Date: September. 2017 KernelVersion: 4.14 Contact: Stephen Hemminger Description: Channel signaling latency -Users: Debuggig tools +Users: Debugging tools What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/out_mask Date: September. 2017 KernelVersion: 4.14 Contact: Stephen Hemminger Description: Outbound channel signaling state -Users: Debuggig tools +Users: Debugging tools What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/pending Date: September. 2017 KernelVersion: 4.14 Contact: Stephen Hemminger Description: Channel interrupt pending state -Users: Debuggig tools +Users: Debugging tools What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/read_avail Date: September. 2017 KernelVersion: 4.14 Contact: Stephen Hemminger Description: Bytes availabble to read -Users: Debuggig tools +Users: Debugging tools What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/write_avail Date: September. 2017 KernelVersion: 4.14 Contact: Stephen Hemminger Description: Bytes availabble to write -Users: Debuggig tools +Users: Debugging tools + +What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/events +Date: September. 2017 +KernelVersion: 4.14 +Contact: Stephen Hemminger +Description: Number of times we have signaled the host +Users: Debugging tools + +What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/interrupts +Date: September. 2017 +KernelVersion: 4.14 +Contact: Stephen Hemminger +Description: Number of times we have taken an interrupt (incoming) +Users: Debugging tools diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index f41901f80b64..b06a6b796819 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -409,6 +409,8 @@ void vmbus_set_event(struct vmbus_channel *channel) if (!channel->is_dedicated_interrupt) vmbus_send_interrupt(child_relid); + ++channel->sig_events; + hv_do_fast_hypercall8(HVCALL_SIGNAL_EVENT, channel->sig_event); } EXPORT_SYMBOL_GPL(vmbus_set_event); diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 1da8e818f4de..bca8188f3c8c 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -944,6 +944,8 @@ static void vmbus_chan_sched(struct hv_per_cpu_context *hv_cpu) if (channel->rescind) continue; + ++channel->interrupts; + switch (channel->callback_mode) { case HV_CALL_ISR: vmbus_channel_isr(channel); @@ -1237,6 +1239,18 @@ static ssize_t channel_latency_show(const struct vmbus_channel *channel, } VMBUS_CHAN_ATTR(latency, S_IRUGO, channel_latency_show, NULL); +static ssize_t channel_interrupts_show(const struct vmbus_channel *channel, char *buf) +{ + return sprintf(buf, "%llu\n", channel->interrupts); +} +VMBUS_CHAN_ATTR(interrupts, S_IRUGO, channel_interrupts_show, NULL); + +static ssize_t channel_events_show(const struct vmbus_channel *channel, char *buf) +{ + return sprintf(buf, "%llu\n", channel->sig_events); +} +VMBUS_CHAN_ATTR(events, S_IRUGO, channel_events_show, NULL); + static struct attribute *vmbus_chan_attrs[] = { &chan_attr_out_mask.attr, &chan_attr_in_mask.attr, @@ -1245,6 +1259,8 @@ static struct attribute *vmbus_chan_attrs[] = { &chan_attr_cpu.attr, &chan_attr_pending.attr, &chan_attr_latency.attr, + &chan_attr_interrupts.attr, + &chan_attr_events.attr, NULL }; diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index ea6b5586ad77..f3e97c5f94c9 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -719,6 +719,10 @@ struct vmbus_channel { struct vmbus_close_msg close_msg; + /* Statistics */ + u64 interrupts; /* Host to Guest interrupts */ + u64 sig_events; /* Guest to Host events */ + /* Channel callback's invoked in softirq context */ struct tasklet_struct callback_event; void (*onchannel_callback)(void *context); -- cgit v1.2.3 From 7fa32e5ec28b1609abc0b797b58267f725fc3964 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 14 Nov 2017 06:53:33 -0700 Subject: Drivers: hv: vmbus: Fix a rescind issue The current rescind processing code will not correctly handle the case where the host immediately rescinds a channel that has been offerred. In this case, we could be blocked in the open call and since the channel is rescinded, the host will not respond and we could be blocked forever in the vmbus open call.i Fix this problem. Signed-off-by: K. Y. Srinivasan Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/hv/channel.c | 10 ++++++++-- drivers/hv/channel_mgmt.c | 7 ++++--- include/linux/hyperv.h | 1 + 3 files changed, 13 insertions(+), 5 deletions(-) (limited to 'include/linux/hyperv.h') diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 19f0cf37e0ed..ba0a092ae085 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -659,22 +659,28 @@ void vmbus_close(struct vmbus_channel *channel) */ return; } - mutex_lock(&vmbus_connection.channel_mutex); /* * Close all the sub-channels first and then close the * primary channel. */ list_for_each_safe(cur, tmp, &channel->sc_list) { cur_channel = list_entry(cur, struct vmbus_channel, sc_list); - vmbus_close_internal(cur_channel); if (cur_channel->rescind) { + wait_for_completion(&cur_channel->rescind_event); + mutex_lock(&vmbus_connection.channel_mutex); + vmbus_close_internal(cur_channel); hv_process_channel_removal( cur_channel->offermsg.child_relid); + } else { + mutex_lock(&vmbus_connection.channel_mutex); + vmbus_close_internal(cur_channel); } + mutex_unlock(&vmbus_connection.channel_mutex); } /* * Now close the primary. */ + mutex_lock(&vmbus_connection.channel_mutex); vmbus_close_internal(channel); mutex_unlock(&vmbus_connection.channel_mutex); } diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index ec5454f3f4a6..c21020b69114 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -333,6 +333,7 @@ static struct vmbus_channel *alloc_channel(void) return NULL; spin_lock_init(&channel->lock); + init_completion(&channel->rescind_event); INIT_LIST_HEAD(&channel->sc_list); INIT_LIST_HEAD(&channel->percpu_list); @@ -898,6 +899,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) /* * Now wait for offer handling to complete. */ + vmbus_rescind_cleanup(channel); while (READ_ONCE(channel->probe_done) == false) { /* * We wait here until any channel offer is currently @@ -913,7 +915,6 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) if (channel->device_obj) { if (channel->chn_rescind_callback) { channel->chn_rescind_callback(channel); - vmbus_rescind_cleanup(channel); return; } /* @@ -922,7 +923,6 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) */ dev = get_device(&channel->device_obj->device); if (dev) { - vmbus_rescind_cleanup(channel); vmbus_device_unregister(channel->device_obj); put_device(dev); } @@ -936,13 +936,14 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) * 2. Then close the primary channel. */ mutex_lock(&vmbus_connection.channel_mutex); - vmbus_rescind_cleanup(channel); if (channel->state == CHANNEL_OPEN_STATE) { /* * The channel is currently not open; * it is safe for us to cleanup the channel. */ hv_process_channel_removal(rescind->child_relid); + } else { + complete(&channel->rescind_event); } mutex_unlock(&vmbus_connection.channel_mutex); } diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index f3e97c5f94c9..6c9336626592 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -708,6 +708,7 @@ struct vmbus_channel { u8 monitor_bit; bool rescind; /* got rescind msg */ + struct completion rescind_event; u32 ringbuffer_gpadlhandle; -- cgit v1.2.3