Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F157146008
D7622.id19615.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
D7622.id19615.diff
View Options
Index: sys/dev/hyperv/include/vmbus.h
===================================================================
--- sys/dev/hyperv/include/vmbus.h
+++ sys/dev/hyperv/include/vmbus.h
@@ -134,6 +134,8 @@
struct vmbus_channel *
vmbus_chan_cpu2chan(struct vmbus_channel *chan, int cpu);
void vmbus_chan_set_readbatch(struct vmbus_channel *chan, bool on);
+int vmbus_chan_array(struct vmbus_channel *pri_chan,
+ struct vmbus_channel **chan_array, int array_max_len);
struct vmbus_channel **
vmbus_subchan_get(struct vmbus_channel *pri_chan,
Index: sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
===================================================================
--- sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
+++ sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
@@ -75,11 +75,10 @@
#include <dev/hyperv/include/hyperv.h>
#include <dev/hyperv/include/vmbus.h>
-
+#include <dev/hyperv/vmbus/vmbus_reg.h>
#include "hv_vstorage.h"
#include "vmbus_if.h"
-#define STORVSC_RINGBUFFER_SIZE (20*PAGE_SIZE)
#define STORVSC_MAX_LUNS_PER_TARGET (64)
#define STORVSC_MAX_IO_REQUESTS (STORVSC_MAX_LUNS_PER_TARGET * 2)
#define BLKVSC_MAX_IDE_DISKS_PER_TARGET (1)
@@ -121,8 +120,6 @@
boolean_t is_init;
} g_hv_sgl_page_pool;
-#define STORVSC_MAX_SG_PAGE_CNT STORVSC_MAX_IO_REQUESTS * STORVSC_DATA_SEGCNT_MAX
-
enum storvsc_request_type {
WRITE_TYPE,
READ_TYPE,
@@ -132,11 +129,28 @@
SYSCTL_NODE(_hw, OID_AUTO, storvsc, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
"Hyper-V storage interface");
+static u_int hv_storvsc_use_win8ext_flags = 1;
+SYSCTL_INT(_hw_storvsc, OID_AUTO, use_win8ext_flags, CTLFLAG_RW,
+ &hv_storvsc_use_win8ext_flags, 0,
+ "Use win8 extension flags or not");
+
static u_int hv_storvsc_use_pim_unmapped = 1;
SYSCTL_INT(_hw_storvsc, OID_AUTO, use_pim_unmapped, CTLFLAG_RDTUN,
&hv_storvsc_use_pim_unmapped, 0,
"Optimize storvsc by using unmapped I/O");
+static u_int hv_storvsc_ringbuffer_size = (64 * PAGE_SIZE);
+SYSCTL_INT(_hw_storvsc, OID_AUTO, ringbuffer_size, CTLFLAG_RDTUN,
+ &hv_storvsc_ringbuffer_size, 0, "Hyper-V storage ringbuffer size");
+
+static u_int hv_storvsc_max_io = 512;
+SYSCTL_INT(_hw_storvsc, OID_AUTO, max_io, CTLFLAG_RDTUN,
+ &hv_storvsc_max_io, 0, "Hyper-V storage max io limit");
+
+#define STORVSC_MAX_IO \
+ (hv_storvsc_ringbuffer_size - PAGE_SIZE) / \
+ MAX_SIZE_BUFRING_ITEM(STORVSC_DATA_SEGCNT_MAX, \
+ VSTOR_PKT_SIZE)
struct hv_storvsc_sysctl {
u_long data_bio_cnt;
u_long data_vaddr_cnt;
@@ -184,10 +198,18 @@
device_t hs_dev;
bus_dma_tag_t storvsc_req_dtag;
struct hv_storvsc_sysctl sysctl_data;
-
- struct vmbus_channel *hs_cpu2chan[MAXCPU];
+ uint32_t hs_nchan;
+ struct vmbus_channel *hs_lun2chan[MAXCPU];
};
+/*
+ * The size of the vmscsi_request has changed in win8. The
+ * additional size is for the newly added elements in the
+ * structure. These elements are valid only when we are talking
+ * to a win8 host.
+ * Track the correct size we need to apply.
+ */
+static int vmscsi_size_delta = sizeof(struct vmscsi_win8_extension);
/**
* HyperV storvsc timeout testing cases:
@@ -211,7 +233,7 @@
char *drv_name;
char *drv_desc;
uint8_t drv_max_luns_per_target;
- uint8_t drv_max_ios_per_target;
+ uint32_t drv_max_ios_per_target;
uint32_t drv_ringbuffer_size;
};
@@ -240,10 +262,10 @@
static struct storvsc_driver_props g_drv_props_table[] = {
{"blkvsc", "Hyper-V IDE Storage Interface",
BLKVSC_MAX_IDE_DISKS_PER_TARGET, BLKVSC_MAX_IO_REQUESTS,
- STORVSC_RINGBUFFER_SIZE},
+ 20*PAGE_SIZE},
{"storvsc", "Hyper-V SCSI Storage Interface",
STORVSC_MAX_LUNS_PER_TARGET, STORVSC_MAX_IO_REQUESTS,
- STORVSC_RINGBUFFER_SIZE}
+ 20*PAGE_SIZE}
};
/*
@@ -253,14 +275,6 @@
static int sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE;
/*
- * The size of the vmscsi_request has changed in win8. The
- * additional size is for the newly added elements in the
- * structure. These elements are valid only when we are talking
- * to a win8 host.
- * Track the correct size we need to apply.
- */
-static int vmscsi_size_delta;
-/*
* The storage protocol version is determined during the
* initial exchange with the host. It will indicate which
* storage functionality is available in the host.
@@ -687,6 +701,7 @@
struct vstor_packet *vstor_packet = &request->vstor_packet;
struct vmbus_channel* outgoing_channel = NULL;
int ret = 0;
+ int ch_sel;
vstor_packet->flags |= REQUEST_COMPLETION_FLAG;
@@ -699,7 +714,8 @@
vstor_packet->operation = VSTOR_OPERATION_EXECUTESRB;
- outgoing_channel = sc->hs_cpu2chan[curcpu];
+ ch_sel = vstor_packet->u.vm_srb.lun + curcpu;
+ outgoing_channel = sc->hs_lun2chan[ch_sel % sc->hs_nchan];
mtx_unlock(&request->softc->hs_lock);
if (request->prp_list.gpa_range.gpa_len) {
@@ -906,17 +922,10 @@
}
static void
-storvsc_create_cpu2chan(struct storvsc_softc *sc)
+storvsc_create_lun2chan(struct storvsc_softc *sc)
{
- int cpu;
-
- CPU_FOREACH(cpu) {
- sc->hs_cpu2chan[cpu] = vmbus_chan_cpu2chan(sc->hs_chan, cpu);
- if (bootverbose) {
- device_printf(sc->hs_dev, "cpu%d -> chan%u\n",
- cpu, vmbus_chan_id(sc->hs_cpu2chan[cpu]));
- }
- }
+ int nchan = vmbus_chan_array(sc->hs_chan, sc->hs_lun2chan, MAXCPU);
+ sc->hs_nchan = nchan;
}
static int
@@ -1029,7 +1038,15 @@
/* fill in driver specific properties */
sc->hs_drv_props = &g_drv_props_table[stor_type];
-
+ sc->hs_drv_props->drv_ringbuffer_size = hv_storvsc_ringbuffer_size;
+ sc->hs_drv_props->drv_max_ios_per_target =
+ STORVSC_MAX_IO > hv_storvsc_max_io ?
+ hv_storvsc_max_io : STORVSC_MAX_IO;
+ if (bootverbose) {
+ printf("storvsc ringbuffer size: %d, max_io: %d\n",
+ sc->hs_drv_props->drv_ringbuffer_size,
+ sc->hs_drv_props->drv_max_ios_per_target);
+ }
/* fill in device specific properties */
sc->hs_unit = device_get_unit(dev);
sc->hs_dev = dev;
@@ -1051,7 +1068,7 @@
* STORVSC_DATA_SEGCNT_MAX segments, each
* segment has one page buffer
*/
- for (i = 0; i < STORVSC_MAX_IO_REQUESTS; i++) {
+ for (i = 0; i < sc->hs_drv_props->drv_max_ios_per_target; i++) {
sgl_node = malloc(sizeof(struct hv_sgl_node),
M_DEVBUF, M_WAITOK|M_ZERO);
@@ -1082,7 +1099,7 @@
}
/* Construct cpu to channel mapping */
- storvsc_create_cpu2chan(sc);
+ storvsc_create_lun2chan(sc);
/*
* Create the device queue.
@@ -1839,18 +1856,39 @@
csio->cdb_len);
}
+ if (hv_storvsc_use_win8ext_flags) {
+ reqp->vstor_packet.u.vm_srb.win8_extension.time_out_value = 60;
+ reqp->vstor_packet.u.vm_srb.win8_extension.srb_flags |=
+ SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
+ }
switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
case CAM_DIR_OUT:
- reqp->vstor_packet.u.vm_srb.data_in = WRITE_TYPE;
+ reqp->vstor_packet.u.vm_srb.data_in = WRITE_TYPE;
+ if (hv_storvsc_use_win8ext_flags) {
+ reqp->vstor_packet.u.vm_srb.win8_extension.srb_flags |=
+ SRB_FLAGS_DATA_OUT;
+ }
break;
case CAM_DIR_IN:
reqp->vstor_packet.u.vm_srb.data_in = READ_TYPE;
+ if (hv_storvsc_use_win8ext_flags) {
+ reqp->vstor_packet.u.vm_srb.win8_extension.srb_flags |=
+ SRB_FLAGS_DATA_IN;
+ }
break;
case CAM_DIR_NONE:
reqp->vstor_packet.u.vm_srb.data_in = UNKNOWN_TYPE;
+ if (hv_storvsc_use_win8ext_flags) {
+ reqp->vstor_packet.u.vm_srb.win8_extension.srb_flags |=
+ SRB_FLAGS_DATA_IN;
+ }
break;
default:
reqp->vstor_packet.u.vm_srb.data_in = UNKNOWN_TYPE;
+ if (hv_storvsc_use_win8ext_flags) {
+ reqp->vstor_packet.u.vm_srb.win8_extension.srb_flags |=
+ SRB_FLAGS_DATA_IN;
+ }
break;
}
Index: sys/dev/hyperv/storvsc/hv_vstorage.h
===================================================================
--- sys/dev/hyperv/storvsc/hv_vstorage.h
+++ sys/dev/hyperv/storvsc/hv_vstorage.h
@@ -253,6 +253,22 @@
#define SRB_STATUS_AUTOSENSE_VALID 0x80
#define SRB_STATUS_INVALID_LUN 0X20
+/*
+ * SRB Flag Bits
+ */
+
+#define SRB_FLAGS_QUEUE_ACTION_ENABLE 0x00000002
+#define SRB_FLAGS_DISABLE_DISCONNECT 0x00000004
+#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER 0x00000008
+#define SRB_FLAGS_BYPASS_FROZEN_QUEUE 0x00000010
+#define SRB_FLAGS_DISABLE_AUTOSENSE 0x00000020
+#define SRB_FLAGS_DATA_IN 0x00000040
+#define SRB_FLAGS_DATA_OUT 0x00000080
+#define SRB_FLAGS_NO_DATA_TRANSFER 0x00000000
+#define SRB_FLAGS_UNSPECIFIED_DIRECTION (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT)
+#define SRB_FLAGS_NO_QUEUE_FREEZE 0x00000100
+#define SRB_FLAGS_ADAPTER_CACHE_ENABLE 0x00000200
+#define SRB_FLAGS_FREE_SENSE_BUFFER 0x00000400
/**
* Packet flags
*/
Index: sys/dev/hyperv/vmbus/vmbus_chan.c
===================================================================
--- sys/dev/hyperv/vmbus/vmbus_chan.c
+++ sys/dev/hyperv/vmbus/vmbus_chan.c
@@ -173,6 +173,9 @@
SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(chid_tree), OID_AUTO,
"cpu", CTLFLAG_RD, &chan->ch_cpuid, 0, "owner CPU id");
+ SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(chid_tree), OID_AUTO,
+ "send", CTLFLAG_RD, &chan->ch_stat_send_nreq, 0,
+ "requests sent from this channel");
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(chid_tree), OID_AUTO,
"mnf", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
chan, 0, vmbus_chan_sysctl_mnf, "I",
@@ -629,6 +632,10 @@
error = vmbus_txbr_write(&chan->ch_txbr, iov, 3, &send_evt);
if (!error && send_evt)
vmbus_chan_signal_tx(chan);
+ // statistc for this channel
+ if (!error) {
+ chan->ch_stat_send_nreq++;
+ }
return error;
}
@@ -668,6 +675,10 @@
error = vmbus_txbr_write(&chan->ch_txbr, iov, 4, &send_evt);
if (!error && send_evt)
vmbus_chan_signal_tx(chan);
+ // statistc for this channel
+ if (!error) {
+ chan->ch_stat_send_nreq++;
+ }
return error;
}
@@ -709,6 +720,10 @@
error = vmbus_txbr_write(&chan->ch_txbr, iov, 4, &send_evt);
if (!error && send_evt)
vmbus_chan_signal_tx(chan);
+ // statistc for this channel
+ if (!error) {
+ chan->ch_stat_send_nreq++;
+ }
return error;
}
@@ -1314,6 +1329,30 @@
return sel;
}
+int
+vmbus_chan_array(struct vmbus_channel *pri_chan,
+ struct vmbus_channel **chan_array, int array_max_len)
+{
+ struct vmbus_channel *chan;
+ int nchan = 0;
+ chan_array[nchan++] = pri_chan;
+
+ if (TAILQ_EMPTY(&pri_chan->ch_subchans)) {
+ return nchan;
+ }
+ mtx_lock(&pri_chan->ch_subchan_lock);
+ TAILQ_FOREACH(chan, &pri_chan->ch_subchans, ch_sublink) {
+ KASSERT(chan->ch_stflags & VMBUS_CHAN_ST_OPENED,
+ ("chan%u is not opened", chan->ch_id));
+ KASSERT(nchan + 1 < array_max_len,
+ ("channel array's capacity %d is reached\n",
+ array_max_len));
+ chan_array[nchan++] = chan;
+ }
+ mtx_unlock(&pri_chan->ch_subchan_lock);
+ return nchan;
+}
+
struct vmbus_channel **
vmbus_subchan_get(struct vmbus_channel *pri_chan, int subchan_cnt)
{
Index: sys/dev/hyperv/vmbus/vmbus_chanvar.h
===================================================================
--- sys/dev/hyperv/vmbus/vmbus_chanvar.h
+++ sys/dev/hyperv/vmbus/vmbus_chanvar.h
@@ -89,7 +89,7 @@
volatile u_long *ch_evtflag; /* event flag loc. */
/*
- * Rarely used fields.
+ * Rarepy used fields.
*/
struct hyperv_mon_param *ch_monprm;
@@ -133,6 +133,7 @@
struct hyperv_guid ch_guid_inst;
struct sysctl_ctx_list ch_sysctl_ctx;
+ u_int ch_stat_send_nreq;
} __aligned(CACHE_LINE_SIZE);
#define VMBUS_CHAN_ISPRIMARY(chan) ((chan)->ch_subidx == 0)
Index: sys/dev/hyperv/vmbus/vmbus_reg.h
===================================================================
--- sys/dev/hyperv/vmbus/vmbus_reg.h
+++ sys/dev/hyperv/vmbus/vmbus_reg.h
@@ -171,6 +171,10 @@
struct vmbus_gpa_range cp_range[];
} __packed;
+#define MAX_SIZE_BUFRING_ITEM(GPA_PAGE_CNT, SRB_SIZE) \
+ (roundup2(__offsetof(struct vmbus_chanpkt_prplist, \
+ cp_range[0].gpa_page[GPA_PAGE_CNT]) + SRB_SIZE, \
+ VMBUS_CHANPKT_SIZE_ALIGN) + sizeof(uint64_t))
/*
* Channel messages
* - Embedded in vmbus_message.msg_data, e.g. response and notification.
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, May 19, 6:24 PM (1 h, 13 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33324911
Default Alt Text
D7622.id19615.diff (11 KB)
Attached To
Mode
D7622: hyperv/storvsc: tune storage performance by changing io max and channel selection
Attached
Detach File
Event Timeline
Log In to Comment