Drivers: hv: vmbus: Expose counters for interrupts and full conditions

Counter values for per-channel interrupts and ring buffer full
conditions are useful for investigating performance.

Expose counters in sysfs for 2 types of guest to host interrupts:
1) Interrupts caused by the channel's outbound ring buffer transitioning
from empty to not empty
2) Interrupts caused by the channel's inbound ring buffer transitioning
from full to not full while a packet is waiting for enough buffer space to
become available

Expose 2 counters in sysfs for the number of times that write operations
encountered a full outbound ring buffer:
1) The total number of write operations that encountered a full
condition
2) The number of write operations that were the first to encounter a
full condition

Increment the outbound full condition counters in the
hv_ringbuffer_write() function because, for most drivers, a full
outbound ring buffer is detected in that function. Also increment the
outbound full condition counters in the set_channel_pending_send_size()
function. In the hv_sock driver, a full outbound ring buffer is detected
and set_channel_pending_send_size() is called before
hv_ringbuffer_write() is called.

I tested this patch by confirming that the sysfs files were created and
observing the counter values. The values seemed to increase by a
reasonable amount when the Hyper-v related drivers were in use.

Signed-off-by: Kimberly Brown <[email protected]>
Reviewed-by:  Michael Kelley <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
This commit is contained in:
Kimberly Brown 2019-02-04 02:13:09 -05:00 • committed by Sasha Levin
commit 396ae57ef1
4 changed files with 128 additions and 1 deletions

View file

@ -74,8 +74,10 @@ static void hv_signal_on_write(u32 old_write, struct vmbus_channel *channel)
* This is the only case we need to signal when the
* ring transitions from being empty to non-empty.
*/
if (old_write == READ_ONCE(rbi->ring_buffer->read_index))
if (old_write == READ_ONCE(rbi->ring_buffer->read_index)) {
++channel->intr_out_empty;
vmbus_setevent(channel);
}
}
/* Get the next write location for the specified ring buffer. */
@ -272,10 +274,19 @@ int hv_ringbuffer_write(struct vmbus_channel *channel,
* is empty since the read index == write index.
*/
if (bytes_avail_towrite <= totalbytes_towrite) {
++channel->out_full_total;
if (!channel->out_full_flag) {
++channel->out_full_first;
channel->out_full_flag = true;
}
spin_unlock_irqrestore(&outring_info->ring_lock, flags);
return -EAGAIN;
}
channel->out_full_flag = false;
/* Write to the ring buffer */
next_write_location = hv_get_next_write_location(outring_info);
@ -530,6 +541,7 @@ void hv_pkt_iter_close(struct vmbus_channel *channel)
if (curr_write_sz <= pending_sz)
return;
++channel->intr_in_full;
vmbus_setevent(channel);
}
EXPORT_SYMBOL_GPL(hv_pkt_iter_close);

View file

@ -1484,6 +1484,38 @@ static ssize_t channel_events_show(const struct vmbus_channel *channel, char *bu
}
static VMBUS_CHAN_ATTR(events, S_IRUGO, channel_events_show, NULL);
static ssize_t channel_intr_in_full_show(const struct vmbus_channel *channel,
char *buf)
{
return sprintf(buf, "%llu\n",
(unsigned long long)channel->intr_in_full);
}
static VMBUS_CHAN_ATTR(intr_in_full, 0444, channel_intr_in_full_show, NULL);
static ssize_t channel_intr_out_empty_show(const struct vmbus_channel *channel,
char *buf)
{
return sprintf(buf, "%llu\n",
(unsigned long long)channel->intr_out_empty);
}
static VMBUS_CHAN_ATTR(intr_out_empty, 0444, channel_intr_out_empty_show, NULL);
static ssize_t channel_out_full_first_show(const struct vmbus_channel *channel,
char *buf)
{
return sprintf(buf, "%llu\n",
(unsigned long long)channel->out_full_first);
}
static VMBUS_CHAN_ATTR(out_full_first, 0444, channel_out_full_first_show, NULL);
static ssize_t channel_out_full_total_show(const struct vmbus_channel *channel,
char *buf)
{
return sprintf(buf, "%llu\n",
(unsigned long long)channel->out_full_total);
}
static VMBUS_CHAN_ATTR(out_full_total, 0444, channel_out_full_total_show, NULL);
static ssize_t subchannel_monitor_id_show(const struct vmbus_channel *channel,
char *buf)
{
@ -1509,6 +1541,10 @@ static struct attribute *vmbus_chan_attrs[] = {
&chan_attr_latency.attr,
&chan_attr_interrupts.attr,
&chan_attr_events.attr,
&chan_attr_intr_in_full.attr,
&chan_attr_intr_out_empty.attr,
&chan_attr_out_full_first.attr,
&chan_attr_out_full_total.attr,
&chan_attr_monitor_id.attr,
&chan_attr_subchannel_id.attr,
NULL