Re: [PATCH 1/3] iscsi-target: Convert iscsi_thread_set usage to kthread.h
On 3/21/2015 8:16 AM, Nicholas A. Bellinger wrote: From: Nicholas Bellinger n...@linux-iscsi.org This patch converts iscsi-target code to use modern kthread.h API callers for creating RX/TX threads for each new iscsi_conn descriptor, and releasing associated RX/TX threads during connection shutdown. This is done using iscsit_start_kthreads() - kthread_run() to start new kthreads from within iscsi_post_login_handler(), and invoking kthread_stop() from existing iscsit_close_connection() code. Also, convert iscsit_logout_post_handler_closesession() code to use cmpxchg when determing when iscsit_cause_connection_reinstatement() needs to sleep waiting for completion. I'll run some tests with this. two comments below. Reported-by: Sagi Grimberg sa...@mellanox.com Cc: Sagi Grimberg sa...@mellanox.com Cc: Slava Shwartsman valyush...@gmail.com Signed-off-by: Nicholas Bellinger n...@linux-iscsi.org --- drivers/target/iscsi/iscsi_target.c | 106 +- drivers/target/iscsi/iscsi_target_erl0.c | 13 ++-- drivers/target/iscsi/iscsi_target_login.c | 59 +++-- include/target/iscsi/iscsi_target_core.h | 7 ++ 4 files changed, 116 insertions(+), 69 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 2accb6e..cb97b59 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -537,7 +537,7 @@ static struct iscsit_transport iscsi_target_transport = { static int __init iscsi_target_init_module(void) { - int ret = 0; + int ret = 0, size; pr_debug(iSCSI-Target ISCSIT_VERSION\n); @@ -546,6 +546,7 @@ static int __init iscsi_target_init_module(void) pr_err(Unable to allocate memory for iscsit_global\n); return -1; } + spin_lock_init(iscsit_global-ts_bitmap_lock); mutex_init(auth_id_lock); spin_lock_init(sess_idr_lock); idr_init(tiqn_idr); @@ -555,15 +556,11 @@ static int __init iscsi_target_init_module(void) if (ret 0) goto out; - ret = iscsi_thread_set_init(); - if (ret 0) + size = BITS_TO_LONGS(ISCSIT_BITMAP_BITS) * sizeof(long); + iscsit_global-ts_bitmap = vzalloc(size); + if (!iscsit_global-ts_bitmap) { + pr_err(Unable to allocate iscsit_global-ts_bitmap\n); goto configfs_out; - - if (iscsi_allocate_thread_sets(TARGET_THREAD_SET_COUNT) != - TARGET_THREAD_SET_COUNT) { - pr_err(iscsi_allocate_thread_sets() returned -unexpected value!\n); - goto ts_out1; } lio_qr_cache = kmem_cache_create(lio_qr_cache, @@ -572,7 +569,7 @@ static int __init iscsi_target_init_module(void) if (!lio_qr_cache) { pr_err(nable to kmem_cache_create() for lio_qr_cache\n); - goto ts_out2; + goto bitmap_out; } lio_dr_cache = kmem_cache_create(lio_dr_cache, @@ -617,10 +614,8 @@ dr_out: kmem_cache_destroy(lio_dr_cache); qr_out: kmem_cache_destroy(lio_qr_cache); -ts_out2: - iscsi_deallocate_thread_sets(); -ts_out1: - iscsi_thread_set_free(); +bitmap_out: + vfree(iscsit_global-ts_bitmap); configfs_out: iscsi_target_deregister_configfs(); out: @@ -630,8 +625,6 @@ out: static void __exit iscsi_target_cleanup_module(void) { - iscsi_deallocate_thread_sets(); - iscsi_thread_set_free(); iscsit_release_discovery_tpg(); iscsit_unregister_transport(iscsi_target_transport); kmem_cache_destroy(lio_qr_cache); @@ -641,6 +634,7 @@ static void __exit iscsi_target_cleanup_module(void) iscsi_target_deregister_configfs(); + vfree(iscsit_global-ts_bitmap); kfree(iscsit_global); } @@ -3710,17 +3704,16 @@ static int iscsit_send_reject( void iscsit_thread_get_cpumask(struct iscsi_conn *conn) { - struct iscsi_thread_set *ts = conn-thread_set; int ord, cpu; /* -* thread_id is assigned from iscsit_global-ts_bitmap from -* within iscsi_thread_set.c:iscsi_allocate_thread_sets() +* bitmap_id is assigned from iscsit_global-ts_bitmap from +* within iscsit_start_kthreads() * -* Here we use thread_id to determine which CPU that this -* iSCSI connection's iscsi_thread_set will be scheduled to +* Here we use bitmap_id to determine which CPU that this +* iSCSI connection's RX/TX threads will be scheduled to * execute upon. */ - ord = ts-thread_id % cpumask_weight(cpu_online_mask); + ord = conn-bitmap_id % cpumask_weight(cpu_online_mask); for_each_online_cpu(cpu) { if (ord-- == 0) { cpumask_set_cpu(cpu, conn-conn_cpumask); @@ -3909,7 +3902,7 @@ check_rsp_state: switch
Re: BUG: SCSI aic7xxx driver and AMD IOMMU
Hi Mark, On Tue, Mar 03, 2015 at 02:36:19PM -0500, Mark Hounschell wrote: It looks like this problem is NOT a bug with the SCSI aic7xxx driver after all. I can duplicate this BUG very easily with other hardware. Simply removing a driver module (whether it its self, has actually used any of the DMA API or not) that is sitting on the same pci bus as a card that is actually using DMA will cause this. And that card that is in use and using DMA will no longer function. It looks and feels like unloading a module causes the IOMMU to improperly unmap valid mappings. You are right, I looked into the code and found the problem. I'll post a fix for testing this week. Joerg -- To unsubscribe from this list: send the line unsubscribe linux-scsi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
laina
hyvää päivää Nämä ovat Skipton Financial Services, tänään tarjoamme lainoja korolla 3%, meidän tyyppinen laina ovat: - yritysten lainoja, sisäisiä lainoja yksityishenkilöille lainat ja perhe lainoja. Jos olet kiinnostunut meidän Laina tarjous Täytä alla oleva lomake. Lainanottajien täydellinen nimi: Määrä tarvitaan Laina: Lainan tarkoitus: Laina Kesto: Puhelin: sukupuoli: Odotamme nopeaa vastausta, jos tarvitset taloudellista tukea. E-mail: tru-skipton_serv...@hotmail.com skiptonfin_servi...@hotmail.com Kiitos, Toteuta rahoitustarpeet on tavoitteemme! Rebecca allso __ As informações existentes nessa mensagem e nos arquivos anexados são para uso restrito, sendo seu sigilo protegido por lei. Caso não seja destinatário, saiba que leitura, divulgação ou cópia são proibidas. Favor apagar as informações e notificar o remetente. O uso impróprio será tratado conforme as normas da empresa e a legislação em vigor.
Re: iSCSI regression with linux 3.9 and 4.0
On Mon, 2015-03-23 at 09:53 +0100, Christian Hesse wrote: I reverted these two commits: commit 3a9794d32984b67a6d8992226918618f0e51e5d5 Author: Brian King brk...@linux.vnet.ibm.com Date: Thu Jan 29 15:54:40 2015 -0600 sd: Fix max transfer length for 4k disks commit bcdb247c6b6a1f3e72b9b787b73f47dd509d17ec Author: Martin K. Petersen martin.peter...@oracle.com Date: Tue Jun 3 18:45:51 2014 -0400 sd: Limit transfer length iSCSI device still fails, max_sectors_kb is still set to 32767. Looks like there is another change that introduced the regression. OK, as Mike Christie suggested, see if you can get a wireshark/tcpdump trace with both the 3.18 (working) and 3.19 (failing) kernels. -Ewan -- To unsubscribe from this list: send the line unsubscribe linux-scsi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 5/7] scsi: storvsc: Fix a bug in copy_from_bounce_buffer()
We may exit this function without properly freeing up the maapings we may have acquired. Fix the bug. Signed-off-by: K. Y. Srinivasan k...@microsoft.com Cc: sta...@vger.kernel.org --- drivers/scsi/storvsc_drv.c | 15 --- 1 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 5c13eec..88f5d79 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -754,21 +754,22 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl, if (bounce_sgl[j].length == PAGE_SIZE) { /* full..move to next entry */ sg_kunmap_atomic(bounce_addr); + bounce_addr = 0; j++; + } - /* if we need to use another bounce buffer */ - if (srclen || i != orig_sgl_count - 1) - bounce_addr = sg_kmap_atomic(bounce_sgl,j); + /* if we need to use another bounce buffer */ + if (srclen bounce_addr == 0) + bounce_addr = sg_kmap_atomic(bounce_sgl, j); - } else if (srclen == 0 i == orig_sgl_count - 1) { - /* unmap the last bounce that is PAGE_SIZE */ - sg_kunmap_atomic(bounce_addr); - } } sg_kunmap_atomic(src_addr - orig_sgl[i].offset); } + if (bounce_addr) + sg_kunmap_atomic(bounce_addr); + local_irq_restore(flags); return total_copied; -- 1.7.4.1 -- To unsubscribe from this list: send the line unsubscribe linux-scsi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH RESEND 1/7] scsi: storvsc: Increase the ring buffer size
Increase the default ring buffer size as this can significantly improve performance especially on high latency storage back-ends. Signed-off-by: K. Y. Srinivasan k...@microsoft.com Reviewed-by: Long Li lon...@microsoft.com --- drivers/scsi/storvsc_drv.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index efc6e44..27fe850 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -308,7 +308,7 @@ enum storvsc_request_type { * This is the end of Protocol specific defines. */ -static int storvsc_ringbuffer_size = (20 * PAGE_SIZE); +static int storvsc_ringbuffer_size = (256 * PAGE_SIZE); module_param(storvsc_ringbuffer_size, int, S_IRUGO); MODULE_PARM_DESC(storvsc_ringbuffer_size, Ring buffer size (bytes)); -- 1.7.4.1 -- To unsubscribe from this list: send the line unsubscribe linux-scsi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH RESEND 4/7] scsi: storvsc: Retrieve information about the capability of the target
The storage protocol informs the guest of the I/O capabilities of the storage stack. Retrieve this information and use it in the guest. Signed-off-by: K. Y. Srinivasan k...@microsoft.com Reviewed-by: Long Li lon...@microsoft.com --- drivers/scsi/storvsc_drv.c |6 ++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index be8f12e..5c13eec 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -377,6 +377,10 @@ struct storvsc_device { unsigned char path_id; unsigned char target_id; + /* +* Max I/O, the device can support. +*/ + u32 max_transfer_bytes; /* Used for vsc/vsp channel reset process */ struct storvsc_cmd_request init_request; struct storvsc_cmd_request reset_request; @@ -974,6 +978,8 @@ static int storvsc_channel_init(struct hv_device *device) STORAGE_CHANNEL_SUPPORTS_MULTI_CHANNEL) process_sub_channels = true; } + stor_device-max_transfer_bytes = + vstor_packet-storage_channel_properties.max_transfer_bytes; memset(vstor_packet, 0, sizeof(struct vstor_packet)); vstor_packet-operation = VSTOR_OPERATION_END_INITIALIZATION; -- 1.7.4.1 -- To unsubscribe from this list: send the line unsubscribe linux-scsi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/7] scsi: storvsc: Miscellaneous enhancements and fixes
This patch-set addresses perf issues discovered on the Azure storage stack. These patches also fix a couple of bugs. K. Y. Srinivasan (7): scsi: storvsc: Increase the ring buffer size scsi: storvsc: Size the queue depth based on the ringbuffer size scsi: storvsc: Always send on the selected outgoing channel scsi: storvsc: Retrieve information about the capability of the target scsi: storvsc: Fix a bug in copy_from_bounce_buffer() scsi: storvsc: Don't assume that the scatterlist is not chained scsi: storvsc: Set the tablesize based on the information given by the host drivers/scsi/storvsc_drv.c | 231 1 files changed, 149 insertions(+), 82 deletions(-) -- 1.7.4.1 -- To unsubscribe from this list: send the line unsubscribe linux-scsi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 6/7] scsi: storvsc: Don't assume that the scatterlist is not chained
The current code assumes that the scatterlists presented are not chained. Fix the code to not make this assumption. Signed-off-by: K. Y. Srinivasan k...@microsoft.com --- drivers/scsi/storvsc_drv.c | 98 +-- 1 files changed, 57 insertions(+), 41 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 88f5d79..a599677 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -626,19 +626,6 @@ cleanup: return NULL; } -/* Disgusting wrapper functions */ -static inline unsigned long sg_kmap_atomic(struct scatterlist *sgl, int idx) -{ - void *addr = kmap_atomic(sg_page(sgl + idx)); - return (unsigned long)addr; -} - -static inline void sg_kunmap_atomic(unsigned long addr) -{ - kunmap_atomic((void *)addr); -} - - /* Assume the original sgl has enough room */ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl, struct scatterlist *bounce_sgl, @@ -653,32 +640,39 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl, unsigned long bounce_addr = 0; unsigned long dest_addr = 0; unsigned long flags; + struct scatterlist *cur_dest_sgl; + struct scatterlist *cur_src_sgl; local_irq_save(flags); - + cur_dest_sgl = orig_sgl; + cur_src_sgl = bounce_sgl; for (i = 0; i orig_sgl_count; i++) { - dest_addr = sg_kmap_atomic(orig_sgl,i) + orig_sgl[i].offset; + dest_addr = (unsigned long) + kmap_atomic(sg_page(cur_dest_sgl)) + + cur_dest_sgl-offset; dest = dest_addr; destlen = orig_sgl[i].length; + destlen = cur_dest_sgl-length; if (bounce_addr == 0) - bounce_addr = sg_kmap_atomic(bounce_sgl,j); + bounce_addr = (unsigned long)kmap_atomic( + sg_page(cur_src_sgl)); while (destlen) { - src = bounce_addr + bounce_sgl[j].offset; - srclen = bounce_sgl[j].length - bounce_sgl[j].offset; + src = bounce_addr + cur_src_sgl-offset; + srclen = cur_src_sgl-length - cur_src_sgl-offset; copylen = min(srclen, destlen); memcpy((void *)dest, (void *)src, copylen); total_copied += copylen; - bounce_sgl[j].offset += copylen; + cur_src_sgl-offset += copylen; destlen -= copylen; dest += copylen; - if (bounce_sgl[j].offset == bounce_sgl[j].length) { + if (cur_src_sgl-offset == cur_src_sgl-length) { /* full */ - sg_kunmap_atomic(bounce_addr); + kunmap_atomic((void *)bounce_addr); j++; /* @@ -692,21 +686,27 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl, /* * We are done; cleanup and return. */ - sg_kunmap_atomic(dest_addr - orig_sgl[i].offset); + kunmap_atomic((void *)(dest_addr - + cur_dest_sgl-offset)); local_irq_restore(flags); return total_copied; } /* if we need to use another bounce buffer */ - if (destlen || i != orig_sgl_count - 1) - bounce_addr = sg_kmap_atomic(bounce_sgl,j); + if (destlen || i != orig_sgl_count - 1) { + cur_src_sgl = sg_next(cur_src_sgl); + bounce_addr = (unsigned long) + kmap_atomic( + sg_page(cur_src_sgl)); + } } else if (destlen == 0 i == orig_sgl_count - 1) { /* unmap the last bounce that is PAGE_SIZE */ - sg_kunmap_atomic(bounce_addr); + kunmap_atomic((void *)bounce_addr); } } - sg_kunmap_atomic(dest_addr - orig_sgl[i].offset); + kunmap_atomic((void *)(dest_addr - cur_dest_sgl-offset)); + cur_dest_sgl =
[PATCH RESEND 2/7] scsi: storvsc: Size the queue depth based on the ringbuffer size
Size the queue depth based on the ringbuffer size. Also accomodate for the fact that we could have multiple channels (ringbuffers) per adaptor. Signed-off-by: K. Y. Srinivasan k...@microsoft.com Reviewed-by: Long Li lon...@microsoft.com --- drivers/scsi/storvsc_drv.c | 27 --- 1 files changed, 16 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 27fe850..5a12897 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -309,10 +309,15 @@ enum storvsc_request_type { */ static int storvsc_ringbuffer_size = (256 * PAGE_SIZE); +static u32 max_outstanding_req_per_channel; + +static int storvsc_vcpus_per_sub_channel = 4; module_param(storvsc_ringbuffer_size, int, S_IRUGO); MODULE_PARM_DESC(storvsc_ringbuffer_size, Ring buffer size (bytes)); +module_param(storvsc_vcpus_per_sub_channel, int, S_IRUGO); +MODULE_PARM_DESC(vcpus_per_sub_channel, Ratio of VCPUs to subchannels); /* * Timeout in seconds for all devices managed by this driver. */ @@ -320,7 +325,6 @@ static int storvsc_timeout = 180; static int msft_blist_flags = BLIST_TRY_VPD_PAGES; -#define STORVSC_MAX_IO_REQUESTS200 static void storvsc_on_channel_callback(void *context); @@ -1376,7 +1380,6 @@ static int storvsc_do_io(struct hv_device *device, static int storvsc_device_configure(struct scsi_device *sdevice) { - scsi_change_queue_depth(sdevice, STORVSC_MAX_IO_REQUESTS); blk_queue_max_segment_size(sdevice-request_queue, PAGE_SIZE); @@ -1646,7 +1649,6 @@ static struct scsi_host_template scsi_driver = { .eh_timed_out = storvsc_eh_timed_out, .slave_configure = storvsc_device_configure, .cmd_per_lun = 255, - .can_queue =STORVSC_MAX_IO_REQUESTS*STORVSC_MAX_TARGETS, .this_id = -1, /* no use setting to 0 since ll_blk_rw reset it to 1 */ /* currently 32 */ @@ -1686,6 +1688,7 @@ static int storvsc_probe(struct hv_device *device, const struct hv_vmbus_device_id *dev_id) { int ret; + int num_cpus = num_online_cpus(); struct Scsi_Host *host; struct hv_host_device *host_dev; bool dev_is_ide = ((dev_id-driver_data == IDE_GUID) ? true : false); @@ -1694,6 +1697,7 @@ static int storvsc_probe(struct hv_device *device, int max_luns_per_target; int max_targets; int max_channels; + int max_sub_channels = 0; /* * Based on the windows host we are running on, @@ -1719,12 +1723,18 @@ static int storvsc_probe(struct hv_device *device, max_luns_per_target = STORVSC_MAX_LUNS_PER_TARGET; max_targets = STORVSC_MAX_TARGETS; max_channels = STORVSC_MAX_CHANNELS; + /* +* On Windows8 and above, we support sub-channels for storage. +* The number of sub-channels offerred is based on the number of +* VCPUs in the guest. +*/ + max_sub_channels = (num_cpus / storvsc_vcpus_per_sub_channel); break; } - if (dev_id-driver_data == SFC_GUID) - scsi_driver.can_queue = (STORVSC_MAX_IO_REQUESTS * -STORVSC_FC_MAX_TARGETS); + scsi_driver.can_queue = (max_outstanding_req_per_channel * +max_sub_channels + 1); + host = scsi_host_alloc(scsi_driver, sizeof(struct hv_host_device)); if (!host) @@ -1837,7 +1847,6 @@ static struct hv_driver storvsc_drv = { static int __init storvsc_drv_init(void) { - u32 max_outstanding_req_per_channel; /* * Divide the ring buffer data size (which is 1 page less @@ -1852,10 +1861,6 @@ static int __init storvsc_drv_init(void) vmscsi_size_delta, sizeof(u64))); - if (max_outstanding_req_per_channel - STORVSC_MAX_IO_REQUESTS) - return -EINVAL; - return vmbus_driver_register(storvsc_drv); } -- 1.7.4.1 -- To unsubscribe from this list: send the line unsubscribe linux-scsi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 7/7] scsi: storvsc: Set the tablesize based on the information given by the host
Set the tablesize based on the information given by the host. Signed-off-by: K. Y. Srinivasan k...@microsoft.com Reviewed-by: Long Li lon...@microsoft.com --- v2: Rebase the code and enable clustering drivers/scsi/storvsc_drv.c | 89 +++ 1 files changed, 64 insertions(+), 25 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index a599677..71871f2 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -351,7 +351,10 @@ struct storvsc_cmd_request { /* Synchronize the request/response if needed */ struct completion wait_event; - struct hv_multipage_buffer data_buffer; + struct vmbus_channel_packet_multipage_buffer mpb; + struct vmbus_packet_mpb_array *payload; + u32 payload_sz; + struct vstor_packet vstor_packet; }; @@ -1133,10 +1136,14 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request) sense_hdr.ascq); scsi_set_resid(scmnd, - cmd_request-data_buffer.len - + cmd_request-payload-range.len - vm_srb-data_transfer_length); scmnd-scsi_done(scmnd); + + if (cmd_request-payload_sz + sizeof(struct vmbus_channel_packet_multipage_buffer)) + kfree(cmd_request-payload); } static void storvsc_on_io_completion(struct hv_device *device, @@ -1338,7 +1345,7 @@ static int storvsc_dev_remove(struct hv_device *device) } static int storvsc_do_io(struct hv_device *device, - struct storvsc_cmd_request *request) +struct storvsc_cmd_request *request) { struct storvsc_device *stor_device; struct vstor_packet *vstor_packet; @@ -1370,13 +1377,14 @@ static int storvsc_do_io(struct hv_device *device, vstor_packet-vm_srb.data_transfer_length = - request-data_buffer.len; + request-payload-range.len; vstor_packet-operation = VSTOR_OPERATION_EXECUTE_SRB; - if (request-data_buffer.len) { - ret = vmbus_sendpacket_multipagebuffer(outgoing_channel, - request-data_buffer, + if (request-payload-range.len) { + + ret = vmbus_sendpacket_mpb_desc(outgoing_channel, + request-payload, request-payload_sz, vstor_packet, (sizeof(struct vstor_packet) - vmscsi_size_delta), @@ -1550,6 +1558,10 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) unsigned int sg_count = 0; struct vmscsi_request *vm_srb; struct scatterlist *cur_sgl; + struct vmbus_packet_mpb_array *payload; + u32 payload_sz; + u32 pfn_cnt; + u32 length; if (vmstor_current_major = VMSTOR_WIN8_MAJOR) { /* @@ -1603,48 +1615,72 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) memcpy(vm_srb-cdb, scmnd-cmnd, vm_srb-cdb_length); - cmd_request-data_buffer.len = scsi_bufflen(scmnd); - if (scsi_sg_count(scmnd)) { - sgl = (struct scatterlist *)scsi_sglist(scmnd); - sg_count = scsi_sg_count(scmnd); + sgl = (struct scatterlist *)scsi_sglist(scmnd); + sg_count = scsi_sg_count(scmnd); + length = scsi_bufflen(scmnd); + payload = (struct vmbus_packet_mpb_array *)cmd_request-mpb; + payload_sz = sizeof(cmd_request-mpb); + + if (sg_count) { /* check if we need to bounce the sgl */ if (do_bounce_buffer(sgl, scsi_sg_count(scmnd)) != -1) { cmd_request-bounce_sgl = - create_bounce_buffer(sgl, scsi_sg_count(scmnd), -scsi_bufflen(scmnd), + create_bounce_buffer(sgl, sg_count, +length, vm_srb-data_in); if (!cmd_request-bounce_sgl) return SCSI_MLQUEUE_HOST_BUSY; cmd_request-bounce_sgl_count = - ALIGN(scsi_bufflen(scmnd), PAGE_SIZE) - PAGE_SHIFT; + ALIGN(length, PAGE_SIZE) PAGE_SHIFT; if (vm_srb-data_in == WRITE_TYPE) copy_to_bounce_buffer(sgl, - cmd_request-bounce_sgl, - scsi_sg_count(scmnd)); + cmd_request-bounce_sgl, sg_count); sgl = cmd_request-bounce_sgl; sg_count = cmd_request-bounce_sgl_count;
[PATCH RESEND 3/7] scsi: storvsc: Always send on the selected outgoing channel
The current code always sent packets without data on the primary channel. Properly distribute sending of packets with no data amongst all available channels. I would like to thank Long Li for noticing this problem. Signed-off-by: K. Y. Srinivasan k...@microsoft.com Reviewed-by: Long Li lon...@microsoft.com --- drivers/scsi/storvsc_drv.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 5a12897..be8f12e 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1362,7 +1362,7 @@ static int storvsc_do_io(struct hv_device *device, vmscsi_size_delta), (unsigned long)request); } else { - ret = vmbus_sendpacket(device-channel, vstor_packet, + ret = vmbus_sendpacket(outgoing_channel, vstor_packet, (sizeof(struct vstor_packet) - vmscsi_size_delta), (unsigned long)request, -- 1.7.4.1 -- To unsubscribe from this list: send the line unsubscribe linux-scsi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] [RESEND] aic7xxx: replace kmalloc/memset by kzalloc
On 03/22/2015 05:31 PM, Michael Opdenacker wrote: This replaces kmalloc + memset by a call to kzalloc (or kcalloc when appropriate, which zeroes memory too) This also fixes one checkpatch.pl issue in the process. This improvement was suggested by make coccicheck Signed-off-by: Michael Opdenacker michael.opdenac...@free-electrons.com Reviewed-by: Hannes Reinecke h...@suse.de Cheers, Hannes -- Dr. Hannes ReineckezSeries Storage h...@suse.de +49 911 74053 688 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton HRB 21284 (AG Nürnberg) -- To unsubscribe from this list: send the line unsubscribe linux-scsi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: iSCSI regression with linux 3.9 and 4.0
Christian Hesse l...@eworm.de on Fri, 2015/03/20 18:59: Ewan Milne emi...@redhat.com on Fri, 2015/03/20 11:46: On Fri, 2015-03-20 at 16:24 +0100, Christian Hesse wrote: I found 'max_sectors_kb' which is inside in directory called 'queue'. Is that the value you asked for? for 4.0 git: # cat max_sectors_kb 32767 If you change max_sectors_kb to a lower value (e.g. 512) can you get the device to work? I will check that on monday. Sitting behind a slow dial up connection right now... No, it still fails the same way. After the error it is back to a value of 32767. Is this because of a tried reconnect? -- Best regards, Chris pgpDNJ3DKoSCU.pgp Description: OpenPGP digital signature
RE: [PATCH 5/7] scsi: storvsc: Fix a bug in copy_from_bounce_buffer()
-Original Message- From: devel [mailto:driverdev-devel-boun...@linuxdriverproject.org] On Behalf Of K. Y. Srinivasan Sent: Monday, March 23, 2015 2:07 PM To: gre...@linuxfoundation.org; linux-ker...@vger.kernel.org; de...@linuxdriverproject.org; oher...@suse.com; jbottom...@parallels.com; h...@infradead.org; linux-scsi@vger.kernel.org; a...@canonical.com; vkuzn...@redhat.com; jasow...@redhat.com Cc: sta...@vger.kernel.org Subject: [PATCH 5/7] scsi: storvsc: Fix a bug in copy_from_bounce_buffer() We may exit this function without properly freeing up the maapings we may have acquired. Fix the bug. Signed-off-by: K. Y. Srinivasan k...@microsoft.com Reviewed-by: Long Li lon...@microsoft.com Cc: sta...@vger.kernel.org --- drivers/scsi/storvsc_drv.c | 15 --- 1 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 5c13eec..88f5d79 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -754,21 +754,22 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl, if (bounce_sgl[j].length == PAGE_SIZE) { /* full..move to next entry */ sg_kunmap_atomic(bounce_addr); + bounce_addr = 0; j++; + } - /* if we need to use another bounce buffer */ - if (srclen || i != orig_sgl_count - 1) - bounce_addr = sg_kmap_atomic(bounce_sgl,j); + /* if we need to use another bounce buffer */ + if (srclen bounce_addr == 0) + bounce_addr = sg_kmap_atomic(bounce_sgl, j); - } else if (srclen == 0 i == orig_sgl_count - 1) { - /* unmap the last bounce that is PAGE_SIZE */ - sg_kunmap_atomic(bounce_addr); - } } sg_kunmap_atomic(src_addr - orig_sgl[i].offset); } + if (bounce_addr) + sg_kunmap_atomic(bounce_addr); + local_irq_restore(flags); return total_copied; -- 1.7.4.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel -- To unsubscribe from this list: send the line unsubscribe linux-scsi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH 6/7] scsi: storvsc: Don't assume that the scatterlist is not chained
-Original Message- From: devel [mailto:driverdev-devel-boun...@linuxdriverproject.org] On Behalf Of K. Y. Srinivasan Sent: Monday, March 23, 2015 2:07 PM To: gre...@linuxfoundation.org; linux-ker...@vger.kernel.org; de...@linuxdriverproject.org; oher...@suse.com; jbottom...@parallels.com; h...@infradead.org; linux-scsi@vger.kernel.org; a...@canonical.com; vkuzn...@redhat.com; jasow...@redhat.com Subject: [PATCH 6/7] scsi: storvsc: Don't assume that the scatterlist is not chained The current code assumes that the scatterlists presented are not chained. Fix the code to not make this assumption. Signed-off-by: K. Y. Srinivasan k...@microsoft.com Reviewed-by: Long Li lon...@microsoft.com --- drivers/scsi/storvsc_drv.c | 98 +-- 1 files changed, 57 insertions(+), 41 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 88f5d79..a599677 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -626,19 +626,6 @@ cleanup: return NULL; } -/* Disgusting wrapper functions */ -static inline unsigned long sg_kmap_atomic(struct scatterlist *sgl, int idx) -{ - void *addr = kmap_atomic(sg_page(sgl + idx)); - return (unsigned long)addr; -} - -static inline void sg_kunmap_atomic(unsigned long addr) -{ - kunmap_atomic((void *)addr); -} - - /* Assume the original sgl has enough room */ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl, struct scatterlist *bounce_sgl, @@ - 653,32 +640,39 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl, unsigned long bounce_addr = 0; unsigned long dest_addr = 0; unsigned long flags; + struct scatterlist *cur_dest_sgl; + struct scatterlist *cur_src_sgl; local_irq_save(flags); - + cur_dest_sgl = orig_sgl; + cur_src_sgl = bounce_sgl; for (i = 0; i orig_sgl_count; i++) { - dest_addr = sg_kmap_atomic(orig_sgl,i) + orig_sgl[i].offset; + dest_addr = (unsigned long) + kmap_atomic(sg_page(cur_dest_sgl)) + + cur_dest_sgl-offset; dest = dest_addr; destlen = orig_sgl[i].length; + destlen = cur_dest_sgl-length; if (bounce_addr == 0) - bounce_addr = sg_kmap_atomic(bounce_sgl,j); + bounce_addr = (unsigned long)kmap_atomic( + sg_page(cur_src_sgl)); while (destlen) { - src = bounce_addr + bounce_sgl[j].offset; - srclen = bounce_sgl[j].length - bounce_sgl[j].offset; + src = bounce_addr + cur_src_sgl-offset; + srclen = cur_src_sgl-length - cur_src_sgl-offset; copylen = min(srclen, destlen); memcpy((void *)dest, (void *)src, copylen); total_copied += copylen; - bounce_sgl[j].offset += copylen; + cur_src_sgl-offset += copylen; destlen -= copylen; dest += copylen; - if (bounce_sgl[j].offset == bounce_sgl[j].length) { + if (cur_src_sgl-offset == cur_src_sgl-length) { /* full */ - sg_kunmap_atomic(bounce_addr); + kunmap_atomic((void *)bounce_addr); j++; /* @@ -692,21 +686,27 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl, /* * We are done; cleanup and return. */ - sg_kunmap_atomic(dest_addr - orig_sgl[i].offset); + kunmap_atomic((void *)(dest_addr - + cur_dest_sgl-offset)); local_irq_restore(flags); return total_copied; } /* if we need to use another bounce buffer */ - if (destlen || i != orig_sgl_count - 1) - bounce_addr = sg_kmap_atomic(bounce_sgl,j); + if (destlen || i != orig_sgl_count - 1) { + cur_src_sgl = sg_next(cur_src_sgl); + bounce_addr = (unsigned long) + kmap_atomic( + sg_page(cur_src_sgl)); + }
Re: [PATCH v3 37/42] hpsa: use block layer tag for command allocation
On 03/17/2015 09:06 PM, Don Brace wrote: From: Webb Scales web...@hp.com Rework slave allocation: - separate the tagging support setup from the hostdata setup - make the hostdata setup act consistently when the lookup fails - make the hostdata setup act consistently when the device is not added - set up the queue depth consistently across these scenarios - if the block layer mq support is not available, explicitly enable and activate the SCSI layer tcq support (and do this at allocation-time so that the tags will be available for INQUIRY commands) Tweak slave configuration so that devices which are masked are also not attached. Reviewed-by: Scott Teel scott.t...@pmcs.com Reviewed-by: Kevin Barnett kevin.barn...@pmcs.com Signed-off-by: Webb Scales web...@hp.com Signed-off-by: Don Brace don.br...@pmcs.com --- drivers/scsi/hpsa.c | 153 +-- drivers/scsi/hpsa.h |1 2 files changed, 123 insertions(+), 31 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 34c178c..4e34a62 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -44,6 +44,7 @@ #include scsi/scsi_host.h #include scsi/scsi_tcq.h #include scsi/scsi_eh.h +#include scsi/scsi_dbg.h #include linux/cciss_ioctl.h #include linux/string.h #include linux/bitmap.h @@ -212,6 +213,9 @@ static int hpsa_compat_ioctl(struct scsi_device *dev, int cmd, static void cmd_free(struct ctlr_info *h, struct CommandList *c); static struct CommandList *cmd_alloc(struct ctlr_info *h); +static void cmd_tagged_free(struct ctlr_info *h, struct CommandList *c); +static struct CommandList *cmd_tagged_alloc(struct ctlr_info *h, + struct scsi_cmnd *scmd); static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h, void *buff, size_t size, u16 page_code, unsigned char *scsi3addr, int cmd_type); @@ -2047,11 +2051,17 @@ static void hpsa_cmd_resolve_events(struct ctlr_info *h, } } +static void hpsa_cmd_resolve_and_free(struct ctlr_info *h, + struct CommandList *c) +{ + hpsa_cmd_resolve_events(h, c); + cmd_tagged_free(h, c); +} + static void hpsa_cmd_free_and_done(struct ctlr_info *h, struct CommandList *c, struct scsi_cmnd *cmd) { - hpsa_cmd_resolve_events(h, c); - cmd_free(h, c); + hpsa_cmd_resolve_and_free(h, c); cmd-scsi_done(cmd); } @@ -2072,8 +2082,7 @@ static void hpsa_cmd_abort_and_free(struct ctlr_info *h, struct CommandList *c, hpsa_set_scsi_cmd_aborted(cmd); dev_warn(h-pdev-dev, CDB %16phN was aborted with status 0x%x\n, c-Request.CDB, c-err_info-ScsiStatus); - hpsa_cmd_resolve_events(h, c); - cmd_free(h, c); /* FIX-ME: change to cmd_tagged_free(h, c) */ + hpsa_cmd_resolve_and_free(h, c); } static void process_ioaccel2_completion(struct ctlr_info *h, @@ -4535,7 +4544,7 @@ static int hpsa_ciss_submit(struct ctlr_info *h, } if (hpsa_scatter_gather(h, c, cmd) 0) { /* Fill SG list */ - cmd_free(h, c); + hpsa_cmd_resolve_and_free(h, c); return SCSI_MLQUEUE_HOST_BUSY; } enqueue_cmd_and_start_io(h, c); @@ -4581,6 +4590,8 @@ static inline void hpsa_cmd_partial_init(struct ctlr_info *h, int index, { dma_addr_t cmd_dma_handle = h-cmd_pool_dhandle + index * sizeof(*c); + BUG_ON(c-cmdindex != index); + memset(c-Request.CDB, 0, sizeof(c-Request.CDB)); memset(c-err_info, 0, sizeof(*c-err_info)); c-busaddr = (u32) cmd_dma_handle; @@ -4675,27 +4686,24 @@ static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd) /* Get the ptr to our adapter structure out of cmd-host. */ h = sdev_to_hba(cmd-device); + + BUG_ON(cmd-request-tag 0); + dev = cmd-device-hostdata; if (!dev) { cmd-result = DID_NO_CONNECT 16; cmd-scsi_done(cmd); return 0; } - memcpy(scsi3addr, dev-scsi3addr, sizeof(scsi3addr)); - if (unlikely(lockup_detected(h))) { - cmd-result = DID_NO_CONNECT 16; - cmd-scsi_done(cmd); - return 0; - } - c = cmd_alloc(h); + memcpy(scsi3addr, dev-scsi3addr, sizeof(scsi3addr)); if (unlikely(lockup_detected(h))) { cmd-result = DID_NO_CONNECT 16; - cmd_free(h, c); cmd-scsi_done(cmd); return 0; } + c = cmd_tagged_alloc(h, cmd); /* * Call alternate submit routine for I/O accelerated commands. @@ -4708,7 +4716,7 @@ static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd) if (rc == 0) return 0; if (rc == SCSI_MLQUEUE_HOST_BUSY) { -
Re: [PATCH RESEND 2/7] scsi: storvsc: Size the queue depth based on the ringbuffer size
On Mon, Mar 23, 2015 at 2:06 PM, K. Y. Srinivasan k...@microsoft.com wrote: Size the queue depth based on the ringbuffer size. Also accomodate for the fact that we could have multiple channels (ringbuffers) per adaptor. Signed-off-by: K. Y. Srinivasan k...@microsoft.com Reviewed-by: Long Li lon...@microsoft.com --- drivers/scsi/storvsc_drv.c | 27 --- 1 files changed, 16 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 27fe850..5a12897 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -309,10 +309,15 @@ enum storvsc_request_type { */ static int storvsc_ringbuffer_size = (256 * PAGE_SIZE); +static u32 max_outstanding_req_per_channel; + +static int storvsc_vcpus_per_sub_channel = 4; module_param(storvsc_ringbuffer_size, int, S_IRUGO); MODULE_PARM_DESC(storvsc_ringbuffer_size, Ring buffer size (bytes)); +module_param(storvsc_vcpus_per_sub_channel, int, S_IRUGO); +MODULE_PARM_DESC(vcpus_per_sub_channel, Ratio of VCPUs to subchannels); /* * Timeout in seconds for all devices managed by this driver. */ @@ -320,7 +325,6 @@ static int storvsc_timeout = 180; static int msft_blist_flags = BLIST_TRY_VPD_PAGES; -#define STORVSC_MAX_IO_REQUESTS200 static void storvsc_on_channel_callback(void *context); @@ -1376,7 +1380,6 @@ static int storvsc_do_io(struct hv_device *device, static int storvsc_device_configure(struct scsi_device *sdevice) { - scsi_change_queue_depth(sdevice, STORVSC_MAX_IO_REQUESTS); blk_queue_max_segment_size(sdevice-request_queue, PAGE_SIZE); @@ -1646,7 +1649,6 @@ static struct scsi_host_template scsi_driver = { .eh_timed_out = storvsc_eh_timed_out, .slave_configure = storvsc_device_configure, .cmd_per_lun = 255, - .can_queue =STORVSC_MAX_IO_REQUESTS*STORVSC_MAX_TARGETS, .this_id = -1, /* no use setting to 0 since ll_blk_rw reset it to 1 */ /* currently 32 */ @@ -1686,6 +1688,7 @@ static int storvsc_probe(struct hv_device *device, const struct hv_vmbus_device_id *dev_id) { int ret; + int num_cpus = num_online_cpus(); struct Scsi_Host *host; struct hv_host_device *host_dev; bool dev_is_ide = ((dev_id-driver_data == IDE_GUID) ? true : false); @@ -1694,6 +1697,7 @@ static int storvsc_probe(struct hv_device *device, int max_luns_per_target; int max_targets; int max_channels; + int max_sub_channels = 0; /* * Based on the windows host we are running on, @@ -1719,12 +1723,18 @@ static int storvsc_probe(struct hv_device *device, max_luns_per_target = STORVSC_MAX_LUNS_PER_TARGET; max_targets = STORVSC_MAX_TARGETS; max_channels = STORVSC_MAX_CHANNELS; + /* +* On Windows8 and above, we support sub-channels for storage. +* The number of sub-channels offerred is based on the number of +* VCPUs in the guest. +*/ + max_sub_channels = (num_cpus / storvsc_vcpus_per_sub_channel); break; } - if (dev_id-driver_data == SFC_GUID) - scsi_driver.can_queue = (STORVSC_MAX_IO_REQUESTS * -STORVSC_FC_MAX_TARGETS); + scsi_driver.can_queue = (max_outstanding_req_per_channel * +max_sub_channels + 1); + If num_online_cpus() returned 1 - 3, can_queue will be set to 1 I think. Is that desired? host = scsi_host_alloc(scsi_driver, sizeof(struct hv_host_device)); if (!host) @@ -1837,7 +1847,6 @@ static struct hv_driver storvsc_drv = { static int __init storvsc_drv_init(void) { - u32 max_outstanding_req_per_channel; /* * Divide the ring buffer data size (which is 1 page less @@ -1852,10 +1861,6 @@ static int __init storvsc_drv_init(void) vmscsi_size_delta, sizeof(u64))); - if (max_outstanding_req_per_channel - STORVSC_MAX_IO_REQUESTS) - return -EINVAL; - return vmbus_driver_register(storvsc_drv); } -- vs; -- To unsubscribe from this list: send the line unsubscribe linux-scsi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH RESEND 2/7] scsi: storvsc: Size the queue depth based on the ringbuffer size
-Original Message- From: Venkatesh Srinivas [mailto:venkate...@google.com] Sent: Monday, March 23, 2015 5:23 PM To: KY Srinivasan Cc: gre...@linuxfoundation.org; Linux Kernel Developers List; de...@linuxdriverproject.org; oher...@suse.com; James E.J. Bottomley; Christoph Hellwig; linux-scsi@vger.kernel.org; a...@canonical.com; vkuzn...@redhat.com; jasow...@redhat.com Subject: Re: [PATCH RESEND 2/7] scsi: storvsc: Size the queue depth based on the ringbuffer size On Mon, Mar 23, 2015 at 2:06 PM, K. Y. Srinivasan k...@microsoft.com wrote: Size the queue depth based on the ringbuffer size. Also accomodate for the fact that we could have multiple channels (ringbuffers) per adaptor. Signed-off-by: K. Y. Srinivasan k...@microsoft.com Reviewed-by: Long Li lon...@microsoft.com --- drivers/scsi/storvsc_drv.c | 27 --- 1 files changed, 16 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 27fe850..5a12897 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -309,10 +309,15 @@ enum storvsc_request_type { */ static int storvsc_ringbuffer_size = (256 * PAGE_SIZE); +static u32 max_outstanding_req_per_channel; + +static int storvsc_vcpus_per_sub_channel = 4; module_param(storvsc_ringbuffer_size, int, S_IRUGO); MODULE_PARM_DESC(storvsc_ringbuffer_size, Ring buffer size (bytes)); +module_param(storvsc_vcpus_per_sub_channel, int, S_IRUGO); +MODULE_PARM_DESC(vcpus_per_sub_channel, Ratio of VCPUs to subchannels); /* * Timeout in seconds for all devices managed by this driver. */ @@ -320,7 +325,6 @@ static int storvsc_timeout = 180; static int msft_blist_flags = BLIST_TRY_VPD_PAGES; -#define STORVSC_MAX_IO_REQUESTS200 static void storvsc_on_channel_callback(void *context); @@ -1376,7 +1380,6 @@ static int storvsc_do_io(struct hv_device *device, static int storvsc_device_configure(struct scsi_device *sdevice) { - scsi_change_queue_depth(sdevice, STORVSC_MAX_IO_REQUESTS); blk_queue_max_segment_size(sdevice-request_queue, PAGE_SIZE); @@ -1646,7 +1649,6 @@ static struct scsi_host_template scsi_driver = { .eh_timed_out = storvsc_eh_timed_out, .slave_configure = storvsc_device_configure, .cmd_per_lun = 255, - .can_queue = STORVSC_MAX_IO_REQUESTS*STORVSC_MAX_TARGETS, .this_id = -1, /* no use setting to 0 since ll_blk_rw reset it to 1 */ /* currently 32 */ @@ -1686,6 +1688,7 @@ static int storvsc_probe(struct hv_device *device, const struct hv_vmbus_device_id *dev_id) { int ret; + int num_cpus = num_online_cpus(); struct Scsi_Host *host; struct hv_host_device *host_dev; bool dev_is_ide = ((dev_id-driver_data == IDE_GUID) ? true : false); @@ -1694,6 +1697,7 @@ static int storvsc_probe(struct hv_device *device, int max_luns_per_target; int max_targets; int max_channels; + int max_sub_channels = 0; /* * Based on the windows host we are running on, @@ -1719,12 +1723,18 @@ static int storvsc_probe(struct hv_device *device, max_luns_per_target = STORVSC_MAX_LUNS_PER_TARGET; max_targets = STORVSC_MAX_TARGETS; max_channels = STORVSC_MAX_CHANNELS; + /* +* On Windows8 and above, we support sub-channels for storage. +* The number of sub-channels offerred is based on the number of +* VCPUs in the guest. +*/ + max_sub_channels = (num_cpus / storvsc_vcpus_per_sub_channel); break; } - if (dev_id-driver_data == SFC_GUID) - scsi_driver.can_queue = (STORVSC_MAX_IO_REQUESTS * -STORVSC_FC_MAX_TARGETS); + scsi_driver.can_queue = (max_outstanding_req_per_channel * +max_sub_channels + 1); + If num_online_cpus() returned 1 - 3, can_queue will be set to 1 I think. Is that desired? can_ queue will be set max_outstanding_req_per_channel in this case. That is what is expected. We will always have the primary channel; Additionally, if the guest has more than 4 VCPUs, the host will offer Additional subchannels for each 4 VCPus in the guest. So for less than 4 VCPus in the guest, we will only have the primary channel. Regards, K. Y N�r��yb�X��ǧv�^�){.n�+{{ay�ʇڙ�,j��f���h���z��w��� ���j:+v���w�j�mzZ+�ݢj��!�i