RE: [PATCH v3 2/3] megaraid_sas : use dev_printk when possible
-Original Message- From: Bjorn Helgaas [mailto:bhelg...@google.com] Sent: Wednesday, July 08, 2015 2:23 AM To: Kashyap Desai; Uday Lingala; Sumit Saxena Cc: megaraidlinux@avagotech.com; linux-scsi@vger.kernel.org; James E.J. Bottomley; linux-ker...@vger.kernel.org; Joe Perches; Christoph Hellwig Subject: [PATCH v3 2/3] megaraid_sas : use dev_printk when possible Use dev_printk() when possible to make messages more useful. Signed-off-by: Bjorn Helgaas bhelg...@google.com --- drivers/scsi/megaraid/megaraid_sas_base.c | 304 +-- drivers/scsi/megaraid/megaraid_sas_fusion.c | 95 2 files changed, 196 insertions(+), 203 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 71b884d..a9bd592 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -216,7 +216,7 @@ struct megasas_cmd *megasas_get_cmd(struct megasas_instance struct megasas_cmd, list); list_del_init(cmd-list); } else { - printk(KERN_ERR megasas: Command pool empty!\n); + dev_err(instance-pdev-dev, Command pool empty!\n); } spin_unlock_irqrestore(instance-mfi_pool_lock, flags); @@ -370,9 +370,9 @@ megasas_adp_reset_xscale(struct megasas_instance *instance, msleep(1000); /* sleep for 3 secs */ pcidata = 0; pci_read_config_dword(instance-pdev, MFI_1068_PCSR_OFFSET, pcidata); - printk(KERN_NOTICE pcidata = %x\n, pcidata); + dev_notice(instance-pdev-dev, pcidata = %x\n, pcidata); if (pcidata 0x2) { - printk(KERN_NOTICE mfi 1068 offset read=%x\n, pcidata); + dev_notice(instance-pdev-dev, mfi 1068 offset read=%x\n, pcidata); pcidata = ~0x2; pci_write_config_dword(instance-pdev, MFI_1068_PCSR_OFFSET, pcidata); @@ -383,9 +383,9 @@ megasas_adp_reset_xscale(struct megasas_instance *instance, pcidata = 0; pci_read_config_dword(instance-pdev, MFI_1068_FW_HANDSHAKE_OFFSET, pcidata); - printk(KERN_NOTICE 1068 offset handshake read=%x\n, pcidata); + dev_notice(instance-pdev-dev, 1068 offset handshake read=%x\n, pcidata); if ((pcidata 0x) == MFI_1068_FW_READY) { - printk(KERN_NOTICE 1068 offset pcidt=%x\n, pcidata); + dev_notice(instance-pdev-dev, 1068 offset pcidt=%x\n, pcidata); pcidata = 0; pci_write_config_dword(instance-pdev, MFI_1068_FW_HANDSHAKE_OFFSET, pcidata); @@ -824,7 +824,7 @@ megasas_adp_reset_gen2(struct megasas_instance *instance, while ( !( HostDiag DIAG_WRITE_ENABLE) ) { msleep(100); HostDiag = (u32)readl(hostdiag_offset); - printk(KERN_NOTICE RESETGEN2: retry=%x, hostdiag=%x\n, + dev_notice(instance-pdev-dev, RESETGEN2: retry=%x, hostdiag=%x\n, retry, HostDiag); if (retry++ = 100) @@ -832,7 +832,7 @@ megasas_adp_reset_gen2(struct megasas_instance *instance, } - printk(KERN_NOTICE ADP_RESET_GEN2: HostDiag=%x\n, HostDiag); + dev_notice(instance-pdev-dev, ADP_RESET_GEN2: HostDiag=%x\n, HostDiag); writel((HostDiag | DIAG_RESET_ADAPTER), hostdiag_offset); @@ -842,7 +842,7 @@ megasas_adp_reset_gen2(struct megasas_instance *instance, while ( ( HostDiag DIAG_RESET_ADAPTER) ) { msleep(100); HostDiag = (u32)readl(hostdiag_offset); - printk(KERN_NOTICE RESET_GEN2: retry=%x, hostdiag=%x\n, + dev_notice(instance-pdev-dev, RESET_GEN2: retry=%x, hostdiag=%x\n, retry, HostDiag); if (retry++ = 1000) @@ -1241,7 +1241,7 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, pthru-sgl); if (pthru-sge_count instance-max_num_sge) { - printk(KERN_ERR megasas: DCDB two many SGE NUM=%x\n, + dev_err(instance-pdev-dev, DCDB too many SGE NUM=%x\n, pthru-sge_count); return 0; } @@ -1382,7 +1382,7 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, ldio-sge_count = megasas_make_sgl32(instance, scp, ldio- sgl); if (ldio-sge_count instance-max_num_sge) { - printk(KERN_ERR megasas: build_ld_io: sge_count = %x\n, + dev_err(instance-pdev-dev, build_ld_io: sge_count = %x\n, ldio-sge_count); return 0; } @@ -1449,24 +1449,24 @@ megasas_dump_pending_frames(struct megasas_instance *instance)
Re: [PATCH v3 5/5] target: Fix wrong setting of sense format for PI errors
On 7/8/2015 1:19 PM, Christoph Hellwig wrote: On Mon, Jul 06, 2015 at 04:15:08PM +0300, Sagi Grimberg wrote: PI errors should be reported in a descriptor format sense data. Fix that by adding a desc_format flag to struct sense_info and pass it to scsi_build_sense_buffer() to do the right thing. Do we really need the additional flag? We only need the descriptor sense format because we add the sector information. So just checking for that should be enough, especially when paired with a comment explaining that logic in the source file. We don't have any other information today, but sector is not the only information that is requires a descriptor format, so maybe it will be a bit awkward to condition the descriptor format on the sector info? -- 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 v3 3/3] megaraid_sas : fix whitespace errors
On 07/07/2015 10:52 PM, Bjorn Helgaas wrote: Fix whitespace and indentation errors. No code change. Signed-off-by: Bjorn Helgaas bhelg...@google.com --- drivers/scsi/megaraid/megaraid_sas_base.c | 244 ++--- 1 file changed, 118 insertions(+), 126 deletions(-) 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: [PATCH v3 5/5] target: Fix wrong setting of sense format for PI errors
On Wed, Jul 08, 2015 at 01:36:04PM +0300, Sagi Grimberg wrote: We don't have any other information today, but sector is not the only information that is requires a descriptor format, so maybe it will be a bit awkward to condition the descriptor format on the sector info? The only reason why you'd want to support descriptor type sense data is because you need to add a second descriptor. If we have another case that needs descriptor sense data it'll also need to add that additional descriptor. So we'll need a conditional for it in the sense data generation anyway. -- 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 3/5] scsi: Add 'access_state' attribute
Add an 'access_state' attribute to display the LUN access state. Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/scsi_sysfs.c | 53 ++ include/scsi/scsi_device.h | 13 include/scsi/scsi_dh.h | 1 + 3 files changed, 67 insertions(+) diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index b4de776..5f1a981 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -81,6 +81,34 @@ const char *scsi_host_state_name(enum scsi_host_state state) return name; } +static const struct { + enum scsi_access_state value; + char*name; +} sdev_access_states[] = { + { SCSI_ACCESS_STATE_UNKNOWN, unknown }, + { SCSI_ACCESS_STATE_OPTIMAL, optimal }, + { SCSI_ACCESS_STATE_ACTIVE, active }, + { SCSI_ACCESS_STATE_PASSIVE, passive }, + { SCSI_ACCESS_STATE_UNAVAILABLE, unavailable }, + { SCSI_ACCESS_STATE_LBA, lba-dependent }, + { SCSI_ACCESS_STATE_OFFLINE, offline }, + { SCSI_ACCESS_STATE_TRANSITIONING, transitioning }, + { SCSI_ACCESS_STATE_PREFERRED, preferred }, +}; +const char *scsi_access_state_name(enum scsi_access_state state) +{ + int i; + char *name = NULL; + + for (i = 0; i ARRAY_SIZE(sdev_access_states); i++) { + if (sdev_access_states[i].value == state) { + name = sdev_access_states[i].name; + break; + } + } + return name; +} + static int check_set(unsigned long long *val, char *src) { char *last; @@ -934,6 +962,30 @@ sdev_store_dh_state(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(dh_state, S_IRUGO | S_IWUSR, sdev_show_dh_state, sdev_store_dh_state); + +static ssize_t +sdev_show_access_state(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct scsi_device *sdev = to_scsi_device(dev); + enum scsi_access_state access_state = SCSI_ACCESS_STATE_UNKNOWN; + bool pref = false; + + if (sdev-handler sdev-handler-state) { + int state = sdev-handler-state(sdev); + + if (state SCSI_ACCESS_STATE_PREFERRED) + pref = true; + + access_state = (state SCSI_ACCESS_STATE_MASK); + } + + return snprintf(buf, 32, %s%s\n, + scsi_access_state_name(access_state), + pref ? preferred :); +} +static DEVICE_ATTR(access_state, S_IRUGO, sdev_show_access_state, NULL); #endif static ssize_t @@ -1007,6 +1059,7 @@ static struct attribute *scsi_sdev_attrs[] = { dev_attr_queue_type.attr, #ifdef CONFIG_SCSI_DH dev_attr_dh_state.attr, + dev_attr_access_state.attr, #endif dev_attr_queue_ramp_up_period.attr, REF_EVT(media_change), diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index d2f8b7a..4a10737 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -50,6 +50,19 @@ enum scsi_device_state { SDEV_CREATED_BLOCK, /* same as above but for created devices */ }; +enum scsi_access_state { + SCSI_ACCESS_STATE_UNKNOWN = 0, + SCSI_ACCESS_STATE_OPTIMAL, + SCSI_ACCESS_STATE_ACTIVE, + SCSI_ACCESS_STATE_PASSIVE, + SCSI_ACCESS_STATE_UNAVAILABLE, + SCSI_ACCESS_STATE_LBA, + SCSI_ACCESS_STATE_OFFLINE, + SCSI_ACCESS_STATE_TRANSITIONING, + SCSI_ACCESS_STATE_PREFERRED = 0x80 +}; +#define SCSI_ACCESS_STATE_MASK 0x7f + enum scsi_device_event { SDEV_EVT_MEDIA_CHANGE = 1,/* media has changed */ SDEV_EVT_INQUIRY_CHANGE_REPORTED, /* 3F 03 UA reported */ diff --git a/include/scsi/scsi_dh.h b/include/scsi/scsi_dh.h index 5c73062..bc1b9f0 100644 --- a/include/scsi/scsi_dh.h +++ b/include/scsi/scsi_dh.h @@ -71,6 +71,7 @@ struct scsi_device_handler { int (*prep_fn)(struct scsi_device *, struct request *); int (*set_params)(struct scsi_device *, const char *); void (*rescan)(struct scsi_device *); + int (*state)(struct scsi_device *); }; #ifdef CONFIG_SCSI_DH -- 1.8.5.2 -- 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 v3 5/5] target: Fix wrong setting of sense format for PI errors
On Wed, Jul 08, 2015 at 12:59:18PM +0200, Hannes Reinecke wrote: Actually it's controlled by the D_SENSE bit in the Control mode page (that's bit[2] of byte 2 in the control mode page). Which is currently set to '0', ie we will be returning fixed sense information. _If_ we were to report descriptor sense we will need to change that, too. Just looked over SPC, and indeed D_SENSE is a strict either fixed or descriptor, not a may return descriptor data. So this patch actually is wrong as we never must return different sense data types based on the sense code. -- 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 v3 5/5] target: Fix wrong setting of sense format for PI errors
On 7/8/2015 1:59 PM, Hannes Reinecke wrote: On 07/08/2015 12:49 PM, Christoph Hellwig wrote: On Wed, Jul 08, 2015 at 01:36:04PM +0300, Sagi Grimberg wrote: We don't have any other information today, but sector is not the only information that is requires a descriptor format, so maybe it will be a bit awkward to condition the descriptor format on the sector info? The only reason why you'd want to support descriptor type sense data is because you need to add a second descriptor. If we have another case that needs descriptor sense data it'll also need to add that additional descriptor. So we'll need a conditional for it in the sense data generation anyway. Actually it's controlled by the D_SENSE bit in the Control mode page (that's bit[2] of byte 2 in the control mode page). Which is currently set to '0', ie we will be returning fixed sense information. _If_ we were to report descriptor sense we will need to change that, too. I missed that bit. And it's actually not true that you'd need descriptor sense to encode the sector information; it'll be stored in the 'information' section (byte 3-6) for fixed format sense. But when I return the sector info in a fixed size format, the initiator is not able to decode the faulty sector: kernel: DIFv1 Type 1 reference failed on sector: 15 tag: 0xfff0 sector MSB: 0x000f kernel: sd 10:0:1:0: [sdc] tag#0 FAILED Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE kernel: sd 10:0:1:0: [sdc] tag#0 Sense Key : Aborted Command [current] kernel: sd 10:0:1:0: [sdc] tag#0 Add. Sense: No additional sense information kernel: sd 10:0:1:0: [sdc] tag#0 CDB: Read(10) 28 20 00 00 00 00 00 00 10 00 kernel: blk_update_request: I/O error, dev sdc, sector 0 Is that a bug? -- 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 v3 5/5] target: Fix wrong setting of sense format for PI errors
On 07/08/2015 12:49 PM, Christoph Hellwig wrote: On Wed, Jul 08, 2015 at 01:36:04PM +0300, Sagi Grimberg wrote: We don't have any other information today, but sector is not the only information that is requires a descriptor format, so maybe it will be a bit awkward to condition the descriptor format on the sector info? The only reason why you'd want to support descriptor type sense data is because you need to add a second descriptor. If we have another case that needs descriptor sense data it'll also need to add that additional descriptor. So we'll need a conditional for it in the sense data generation anyway. Actually it's controlled by the D_SENSE bit in the Control mode page (that's bit[2] of byte 2 in the control mode page). Which is currently set to '0', ie we will be returning fixed sense information. _If_ we were to report descriptor sense we will need to change that, too. And it's actually not true that you'd need descriptor sense to encode the sector information; it'll be stored in the 'information' section (byte 3-6) for fixed format sense. 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
[PATCH 5/5] scsi_dh_rdac: Add 'state' callback
Add a 'state' callback to display the current LUN access state to sysfs. Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/device_handler/scsi_dh_rdac.c | 17 + 1 file changed, 17 insertions(+) diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index 3613581..151b736 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c @@ -834,6 +834,22 @@ static void rdac_bus_detach( struct scsi_device *sdev ) kfree(h); } +static int rdac_state(struct scsi_device *sdev) +{ + struct rdac_dh_data *h = sdev-handler_data; + int access_state = SCSI_ACCESS_STATE_OPTIMAL; + + if (h-lun_state == RDAC_LUN_UNOWNED) + access_state = SCSI_ACCESS_STATE_ACTIVE; + if (h-state == RDAC_STATE_PASSIVE) + access_state = SCSI_ACCESS_STATE_PASSIVE; + + if (h-preferred == RDAC_PREFERRED) + access_state |= SCSI_ACCESS_STATE_PREFERRED; + + return access_state; +} + static struct scsi_device_handler rdac_dh = { .name = RDAC_NAME, .module = THIS_MODULE, @@ -842,6 +858,7 @@ static struct scsi_device_handler rdac_dh = { .attach = rdac_bus_attach, .detach = rdac_bus_detach, .activate = rdac_activate, + .state = rdac_state, }; static int __init rdac_init(void) -- 1.8.5.2 -- 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 1/5] scsi: rescan VPD attributes
This patch implements a VPD page rescan if the 'rescan' sysfs attribute is triggered. Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/device_handler/scsi_dh_alua.c | 11 +++ drivers/scsi/scsi.c| 20 +--- drivers/scsi/scsi_scan.c | 4 drivers/scsi/scsi_sysfs.c | 8 ++-- drivers/scsi/ses.c | 6 -- include/scsi/scsi_device.h | 1 + 6 files changed, 39 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index d077014..e4cabc8 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -264,8 +264,11 @@ static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h) int device_id_size, device_id_type = 0; struct alua_port_group *tmp_pg, *pg = NULL; - if (!sdev-vpd_pg83) + rcu_read_lock(); + if (!rcu_dereference(sdev-vpd_pg83)) { + rcu_read_unlock(); return SCSI_DH_DEV_UNSUPP; + } /* * Look for the correct descriptor. @@ -281,8 +284,8 @@ static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h) */ memset(device_id_str, 0, 256); device_id_size = 0; - d = sdev-vpd_pg83 + 4; - while (d sdev-vpd_pg83 + sdev-vpd_pg83_len) { + d = rcu_dereference(sdev-vpd_pg83) + 4; + while (d rcu_dereference(sdev-vpd_pg83) + sdev-vpd_pg83_len) { switch (d[1] 0xf) { case 0x2: /* EUI-64 */ @@ -366,7 +369,7 @@ static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h) } d += d[3] + 4; } - + rcu_read_unlock(); if (group_id == -1) { /* * Internal error; TPGS supported but required diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 207d6a7..f1c0fb5 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -803,7 +803,7 @@ void scsi_attach_vpd(struct scsi_device *sdev) int vpd_len = SCSI_VPD_PG_LEN; int pg80_supported = 0; int pg83_supported = 0; - unsigned char *vpd_buf; + unsigned char *vpd_buf, *orig_vpd_buf = NULL; if (sdev-skip_vpd_pages) return; @@ -849,8 +849,16 @@ retry_pg80: kfree(vpd_buf); goto retry_pg80; } + mutex_lock(sdev-inquiry_mutex); + orig_vpd_buf = sdev-vpd_pg80; sdev-vpd_pg80_len = result; - sdev-vpd_pg80 = vpd_buf; + rcu_assign_pointer(sdev-vpd_pg80, vpd_buf); + mutex_unlock(sdev-inquiry_mutex); + synchronize_rcu(); + if (orig_vpd_buf) { + kfree(orig_vpd_buf); + orig_vpd_buf = NULL; + } vpd_len = SCSI_VPD_PG_LEN; } @@ -870,8 +878,14 @@ retry_pg83: kfree(vpd_buf); goto retry_pg83; } + mutex_lock(sdev-inquiry_mutex); + orig_vpd_buf = sdev-vpd_pg83; sdev-vpd_pg83_len = result; - sdev-vpd_pg83 = vpd_buf; + rcu_assign_pointer(sdev-vpd_pg83, vpd_buf); + mutex_unlock(sdev-inquiry_mutex); + synchronize_rcu(); + if (orig_vpd_buf) + kfree(orig_vpd_buf); } } diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index f9f3f82..190d743 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -235,6 +235,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, INIT_LIST_HEAD(sdev-starved_entry); INIT_LIST_HEAD(sdev-event_list); spin_lock_init(sdev-list_lock); + mutex_init(sdev-inquiry_mutex); INIT_WORK(sdev-event_work, scsi_evt_thread); INIT_WORK(sdev-requeue_work, scsi_requeue_run_queue); @@ -1516,6 +1517,9 @@ EXPORT_SYMBOL(scsi_add_device); void scsi_rescan_device(struct device *dev) { device_lock(dev); + + scsi_attach_vpd(to_scsi_device(dev)); + if (dev-driver try_module_get(dev-driver-owner)) { struct scsi_driver *drv = to_scsi_driver(dev-driver); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index e3c3b86..b4de776 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -759,11 +759,15 @@ show_vpd_##_page(struct file *filp, struct kobject *kobj, \ { \ struct device *dev = container_of(kobj, struct device, kobj); \ struct scsi_device *sdev = to_scsi_device(dev); \ + int ret;
[PATCH 0/5] device handler interface update
Hi all, the current scsi_dh interface is very limited in functionality. In particular it's not possible to update the internal state without triggering a failover, and it not possible to figure out the internal state of the device handler. This patchset adds the functionality to rescan the device handler if something has changed and adds a new sysfs attribute 'access_state' to display the internal state. To make this work the first patch implements functionality to rescan the VPD information, as it might have changed, too. The patchset is relative to my asynchronous ALUA update posted earlier. The entire tree can be found on git.kernel.org: kernel/git/hare/scsi-devel.git branch alua.v3 As usual, reviews and comments are welcome. Hannes Reinecke (5): scsi: rescan VPD attributes scsi_dh: add 'rescan' callback scsi: Add 'access_state' attribute scsi_dh_alua: add 'state' callback function scsi_dh_rdac: Add 'state' callback drivers/scsi/device_handler/scsi_dh_alua.c | 111 + drivers/scsi/device_handler/scsi_dh_rdac.c | 17 + drivers/scsi/scsi.c| 20 +- drivers/scsi/scsi_lib.c| 1 + drivers/scsi/scsi_scan.c | 10 +++ drivers/scsi/scsi_sysfs.c | 61 +++- drivers/scsi/ses.c | 6 +- include/scsi/scsi_device.h | 14 include/scsi/scsi_dh.h | 2 + 9 files changed, 220 insertions(+), 22 deletions(-) -- 1.8.5.2 -- 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 4/5] scsi_dh_alua: add 'state' callback function
Add a 'state' callback function to display the current path status in sysfs. Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/device_handler/scsi_dh_alua.c | 47 ++ 1 file changed, 47 insertions(+) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 5b52017..99c4b0f 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -1182,6 +1182,52 @@ static void alua_check(struct scsi_device *sdev, bool force) } /* + * alua_state - report path status + * @sdev: device on the path to be checked + * + * Check the device status + */ +static int alua_state(struct scsi_device *sdev) +{ + struct alua_dh_data *h = sdev-handler_data; + struct alua_port_group *pg = NULL; + int access_state = SCSI_ACCESS_STATE_UNKNOWN; + + rcu_read_lock(); + if (h) + pg = rcu_dereference(h-pg); + if (pg) { + switch (pg-state) { + case TPGS_STATE_OPTIMIZED: + access_state = SCSI_ACCESS_STATE_OPTIMAL; + break; + case TPGS_STATE_NONOPTIMIZED: + access_state = SCSI_ACCESS_STATE_ACTIVE; + break; + case TPGS_STATE_STANDBY: + access_state = SCSI_ACCESS_STATE_PASSIVE; + break; + case TPGS_STATE_UNAVAILABLE: + access_state = SCSI_ACCESS_STATE_UNAVAILABLE; + break; + case TPGS_STATE_LBA_DEPENDENT: + access_state = SCSI_ACCESS_STATE_LBA; + break; + case TPGS_STATE_OFFLINE: + access_state = SCSI_ACCESS_STATE_OFFLINE; + break; + case TPGS_STATE_TRANSITIONING: + access_state = SCSI_ACCESS_STATE_TRANSITIONING; + break; + } + if (pg-pref) + access_state |= SCSI_ACCESS_STATE_PREFERRED; + } + rcu_read_unlock(); + return access_state; +} + +/* * alua_prep_fn - request callback * * Fail I/O to all paths not in state @@ -1288,6 +1334,7 @@ static struct scsi_device_handler alua_dh = { .activate = alua_activate, .rescan = alua_rescan, .set_params = alua_set_params, + .state = alua_state, }; static int __init alua_init(void) -- 1.8.5.2 -- 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 2/5] scsi_dh: add 'rescan' callback
If a device needs to be rescanned the device_handler might need to be rechecked, too. So add a 'rescan' callback to the device handler and call it upon scsi_rescan_device(). Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/device_handler/scsi_dh_alua.c | 53 +++--- drivers/scsi/scsi_lib.c| 1 + drivers/scsi/scsi_scan.c | 8 - include/scsi/scsi_dh.h | 1 + 4 files changed, 51 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index e4cabc8..5b52017 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -262,7 +262,8 @@ static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h) int group_id = -1; char device_id_str[256], *device_id = NULL; int device_id_size, device_id_type = 0; - struct alua_port_group *tmp_pg, *pg = NULL; + struct alua_port_group *tmp_pg, *pg = NULL, *old_pg = NULL; + bool pg_found = false; rcu_read_lock(); if (!rcu_dereference(sdev-vpd_pg83)) { @@ -407,17 +408,25 @@ static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h) if (memcmp(tmp_pg-device_id, device_id, device_id_size)) continue; - kref_get(tmp_pg-kref); spin_lock(h-pg_lock); - rcu_assign_pointer(h-pg, tmp_pg); + pg = rcu_dereference(h-pg); + if (pg) { + /* +* This can happen if the VPD information changed +*/ + if (tmp_pg != pg) { + old_pg = pg; + kref_get(tmp_pg-kref); + rcu_assign_pointer(h-pg, tmp_pg); + } + pg_found = true; + } spin_unlock(h-pg_lock); break; } spin_unlock(port_group_lock); - if (h-pg) { - synchronize_rcu(); - return SCSI_DH_OK; - } + if (pg_found) + goto out; pg = kzalloc(sizeof(struct alua_port_group), GFP_KERNEL); if (!pg) { @@ -466,12 +475,17 @@ static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h) if (memcmp(tmp_pg-device_id, pg-device_id, device_id_size)) continue; - kref_get(tmp_pg-kref); spin_lock(h-pg_lock); - rcu_assign_pointer(h-pg, tmp_pg); + pg = rcu_dereference(h-pg); + if (pg) { + if (tmp_pg != pg) { + old_pg = pg; + kref_get(tmp_pg-kref); + rcu_assign_pointer(h-pg, tmp_pg); + } + pg = NULL; + } spin_unlock(h-pg_lock); - kfree(pg); - pg = NULL; break; } if (pg) { @@ -481,6 +495,13 @@ static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h) spin_unlock(h-pg_lock); } spin_unlock(port_group_lock); +out: + if (old_pg) { + synchronize_rcu(); + if (old_pg-rtpg_sdev) + flush_workqueue(old_pg-work_q); + kref_put(pg-kref, release_port_group); + } return SCSI_DH_OK; } @@ -1011,6 +1032,8 @@ static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h) kref_get(pg-kref); rcu_read_unlock(); } + } else { + WARN_ON(rcu_dereference(h-pg)); } complete(h-init_complete); if (pg) { @@ -1195,6 +1218,13 @@ static int alua_prep_fn(struct scsi_device *sdev, struct request *req) } +static void alua_rescan(struct scsi_device *sdev) +{ + struct alua_dh_data *h = sdev-handler_data; + + alua_initialize(sdev, h); +} + /* * alua_bus_attach - Attach device handler * @sdev: device to be attached to @@ -1256,6 +1286,7 @@ static struct scsi_device_handler alua_dh = { .prep_fn = alua_prep_fn, .check_sense = alua_check_sense, .activate = alua_activate, + .rescan = alua_rescan, .set_params = alua_set_params, }; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 18ab4ad..991b9e1 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -2704,6 +2704,7 @@ static void scsi_evt_emit(struct scsi_device *sdev, struct scsi_event *evt) envp[idx++] = SDEV_MEDIA_CHANGE=1; break; case SDEV_EVT_INQUIRY_CHANGE_REPORTED: +
Re: [PATCH v3 5/5] target: Fix wrong setting of sense format for PI errors
On 7/8/2015 2:44 PM, Christoph Hellwig wrote: On Wed, Jul 08, 2015 at 12:59:18PM +0200, Hannes Reinecke wrote: Actually it's controlled by the D_SENSE bit in the Control mode page (that's bit[2] of byte 2 in the control mode page). Which is currently set to '0', ie we will be returning fixed sense information. _If_ we were to report descriptor sense we will need to change that, too. Just looked over SPC, and indeed D_SENSE is a strict either fixed or descriptor, not a may return descriptor data. So this patch actually is wrong as we never must return different sense data types based on the sense code. I'll send out v4 without this patch altogether. -- 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 20/20] scsi_dh_alua: Update version to 2.0
Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/device_handler/scsi_dh_alua.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 30310c8..d077014 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -31,7 +31,7 @@ #include scsi/scsi_dh.h #define ALUA_DH_NAME alua -#define ALUA_DH_VER 1.3 +#define ALUA_DH_VER 2.0 #define TPGS_STATE_OPTIMIZED 0x0 #define TPGS_STATE_NONOPTIMIZED0x1 -- 1.8.5.2 -- 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 09/20] scsi_dh_alua: switch to scsi_execute()
All commands are issued synchronously, so no need to open-code scsi_execute anymore. Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/device_handler/scsi_dh_alua.c | 108 - 1 file changed, 27 insertions(+), 81 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 76bc66d..61301cf 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -103,72 +103,29 @@ static int realloc_buffer(struct alua_dh_data *h, unsigned len) return 0; } -static struct request *get_alua_req(struct scsi_device *sdev, - void *buffer, unsigned buflen, int rw) -{ - struct request *rq; - struct request_queue *q = sdev-request_queue; - - rq = blk_get_request(q, rw, GFP_NOIO); - - if (IS_ERR(rq)) { - sdev_printk(KERN_INFO, sdev, - %s: blk_get_request failed\n, __func__); - return NULL; - } - blk_rq_set_block_pc(rq); - - if (buflen blk_rq_map_kern(q, rq, buffer, buflen, GFP_NOIO)) { - blk_put_request(rq); - sdev_printk(KERN_INFO, sdev, - %s: blk_rq_map_kern failed\n, __func__); - return NULL; - } - - rq-cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | -REQ_FAILFAST_DRIVER; - rq-retries = ALUA_FAILOVER_RETRIES; - rq-timeout = ALUA_FAILOVER_TIMEOUT * HZ; - - return rq; -} - /* * submit_rtpg - Issue a REPORT TARGET GROUP STATES command * @sdev: sdev the command should be sent to */ -static unsigned submit_rtpg(struct scsi_device *sdev, unsigned char *buff, +static int submit_rtpg(struct scsi_device *sdev, unsigned char *buff, int bufflen, unsigned char *sense, int flags) { - struct request *rq; - int err; - - rq = get_alua_req(sdev, buff, bufflen, READ); - if (!rq) { - err = DRIVER_BUSY 24; - goto done; - } + u8 cdb[16]; + int req_flags = REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | + REQ_FAILFAST_DRIVER; /* Prepare the command. */ - rq-cmd[0] = MAINTENANCE_IN; + memset(cdb, 0x0, 16); + cdb[0] = MAINTENANCE_IN; if (!(flags ALUA_RTPG_EXT_HDR_UNSUPP)) - rq-cmd[1] = MI_REPORT_TARGET_PGS | MI_EXT_HDR_PARAM_FMT; + cdb[1] = MI_REPORT_TARGET_PGS | MI_EXT_HDR_PARAM_FMT; else - rq-cmd[1] = MI_REPORT_TARGET_PGS; - put_unaligned_be32(bufflen, rq-cmd[6]); - rq-cmd_len = COMMAND_SIZE(MAINTENANCE_IN); + cdb[1] = MI_REPORT_TARGET_PGS; + put_unaligned_be32(bufflen, cdb[6]); - rq-sense = sense; - memset(rq-sense, 0, SCSI_SENSE_BUFFERSIZE); - rq-sense_len = 0; - - blk_execute_rq(rq-q, NULL, rq, 1); - if (rq-errors) - err = rq-errors; - - blk_put_request(rq); -done: - return err; + return scsi_execute(sdev, cdb, DMA_FROM_DEVICE, buff, bufflen, + sense, ALUA_FAILOVER_TIMEOUT * HZ, + ALUA_FAILOVER_RETRIES, req_flags, NULL); } /* @@ -178,40 +135,29 @@ done: * to 'active/optimized' and let the array firmware figure out * the states of the remaining groups. */ -static unsigned submit_stpg(struct scsi_device *sdev, int group_id, - unsigned char *sense) +static int submit_stpg(struct scsi_device *sdev, int group_id, + unsigned char *sense) { - struct request *rq; + u8 cdb[COMMAND_SIZE(MAINTENANCE_OUT)]; unsigned char stpg_data[8]; int stpg_len = 8; - int err = 0; + int req_flags = REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | + REQ_FAILFAST_DRIVER; /* Prepare the data buffer */ memset(stpg_data, 0, stpg_len); stpg_data[4] = TPGS_STATE_OPTIMIZED 0x0f; put_unaligned_be16(group_id, stpg_data[6]); - rq = get_alua_req(sdev, stpg_data, stpg_len, WRITE); - if (!rq) - return DRIVER_BUSY 24; - /* Prepare the command. */ - rq-cmd[0] = MAINTENANCE_OUT; - rq-cmd[1] = MO_SET_TARGET_PGS; - put_unaligned_be32(stpg_len, rq-cmd[6]); - rq-cmd_len = COMMAND_SIZE(MAINTENANCE_OUT); - - rq-sense = sense; - memset(rq-sense, 0, SCSI_SENSE_BUFFERSIZE); - rq-sense_len = 0; - - blk_execute_rq(rq-q, NULL, rq, 1); - if (rq-errors) - err = rq-errors; - - blk_put_request(rq); - - return err; + memset(cdb, 0x0, COMMAND_SIZE(MAINTENANCE_OUT)); + cdb[0] = MAINTENANCE_OUT; + cdb[1] = MO_SET_TARGET_PGS; + put_unaligned_be32(stpg_len, cdb[6]); + + return scsi_execute(sdev, cdb, DMA_TO_DEVICE, stpg_data, stpg_len, +
[PATCH 11/20] scsi_dh_alua: Use separate alua_port_group structure
The port group needs to be a separate structure as several LUNs might belong to the same group. Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/device_handler/scsi_dh_alua.c | 210 +++-- 1 file changed, 137 insertions(+), 73 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index ea4a920..3f18f6b 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -64,9 +64,13 @@ #define ALUA_OPTIMIZE_STPG 1 #define ALUA_RTPG_EXT_HDR_UNSUPP 2 -struct alua_dh_data { +static LIST_HEAD(port_group_list); +static DEFINE_SPINLOCK(port_group_lock); + +struct alua_port_group { + struct kref kref; + struct list_headnode; int group_id; - int rel_port; int tpgs; int state; int pref; @@ -75,6 +79,12 @@ struct alua_dh_data { unsigned char *buff; int bufflen; unsigned char transition_tmo; +}; + +struct alua_dh_data { + struct alua_port_group *pg; + int rel_port; + int tpgs; struct scsi_device *sdev; activate_complete callback_fn; void*callback_data; @@ -86,21 +96,35 @@ struct alua_dh_data { static char print_alua_state(int); static int alua_check_sense(struct scsi_device *, struct scsi_sense_hdr *); -static int realloc_buffer(struct alua_dh_data *h, unsigned len) +static int realloc_buffer(struct alua_port_group *pg, unsigned len) { - if (h-buff h-buff != h-inq) - kfree(h-buff); + if (pg-buff pg-buff != pg-inq) + kfree(pg-buff); - h-buff = kmalloc(len, GFP_NOIO); - if (!h-buff) { - h-buff = h-inq; - h-bufflen = ALUA_INQUIRY_SIZE; + pg-buff = kmalloc(len, GFP_NOIO); + if (!pg-buff) { + pg-buff = pg-inq; + pg-bufflen = ALUA_INQUIRY_SIZE; return 1; } - h-bufflen = len; + pg-bufflen = len; return 0; } +static void release_port_group(struct kref *kref) +{ + struct alua_port_group *pg; + + pg = container_of(kref, struct alua_port_group, kref); + printk(KERN_WARNING alua: release port group %d\n, pg-group_id); + spin_lock(port_group_lock); + list_del(pg-node); + spin_unlock(port_group_lock); + if (pg-buff pg-inq != pg-buff) + kfree(pg-buff); + kfree(pg); +} + /* * submit_rtpg - Issue a REPORT TARGET GROUP STATES command * @sdev: sdev the command should be sent to @@ -223,6 +247,8 @@ static int alua_check_tpgs(struct scsi_device *sdev, struct alua_dh_data *h) static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h) { unsigned char *d; + int group_id = -1; + struct alua_port_group *pg = NULL; if (!sdev-vpd_pg83) return SCSI_DH_DEV_UNSUPP; @@ -239,7 +265,7 @@ static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h) break; case 0x5: /* Target port group */ - h-group_id = (d[6] 8) + d[7]; + group_id = (d[6] 8) + d[7]; break; default: break; @@ -247,7 +273,7 @@ static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h) d += d[3] + 4; } - if (h-group_id == -1) { + if (group_id == -1) { /* * Internal error; TPGS supported but required * VPD identification descriptors not present. @@ -256,15 +282,33 @@ static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h) sdev_printk(KERN_INFO, sdev, %s: No target port descriptors found\n, ALUA_DH_NAME); - h-state = TPGS_STATE_OPTIMIZED; h-tpgs = TPGS_MODE_NONE; return SCSI_DH_DEV_UNSUPP; } sdev_printk(KERN_INFO, sdev, %s: port group %02x rel port %02x\n, - ALUA_DH_NAME, h-group_id, h-rel_port); + ALUA_DH_NAME, group_id, h-rel_port); - return 0; + pg = kzalloc(sizeof(struct alua_port_group), GFP_KERNEL); + if (!pg) { + sdev_printk(KERN_WARNING, sdev, + %s: kzalloc port group failed\n, + ALUA_DH_NAME); + /* Temporary failure, bypass */ + return SCSI_DH_DEV_TEMP_BUSY; + } + pg-group_id = group_id; + pg-buff = pg-inq; + pg-bufflen = ALUA_INQUIRY_SIZE; +
[PATCH 10/20] scsi_dh_alua: put sense buffer on stack
We don't need to have the sense buffer available all the time, putting it on stack is totally sufficient. Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/device_handler/scsi_dh_alua.c | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 61301cf..ea4a920 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -75,8 +75,6 @@ struct alua_dh_data { unsigned char *buff; int bufflen; unsigned char transition_tmo; - unsigned char sense[SCSI_SENSE_BUFFERSIZE]; - int senselen; struct scsi_device *sdev; activate_complete callback_fn; void*callback_data; @@ -379,6 +377,7 @@ static int alua_check_sense(struct scsi_device *sdev, */ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h, int wait_for_transition) { + unsigned char sense[SCSI_SENSE_BUFFERSIZE]; struct scsi_sense_hdr sense_hdr; int len, k, off, valid_states = 0; unsigned char *ucp; @@ -393,11 +392,11 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h, int wait_ expiry = round_jiffies_up(jiffies + h-transition_tmo * HZ); retry: - retval = submit_rtpg(sdev, h-buff, h-bufflen, h-sense, h-flags); + retval = submit_rtpg(sdev, h-buff, h-bufflen, sense, h-flags); if (retval) { if (!(driver_byte(retval) DRIVER_SENSE) || - !scsi_normalize_sense(h-sense, SCSI_SENSE_BUFFERSIZE, + !scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, sense_hdr)) { sdev_printk(KERN_INFO, sdev, %s: rtpg failed, result %d\n, @@ -532,6 +531,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h, int wait_ static unsigned alua_stpg(struct scsi_device *sdev, struct alua_dh_data *h) { int retval; + unsigned char sense[SCSI_SENSE_BUFFERSIZE]; struct scsi_sense_hdr sense_hdr; if (!(h-tpgs TPGS_MODE_EXPLICIT)) { @@ -564,11 +564,11 @@ static unsigned alua_stpg(struct scsi_device *sdev, struct alua_dh_data *h) } /* Set state to transitioning */ h-state = TPGS_STATE_TRANSITIONING; - retval = submit_stpg(sdev, h-group_id, h-sense); + retval = submit_stpg(sdev, h-group_id, sense); if (retval) { if (!(driver_byte(retval) DRIVER_SENSE) || - !scsi_normalize_sense(h-sense, SCSI_SENSE_BUFFERSIZE, + !scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, sense_hdr)) { sdev_printk(KERN_INFO, sdev, %s: stpg failed, result %d, -- 1.8.5.2 -- 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 12/20] scsi_dh_alua: allocate RTPG buffer separately
The RTPG buffer will only evaluated within alua_rtpg(), so we can allocate it locally there and avoid having to put it into the global structure. Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/device_handler/scsi_dh_alua.c | 55 -- 1 file changed, 21 insertions(+), 34 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 3f18f6b..e8bfbce 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -56,7 +56,7 @@ #define TPGS_MODE_IMPLICIT 0x1 #define TPGS_MODE_EXPLICIT 0x2 -#define ALUA_INQUIRY_SIZE 36 +#define ALUA_RTPG_SIZE 128 #define ALUA_FAILOVER_TIMEOUT 60 #define ALUA_FAILOVER_RETRIES 5 @@ -75,9 +75,6 @@ struct alua_port_group { int state; int pref; unsignedflags; /* used for optimizing STPG */ - unsigned char inq[ALUA_INQUIRY_SIZE]; - unsigned char *buff; - int bufflen; unsigned char transition_tmo; }; @@ -96,21 +93,6 @@ struct alua_dh_data { static char print_alua_state(int); static int alua_check_sense(struct scsi_device *, struct scsi_sense_hdr *); -static int realloc_buffer(struct alua_port_group *pg, unsigned len) -{ - if (pg-buff pg-buff != pg-inq) - kfree(pg-buff); - - pg-buff = kmalloc(len, GFP_NOIO); - if (!pg-buff) { - pg-buff = pg-inq; - pg-bufflen = ALUA_INQUIRY_SIZE; - return 1; - } - pg-bufflen = len; - return 0; -} - static void release_port_group(struct kref *kref) { struct alua_port_group *pg; @@ -120,8 +102,6 @@ static void release_port_group(struct kref *kref) spin_lock(port_group_lock); list_del(pg-node); spin_unlock(port_group_lock); - if (pg-buff pg-inq != pg-buff) - kfree(pg-buff); kfree(pg); } @@ -298,8 +278,6 @@ static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h) return SCSI_DH_DEV_TEMP_BUSY; } pg-group_id = group_id; - pg-buff = pg-inq; - pg-bufflen = ALUA_INQUIRY_SIZE; pg-tpgs = h-tpgs; pg-state = TPGS_STATE_OPTIMIZED; kref_init(pg-kref); @@ -423,8 +401,8 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg, int w { unsigned char sense[SCSI_SENSE_BUFFERSIZE]; struct scsi_sense_hdr sense_hdr; - int len, k, off, valid_states = 0; - unsigned char *ucp; + int len, k, off, valid_states = 0, bufflen = ALUA_RTPG_SIZE; + unsigned char *ucp, *buff; unsigned err, retval; unsigned long expiry, interval = 0; unsigned int tpg_desc_tbl_off; @@ -435,8 +413,12 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg, int w else expiry = round_jiffies_up(jiffies + pg-transition_tmo * HZ); + buff = kzalloc(bufflen, GFP_KERNEL); + if (!buff) + return SCSI_DH_DEV_TEMP_BUSY; + retry: - retval = submit_rtpg(sdev, pg-buff, pg-bufflen, sense, pg-flags); + retval = submit_rtpg(sdev, buff, bufflen, sense, pg-flags); if (retval) { if (!(driver_byte(retval) DRIVER_SENSE) || @@ -449,6 +431,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg, int w err = SCSI_DH_DEV_TEMP_BUSY; else err = SCSI_DH_IO; + kfree(buff); return err; } @@ -477,14 +460,18 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg, int w sdev_printk(KERN_ERR, sdev, %s: rtpg failed\n, ALUA_DH_NAME); scsi_print_sense_hdr(sdev, ALUA_DH_NAME, sense_hdr); + kfree(buff); return SCSI_DH_IO; } - len = get_unaligned_be32(pg-buff[0]) + 4; + len = get_unaligned_be32(buff[0]) + 4; - if (len pg-bufflen) { + if (len bufflen) { /* Resubmit with the correct length */ - if (realloc_buffer(pg, len)) { + kfree(buff); + bufflen = len; + buff = kmalloc(bufflen, GFP_KERNEL); + if (!buff) { sdev_printk(KERN_WARNING, sdev, %s: kmalloc buffer failed\n,__func__); /* Temporary failure, bypass */ @@ -494,9 +481,8 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg, int w } orig_transition_tmo = pg-transition_tmo; - if ((pg-buff[4] RTPG_FMT_MASK) == RTPG_FMT_EXT_HDR -
[PATCH 14/20] scsi_dh_alua: parse target device id
Parse VPD descriptor to figure out the device identification. As devices might implement several descriptors the order of preference is: - NAA IEE Registered Extended - EUI-64 based 16-byte - EUI-64 based 12-byte - NAA IEEE Registered - NAA IEEE Extended A SCSI name string descriptor is preferred to all of them if the identification is longer than 16 bytes. Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/device_handler/scsi_dh_alua.c | 152 - 1 file changed, 147 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index f4d851a..6991171 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -70,6 +70,9 @@ static DEFINE_SPINLOCK(port_group_lock); struct alua_port_group { struct kref kref; struct list_headnode; + unsigned char device_id[256]; + unsigned char device_id_str[256]; + int device_id_size; int group_id; int tpgs; int state; @@ -227,17 +230,84 @@ static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h) { unsigned char *d; int group_id = -1; - struct alua_port_group *pg = NULL; + char device_id_str[256], *device_id = NULL; + int device_id_size, device_id_type = 0; + struct alua_port_group *tmp_pg, *pg = NULL; if (!sdev-vpd_pg83) return SCSI_DH_DEV_UNSUPP; /* * Look for the correct descriptor. +* Order of preference for lun descriptor: +* - SCSI name string +* - NAA IEEE Registered Extended +* - EUI-64 based 16-byte +* - EUI-64 based 12-byte +* - NAA IEEE Registered +* - NAA IEEE Extended +* as longer descriptors reduce the likelyhood +* of identification clashes. */ + memset(device_id_str, 0, 256); + device_id_size = 0; d = sdev-vpd_pg83 + 4; while (d sdev-vpd_pg83 + sdev-vpd_pg83_len) { switch (d[1] 0xf) { + case 0x2: + /* EUI-64 */ + if ((d[1] 0x30) == 0x00) { + if (device_id_size d[3]) + break; + /* Prefer NAA IEEE Registered Extended */ + if (device_id_type == 0x3 + device_id_size == d[3]) + break; + device_id_size = d[3]; + device_id = d + 4; + device_id_type = d[1] 0xf; + switch (device_id_size) { + case 8: + sprintf(device_id_str, + eui.%8phN, d + 4); + break; + case 12: + sprintf(device_id_str, + eui.%12phN, d + 4); + break; + case 16: + sprintf(device_id_str, + eui.%16phN, d + 4); + break; + default: + device_id_size = 0; + break; + } + } + break; + case 0x3: + /* NAA */ + if ((d[1] 0x30) == 0x00) { + if (device_id_size d[3]) + break; + device_id_size = d[3]; + device_id = d + 4; + device_id_type = d[1] 0xf; + switch (device_id_size) { + case 8: + sprintf(device_id_str, + naa.%8phN, d + 4); + break; + case 16: + sprintf(device_id_str, + naa.%16phN, d + 4); + break; + default: + device_id_size = 0; + break; + } + } + break; case 0x4: /* Relative target port
[PATCH 15/20] revert scsi_dh_alua: ALUA hander attach should succeed while TPG is transitioning
This reverts commit a8e5a2d593cbfccf530c3382c2c328d2edaa7b66 Obsoleted by the next patch. Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/device_handler/scsi_dh_alua.c | 22 -- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 6991171..88c150a 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -498,13 +498,12 @@ static int alua_check_sense(struct scsi_device *sdev, /* * alua_rtpg - Evaluate REPORT TARGET GROUP STATES * @sdev: the device to be evaluated. - * @wait_for_transition: if nonzero, wait ALUA_FAILOVER_TIMEOUT seconds for device to exit transitioning state * * Evaluate the Target Port Group State. * Returns SCSI_DH_DEV_OFFLINED if the path is * found to be unusable. */ -static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg, int wait_for_transition) +static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg) { unsigned char sense[SCSI_SENSE_BUFFERSIZE]; struct scsi_sense_hdr sense_hdr; @@ -600,7 +599,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg, int w else pg-transition_tmo = ALUA_FAILOVER_TIMEOUT; - if (wait_for_transition (orig_transition_tmo != pg-transition_tmo)) { + if (orig_transition_tmo != pg-transition_tmo) { sdev_printk(KERN_INFO, sdev, %s: transition timeout set to %d seconds\n, ALUA_DH_NAME, pg-transition_tmo); @@ -638,19 +637,14 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg, int w switch (pg-state) { case TPGS_STATE_TRANSITIONING: - if (wait_for_transition) { - if (time_before(jiffies, expiry)) { - /* State transition, retry */ - interval += 2000; - msleep(interval); - goto retry; - } - err = SCSI_DH_RETRY; - } else { - err = SCSI_DH_OK; + if (time_before(jiffies, expiry)) { + /* State transition, retry */ + interval += 2000; + msleep(interval); + goto retry; } - /* Transitioning time exceeded, set port to standby */ + err = SCSI_DH_RETRY; pg-state = TPGS_STATE_STANDBY; break; case TPGS_STATE_OFFLINE: -- 1.8.5.2 -- 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 13/20] scsi_dh_alua: simplify sense code handling
Most sense code is already handled in the generic code, so we shouldn't be adding special cases here. However, when doing so we need to check for unit attention whenever we're sending an internal command. Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/device_handler/scsi_dh_alua.c | 50 +++--- 1 file changed, 11 insertions(+), 39 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index e8bfbce..f4d851a 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -91,7 +91,6 @@ struct alua_dh_data { #define ALUA_POLICY_SWITCH_ALL 1 static char print_alua_state(int); -static int alua_check_sense(struct scsi_device *, struct scsi_sense_hdr *); static void release_port_group(struct kref *kref) { @@ -321,28 +320,6 @@ static int alua_check_sense(struct scsi_device *sdev, * LUN Not Accessible - ALUA state transition */ return ADD_TO_MLQUEUE; - if (sense_hdr-asc == 0x04 sense_hdr-ascq == 0x0b) - /* -* LUN Not Accessible -- Target port in standby state -*/ - return SUCCESS; - if (sense_hdr-asc == 0x04 sense_hdr-ascq == 0x0c) - /* -* LUN Not Accessible -- Target port in unavailable state -*/ - return SUCCESS; - if (sense_hdr-asc == 0x04 sense_hdr-ascq == 0x12) - /* -* LUN Not Ready -- Offline -*/ - return SUCCESS; - if (sdev-allow_restart - sense_hdr-asc == 0x04 sense_hdr-ascq == 0x02) - /* -* if the device is not started, we need to wake -* the error handler to start the motor -*/ - return FAILED; break; case UNIT_ATTENTION: if (sense_hdr-asc == 0x29 sense_hdr-ascq == 0x00) @@ -357,7 +334,7 @@ static int alua_check_sense(struct scsi_device *sdev, return ADD_TO_MLQUEUE; if (sense_hdr-asc == 0x2a sense_hdr-ascq == 0x01) /* -* Mode Parameters Changed +* Mode Parameter Changed */ return ADD_TO_MLQUEUE; if (sense_hdr-asc == 0x2a sense_hdr-ascq == 0x06) @@ -370,18 +347,6 @@ static int alua_check_sense(struct scsi_device *sdev, * Implicit ALUA state transition failed */ return ADD_TO_MLQUEUE; - if (sense_hdr-asc == 0x3f sense_hdr-ascq == 0x03) - /* -* Inquiry data has changed -*/ - return ADD_TO_MLQUEUE; - if (sense_hdr-asc == 0x3f sense_hdr-ascq == 0x0e) - /* -* REPORTED_LUNS_DATA_HAS_CHANGED is reported -* when switching controllers on targets like -* Intel Multi-Flex. We can just retry. -*/ - return ADD_TO_MLQUEUE; break; } @@ -449,9 +414,16 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg, int w pg-flags |= ALUA_RTPG_EXT_HDR_UNSUPP; goto retry; } - - err = alua_check_sense(sdev, sense_hdr); - if (err == ADD_TO_MLQUEUE time_before(jiffies, expiry)) { + /* +* Retry on ALUA state transition or if any +* UNIT ATTENTION occurred. +*/ + if (sense_hdr.sense_key == NOT_READY + sense_hdr.asc == 0x04 sense_hdr.ascq == 0x0a) + err = SCSI_DH_RETRY; + if (sense_hdr.sense_key == UNIT_ATTENTION) + err = SCSI_DH_RETRY; + if (err == SCSI_DH_RETRY time_before(jiffies, expiry)) { sdev_printk(KERN_ERR, sdev, %s: rtpg retry\n, ALUA_DH_NAME); scsi_print_sense_hdr(sdev, ALUA_DH_NAME, sense_hdr); -- 1.8.5.2 -- 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 v3 4/5] target: Use scsi helpers to build the sense data correctly
On 7/8/2015 1:17 PM, Christoph Hellwig wrote: --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -7,6 +7,7 @@ #include linux/blkdev.h #include linux/percpu_ida.h #include linux/t10-pi.h +#include scsi/scsi_common.h #include net/sock.h #include net/tcp.h Please only add the include in the files that need it. (And many of the existing includes should be fixed up the same way, but that's a different story). OK, I'll move it. -- 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 v3 2/5] target: Split transport_send_check_condition_and_sense()
On 7/8/2015 1:15 PM, Christoph Hellwig wrote: + if (r == (__force int)TCM_CHECK_CONDITION_UNIT_ATTENTION) { You probably want to compare reason here to avoid the cast. I do want it... -- 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 3/3] sd: do not try to spin-up disks for ALUA 'transitioning' state
On 07/08/2015 10:41 AM, Sagi Grimberg wrote: On 7/8/2015 10:41 AM, Hannes Reinecke wrote: If a disk reports an ALUA 'transitioning' state we should not try to spin up the device. Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/sd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 7c0bdaa..180a6e8 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1801,6 +1801,8 @@ sd_spinup_disk(struct scsi_disk *sdkp) if (sense_valid sshdr.sense_key == NOT_READY) { if (sshdr.asc == 4 sshdr.ascq == 3) break;/* manual intervention required */ +if (sshdr.asc == 4 sshdr.ascq == 0xa) +break; /* transitioning */ if (sshdr.asc == 4 sshdr.ascq == 0xb) break;/* standby */ if (sshdr.asc == 4 sshdr.ascq == 0xc) Hi Hannes, Just nit-picking, but do you think that these four if statements can be re-organized to condition (asc == 4) once and OR on the rest? Sure they can, I don't mind. Once we have a general agreement about these patches (hint, hint :-) I can update it. Cheers, Hannes -- Dr. Hannes Reinecke zSeries Storage h...@suse.de +49 911 74053 688 SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg GF: J. Hawn, J. Guild, F. Imendörffer, HRB 16746 (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
[PATCH 16/20] scsi_dh_alua: Use workqueue for RTPG
The current ALUA device_handler has two drawbacks: - We're sending a 'SET TARGET PORT GROUP' command to every LUN, disregarding the fact that several LUNs might be in a port group and will be automatically switched whenever _any_ LUN within that port group receives the command. - Whenever a LUN is in 'transitioning' mode we cannot block I/O to that LUN, instead the controller has to abort the command. This leads to increased traffic across the wire and heavy load on the controller during switchover. With this patch the RTPG handling is moved to a per-portgroup workqueue. This reduces the number of 'REPORT TARGET PORT GROUP' and 'SET TARGET PORT GROUPS' sent to the controller as we're sending them now per port group, and not per device as previously. It also allows us to block I/O to any LUN / port group found to be in 'transitioning' ALUA mode, as the workqueue item will be requeued until the controller moves out of transitioning. Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/device_handler/scsi_dh_alua.c | 412 - 1 file changed, 349 insertions(+), 63 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 88c150a..ea47d15 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -22,6 +22,8 @@ #include linux/slab.h #include linux/delay.h #include linux/module.h +#include linux/workqueue.h +#include linux/rcupdate.h #include asm/unaligned.h #include scsi/scsi.h #include scsi/scsi_dbg.h @@ -59,10 +61,15 @@ #define ALUA_RTPG_SIZE 128 #define ALUA_FAILOVER_TIMEOUT 60 #define ALUA_FAILOVER_RETRIES 5 +#define ALUA_RTPG_DELAY_MSECS 5 /* device handler flags */ -#define ALUA_OPTIMIZE_STPG 1 -#define ALUA_RTPG_EXT_HDR_UNSUPP 2 +#define ALUA_OPTIMIZE_STPG 0x01 +#define ALUA_RTPG_EXT_HDR_UNSUPP 0x02 +/* State machine flags */ +#define ALUA_PG_RUN_RTPG 0x10 +#define ALUA_PG_RUN_STPG 0x20 + static LIST_HEAD(port_group_list); static DEFINE_SPINLOCK(port_group_lock); @@ -79,13 +86,29 @@ struct alua_port_group { int pref; unsignedflags; /* used for optimizing STPG */ unsigned char transition_tmo; + unsigned long expiry; + unsigned long interval; + charwork_q_name[264]; + struct workqueue_struct *work_q; + struct delayed_work rtpg_work; + struct delayed_work stpg_work; + struct delayed_work qdata_work; + spinlock_t rtpg_lock; + struct list_headrtpg_list; + struct scsi_device *rtpg_sdev; }; struct alua_dh_data { struct alua_port_group *pg; + spinlock_t pg_lock; int rel_port; int tpgs; - struct scsi_device *sdev; + int error; + struct completion init_complete; +}; + +struct alua_queue_data { + struct list_headentry; activate_complete callback_fn; void*callback_data; }; @@ -94,6 +117,10 @@ struct alua_dh_data { #define ALUA_POLICY_SWITCH_ALL 1 static char print_alua_state(int); +static void alua_rtpg_work(struct work_struct *work); +static void alua_stpg_work(struct work_struct *work); +static void alua_qdata_work(struct work_struct *work); +static void alua_check(struct scsi_device *sdev); static void release_port_group(struct kref *kref) { @@ -104,6 +131,9 @@ static void release_port_group(struct kref *kref) spin_lock(port_group_lock); list_del(pg-node); spin_unlock(port_group_lock); + WARN_ON(pg-rtpg_sdev); + if (pg-work_q) + destroy_workqueue(pg-work_q); kfree(pg); } @@ -374,13 +404,17 @@ static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h) if (memcmp(tmp_pg-device_id, device_id, device_id_size)) continue; - h-pg = tmp_pg; kref_get(tmp_pg-kref); + spin_lock(h-pg_lock); + rcu_assign_pointer(h-pg, tmp_pg); + spin_unlock(h-pg_lock); break; } spin_unlock(port_group_lock); - if (h-pg) + if (h-pg) { + synchronize_rcu(); return SCSI_DH_OK; + } pg = kzalloc(sizeof(struct alua_port_group), GFP_KERNEL); if (!pg) { @@ -402,6 +436,20 @@ static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h) pg-tpgs = h-tpgs; pg-state = TPGS_STATE_OPTIMIZED; kref_init(pg-kref); + INIT_DELAYED_WORK(pg-rtpg_work, alua_rtpg_work); + INIT_DELAYED_WORK(pg-stpg_work,
[PATCH 18/20] scsi_dh_alua: update all port states
When we read in the target port group state we should be updating all affected port groups, otherwise we risk running out of sync. Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/device_handler/scsi_dh_alua.c | 28 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index aa58659..44b57bc 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -560,11 +560,13 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg) { unsigned char sense[SCSI_SENSE_BUFFERSIZE]; struct scsi_sense_hdr sense_hdr; + struct alua_port_group *tmp_pg; int len, k, off, valid_states = 0, bufflen = ALUA_RTPG_SIZE; unsigned char *ucp, *buff; unsigned err, retval; unsigned int tpg_desc_tbl_off; unsigned char orig_transition_tmo; + unsigned long flags; if (!pg-expiry) { if (!pg-transition_tmo) @@ -669,17 +671,35 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg) else tpg_desc_tbl_off = 4; + spin_lock_irqsave(port_group_lock, flags); for (k = tpg_desc_tbl_off, ucp = buff + tpg_desc_tbl_off; k len; k += off, ucp += off) { - if (pg-group_id == (ucp[2] 8) + ucp[3]) { - pg-state = ucp[0] 0x0f; - pg-pref = ucp[0] 7; - valid_states = ucp[1]; + list_for_each_entry(tmp_pg, port_group_list, node) { + u16 group_id = get_unaligned_be16(ucp[2]); + if (tmp_pg-group_id != group_id) + continue; + if (tmp_pg-device_id_size != pg-device_id_size) + continue; + if (memcmp(tmp_pg-device_id, pg-device_id, + tmp_pg-device_id_size)) + continue; + tmp_pg-state = ucp[0] 0x0f; + tmp_pg-pref = ucp[0] 7; + sdev_printk(KERN_INFO, sdev, + %s: device %s port group %02x + state %c %s\n, ALUA_DH_NAME, + tmp_pg-device_id_str, tmp_pg-group_id, + print_alua_state(tmp_pg-state), + tmp_pg-pref ? + preferred : non-preferred); + if (tmp_pg == pg) + valid_states = ucp[1]; } off = 8 + (ucp[7] * 4); } + spin_unlock_irqrestore(port_group_lock, flags); sdev_printk(KERN_INFO, sdev, %s: port group %02x state %c %s supports %c%c%c%c%c%c%c\n, -- 1.8.5.2 -- 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 01/20] scsi_dh_alua: Disable ALUA handling for non-disk devices
Non-disk devices might support ALUA, but the firmware implementation is untested and frequently broken. As we're don't actually need it disable ALUA support for non-disk device for now. Signed-off-by: Hannes Reinecke h...@suse.de Reviewed-by: Bart Van Assche bart.vanass...@sandisk.com --- drivers/scsi/device_handler/scsi_dh_alua.c | 12 1 file changed, 12 insertions(+) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index cc2773b..7d01ef0 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -320,6 +320,18 @@ static int alua_check_tpgs(struct scsi_device *sdev, struct alua_dh_data *h) { int err = SCSI_DH_OK; + /* +* ALUA support for non-disk devices is fraught with +* difficulties, so disable it for now. +*/ + if (sdev-type != TYPE_DISK) { + h-tpgs = TPGS_MODE_NONE; + sdev_printk(KERN_INFO, sdev, + %s: disable for non-disk devices\n, + ALUA_DH_NAME); + return SCSI_DH_DEV_UNSUPP; + } + h-tpgs = scsi_device_tpgs(sdev); switch (h-tpgs) { case TPGS_MODE_EXPLICIT|TPGS_MODE_IMPLICIT: -- 1.8.5.2 -- 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 03/20] scsi_dh_alua: improved logging
Issue different logging messages if ALUA is not supported or the TPGS setting is invalid. Reviewed-by: Christoph Hellwig h...@lst.de Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/device_handler/scsi_dh_alua.c | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index f15b977..a20c8bf 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -310,12 +310,18 @@ static int alua_check_tpgs(struct scsi_device *sdev, struct alua_dh_data *h) sdev_printk(KERN_INFO, sdev, %s: supports implicit TPGS\n, ALUA_DH_NAME); break; - default: - h-tpgs = TPGS_MODE_NONE; + case TPGS_MODE_NONE: sdev_printk(KERN_INFO, sdev, %s: not supported\n, ALUA_DH_NAME); err = SCSI_DH_DEV_UNSUPP; break; + default: + sdev_printk(KERN_INFO, sdev, + %s: unsupported TPGS setting %d\n, + ALUA_DH_NAME, h-tpgs); + h-tpgs = TPGS_MODE_NONE; + err = SCSI_DH_DEV_UNSUPP; + break; } return err; -- 1.8.5.2 -- 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 17/20] scsi_dh_alua: Recheck state on unit attention
When we receive a unit attention code of 'ALUA state changed' we should recheck the state, as it might be due to an implicit ALUA state transition. At the same time a workqueue item might already be queued, which should be started immediately to avoid any delays. Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/device_handler/scsi_dh_alua.c | 48 +++--- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index ea47d15..aa58659 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -120,7 +120,7 @@ static char print_alua_state(int); static void alua_rtpg_work(struct work_struct *work); static void alua_stpg_work(struct work_struct *work); static void alua_qdata_work(struct work_struct *work); -static void alua_check(struct scsi_device *sdev); +static void alua_check(struct scsi_device *sdev, bool force); static void release_port_group(struct kref *kref) { @@ -505,7 +505,7 @@ static char print_alua_state(int state) } static int alua_check_sense(struct scsi_device *sdev, - struct scsi_sense_hdr *sense_hdr) +struct scsi_sense_hdr *sense_hdr) { switch (sense_hdr-sense_key) { case NOT_READY: @@ -514,36 +514,34 @@ static int alua_check_sense(struct scsi_device *sdev, * LUN Not Accessible - ALUA state transition * Kickoff worker to update internal state. */ - alua_check(sdev); - return ADD_TO_MLQUEUE; + alua_check(sdev, false); + return NEEDS_RETRY; } break; case UNIT_ATTENTION: - if (sense_hdr-asc == 0x29 sense_hdr-ascq == 0x00) - /* -* Power On, Reset, or Bus Device Reset, just retry. -*/ - return ADD_TO_MLQUEUE; - if (sense_hdr-asc == 0x29 sense_hdr-ascq == 0x04) - /* -* Device internal reset -*/ - return ADD_TO_MLQUEUE; - if (sense_hdr-asc == 0x2a sense_hdr-ascq == 0x01) + if (sense_hdr-asc == 0x29 sense_hdr-ascq == 0x00) { /* -* Mode Parameter Changed +* Power On, Reset, or Bus Device Reset. +* Might have obscured a state transition, +* so schedule a recheck. */ + alua_check(sdev, true); return ADD_TO_MLQUEUE; - if (sense_hdr-asc == 0x2a sense_hdr-ascq == 0x06) + } + if (sense_hdr-asc == 0x2a sense_hdr-ascq == 0x06) { /* * ALUA state changed */ + alua_check(sdev, true); return ADD_TO_MLQUEUE; - if (sense_hdr-asc == 0x2a sense_hdr-ascq == 0x07) + } + if (sense_hdr-asc == 0x2a sense_hdr-ascq == 0x07) { /* * Implicit ALUA state transition failed */ + alua_check(sdev, true); return ADD_TO_MLQUEUE; + } break; } @@ -899,7 +897,7 @@ static void alua_qdata_work(struct work_struct *work) static void alua_rtpg_queue(struct alua_port_group *pg, struct scsi_device *sdev, - struct alua_queue_data *qdata) + struct alua_queue_data *qdata, bool force) { int start_queue = 0; unsigned long flags; @@ -920,7 +918,9 @@ static void alua_rtpg_queue(struct alua_port_group *pg, pg-rtpg_sdev = sdev; scsi_device_get(sdev); start_queue = 1; - } + } else if (!(pg-flags ALUA_PG_RUN_RTPG) force) + start_queue = 1; + spin_unlock_irqrestore(pg-rtpg_lock, flags); if (start_queue) @@ -959,7 +959,7 @@ static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h) complete(h-init_complete); if (pg) { pg-expiry = 0; - alua_rtpg_queue(pg, sdev, NULL); + alua_rtpg_queue(pg, sdev, NULL, true); kref_put(pg-kref, release_port_group); } return h-error; @@ -1072,7 +1072,7 @@ static int alua_activate(struct scsi_device *sdev, pg-flags |= ALUA_OPTIMIZE_STPG; spin_unlock_irqrestore(pg-rtpg_lock, flags); } - alua_rtpg_queue(pg, sdev, qdata); +
[PATCH 08/20] scsi_dh_alua: Make stpg synchronous
We should be issuing STPG synchronously as we need to evaluate the return code on failure. Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/device_handler/scsi_dh_alua.c | 189 + 1 file changed, 87 insertions(+), 102 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 28a3b99..76bc66d 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -172,94 +172,46 @@ done: } /* - * stpg_endio - Evaluate SET TARGET GROUP STATES - * @sdev: the device to be evaluated - * @state: the new target group state - * - * Evaluate a SET TARGET GROUP STATES command response. - */ -static void stpg_endio(struct request *req, int error) -{ - struct alua_dh_data *h = req-end_io_data; - struct scsi_sense_hdr sense_hdr; - unsigned err = SCSI_DH_OK; - - if (host_byte(req-errors) != DID_OK || - msg_byte(req-errors) != COMMAND_COMPLETE) { - err = SCSI_DH_IO; - goto done; - } - - if (scsi_normalize_sense(h-sense, SCSI_SENSE_BUFFERSIZE, -sense_hdr)) { - err = alua_check_sense(h-sdev, sense_hdr); - if (err == ADD_TO_MLQUEUE) { - err = SCSI_DH_RETRY; - goto done; - } - sdev_printk(KERN_INFO, h-sdev, %s: stpg failed\n, - ALUA_DH_NAME); - scsi_print_sense_hdr(h-sdev, ALUA_DH_NAME, sense_hdr); - err = SCSI_DH_IO; - } else if (error) - err = SCSI_DH_IO; - - if (err == SCSI_DH_OK) { - h-state = TPGS_STATE_OPTIMIZED; - sdev_printk(KERN_INFO, h-sdev, - %s: port group %02x switched to state %c\n, - ALUA_DH_NAME, h-group_id, - print_alua_state(h-state)); - } -done: - req-end_io_data = NULL; - __blk_put_request(req-q, req); - if (h-callback_fn) { - h-callback_fn(h-callback_data, err); - h-callback_fn = h-callback_data = NULL; - } - return; -} - -/* * submit_stpg - Issue a SET TARGET GROUP STATES command * * Currently we're only setting the current target port group state * to 'active/optimized' and let the array firmware figure out * the states of the remaining groups. */ -static unsigned submit_stpg(struct alua_dh_data *h) +static unsigned submit_stpg(struct scsi_device *sdev, int group_id, + unsigned char *sense) { struct request *rq; + unsigned char stpg_data[8]; int stpg_len = 8; - struct scsi_device *sdev = h-sdev; + int err = 0; /* Prepare the data buffer */ - memset(h-buff, 0, stpg_len); - h-buff[4] = TPGS_STATE_OPTIMIZED 0x0f; - h-buff[6] = (h-group_id 8) 0xff; - h-buff[7] = h-group_id 0xff; + memset(stpg_data, 0, stpg_len); + stpg_data[4] = TPGS_STATE_OPTIMIZED 0x0f; + put_unaligned_be16(group_id, stpg_data[6]); - rq = get_alua_req(sdev, h-buff, stpg_len, WRITE); + rq = get_alua_req(sdev, stpg_data, stpg_len, WRITE); if (!rq) - return SCSI_DH_RES_TEMP_UNAVAIL; + return DRIVER_BUSY 24; /* Prepare the command. */ rq-cmd[0] = MAINTENANCE_OUT; rq-cmd[1] = MO_SET_TARGET_PGS; - rq-cmd[6] = (stpg_len 24) 0xff; - rq-cmd[7] = (stpg_len 16) 0xff; - rq-cmd[8] = (stpg_len 8) 0xff; - rq-cmd[9] = stpg_len 0xff; + put_unaligned_be32(stpg_len, rq-cmd[6]); rq-cmd_len = COMMAND_SIZE(MAINTENANCE_OUT); - rq-sense = h-sense; + rq-sense = sense; memset(rq-sense, 0, SCSI_SENSE_BUFFERSIZE); - rq-sense_len = h-senselen = 0; - rq-end_io_data = h; + rq-sense_len = 0; + + blk_execute_rq(rq-q, NULL, rq, 1); + if (rq-errors) + err = rq-errors; + + blk_put_request(rq); - blk_execute_rq_nowait(rq-q, NULL, rq, 1, stpg_endio); - return SCSI_DH_OK; + return err; } /* @@ -498,7 +450,8 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h, int wait_ retval = submit_rtpg(sdev, h-buff, h-bufflen, h-sense, h-flags); if (retval) { - if (!scsi_normalize_sense(h-sense, SCSI_SENSE_BUFFERSIZE, + if (!(driver_byte(retval) DRIVER_SENSE) || + !scsi_normalize_sense(h-sense, SCSI_SENSE_BUFFERSIZE, sense_hdr)) { sdev_printk(KERN_INFO, sdev, %s: rtpg failed, result %d\n, @@ -624,6 +577,69 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h, int wait_ } /* + * alua_stpg - Issue a SET TARGET GROUP STATES command + * + * Issue a
[PATCH 19/20] scsi_dh_alua: Send TEST UNIT READY to poll for transitioning
Sending a 'REPORT TARGET PORT GROUP' command is a costly operation, as the array has to gather information about all ports. So instead of using RTPG to poll for a status update when a port is in transitioning we should be sending a TEST UNIT READY, and wait for the sense code to report success. Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/device_handler/scsi_dh_alua.c | 33 ++ 1 file changed, 33 insertions(+) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 44b57bc..30310c8 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -549,6 +549,30 @@ static int alua_check_sense(struct scsi_device *sdev, } /* + * alua_tur - Send a TEST UNIT READY + * @sdev: device to which the TEST UNIT READY command should be send + * + * Send a TEST UNIT READY to @sdev to figure out the device state + * Returns SCSI_DH_RETRY if the sense code is NOT READY/ALUA TRANSITIONING, + * SCSI_DH_OK if no error occured, and SCSI_DH_IO otherwise. + */ +static int alua_tur(struct scsi_device *sdev) +{ + struct scsi_sense_hdr sense_hdr; + int retval; + + retval = scsi_test_unit_ready(sdev, ALUA_FAILOVER_TIMEOUT * HZ, + ALUA_FAILOVER_RETRIES, sense_hdr); + if (sense_hdr.sense_key == NOT_READY + sense_hdr.asc == 0x04 sense_hdr.ascq == 0x0a) + return SCSI_DH_RETRY; + else if (retval) + return SCSI_DH_IO; + else + return SCSI_DH_OK; +} + +/* * alua_rtpg - Evaluate REPORT TARGET GROUP STATES * @sdev: the device to be evaluated. * @@ -820,7 +844,16 @@ static void alua_rtpg_work(struct work_struct *work) return; } if (pg-flags ALUA_PG_RUN_RTPG) { + int state = pg-state; spin_unlock_irqrestore(pg-rtpg_lock, flags); + if (state == TPGS_STATE_TRANSITIONING) { + if (alua_tur(sdev) == SCSI_DH_RETRY) { + queue_delayed_work(pg-work_q, pg-rtpg_work, + pg-interval * HZ); + return; + } + /* Send RTPG on failure or if TUR indicates SUCCESS */ + } err = alua_rtpg(sdev, pg); if (err == SCSI_DH_RETRY) { queue_delayed_work(pg-work_q, pg-rtpg_work, -- 1.8.5.2 -- 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 00/10] Integrate scsi_dh better into the scsi core V4
This series ties scsi_dh deeper into the scsi core, and fixes all kinds of issues in it, most importantly the race between using and detaching device handlers. Changes since V1: - updated comments / strings based on review feedback - moved scsi_dh.c to drivers/scsi to fix the srcdir = objdir build - changed the old patch 2 to have saner handling of mismatching device handlers in dm. - dropped patch 1: not having a hw handler is fine if we don't plan to change it anyway - dropped patch 3: not necessary anymore. Changes since V2: - Fixup issues during attaching device_handler from dm-multipath - Add patch to clarify scsi_dh_activate() error codes Changes since V3: - Fixup device handler attach. - Zero out device handler on detach - Move 'dh_state' attribute to generic code Christoph Hellwig (8): dm-mpath, scsi_dh: don't let dm detach device handlers dm-mpath, scsi_dh: request scsi_dh modules in scsi_dh, not dm-mpath scsi_dh: move to drivers/scsi scsi_dh: integrate into the core SCSI code scsi_dh: move device matching to the core code scsi_dh: kill struct scsi_dh_data scsi_dh: add a common helper to get a scsi_device from a request_queue scsi_dh: don't allow to detach device handlers at runtime Hannes Reinecke (2): scsi_dh: return individual errors in scsi_dh_activate() scsi_dh: move 'dh_state' sysfs attribute to generic code drivers/md/dm-mpath.c | 27 +- drivers/scsi/Makefile | 1 + drivers/scsi/device_handler/Kconfig | 2 +- drivers/scsi/device_handler/Makefile| 1 - drivers/scsi/device_handler/scsi_dh.c | 621 drivers/scsi/device_handler/scsi_dh_alua.c | 31 +- drivers/scsi/device_handler/scsi_dh_emc.c | 58 +-- drivers/scsi/device_handler/scsi_dh_hp_sw.c | 55 +-- drivers/scsi/device_handler/scsi_dh_rdac.c | 80 +--- drivers/scsi/scsi_dh.c | 371 + drivers/scsi/scsi_error.c | 6 +- drivers/scsi/scsi_lib.c | 6 +- drivers/scsi/scsi_priv.h| 9 + drivers/scsi/scsi_sysfs.c | 70 include/scsi/scsi_device.h | 27 +- include/scsi/scsi_dh.h | 29 +- 16 files changed, 529 insertions(+), 865 deletions(-) delete mode 100644 drivers/scsi/device_handler/scsi_dh.c create mode 100644 drivers/scsi/scsi_dh.c -- 1.8.5.2 -- 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 04/10] scsi_dh: integrate into the core SCSI code
From: Christoph Hellwig h...@lst.de Stop building scsi_dh as a separate module and integrate it fully into the core SCSI code with explicit callouts at bus scan time. For now the callouts are placed at the same point as the old bus notifiers were called, but in the future we will be able to look at ALUA INQUIRY data earlier on. Note that this also means that the device handler modules need to be loaded by the time we scan the bus. The next patches will add support for autoloading device handlers at bus scan time to make sure they are always loaded if they are enabled in the kernel config. Signed-off-by: Christoph Hellwig h...@lst.de Reviewed-by: Martin K. Petersen martin.peter...@oracle.com Reviewed-by: Hannes Reinecke h...@suse.de Acked-by: Mike Snitzer snit...@redhat.com --- drivers/scsi/Makefile | 2 +- drivers/scsi/device_handler/Kconfig | 2 +- drivers/scsi/scsi_dh.c | 183 +++- drivers/scsi/scsi_priv.h| 9 ++ drivers/scsi/scsi_sysfs.c | 10 ++ include/scsi/scsi_dh.h | 2 +- 6 files changed, 34 insertions(+), 174 deletions(-) diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 22f54b0..ef260bb 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -171,7 +171,7 @@ scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o scsi_mod-$(CONFIG_SCSI_PROC_FS)+= scsi_proc.o scsi_mod-y += scsi_trace.o scsi_logging.o scsi_mod-$(CONFIG_PM) += scsi_pm.o -obj-$(CONFIG_SCSI_DH) += scsi_dh.o +scsi_mod-$(CONFIG_SCSI_DH) += scsi_dh.o hv_storvsc-y := storvsc_drv.o diff --git a/drivers/scsi/device_handler/Kconfig b/drivers/scsi/device_handler/Kconfig index 69abd0a..e5647d5 100644 --- a/drivers/scsi/device_handler/Kconfig +++ b/drivers/scsi/device_handler/Kconfig @@ -3,7 +3,7 @@ # menuconfig SCSI_DH - tristate SCSI Device Handlers + bool SCSI Device Handlers depends on SCSI default n help diff --git a/drivers/scsi/scsi_dh.c b/drivers/scsi/scsi_dh.c index 3c06c72..2d6a8bd 100644 --- a/drivers/scsi/scsi_dh.c +++ b/drivers/scsi/scsi_dh.c @@ -57,15 +57,8 @@ static struct scsi_device_handler *scsi_dh_lookup(const char *name) return dh; } -/* - * device_handler_match_function - Match a device handler to a device - * @sdev - SCSI device to be tested - * - * Tests @sdev against the match function of all registered device_handler. - * Returns the found device handler or NULL if not found. - */ static struct scsi_device_handler * -device_handler_match_function(struct scsi_device *sdev) +device_handler_match(struct scsi_device *sdev) { struct scsi_device_handler *tmp_dh, *found_dh = NULL; @@ -81,29 +74,6 @@ device_handler_match_function(struct scsi_device *sdev) } /* - * device_handler_match - Attach a device handler to a device - * @scsi_dh - The device handler to match against or NULL - * @sdev - SCSI device to be tested against @scsi_dh - * - * Tests @sdev against the device handler @scsi_dh or against - * all registered device_handler if @scsi_dh == NULL. - * Returns the found device handler or NULL if not found. - */ -static struct scsi_device_handler * -device_handler_match(struct scsi_device_handler *scsi_dh, -struct scsi_device *sdev) -{ - struct scsi_device_handler *found_dh; - - found_dh = device_handler_match_function(sdev); - - if (scsi_dh found_dh != scsi_dh) - found_dh = NULL; - - return found_dh; -} - -/* * scsi_dh_handler_attach - Attach a device handler to a device * @sdev - SCSI device the device handler should attach to * @scsi_dh - The device handler to attach @@ -211,119 +181,26 @@ static struct device_attribute scsi_dh_state_attr = __ATTR(dh_state, S_IRUGO | S_IWUSR, show_dh_state, store_dh_state); -/* - * scsi_dh_sysfs_attr_add - Callback for scsi_init_dh - */ -static int scsi_dh_sysfs_attr_add(struct device *dev, void *data) +int scsi_dh_add_device(struct scsi_device *sdev) { - struct scsi_device *sdev; + struct scsi_device_handler *devinfo; int err; - if (!scsi_is_sdev_device(dev)) - return 0; - - sdev = to_scsi_device(dev); - - err = device_create_file(sdev-sdev_gendev, -scsi_dh_state_attr); - - return 0; -} - -/* - * scsi_dh_sysfs_attr_remove - Callback for scsi_exit_dh - */ -static int scsi_dh_sysfs_attr_remove(struct device *dev, void *data) -{ - struct scsi_device *sdev; - - if (!scsi_is_sdev_device(dev)) - return 0; - - sdev = to_scsi_device(dev); - - device_remove_file(sdev-sdev_gendev, - scsi_dh_state_attr); - - return 0; -} + err = device_create_file(sdev-sdev_gendev, scsi_dh_state_attr); + if (err) + return err; -/* - * scsi_dh_notifier - notifier chain
[PATCH 02/10] dm-mpath, scsi_dh: request scsi_dh modules in scsi_dh, not dm-mpath
From: Christoph Hellwig h...@lst.de This way we can reused the same code any attachment method, not just those requested from dm-mpath. Signed-off-by: Christoph Hellwig h...@lst.de Reviewed-by: Martin K. Petersen martin.peter...@oracle.com Reviewed-by: Hannes Reinecke h...@suse.de Acked-by: Mike Snitzer snit...@redhat.com --- drivers/md/dm-mpath.c | 6 -- drivers/scsi/device_handler/scsi_dh.c | 35 ++- include/scsi/scsi_dh.h| 5 - 3 files changed, 18 insertions(+), 28 deletions(-) diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index a9f58fd..5a67671 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -725,12 +725,6 @@ static int parse_hw_handler(struct dm_arg_set *as, struct multipath *m) return 0; m-hw_handler_name = kstrdup(dm_shift_arg(as), GFP_KERNEL); - if (!try_then_request_module(scsi_dh_handler_exist(m-hw_handler_name), -scsi_dh_%s, m-hw_handler_name)) { - ti-error = unknown hardware handler type; - ret = -EINVAL; - goto fail; - } if (hw_argc 1) { char *p; diff --git a/drivers/scsi/device_handler/scsi_dh.c b/drivers/scsi/device_handler/scsi_dh.c index 869b5bd..5bd0af6 100644 --- a/drivers/scsi/device_handler/scsi_dh.c +++ b/drivers/scsi/device_handler/scsi_dh.c @@ -29,7 +29,7 @@ static DEFINE_SPINLOCK(list_lock); static LIST_HEAD(scsi_dh_list); -static struct scsi_device_handler *get_device_handler(const char *name) +static struct scsi_device_handler *__scsi_dh_lookup(const char *name) { struct scsi_device_handler *tmp, *found = NULL; @@ -44,6 +44,19 @@ static struct scsi_device_handler *get_device_handler(const char *name) return found; } +static struct scsi_device_handler *scsi_dh_lookup(const char *name) +{ + struct scsi_device_handler *dh; + + dh = __scsi_dh_lookup(name); + if (!dh) { + request_module(name); + dh = __scsi_dh_lookup(name); + } + + return dh; +} + /* * device_handler_match_function - Match a device handler to a device * @sdev - SCSI device to be tested @@ -158,7 +171,7 @@ store_dh_state(struct device *dev, struct device_attribute *attr, /* * Attach to a device handler */ - if (!(scsi_dh = get_device_handler(buf))) + if (!(scsi_dh = scsi_dh_lookup(buf))) return err; err = scsi_dh_handler_attach(sdev, scsi_dh); } else { @@ -322,8 +335,7 @@ static int scsi_dh_notifier_remove(struct device *dev, void *data) */ int scsi_register_device_handler(struct scsi_device_handler *scsi_dh) { - - if (get_device_handler(scsi_dh-name)) + if (__scsi_dh_lookup(scsi_dh-name)) return -EBUSY; if (!scsi_dh-attach || !scsi_dh-detach) @@ -350,7 +362,7 @@ EXPORT_SYMBOL_GPL(scsi_register_device_handler); int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh) { - if (!get_device_handler(scsi_dh-name)) + if (!__scsi_dh_lookup(scsi_dh-name)) return -ENODEV; bus_for_each_dev(scsi_bus_type, NULL, scsi_dh, @@ -455,17 +467,6 @@ int scsi_dh_set_params(struct request_queue *q, const char *params) EXPORT_SYMBOL_GPL(scsi_dh_set_params); /* - * scsi_dh_handler_exist - Return TRUE(1) if a device handler exists for - * the given name. FALSE(0) otherwise. - * @name - name of the device handler. - */ -int scsi_dh_handler_exist(const char *name) -{ - return (get_device_handler(name) != NULL); -} -EXPORT_SYMBOL_GPL(scsi_dh_handler_exist); - -/* * scsi_dh_attach - Attach device handler * @q - Request queue that is associated with the scsi_device * the handler should be attached to @@ -478,7 +479,7 @@ int scsi_dh_attach(struct request_queue *q, const char *name) struct scsi_device_handler *scsi_dh; int err = 0; - scsi_dh = get_device_handler(name); + scsi_dh = scsi_dh_lookup(name); if (!scsi_dh) return -EINVAL; diff --git a/include/scsi/scsi_dh.h b/include/scsi/scsi_dh.h index 99c9196..966b921 100644 --- a/include/scsi/scsi_dh.h +++ b/include/scsi/scsi_dh.h @@ -57,7 +57,6 @@ enum { }; #if defined(CONFIG_SCSI_DH) || defined(CONFIG_SCSI_DH_MODULE) extern int scsi_dh_activate(struct request_queue *, activate_complete, void *); -extern int scsi_dh_handler_exist(const char *); extern int scsi_dh_attach(struct request_queue *, const char *); extern const char *scsi_dh_attached_handler_name(struct request_queue *, gfp_t); extern int scsi_dh_set_params(struct request_queue *, const char *); @@ -68,10 +67,6 @@ static inline int scsi_dh_activate(struct request_queue *req, fn(data, 0); return 0; } -static inline int scsi_dh_handler_exist(const char *name) -{ - return
[PATCH 08/10] scsi_dh: don't allow to detach device handlers at runtime
From: Christoph Hellwig h...@lst.de The I/O submission and completion pathes call into the device handler without any synchronization agains detachment. So disallow detaching device handlers at runtime. Signed-off-by: Christoph Hellwig h...@lst.de Reviewed-by: Martin K. Petersen martin.peter...@oracle.com Reviewed-by: Hannes Reinecke h...@suse.de --- drivers/scsi/scsi_dh.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/scsi_dh.c b/drivers/scsi/scsi_dh.c index 265e3dd..7723280 100644 --- a/drivers/scsi/scsi_dh.c +++ b/drivers/scsi/scsi_dh.c @@ -180,8 +180,10 @@ store_dh_state(struct device *dev, struct device_attribute *attr, /* * Detach from a device handler */ - scsi_dh_handler_detach(sdev); - err = 0; + sdev_printk(KERN_WARNING, sdev, + can't detach handler %s.\n, + sdev-handler-name); + err = -EINVAL; } else if (!strncmp(buf, activate, 8)) { /* * Activate a device handler -- 1.8.5.2 -- 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 v3 3/3] megaraid_sas : fix whitespace errors
-Original Message- From: Bjorn Helgaas [mailto:bhelg...@google.com] Sent: Wednesday, July 08, 2015 2:23 AM To: Kashyap Desai; Uday Lingala; Sumit Saxena Cc: megaraidlinux@avagotech.com; linux-scsi@vger.kernel.org; James E.J. Bottomley; linux-ker...@vger.kernel.org; Joe Perches; Christoph Hellwig Subject: [PATCH v3 3/3] megaraid_sas : fix whitespace errors Fix whitespace and indentation errors. No code change. Signed-off-by: Bjorn Helgaas bhelg...@google.com --- drivers/scsi/megaraid/megaraid_sas_base.c | 244 ++-- - 1 file changed, 118 insertions(+), 126 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index a9bd592..5156faa 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -273,6 +273,7 @@ static inline void megasas_enable_intr_xscale(struct megasas_instance *instance) { struct megasas_register_set __iomem *regs; + regs = instance-reg_set; writel(0, (regs)-outbound_intr_mask); @@ -289,6 +290,7 @@ megasas_disable_intr_xscale(struct megasas_instance *instance) { struct megasas_register_set __iomem *regs; u32 mask = 0x1f; + regs = instance-reg_set; writel(mask, regs-outbound_intr_mask); /* Dummy readl to force pci flush */ @@ -313,6 +315,7 @@ megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs) { u32 status; u32 mfiStatus = 0; + /* * Check if it is our interrupt */ @@ -348,6 +351,7 @@ megasas_fire_cmd_xscale(struct megasas_instance *instance, struct megasas_register_set __iomem *regs) { unsigned long flags; + spin_lock_irqsave(instance-hba_lock, flags); writel((frame_phys_addr 3)|(frame_count), (regs)-inbound_queue_port); @@ -364,6 +368,7 @@ megasas_adp_reset_xscale(struct megasas_instance *instance, { u32 i; u32 pcidata; + writel(MFI_ADP_RESET, regs-inbound_doorbell); for (i = 0; i 3; i++) @@ -402,7 +407,6 @@ static int megasas_check_reset_xscale(struct megasas_instance *instance, struct megasas_register_set __iomem *regs) { - if ((instance-adprecovery != MEGASAS_HBA_OPERATIONAL) (le32_to_cpu(*instance-consumer) == MEGASAS_ADPRESET_INPROG_SIGN)) @@ -433,7 +437,7 @@ static struct megasas_instance_template megasas_instance_template_xscale = { /** *The following functions are defined for ppc (deviceid : 0x60) -*controllers +*controllers */ /** @@ -444,6 +448,7 @@ static inline void megasas_enable_intr_ppc(struct megasas_instance *instance) { struct megasas_register_set __iomem *regs; + regs = instance-reg_set; writel(0x, (regs)-outbound_doorbell_clear); @@ -462,6 +467,7 @@ megasas_disable_intr_ppc(struct megasas_instance *instance) { struct megasas_register_set __iomem *regs; u32 mask = 0x; + regs = instance-reg_set; writel(mask, regs-outbound_intr_mask); /* Dummy readl to force pci flush */ @@ -522,6 +528,7 @@ megasas_fire_cmd_ppc(struct megasas_instance *instance, struct megasas_register_set __iomem *regs) { unsigned long flags; + spin_lock_irqsave(instance-hba_lock, flags); writel((frame_phys_addr | (frame_count1))|1, (regs)-inbound_queue_port); @@ -566,6 +573,7 @@ static inline void megasas_enable_intr_skinny(struct megasas_instance *instance) { struct megasas_register_set __iomem *regs; + regs = instance-reg_set; writel(0x, (regs)-outbound_intr_mask); @@ -584,6 +592,7 @@ megasas_disable_intr_skinny(struct megasas_instance *instance) { struct megasas_register_set __iomem *regs; u32 mask = 0x; + regs = instance-reg_set; writel(mask, regs-outbound_intr_mask); /* Dummy readl to force pci flush */ @@ -634,8 +643,8 @@ megasas_clear_intr_skinny(struct megasas_register_set __iomem *regs) writel(status, regs-outbound_intr_status); /* - * dummy read to flush PCI - */ + * dummy read to flush PCI + */ readl(regs-outbound_intr_status); return mfiStatus; @@ -654,6 +663,7 @@ megasas_fire_cmd_skinny(struct megasas_instance *instance, struct megasas_register_set __iomem *regs) { unsigned long flags; + spin_lock_irqsave(instance-hba_lock, flags); writel(upper_32_bits(frame_phys_addr), (regs)-inbound_high_queue_port); @@ -706,6 +716,7 @@ static inline void megasas_enable_intr_gen2(struct megasas_instance *instance) { struct megasas_register_set __iomem *regs; + regs = instance-reg_set; writel(0x, (regs)-outbound_doorbell_clear); @@ -725,6 +736,7 @@ megasas_disable_intr_gen2(struct
Re: blk-mq vs kmemleak
On Tue, Jul 07, 2015 at 06:59:37AM -0700, Bart Van Assche wrote: Please note that my test was run with CONFIG_SLUB_DEBUG=y which causes a red zone to be allocated before and after each block of allocated memory. Could that explain the kmalloc-96 objects ? 96 is almost guaranteed to be the sense buffer allocated in scsi_init_request and freed in scsi_exit_request. -- 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 v3 5/5] target: Fix wrong setting of sense format for PI errors
On Mon, Jul 06, 2015 at 04:15:08PM +0300, Sagi Grimberg wrote: PI errors should be reported in a descriptor format sense data. Fix that by adding a desc_format flag to struct sense_info and pass it to scsi_build_sense_buffer() to do the right thing. Do we really need the additional flag? We only need the descriptor sense format because we add the sector information. So just checking for that should be enough, especially when paired with a comment explaining that logic in the source file. -- 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 v3 2/3] megaraid_sas : use dev_printk when possible
On 07/07/2015 10:52 PM, Bjorn Helgaas wrote: Use dev_printk() when possible to make messages more useful. Signed-off-by: Bjorn Helgaas bhelg...@google.com --- drivers/scsi/megaraid/megaraid_sas_base.c | 304 +-- drivers/scsi/megaraid/megaraid_sas_fusion.c | 95 2 files changed, 196 insertions(+), 203 deletions(-) [ .. ] @@ -1873,8 +1872,8 @@ static int megasas_get_ld_vf_affiliation_111(struct megasas_instance *instance, cmd = megasas_get_cmd(instance); if (!cmd) { - printk(KERN_DEBUG megasas: megasas_get_ld_vf_affiliation_111: -Failed to get cmd for scsi%d.\n, + dev_printk(KERN_DEBUG, instance-pdev-dev, megasas_get_ld_vf_affiliation_111: +Failed to get cmd for scsi%d\n, instance-host-host_no); return -ENOMEM; } Makes one wonder why we don't have a 'dev_debug'; dev_notice() and dev_warn() are there ... Otherwise: 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
[Bug 101201] New: hpsa hang when creating ext4 FS
https://bugzilla.kernel.org/show_bug.cgi?id=101201 Bug ID: 101201 Summary: hpsa hang when creating ext4 FS Product: SCSI Drivers Version: 2.5 Kernel Version: 3.16.7-ckt11-1 Hardware: x86-64 OS: Linux Tree: Mainline Status: NEW Severity: normal Priority: P1 Component: Other Assignee: scsi_drivers-ot...@kernel-bugs.osdl.org Reporter: elac...@easter-eggs.com Regression: No Hardware: HP ProLiant DL385p Gen8 with 2 SSD 100G and 2 HD SATA 3TB, configured in HBA mode, no HW RAID set up. I boot on the Debian 8 installer, then - load hpsa - create one partition on each of the SSD - create a soft RAID 1 using mdadm on those 2 partition - raid synchronize successfully - create a pv, then a vg on this raid without problem - doing mkswap on a LV without problem - doing mkfs.ext4 on a LV - the process HANG dmesg gives: [ 1490.566398] hpsa :03:00.0: Abort request on C6:B2:T0:L0 [ 1490.566819] hpsa :03:00.0: ABORT REQUEST on C6:B2:T0:L0 Tag:0x:0030 Command:0x42 SN:0x1687d9 REQUEST SUCCEEDED. [ 1540.309302] hpsa :03:00.0: ABORT REQUEST on C6:B2:T0:L0 Tag:0x:0030 Command:0x42 SN:0x1687d9 FAILED. Aborted command has not completed after 30 seconds. [ 1540.309319] hpsa :03:00.0: Abort request on C6:B2:T1:L0 [ 1540.345047] hpsa :03:00.0: ABORT REQUEST on C6:B2:T1:L0 Tag:0x:0010 Command:0x42 SN:0x1687d8 REQUEST SUCCEEDED. [ 1588.796036] hpsa :03:00.0: ABORT REQUEST on C6:B2:T1:L0 Tag:0x:0010 Command:0x42 SN:0x1687d8 FAILED. Aborted command has not completed after 30 seconds. [ 1588.796090] hpsa :03:00.0: resetting device 6:2:0:0 the mkfs process doesn't finish and I can no longer access disks (parted, etc..) I can repeat this on two identical servers. I looked at kernel changelogs and did not see anything that may fix this on recent releases. -- You are receiving this mail because: You are watching the assignee of the bug. -- 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 1/3] sd: Fixup capacity for ALUA standby or transitioning ports
If a target port is in ALUA 'standby' or 'transitioning' state it might not need to respond to a 'READ CAPACITY' command. So fixup the initialization for these cases. Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/sd.c | 22 ++ 1 file changed, 22 insertions(+) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 3b2fcb4..03fdfa9 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1981,6 +1981,16 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp, * give it one more chance */ if (--reset_retries 0) continue; + if (sense_valid + sshdr.sense_key == NOT_READY + sshdr.asc == 0x04 sshdr.ascq == 0x0a) + /* Target port in transition */ + return 0; + if (sense_valid + sshdr.sense_key == NOT_READY + sshdr.asc == 0x04 sshdr.ascq == 0x0b) + /* Target port in standy state */ + return 0; } retries--; @@ -2063,6 +2073,16 @@ static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp, * give it one more chance */ if (--reset_retries 0) continue; + if (sense_valid + sshdr.sense_key == NOT_READY + sshdr.asc == 0x04 sshdr.ascq == 0x0a) + /* Target port in transition */ + return 0; + if (sense_valid + sshdr.sense_key == NOT_READY + sshdr.asc == 0x04 sshdr.ascq == 0x0b) + /* Target port in standy state */ + return 0; } retries--; @@ -2177,6 +2197,8 @@ got_data: sector_size = 512; sd_printk(KERN_NOTICE, sdkp, Sector size 0 reported, assuming 512.\n); + if (!sdkp-physical_block_size) + sdkp-physical_block_size = sector_size; } if (sector_size != 512 -- 1.8.5.2 -- 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 07/10] scsi_dh: add a common helper to get a scsi_device from a request_queue
From: Christoph Hellwig h...@lst.de And cleanup the various messy opencoded versions of this. Note that this moves the sdev_state checks outside the queue_lock coverage, but as we don't hold the lock over the activation they are only advisory anyway. Signed-off-by: Christoph Hellwig h...@lst.de Reviewed-by: Martin K. Petersen martin.peter...@oracle.com Reviewed-by: Hannes Reinecke h...@suse.de --- drivers/scsi/scsi_dh.c | 99 +++--- 1 file changed, 46 insertions(+), 53 deletions(-) diff --git a/drivers/scsi/scsi_dh.c b/drivers/scsi/scsi_dh.c index bfa6b3a..265e3dd 100644 --- a/drivers/scsi/scsi_dh.c +++ b/drivers/scsi/scsi_dh.c @@ -282,6 +282,20 @@ int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh) } EXPORT_SYMBOL_GPL(scsi_unregister_device_handler); +static struct scsi_device *get_sdev_from_queue(struct request_queue *q) +{ + struct scsi_device *sdev; + unsigned long flags; + + spin_lock_irqsave(q-queue_lock, flags); + sdev = q-queuedata; + if (!sdev || !get_device(sdev-sdev_gendev)) + sdev = NULL; + spin_unlock_irqrestore(q-queue_lock, flags); + + return sdev; +} + /* * scsi_dh_activate - activate the path associated with the scsi_device * corresponding to the given request queue. @@ -297,41 +311,37 @@ EXPORT_SYMBOL_GPL(scsi_unregister_device_handler); */ int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data) { - int err = 0; - unsigned long flags; struct scsi_device *sdev; - struct device *dev = NULL; + int err = SCSI_DH_NOSYS; - spin_lock_irqsave(q-queue_lock, flags); - sdev = q-queuedata; + sdev = get_sdev_from_queue(q); if (!sdev) { - spin_unlock_irqrestore(q-queue_lock, flags); - err = SCSI_DH_NOSYS; if (fn) fn(data, err); return err; } - dev = get_device(sdev-sdev_gendev); - if (!sdev-handler || !dev || - sdev-sdev_state == SDEV_CANCEL || + if (!sdev-handler) + goto out_fn; + if (sdev-sdev_state == SDEV_CANCEL || sdev-sdev_state == SDEV_DEL) - err = SCSI_DH_NOSYS; - if (sdev-sdev_state == SDEV_OFFLINE) - err = SCSI_DH_DEV_OFFLINED; - spin_unlock_irqrestore(q-queue_lock, flags); + goto out_fn; - if (err) { - if (fn) - fn(data, err); - goto out; - } + err = SCSI_DH_DEV_OFFLINED; + if (sdev-sdev_state == SDEV_OFFLINE) + goto out_fn; if (sdev-handler-activate) err = sdev-handler-activate(sdev, fn, data); -out: - put_device(dev); + +out_put_device: + put_device(sdev-sdev_gendev); return err; + +out_fn: + if (fn) + fn(data, err); + goto out_put_device; } EXPORT_SYMBOL_GPL(scsi_dh_activate); @@ -347,21 +357,15 @@ EXPORT_SYMBOL_GPL(scsi_dh_activate); */ int scsi_dh_set_params(struct request_queue *q, const char *params) { - int err = -SCSI_DH_NOSYS; - unsigned long flags; struct scsi_device *sdev; + int err = -SCSI_DH_NOSYS; - spin_lock_irqsave(q-queue_lock, flags); - sdev = q-queuedata; - if (sdev-handler - sdev-handler-set_params - get_device(sdev-sdev_gendev)) - err = 0; - spin_unlock_irqrestore(q-queue_lock, flags); - - if (err) + sdev = get_sdev_from_queue(q); + if (!sdev) return err; - err = sdev-handler-set_params(sdev, params); + + if (sdev-handler sdev-handler-set_params) + err = sdev-handler-set_params(sdev, params); put_device(sdev-sdev_gendev); return err; } @@ -375,23 +379,19 @@ EXPORT_SYMBOL_GPL(scsi_dh_set_params); */ int scsi_dh_attach(struct request_queue *q, const char *name) { - unsigned long flags; struct scsi_device *sdev; struct scsi_device_handler *scsi_dh; int err = 0; - scsi_dh = scsi_dh_lookup(name); - if (!scsi_dh) - return -EINVAL; - - spin_lock_irqsave(q-queue_lock, flags); - sdev = q-queuedata; - if (!sdev || !get_device(sdev-sdev_gendev)) - err = -ENODEV; - spin_unlock_irqrestore(q-queue_lock, flags); + sdev = get_sdev_from_queue(q); + if (!sdev) + return -ENODEV; - if (err) - return err; + scsi_dh = scsi_dh_lookup(name); + if (!scsi_dh) { + err = -EINVAL; + goto out_put_device; + } if (sdev-handler) { if (sdev-handler != scsi_dh) @@ -418,22 +418,15 @@ EXPORT_SYMBOL_GPL(scsi_dh_attach); */ const char *scsi_dh_attached_handler_name(struct request_queue *q, gfp_t gfp) { - unsigned long flags;
[PATCH 01/10] dm-mpath, scsi_dh: don't let dm detach device handlers
From: Christoph Hellwig h...@lst.de While allowing dm-mpath to attach device handlers is a functionality we need for backwards compatibility reason there is no reason to reference count them and detach them if dm-mpath stops using the device for some reason. If the device handler works for the given device it can just stay attached, and we can take the retain_hw_handler codepath. Signed-off-by: Christoph Hellwig h...@lst.de Acked-by: Mike Snitzer snit...@redhat.com Acked-by: Hannes Reinecke h...@suse.de --- drivers/md/dm-mpath.c | 21 +++- drivers/scsi/device_handler/scsi_dh.c | 96 --- include/scsi/scsi_device.h| 1 - include/scsi/scsi_dh.h| 5 -- 4 files changed, 28 insertions(+), 95 deletions(-) diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index eff7bdd..a9f58fd 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -159,12 +159,9 @@ static struct priority_group *alloc_priority_group(void) static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti) { struct pgpath *pgpath, *tmp; - struct multipath *m = ti-private; list_for_each_entry_safe(pgpath, tmp, pgpaths, list) { list_del(pgpath-list); - if (m-hw_handler_name) - scsi_dh_detach(bdev_get_queue(pgpath-path.dev-bdev)); dm_put_device(ti, pgpath-path.dev); free_pgpath(pgpath); } @@ -580,6 +577,7 @@ static struct pgpath *parse_path(struct dm_arg_set *as, struct path_selector *ps q = bdev_get_queue(p-path.dev-bdev); if (m-retain_attached_hw_handler) { +retain: attached_handler_name = scsi_dh_attached_handler_name(q, GFP_KERNEL); if (attached_handler_name) { /* @@ -599,20 +597,14 @@ static struct pgpath *parse_path(struct dm_arg_set *as, struct path_selector *ps } if (m-hw_handler_name) { - /* -* Increments scsi_dh reference, even when using an -* already-attached handler. -*/ r = scsi_dh_attach(q, m-hw_handler_name); if (r == -EBUSY) { - /* -* Already attached to different hw_handler: -* try to reattach with correct one. -*/ - scsi_dh_detach(q); - r = scsi_dh_attach(q, m-hw_handler_name); - } + char b[BDEVNAME_SIZE]; + printk(KERN_INFO dm-mpath: retaining handler on device %s\n, + bdevname(p-path.dev-bdev, b)); + goto retain; + } if (r 0) { ti-error = error attaching hardware handler; dm_put_device(ti, p-path.dev); @@ -624,7 +616,6 @@ static struct pgpath *parse_path(struct dm_arg_set *as, struct path_selector *ps if (r 0) { ti-error = unable to set hardware handler parameters; - scsi_dh_detach(q); dm_put_device(ti, p-path.dev); goto bad; } diff --git a/drivers/scsi/device_handler/scsi_dh.c b/drivers/scsi/device_handler/scsi_dh.c index 1efebc9..869b5bd 100644 --- a/drivers/scsi/device_handler/scsi_dh.c +++ b/drivers/scsi/device_handler/scsi_dh.c @@ -100,14 +100,6 @@ static int scsi_dh_handler_attach(struct scsi_device *sdev, { struct scsi_dh_data *d; - if (sdev-scsi_dh_data) { - if (sdev-scsi_dh_data-scsi_dh != scsi_dh) - return -EBUSY; - - kref_get(sdev-scsi_dh_data-kref); - return 0; - } - if (!try_module_get(scsi_dh-module)) return -EINVAL; @@ -120,7 +112,6 @@ static int scsi_dh_handler_attach(struct scsi_device *sdev, } d-scsi_dh = scsi_dh; - kref_init(d-kref); d-sdev = sdev; spin_lock_irq(sdev-request_queue-queue_lock); @@ -129,12 +120,14 @@ static int scsi_dh_handler_attach(struct scsi_device *sdev, return 0; } -static void __detach_handler (struct kref *kref) +/* + * scsi_dh_handler_detach - Detach a device handler from a device + * @sdev - SCSI device the device handler should be detached from + */ +static void scsi_dh_handler_detach(struct scsi_device *sdev) { - struct scsi_dh_data *scsi_dh_data = - container_of(kref, struct scsi_dh_data, kref); + struct scsi_dh_data *scsi_dh_data = sdev-scsi_dh_data; struct scsi_device_handler *scsi_dh = scsi_dh_data-scsi_dh; - struct scsi_device *sdev = scsi_dh_data-sdev; scsi_dh-detach(sdev); @@ -147,30
Re: [PATCH 3/3] sd: do not try to spin-up disks for ALUA 'transitioning' state
On 7/8/2015 10:41 AM, Hannes Reinecke wrote: If a disk reports an ALUA 'transitioning' state we should not try to spin up the device. Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/sd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 7c0bdaa..180a6e8 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1801,6 +1801,8 @@ sd_spinup_disk(struct scsi_disk *sdkp) if (sense_valid sshdr.sense_key == NOT_READY) { if (sshdr.asc == 4 sshdr.ascq == 3) break; /* manual intervention required */ + if (sshdr.asc == 4 sshdr.ascq == 0xa) + break; /* transitioning */ if (sshdr.asc == 4 sshdr.ascq == 0xb) break; /* standby */ if (sshdr.asc == 4 sshdr.ascq == 0xc) Hi Hannes, Just nit-picking, but do you think that these four if statements can be re-organized to condition (asc == 4) once and OR on the rest? -- 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 10/10] scsi_dh: move 'dh_state' sysfs attribute to generic code
As scsi_dh.c is now always compiled in we should be moving the 'dh_state' attribute to the generic code. Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/scsi_dh.c| 65 --- drivers/scsi/scsi_sysfs.c | 60 +++ 2 files changed, 60 insertions(+), 65 deletions(-) diff --git a/drivers/scsi/scsi_dh.c b/drivers/scsi/scsi_dh.c index a9494f3..42f20f1 100644 --- a/drivers/scsi/scsi_dh.c +++ b/drivers/scsi/scsi_dh.c @@ -153,76 +153,12 @@ static void scsi_dh_handler_detach(struct scsi_device *sdev) module_put(sdev-handler-module); } -/* - * Functions for sysfs attribute 'dh_state' - */ -static ssize_t -store_dh_state(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct scsi_device *sdev = to_scsi_device(dev); - struct scsi_device_handler *scsi_dh; - int err = -EINVAL; - - if (sdev-sdev_state == SDEV_CANCEL || - sdev-sdev_state == SDEV_DEL) - return -ENODEV; - - if (!sdev-handler) { - /* -* Attach to a device handler -*/ - if (!(scsi_dh = scsi_dh_lookup(buf))) - return err; - err = scsi_dh_handler_attach(sdev, scsi_dh); - } else { - if (!strncmp(buf, detach, 6)) { - /* -* Detach from a device handler -*/ - sdev_printk(KERN_WARNING, sdev, - can't detach handler %s.\n, - sdev-handler-name); - err = -EINVAL; - } else if (!strncmp(buf, activate, 8)) { - /* -* Activate a device handler -*/ - if (sdev-handler-activate) - err = sdev-handler-activate(sdev, NULL, NULL); - else - err = 0; - } - } - - return err0?err:count; -} - -static ssize_t -show_dh_state(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct scsi_device *sdev = to_scsi_device(dev); - - if (!sdev-handler) - return snprintf(buf, 20, detached\n); - - return snprintf(buf, 20, %s\n, sdev-handler-name); -} - -static struct device_attribute scsi_dh_state_attr = - __ATTR(dh_state, S_IRUGO | S_IWUSR, show_dh_state, - store_dh_state); - int scsi_dh_add_device(struct scsi_device *sdev) { struct scsi_device_handler *devinfo = NULL; const char *drv; int err; - err = device_create_file(sdev-sdev_gendev, scsi_dh_state_attr); - if (err) - return err; - drv = scsi_dh_find_driver(sdev); if (drv) devinfo = scsi_dh_lookup(drv); @@ -235,7 +171,6 @@ void scsi_dh_remove_device(struct scsi_device *sdev) { if (sdev-handler) scsi_dh_handler_detach(sdev); - device_remove_file(sdev-sdev_gendev, scsi_dh_state_attr); } /* diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index c8a120f..e3c3b86 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -17,6 +17,7 @@ #include scsi/scsi_device.h #include scsi/scsi_host.h #include scsi/scsi_tcq.h +#include scsi/scsi_dh.h #include scsi/scsi_transport.h #include scsi/scsi_driver.h @@ -875,6 +876,62 @@ sdev_show_function(queue_depth, %d\n); static DEVICE_ATTR(queue_depth, S_IRUGO | S_IWUSR, sdev_show_queue_depth, sdev_store_queue_depth); +#ifdef CONFIG_SCSI_DH +static ssize_t +sdev_show_dh_state(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct scsi_device *sdev = to_scsi_device(dev); + + if (!sdev-handler) + return snprintf(buf, 20, detached\n); + + return snprintf(buf, 20, %s\n, sdev-handler-name); +} + +static ssize_t +sdev_store_dh_state(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct scsi_device *sdev = to_scsi_device(dev); + int err = -EINVAL; + + if (sdev-sdev_state == SDEV_CANCEL || + sdev-sdev_state == SDEV_DEL) + return -ENODEV; + + if (!sdev-handler) { + /* +* Attach to a device handler +*/ + err = scsi_dh_attach(sdev-request_queue, buf); + } else { + if (!strncmp(buf, detach, 6)) { + /* +* Detach from a device handler +*/ + sdev_printk(KERN_WARNING, sdev, + can't detach handler %s.\n, + sdev-handler-name); + err =
Re: [PATCH v3 2/5] target: Split transport_send_check_condition_and_sense()
+ if (r == (__force int)TCM_CHECK_CONDITION_UNIT_ATTENTION) { You probably want to compare reason here to avoid the cast. Otherwise looks good, Reviewed-by: Christoph Hellwig h...@lst.de -- 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 v3 1/3] megaraid : use dev_printk when possible
On 07/07/2015 10:52 PM, Bjorn Helgaas wrote: Use dev_printk() when possible to make messages more useful. Signed-off-by: Bjorn Helgaas bhelg...@google.com --- drivers/scsi/megaraid.c | 140 ++- 1 file changed, 66 insertions(+), 74 deletions(-) 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
[PATCH 2/3] scsi: rescan device if an invalid capacity had been reported
Device paths in ALUA state 'standby' do not necessarily support the READ_CAPACITY command. This patch adds a new flag 'invalid_capacity' to the scsi device, and rescans the device if an ALUA state change occurred. Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/scsi_lib.c| 4 drivers/scsi/sd.c | 19 ++- include/scsi/scsi_device.h | 1 + 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index c005e42..d4245f0 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -2701,6 +2701,7 @@ static void scsi_evt_emit(struct scsi_device *sdev, struct scsi_event *evt) envp[idx++] = SDEV_UA=INQUIRY_DATA_HAS_CHANGED; break; case SDEV_EVT_CAPACITY_CHANGE_REPORTED: + scsi_rescan_device(sdev-sdev_gendev); envp[idx++] = SDEV_UA=CAPACITY_DATA_HAS_CHANGED; break; case SDEV_EVT_SOFT_THRESHOLD_REACHED_REPORTED: @@ -2713,6 +2714,9 @@ static void scsi_evt_emit(struct scsi_device *sdev, struct scsi_event *evt) envp[idx++] = SDEV_UA=REPORTED_LUNS_DATA_HAS_CHANGED; break; case SDEV_EVT_ALUA_STATE_CHANGE_REPORTED: + if (sdev-invalid_capacity) + scsi_rescan_device(sdev-sdev_gendev); + envp[idx++] = SDEV_UA=ASYMMETRIC_ACCESS_STATE_CHANGED; break; default: diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 03fdfa9..7c0bdaa 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1983,14 +1983,18 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp, continue; if (sense_valid sshdr.sense_key == NOT_READY - sshdr.asc == 0x04 sshdr.ascq == 0x0a) + sshdr.asc == 0x04 sshdr.ascq == 0x0a) { /* Target port in transition */ + sdp-invalid_capacity = 1; return 0; + } if (sense_valid sshdr.sense_key == NOT_READY - sshdr.asc == 0x04 sshdr.ascq == 0x0b) + sshdr.asc == 0x04 sshdr.ascq == 0x0b) { /* Target port in standy state */ + sdp-invalid_capacity = 1; return 0; + } } retries--; @@ -2075,14 +2079,18 @@ static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp, continue; if (sense_valid sshdr.sense_key == NOT_READY - sshdr.asc == 0x04 sshdr.ascq == 0x0a) + sshdr.asc == 0x04 sshdr.ascq == 0x0a) { /* Target port in transition */ + sdp-invalid_capacity = 1; return 0; + } if (sense_valid sshdr.sense_key == NOT_READY - sshdr.asc == 0x04 sshdr.ascq == 0x0b) + sshdr.asc == 0x04 sshdr.ascq == 0x0b) { /* Target port in standy state */ + sdp-invalid_capacity = 1; return 0; + } } retries--; @@ -2199,7 +2207,8 @@ got_data: assuming 512.\n); if (!sdkp-physical_block_size) sdkp-physical_block_size = sector_size; - } + } else + sdp-invalid_capacity = 0; if (sector_size != 512 sector_size != 1024 diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 50c2a36..99bde5a 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -175,6 +175,7 @@ struct scsi_device { unsigned no_dif:1; /* T10 PI (DIF) should be disabled */ unsigned broken_fua:1; /* Don't set FUA bit */ unsigned lun_in_cdb:1; /* Store LUN bits in CDB[1] */ + unsigned invalid_capacity:1;/* READ_CAPACITY not supported */ atomic_t disk_events_disable_depth; /* disable depth for disk events */ -- 1.8.5.2 -- 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 v1 Resend] mpt2sas: setpci reset kernel oops fix
On Wed, Jul 08, 2015 at 11:17:47AM +0530, Nagarajkumar Narayanan wrote: Note: pci_access_mutex is used only if nytro warpdrive cards (ioc-is_warpdrive based on device id) are used as we could not test this case with other SAS2 HBA cards We can remove this check if this behaviour confirmed from other cards. I don't see any downside of taking the lock, and conditional locking like this is a always a bad sign. -- 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 03/10] scsi_dh: move to drivers/scsi
From: Christoph Hellwig h...@lst.de Prepare for building scsi_dh.c into the core SCSI module by moving it to drivers/scsi. Signed-off-by: Christoph Hellwig h...@lst.de Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/Makefile | 1 + drivers/scsi/device_handler/Makefile | 1 - drivers/scsi/device_handler/scsi_dh.c | 570 -- drivers/scsi/scsi_dh.c| 570 ++ 4 files changed, 571 insertions(+), 571 deletions(-) delete mode 100644 drivers/scsi/device_handler/scsi_dh.c create mode 100644 drivers/scsi/scsi_dh.c diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 91209e3..22f54b0 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -171,6 +171,7 @@ scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o scsi_mod-$(CONFIG_SCSI_PROC_FS)+= scsi_proc.o scsi_mod-y += scsi_trace.o scsi_logging.o scsi_mod-$(CONFIG_PM) += scsi_pm.o +obj-$(CONFIG_SCSI_DH) += scsi_dh.o hv_storvsc-y := storvsc_drv.o diff --git a/drivers/scsi/device_handler/Makefile b/drivers/scsi/device_handler/Makefile index e1d2ea0..09866c5 100644 --- a/drivers/scsi/device_handler/Makefile +++ b/drivers/scsi/device_handler/Makefile @@ -1,7 +1,6 @@ # # SCSI Device Handler # -obj-$(CONFIG_SCSI_DH) += scsi_dh.o obj-$(CONFIG_SCSI_DH_RDAC) += scsi_dh_rdac.o obj-$(CONFIG_SCSI_DH_HP_SW)+= scsi_dh_hp_sw.o obj-$(CONFIG_SCSI_DH_EMC) += scsi_dh_emc.o diff --git a/drivers/scsi/device_handler/scsi_dh.c b/drivers/scsi/device_handler/scsi_dh.c deleted file mode 100644 index 5bd0af6..000 --- a/drivers/scsi/device_handler/scsi_dh.c +++ /dev/null @@ -1,570 +0,0 @@ -/* - * SCSI device handler infrastruture. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Copyright IBM Corporation, 2007 - * Authors: - * Chandra Seetharaman sekha...@us.ibm.com - * Mike Anderson andm...@linux.vnet.ibm.com - */ - -#include linux/slab.h -#include linux/module.h -#include scsi/scsi_dh.h -#include ../scsi_priv.h - -static DEFINE_SPINLOCK(list_lock); -static LIST_HEAD(scsi_dh_list); - -static struct scsi_device_handler *__scsi_dh_lookup(const char *name) -{ - struct scsi_device_handler *tmp, *found = NULL; - - spin_lock(list_lock); - list_for_each_entry(tmp, scsi_dh_list, list) { - if (!strncmp(tmp-name, name, strlen(tmp-name))) { - found = tmp; - break; - } - } - spin_unlock(list_lock); - return found; -} - -static struct scsi_device_handler *scsi_dh_lookup(const char *name) -{ - struct scsi_device_handler *dh; - - dh = __scsi_dh_lookup(name); - if (!dh) { - request_module(name); - dh = __scsi_dh_lookup(name); - } - - return dh; -} - -/* - * device_handler_match_function - Match a device handler to a device - * @sdev - SCSI device to be tested - * - * Tests @sdev against the match function of all registered device_handler. - * Returns the found device handler or NULL if not found. - */ -static struct scsi_device_handler * -device_handler_match_function(struct scsi_device *sdev) -{ - struct scsi_device_handler *tmp_dh, *found_dh = NULL; - - spin_lock(list_lock); - list_for_each_entry(tmp_dh, scsi_dh_list, list) { - if (tmp_dh-match tmp_dh-match(sdev)) { - found_dh = tmp_dh; - break; - } - } - spin_unlock(list_lock); - return found_dh; -} - -/* - * device_handler_match - Attach a device handler to a device - * @scsi_dh - The device handler to match against or NULL - * @sdev - SCSI device to be tested against @scsi_dh - * - * Tests @sdev against the device handler @scsi_dh or against - * all registered device_handler if @scsi_dh == NULL. - * Returns the found device handler or NULL if not found. - */ -static struct scsi_device_handler * -device_handler_match(struct scsi_device_handler *scsi_dh, -struct scsi_device *sdev) -{ - struct scsi_device_handler *found_dh; - - found_dh = device_handler_match_function(sdev); - - if (scsi_dh found_dh !=
[PATCH 06/10] scsi_dh: kill struct scsi_dh_data
From: Christoph Hellwig h...@lst.de Add a -handler and a -handler_data field to struct scsi_device and kill this indirection. Also move struct scsi_device_handler to scsi_dh.h so that changes to it don't require rebuilding every SCSI LLDD. Signed-off-by: Christoph Hellwig h...@lst.de Reviewed-by: Martin K. Petersen martin.peter...@oracle.com Reviewed-by: Hannes Reinecke h...@suse.de --- drivers/scsi/device_handler/scsi_dh_alua.c | 25 -- drivers/scsi/device_handler/scsi_dh_emc.c | 29 +-- drivers/scsi/device_handler/scsi_dh_hp_sw.c | 25 -- drivers/scsi/device_handler/scsi_dh_rdac.c | 30 +--- drivers/scsi/scsi_dh.c | 75 +++-- drivers/scsi/scsi_error.c | 6 +-- drivers/scsi/scsi_lib.c | 6 +-- include/scsi/scsi_device.h | 25 ++ include/scsi/scsi_dh.h | 17 +++ 9 files changed, 98 insertions(+), 140 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index ace2457..cc2773b 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -62,7 +62,6 @@ #define ALUA_OPTIMIZE_STPG 1 struct alua_dh_data { - struct scsi_dh_data dh_data; int group_id; int rel_port; int tpgs; @@ -86,11 +85,6 @@ struct alua_dh_data { static char print_alua_state(int); static int alua_check_sense(struct scsi_device *, struct scsi_sense_hdr *); -static inline struct alua_dh_data *get_alua_data(struct scsi_device *sdev) -{ - return container_of(sdev-scsi_dh_data, struct alua_dh_data, dh_data); -} - static int realloc_buffer(struct alua_dh_data *h, unsigned len) { if (h-buff h-buff != h-inq) @@ -708,7 +702,7 @@ out: */ static int alua_set_params(struct scsi_device *sdev, const char *params) { - struct alua_dh_data *h = get_alua_data(sdev); + struct alua_dh_data *h = sdev-handler_data; unsigned int optimize = 0, argc; const char *p = params; int result = SCSI_DH_OK; @@ -746,7 +740,7 @@ MODULE_PARM_DESC(optimize_stpg, Allow use of a non-optimized path, rather than static int alua_activate(struct scsi_device *sdev, activate_complete fn, void *data) { - struct alua_dh_data *h = get_alua_data(sdev); + struct alua_dh_data *h = sdev-handler_data; int err = SCSI_DH_OK; int stpg = 0; @@ -804,7 +798,7 @@ out: */ static int alua_prep_fn(struct scsi_device *sdev, struct request *req) { - struct alua_dh_data *h = get_alua_data(sdev); + struct alua_dh_data *h = sdev-handler_data; int ret = BLKPREP_OK; if (h-state == TPGS_STATE_TRANSITIONING) @@ -823,14 +817,14 @@ static int alua_prep_fn(struct scsi_device *sdev, struct request *req) * alua_bus_attach - Attach device handler * @sdev: device to be attached to */ -static struct scsi_dh_data *alua_bus_attach(struct scsi_device *sdev) +static int alua_bus_attach(struct scsi_device *sdev) { struct alua_dh_data *h; int err; h = kzalloc(sizeof(*h) , GFP_KERNEL); if (!h) - return ERR_PTR(-ENOMEM); + return -ENOMEM; h-tpgs = TPGS_MODE_UNINITIALIZED; h-state = TPGS_STATE_OPTIMIZED; h-group_id = -1; @@ -843,11 +837,11 @@ static struct scsi_dh_data *alua_bus_attach(struct scsi_device *sdev) if (err != SCSI_DH_OK err != SCSI_DH_DEV_OFFLINED) goto failed; - sdev_printk(KERN_NOTICE, sdev, %s: Attached\n, ALUA_DH_NAME); - return h-dh_data; + sdev-handler_data = h; + return 0; failed: kfree(h); - return ERR_PTR(-EINVAL); + return -EINVAL; } /* @@ -856,10 +850,11 @@ failed: */ static void alua_bus_detach(struct scsi_device *sdev) { - struct alua_dh_data *h = get_alua_data(sdev); + struct alua_dh_data *h = sdev-handler_data; if (h-buff h-inq != h-buff) kfree(h-buff); + sdev-handler_data = NULL; kfree(h); } diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c index fd31e67..e6fb97c 100644 --- a/drivers/scsi/device_handler/scsi_dh_emc.c +++ b/drivers/scsi/device_handler/scsi_dh_emc.c @@ -72,7 +72,6 @@ static const char * lun_state[] = }; struct clariion_dh_data { - struct scsi_dh_data dh_data; /* * Flags: * CLARIION_SHORT_TRESPASS @@ -114,13 +113,6 @@ struct clariion_dh_data { int current_sp; }; -static inline struct clariion_dh_data - *get_clariion_data(struct scsi_device *sdev) -{ - return container_of(sdev-scsi_dh_data, struct clariion_dh_data, - dh_data); -} - /* * Parse MODE_SELECT cmd reply. */ @@ -450,7
[PATCH 09/10] scsi_dh: return individual errors in scsi_dh_activate()
When calling scsi_dh_activate() we should be returning individual errors and not lumping all into one. Reviewed-by: Bart van Assche bart.vanass...@sandisk.com Reviewed-by: Christoph Hellwig h...@lst.de Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/scsi_dh.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/scsi_dh.c b/drivers/scsi/scsi_dh.c index 7723280..a9494f3 100644 --- a/drivers/scsi/scsi_dh.c +++ b/drivers/scsi/scsi_dh.c @@ -325,6 +325,7 @@ int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data) if (!sdev-handler) goto out_fn; + err = SCSI_DH_NOTCONN; if (sdev-sdev_state == SDEV_CANCEL || sdev-sdev_state == SDEV_DEL) goto out_fn; -- 1.8.5.2 -- 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 05/10] scsi_dh: move device matching to the core code
From: Christoph Hellwig h...@lst.de Add a single list of devices that need non-ALUA device handlers to the core scsi_dh code so that we can autoload the modules for them at probe time. While this is a little ugly in terms of architecture it actually significantly simplifies the code in addition to the new autoloading functionality. Signed-off-by: Christoph Hellwig h...@lst.de Reviewed-by: Martin K. Petersen martin.peter...@oracle.com Reviewed-by: Hannes Reinecke h...@suse.de Acked-by: Mike Snitzer snit...@redhat.com --- drivers/scsi/device_handler/scsi_dh_alua.c | 6 --- drivers/scsi/device_handler/scsi_dh_emc.c | 29 -- drivers/scsi/device_handler/scsi_dh_hp_sw.c | 30 --- drivers/scsi/device_handler/scsi_dh_rdac.c | 50 - drivers/scsi/scsi_dh.c | 84 ++--- include/scsi/scsi_device.h | 1 - 6 files changed, 66 insertions(+), 134 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 854b568..ace2457 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -819,11 +819,6 @@ static int alua_prep_fn(struct scsi_device *sdev, struct request *req) } -static bool alua_match(struct scsi_device *sdev) -{ - return (scsi_device_tpgs(sdev) != 0); -} - /* * alua_bus_attach - Attach device handler * @sdev: device to be attached to @@ -877,7 +872,6 @@ static struct scsi_device_handler alua_dh = { .check_sense = alua_check_sense, .activate = alua_activate, .set_params = alua_set_params, - .match = alua_match, }; static int __init alua_init(void) diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c index 6ed1caa..fd31e67 100644 --- a/drivers/scsi/device_handler/scsi_dh_emc.c +++ b/drivers/scsi/device_handler/scsi_dh_emc.c @@ -622,34 +622,6 @@ done: return result; } -static const struct { - char *vendor; - char *model; -} clariion_dev_list[] = { - {DGC, RAID}, - {DGC, DISK}, - {DGC, VRAID}, - {NULL, NULL}, -}; - -static bool clariion_match(struct scsi_device *sdev) -{ - int i; - - if (scsi_device_tpgs(sdev)) - return false; - - for (i = 0; clariion_dev_list[i].vendor; i++) { - if (!strncmp(sdev-vendor, clariion_dev_list[i].vendor, - strlen(clariion_dev_list[i].vendor)) - !strncmp(sdev-model, clariion_dev_list[i].model, - strlen(clariion_dev_list[i].model))) { - return true; - } - } - return false; -} - static struct scsi_dh_data *clariion_bus_attach(struct scsi_device *sdev) { struct clariion_dh_data *h; @@ -698,7 +670,6 @@ static struct scsi_device_handler clariion_dh = { .activate = clariion_activate, .prep_fn= clariion_prep_fn, .set_params = clariion_set_params, - .match = clariion_match, }; static int __init clariion_init(void) diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c index 485d995..1bf10d3 100644 --- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c +++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c @@ -311,35 +311,6 @@ static int hp_sw_activate(struct scsi_device *sdev, return 0; } -static const struct { - char *vendor; - char *model; -} hp_sw_dh_data_list[] = { - {COMPAQ, MSA1000 VOLUME}, - {COMPAQ, HSV110}, - {HP, HSV100}, - {DEC, HSG80}, - {NULL, NULL}, -}; - -static bool hp_sw_match(struct scsi_device *sdev) -{ - int i; - - if (scsi_device_tpgs(sdev)) - return false; - - for (i = 0; hp_sw_dh_data_list[i].vendor; i++) { - if (!strncmp(sdev-vendor, hp_sw_dh_data_list[i].vendor, - strlen(hp_sw_dh_data_list[i].vendor)) - !strncmp(sdev-model, hp_sw_dh_data_list[i].model, - strlen(hp_sw_dh_data_list[i].model))) { - return true; - } - } - return false; -} - static struct scsi_dh_data *hp_sw_bus_attach(struct scsi_device *sdev) { struct hp_sw_dh_data *h; @@ -379,7 +350,6 @@ static struct scsi_device_handler hp_sw_dh = { .detach = hp_sw_bus_detach, .activate = hp_sw_activate, .prep_fn= hp_sw_prep_fn, - .match = hp_sw_match, }; static int __init hp_sw_init(void) diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index b46ace3..d89616f 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c @@ -778,55 +778,6 @@ static int rdac_check_sense(struct scsi_device *sdev, return SCSI_RETURN_NOT_HANDLED;
[PATCH 02/20] scsi_dh_alua: Use vpd_pg83 information
The SCSI device now has the VPD page 0x83 information attached, so there is no need to query it again. Reviewed-by: Christoph Hellwig h...@lst.de Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/device_handler/scsi_dh_alua.c | 83 +- 1 file changed, 13 insertions(+), 70 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 7d01ef0..f15b977 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -131,43 +131,6 @@ static struct request *get_alua_req(struct scsi_device *sdev, } /* - * submit_vpd_inquiry - Issue an INQUIRY VPD page 0x83 command - * @sdev: sdev the command should be sent to - */ -static int submit_vpd_inquiry(struct scsi_device *sdev, struct alua_dh_data *h) -{ - struct request *rq; - int err = SCSI_DH_RES_TEMP_UNAVAIL; - - rq = get_alua_req(sdev, h-buff, h-bufflen, READ); - if (!rq) - goto done; - - /* Prepare the command. */ - rq-cmd[0] = INQUIRY; - rq-cmd[1] = 1; - rq-cmd[2] = 0x83; - rq-cmd[4] = h-bufflen; - rq-cmd_len = COMMAND_SIZE(INQUIRY); - - rq-sense = h-sense; - memset(rq-sense, 0, SCSI_SENSE_BUFFERSIZE); - rq-sense_len = h-senselen = 0; - - err = blk_execute_rq(rq-q, NULL, rq, 1); - if (err == -EIO) { - sdev_printk(KERN_INFO, sdev, - %s: evpd inquiry failed with %x\n, - ALUA_DH_NAME, rq-errors); - h-senselen = rq-sense_len; - err = SCSI_DH_IO; - } - blk_put_request(rq); -done: - return err; -} - -/* * submit_rtpg - Issue a REPORT TARGET GROUP STATES command * @sdev: sdev the command should be sent to */ @@ -359,43 +322,24 @@ static int alua_check_tpgs(struct scsi_device *sdev, struct alua_dh_data *h) } /* - * alua_vpd_inquiry - Evaluate INQUIRY vpd page 0x83 + * alua_check_vpd - Evaluate INQUIRY vpd page 0x83 * @sdev: device to be checked * * Extract the relative target port and the target port group * descriptor from the list of identificators. */ -static int alua_vpd_inquiry(struct scsi_device *sdev, struct alua_dh_data *h) +static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h) { - int len; - unsigned err; unsigned char *d; - retry: - err = submit_vpd_inquiry(sdev, h); - - if (err != SCSI_DH_OK) - return err; - - /* Check if vpd page exceeds initial buffer */ - len = (h-buff[2] 8) + h-buff[3] + 4; - if (len h-bufflen) { - /* Resubmit with the correct length */ - if (realloc_buffer(h, len)) { - sdev_printk(KERN_WARNING, sdev, - %s: kmalloc buffer failed\n, - ALUA_DH_NAME); - /* Temporary failure, bypass */ - return SCSI_DH_DEV_TEMP_BUSY; - } - goto retry; - } + if (!sdev-vpd_pg83) + return SCSI_DH_DEV_UNSUPP; /* -* Now look for the correct descriptor. +* Look for the correct descriptor. */ - d = h-buff + 4; - while (d h-buff + len) { + d = sdev-vpd_pg83 + 4; + while (d sdev-vpd_pg83 + sdev-vpd_pg83_len) { switch (d[1] 0xf) { case 0x4: /* Relative target port */ @@ -422,14 +366,13 @@ static int alua_vpd_inquiry(struct scsi_device *sdev, struct alua_dh_data *h) ALUA_DH_NAME); h-state = TPGS_STATE_OPTIMIZED; h-tpgs = TPGS_MODE_NONE; - err = SCSI_DH_DEV_UNSUPP; - } else { - sdev_printk(KERN_INFO, sdev, - %s: port group %02x rel port %02x\n, - ALUA_DH_NAME, h-group_id, h-rel_port); + return SCSI_DH_DEV_UNSUPP; } + sdev_printk(KERN_INFO, sdev, + %s: port group %02x rel port %02x\n, + ALUA_DH_NAME, h-group_id, h-rel_port); - return err; + return 0; } static char print_alua_state(int state) @@ -692,7 +635,7 @@ static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h) if (err != SCSI_DH_OK) goto out; - err = alua_vpd_inquiry(sdev, h); + err = alua_check_vpd(sdev, h); if (err != SCSI_DH_OK) goto out; -- 1.8.5.2 -- 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
[PATCHv2 00/20] asynchronous ALUA device handler
Hi all, here is an update to the ALUA device handler. The main features are: - Topology discovery: the device handler creates a separate port_group structure, which is used to update all paths to the same port group. With that we achieve a significant reduction of the number of RTPGs. - Asynchronous state update: The ALUA state is now updated from a workqueue item, so all concurrent RTPG calls are coaleasced. The ALUA state update is also triggered by sense codes indicating an ALUA state change. - Use the existing vpd page 0x83 to detect device IDs The patchset is relative to the V3 version of the scsi_dh update. The entire tree can be found at kernel/hare/scsi-devel branch alua.v3 on git.kernel.org As usual, reviews and comments are welcome. Changes to v1: - Split off rtpg workqueue into separate items - User per-port workqueues - Incorporate review from Bart - Incorporate review from hch Hannes Reinecke (20): scsi_dh_alua: Disable ALUA handling for non-disk devices scsi_dh_alua: Use vpd_pg83 information scsi_dh_alua: improved logging scsi_dh_alua: Improve error handling scsi: remove scsi_show_sense_hdr() scsi_dh_alua: use flag for RTPG extended header scsi_dh_alua: Pass buffer as function argument scsi_dh_alua: Make stpg synchronous scsi_dh_alua: switch to scsi_execute() scsi_dh_alua: put sense buffer on stack scsi_dh_alua: Use separate alua_port_group structure scsi_dh_alua: allocate RTPG buffer separately scsi_dh_alua: simplify sense code handling scsi_dh_alua: parse target device id revert scsi_dh_alua: ALUA hander attach should succeed while TPG is transitioning scsi_dh_alua: Use workqueue for RTPG scsi_dh_alua: Recheck state on unit attention scsi_dh_alua: update all port states scsi_dh_alua: Send TEST UNIT READY to poll for transitioning scsi_dh_alua: Update version to 2.0 drivers/scsi/device_handler/scsi_dh_alua.c | 1231 ++-- include/scsi/scsi_dbg.h|2 - 2 files changed, 809 insertions(+), 424 deletions(-) -- 1.8.5.2 -- 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 07/20] scsi_dh_alua: Pass buffer as function argument
Pass in the buffer as a function argument for submit_vpd() and submit_rtpg(). Reviewed-by: Bart Van Assche bart.vanass...@sandisk.com Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/device_handler/scsi_dh_alua.c | 24 +++- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 3f4fe0e..28a3b99 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -22,6 +22,7 @@ #include linux/slab.h #include linux/delay.h #include linux/module.h +#include asm/unaligned.h #include scsi/scsi.h #include scsi/scsi_dbg.h #include scsi/scsi_eh.h @@ -136,12 +137,13 @@ static struct request *get_alua_req(struct scsi_device *sdev, * submit_rtpg - Issue a REPORT TARGET GROUP STATES command * @sdev: sdev the command should be sent to */ -static unsigned submit_rtpg(struct scsi_device *sdev, struct alua_dh_data *h) +static unsigned submit_rtpg(struct scsi_device *sdev, unsigned char *buff, + int bufflen, unsigned char *sense, int flags) { struct request *rq; int err; - rq = get_alua_req(sdev, h-buff, h-bufflen, READ); + rq = get_alua_req(sdev, buff, bufflen, READ); if (!rq) { err = DRIVER_BUSY 24; goto done; @@ -149,25 +151,21 @@ static unsigned submit_rtpg(struct scsi_device *sdev, struct alua_dh_data *h) /* Prepare the command. */ rq-cmd[0] = MAINTENANCE_IN; - if (!(h-flags ALUA_RTPG_EXT_HDR_UNSUPP)) + if (!(flags ALUA_RTPG_EXT_HDR_UNSUPP)) rq-cmd[1] = MI_REPORT_TARGET_PGS | MI_EXT_HDR_PARAM_FMT; else rq-cmd[1] = MI_REPORT_TARGET_PGS; - rq-cmd[6] = (h-bufflen 24) 0xff; - rq-cmd[7] = (h-bufflen 16) 0xff; - rq-cmd[8] = (h-bufflen 8) 0xff; - rq-cmd[9] = h-bufflen 0xff; + put_unaligned_be32(bufflen, rq-cmd[6]); rq-cmd_len = COMMAND_SIZE(MAINTENANCE_IN); - rq-sense = h-sense; + rq-sense = sense; memset(rq-sense, 0, SCSI_SENSE_BUFFERSIZE); - rq-sense_len = h-senselen = 0; + rq-sense_len = 0; blk_execute_rq(rq-q, NULL, rq, 1); - if (rq-errors) { + if (rq-errors) err = rq-errors; - h-senselen = rq-sense_len; - } + blk_put_request(rq); done: return err; @@ -497,7 +495,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h, int wait_ expiry = round_jiffies_up(jiffies + h-transition_tmo * HZ); retry: - retval = submit_rtpg(sdev, h); + retval = submit_rtpg(sdev, h-buff, h-bufflen, h-sense, h-flags); if (retval) { if (!scsi_normalize_sense(h-sense, SCSI_SENSE_BUFFERSIZE, -- 1.8.5.2 -- 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 05/20] scsi: remove scsi_show_sense_hdr()
Last caller is gone, so remove it. Reviewed-by: Bart Van Assche bart.vanass...@sandisk.com Reviewed-by: Reviewed-by: Christoph Hellwig h...@lst.de Signed-off-by: Hannes Reinecke h...@suse.de --- include/scsi/scsi_dbg.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/scsi/scsi_dbg.h b/include/scsi/scsi_dbg.h index f8170e9..56710e0 100644 --- a/include/scsi/scsi_dbg.h +++ b/include/scsi/scsi_dbg.h @@ -12,8 +12,6 @@ extern size_t __scsi_format_command(char *, size_t, const unsigned char *, size_t); extern void scsi_show_extd_sense(const struct scsi_device *, const char *, unsigned char, unsigned char); -extern void scsi_show_sense_hdr(const struct scsi_device *, const char *, - const struct scsi_sense_hdr *); extern void scsi_print_sense_hdr(const struct scsi_device *, const char *, const struct scsi_sense_hdr *); extern void scsi_print_sense(const struct scsi_cmnd *); -- 1.8.5.2 -- 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 04/20] scsi_dh_alua: Improve error handling
Improve error handling and use standard logging functions instead of hand-crafted ones. Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/device_handler/scsi_dh_alua.c | 78 +++--- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index a20c8bf..0b92319 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -23,6 +23,7 @@ #include linux/delay.h #include linux/module.h #include scsi/scsi.h +#include scsi/scsi_dbg.h #include scsi/scsi_eh.h #include scsi/scsi_dh.h @@ -138,11 +139,13 @@ static unsigned submit_rtpg(struct scsi_device *sdev, struct alua_dh_data *h, bool rtpg_ext_hdr_req) { struct request *rq; - int err = SCSI_DH_RES_TEMP_UNAVAIL; + int err; rq = get_alua_req(sdev, h-buff, h-bufflen, READ); - if (!rq) + if (!rq) { + err = DRIVER_BUSY 24; goto done; + } /* Prepare the command. */ rq-cmd[0] = MAINTENANCE_IN; @@ -160,13 +163,10 @@ static unsigned submit_rtpg(struct scsi_device *sdev, struct alua_dh_data *h, memset(rq-sense, 0, SCSI_SENSE_BUFFERSIZE); rq-sense_len = h-senselen = 0; - err = blk_execute_rq(rq-q, NULL, rq, 1); - if (err == -EIO) { - sdev_printk(KERN_INFO, sdev, - %s: rtpg failed with %x\n, - ALUA_DH_NAME, rq-errors); + blk_execute_rq(rq-q, NULL, rq, 1); + if (rq-errors) { + err = rq-errors; h-senselen = rq-sense_len; - err = SCSI_DH_IO; } blk_put_request(rq); done: @@ -174,13 +174,11 @@ done: } /* - * alua_stpg - Evaluate SET TARGET GROUP STATES + * stpg_endio - Evaluate SET TARGET GROUP STATES * @sdev: the device to be evaluated * @state: the new target group state * - * Send a SET TARGET GROUP STATES command to the device. - * We only have to test here if we should resubmit the command; - * any other error is assumed as a failure. + * Evaluate a SET TARGET GROUP STATES command response. */ static void stpg_endio(struct request *req, int error) { @@ -194,22 +192,16 @@ static void stpg_endio(struct request *req, int error) goto done; } - if (req-sense_len 0) { - err = scsi_normalize_sense(h-sense, SCSI_SENSE_BUFFERSIZE, - sense_hdr); - if (!err) { - err = SCSI_DH_IO; - goto done; - } + if (scsi_normalize_sense(h-sense, SCSI_SENSE_BUFFERSIZE, +sense_hdr)) { err = alua_check_sense(h-sdev, sense_hdr); if (err == ADD_TO_MLQUEUE) { err = SCSI_DH_RETRY; goto done; } - sdev_printk(KERN_INFO, h-sdev, - %s: stpg sense code: %02x/%02x/%02x\n, - ALUA_DH_NAME, sense_hdr.sense_key, - sense_hdr.asc, sense_hdr.ascq); + sdev_printk(KERN_INFO, h-sdev, %s: stpg failed\n, + ALUA_DH_NAME); + scsi_print_sense_hdr(h-sdev, ALUA_DH_NAME, sense_hdr); err = SCSI_DH_IO; } else if (error) err = SCSI_DH_IO; @@ -494,7 +486,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h, int wait_ struct scsi_sense_hdr sense_hdr; int len, k, off, valid_states = 0; unsigned char *ucp; - unsigned err; + unsigned err, retval; bool rtpg_ext_hdr_req = 1; unsigned long expiry, interval = 0; unsigned int tpg_desc_tbl_off; @@ -506,13 +498,20 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h, int wait_ expiry = round_jiffies_up(jiffies + h-transition_tmo * HZ); retry: - err = submit_rtpg(sdev, h, rtpg_ext_hdr_req); - - if (err == SCSI_DH_IO h-senselen 0) { - err = scsi_normalize_sense(h-sense, SCSI_SENSE_BUFFERSIZE, - sense_hdr); - if (!err) - return SCSI_DH_IO; + retval = submit_rtpg(sdev, h, rtpg_ext_hdr_req); + + if (retval) { + if (!scsi_normalize_sense(h-sense, SCSI_SENSE_BUFFERSIZE, + sense_hdr)) { + sdev_printk(KERN_INFO, sdev, + %s: rtpg failed, result %d\n, + ALUA_DH_NAME, retval); + if (driver_byte(retval) == DRIVER_BUSY) + err = SCSI_DH_DEV_TEMP_BUSY; + else + err =
[PATCH 06/20] scsi_dh_alua: use flag for RTPG extended header
We should be using a flag when RTPG extended header is not supported, that saves us sending RTPG twice for older arrays. Reviewed-by: Bart Van Assche bart.vanass...@sandisk.com Reviewed-by: Christoph Hellwig h...@lst.de Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/device_handler/scsi_dh_alua.c | 15 +++ 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 0b92319..3f4fe0e 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -59,8 +59,9 @@ #define ALUA_FAILOVER_TIMEOUT 60 #define ALUA_FAILOVER_RETRIES 5 -/* flags passed from user level */ +/* device handler flags */ #define ALUA_OPTIMIZE_STPG 1 +#define ALUA_RTPG_EXT_HDR_UNSUPP 2 struct alua_dh_data { int group_id; @@ -135,8 +136,7 @@ static struct request *get_alua_req(struct scsi_device *sdev, * submit_rtpg - Issue a REPORT TARGET GROUP STATES command * @sdev: sdev the command should be sent to */ -static unsigned submit_rtpg(struct scsi_device *sdev, struct alua_dh_data *h, - bool rtpg_ext_hdr_req) +static unsigned submit_rtpg(struct scsi_device *sdev, struct alua_dh_data *h) { struct request *rq; int err; @@ -149,7 +149,7 @@ static unsigned submit_rtpg(struct scsi_device *sdev, struct alua_dh_data *h, /* Prepare the command. */ rq-cmd[0] = MAINTENANCE_IN; - if (rtpg_ext_hdr_req) + if (!(h-flags ALUA_RTPG_EXT_HDR_UNSUPP)) rq-cmd[1] = MI_REPORT_TARGET_PGS | MI_EXT_HDR_PARAM_FMT; else rq-cmd[1] = MI_REPORT_TARGET_PGS; @@ -487,7 +487,6 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h, int wait_ int len, k, off, valid_states = 0; unsigned char *ucp; unsigned err, retval; - bool rtpg_ext_hdr_req = 1; unsigned long expiry, interval = 0; unsigned int tpg_desc_tbl_off; unsigned char orig_transition_tmo; @@ -498,7 +497,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h, int wait_ expiry = round_jiffies_up(jiffies + h-transition_tmo * HZ); retry: - retval = submit_rtpg(sdev, h, rtpg_ext_hdr_req); + retval = submit_rtpg(sdev, h); if (retval) { if (!scsi_normalize_sense(h-sense, SCSI_SENSE_BUFFERSIZE, @@ -521,10 +520,10 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h, int wait_ * The retry without rtpg_ext_hdr_req set * handles this. */ - if (rtpg_ext_hdr_req == 1 + if (!(h-flags ALUA_RTPG_EXT_HDR_UNSUPP) sense_hdr.sense_key == ILLEGAL_REQUEST sense_hdr.asc == 0x24 sense_hdr.ascq == 0) { - rtpg_ext_hdr_req = 0; + h-flags |= ALUA_RTPG_EXT_HDR_UNSUPP; goto retry; } -- 1.8.5.2 -- 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 v3 2/3] megaraid_sas : use dev_printk when possible
On Wed, Jul 8, 2015 at 5:47 AM, Hannes Reinecke h...@suse.de wrote: On 07/07/2015 10:52 PM, Bjorn Helgaas wrote: Use dev_printk() when possible to make messages more useful. Signed-off-by: Bjorn Helgaas bhelg...@google.com --- drivers/scsi/megaraid/megaraid_sas_base.c | 304 +-- drivers/scsi/megaraid/megaraid_sas_fusion.c | 95 2 files changed, 196 insertions(+), 203 deletions(-) [ .. ] @@ -1873,8 +1872,8 @@ static int megasas_get_ld_vf_affiliation_111(struct megasas_instance *instance, cmd = megasas_get_cmd(instance); if (!cmd) { - printk(KERN_DEBUG megasas: megasas_get_ld_vf_affiliation_111: -Failed to get cmd for scsi%d.\n, + dev_printk(KERN_DEBUG, instance-pdev-dev, megasas_get_ld_vf_affiliation_111: +Failed to get cmd for scsi%d\n, instance-host-host_no); return -ENOMEM; } Makes one wonder why we don't have a 'dev_debug'; dev_notice() and dev_warn() are there ... There actually is a 'dev_dbg()' but when CONFIG_DYNAMIC_DEBUG is set, I think dev_dbg() generates no output by default. So to preserve the previous behavior of this message always appears in the dmesg log no matter what the dynamic debug setting, I used dev_printk(KERN_DEBUG). Somebody who maintains these drivers could probably go through and convert these to either dev_info() or dev_dbg() depending on what they need. That would require more judgment than I wanted to get into :) Thanks for taking a look at these! Bjorn -- 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 v3 5/5] target: Fix wrong setting of sense format for PI errors
On 7/8/2015 2:14 PM, Sagi Grimberg wrote: And it's actually not true that you'd need descriptor sense to encode the sector information; it'll be stored in the 'information' section (byte 3-6) for fixed format sense. But when I return the sector info in a fixed size format, the initiator is not able to decode the faulty sector: kernel: DIFv1 Type 1 reference failed on sector: 15 tag: 0xfff0 sector MSB: 0x000f kernel: sd 10:0:1:0: [sdc] tag#0 FAILED Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE kernel: sd 10:0:1:0: [sdc] tag#0 Sense Key : Aborted Command [current] kernel: sd 10:0:1:0: [sdc] tag#0 Add. Sense: No additional sense information kernel: sd 10:0:1:0: [sdc] tag#0 CDB: Read(10) 28 20 00 00 00 00 00 00 10 00 kernel: blk_update_request: I/O error, dev sdc, sector 0 Is that a bug? Bleh, found the bug... It was in scsi_set_sense_information() For Fixed sized sense the information field is 4 bytes so this fixes it: diff --git a/drivers/scsi/scsi_common.c b/drivers/scsi/scsi_common.c index 41432c1..8cfb7ee 100644 --- a/drivers/scsi/scsi_common.c +++ b/drivers/scsi/scsi_common.c @@ -270,7 +270,7 @@ void scsi_set_sense_information(u8 *buf, u64 info) put_unaligned_be64(info, ucp[4]); } else if ((buf[0] 0x7f) == 0x70) { buf[0] |= 0x80; - put_unaligned_be64(info, buf[3]); + put_unaligned_be32(info, buf[3]); } } EXPORT_SYMBOL(scsi_set_sense_information); I'll send out a separate patch. Thanks Hannes and Christoph for catching this. Sagi. -- 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 v4 4/5] target: Use scsi helpers to build the sense data correctly
Instead of open coding the sense buffer construction, use scsi scsi_build_sense_buffer() and scsi_set_sense_information() helpers which moved to scsi_common. Signed-off-by: Sagi Grimberg sa...@mellanox.com Reviewed-by: Christoph Hellwig h...@lst.de --- drivers/target/target_core_spc.c | 31 +-- drivers/target/target_core_transport.c | 21 - 2 files changed, 9 insertions(+), 43 deletions(-) diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index b074443..c43dcbf 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -1157,32 +1157,11 @@ static sense_reason_t spc_emulate_request_sense(struct se_cmd *cmd) if (!rbuf) return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - if (!core_scsi3_ua_clear_for_request_sense(cmd, ua_asc, ua_ascq)) { - /* -* CURRENT ERROR, UNIT ATTENTION -*/ - buf[0] = 0x70; - buf[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION; - - /* -* The Additional Sense Code (ASC) from the UNIT ATTENTION -*/ - buf[SPC_ASC_KEY_OFFSET] = ua_asc; - buf[SPC_ASCQ_KEY_OFFSET] = ua_ascq; - buf[7] = 0x0A; - } else { - /* -* CURRENT ERROR, NO SENSE -*/ - buf[0] = 0x70; - buf[SPC_SENSE_KEY_OFFSET] = NO_SENSE; - - /* -* NO ADDITIONAL SENSE INFORMATION -*/ - buf[SPC_ASC_KEY_OFFSET] = 0x00; - buf[7] = 0x0A; - } + if (!core_scsi3_ua_clear_for_request_sense(cmd, ua_asc, ua_ascq)) + scsi_build_sense_buffer(0, buf, UNIT_ATTENTION, + ua_asc, ua_ascq); + else + scsi_build_sense_buffer(0, buf, NO_SENSE, 0x0, 0x0); memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd-data_length)); transport_kunmap_data_sg(cmd); diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 31373f3..923e69d 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -38,6 +38,7 @@ #include net/sock.h #include net/tcp.h #include scsi/scsi_proto.h +#include scsi/scsi_common.h #include target/target_core_base.h #include target/target_core_backend.h @@ -2620,19 +2621,6 @@ bool transport_wait_for_tasks(struct se_cmd *cmd) } EXPORT_SYMBOL(transport_wait_for_tasks); -static -void transport_err_sector_info(unsigned char *buffer, sector_t bad_sector) -{ - /* Place failed LBA in sense data information descriptor 0. */ - buffer[SPC_ADD_SENSE_LEN_OFFSET] = 0xc; - buffer[SPC_DESC_TYPE_OFFSET] = 0; /* Information */ - buffer[SPC_ADDITIONAL_DESC_LEN_OFFSET] = 0xa; - buffer[SPC_VALIDITY_OFFSET] = 0x80; - - /* Descriptor Information: failing sector */ - put_unaligned_be64(bad_sector, buffer[12]); -} - struct sense_info { u8 key; u8 asc; @@ -2759,7 +2747,6 @@ static void translate_sense_reason(struct se_cmd *cmd, sense_reason_t reason) si = sense_info_table[(__force int) TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE]; - buffer[SPC_SENSE_KEY_OFFSET] = si-key; if (reason == TCM_CHECK_CONDITION_UNIT_ATTENTION) { core_scsi3_ua_for_check_condition(cmd, asc, ascq); WARN_ON_ONCE(asc == 0); @@ -2771,10 +2758,10 @@ static void translate_sense_reason(struct se_cmd *cmd, sense_reason_t reason) asc = si-asc; ascq = si-ascq; } - buffer[SPC_ASC_KEY_OFFSET] = asc; - buffer[SPC_ASCQ_KEY_OFFSET] = ascq; + + scsi_build_sense_buffer(0, buffer, si-key, asc, ascq); if (si-add_sector_info) - transport_err_sector_info(cmd-sense_buffer, cmd-bad_sector); + scsi_set_sense_information(buffer, cmd-bad_sector); } int -- 1.8.4.3 -- 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 v4 4/5] target: Use scsi helpers to build the sense data correctly
On 07/08/2015 04:58 PM, Sagi Grimberg wrote: Instead of open coding the sense buffer construction, use scsi scsi_build_sense_buffer() and scsi_set_sense_information() helpers which moved to scsi_common. Signed-off-by: Sagi Grimberg sa...@mellanox.com Reviewed-by: Christoph Hellwig h...@lst.de --- drivers/target/target_core_spc.c | 31 +-- drivers/target/target_core_transport.c | 21 - 2 files changed, 9 insertions(+), 43 deletions(-) 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
[PATCH v4 5/5] target: Return ABORTED_COMMAND sense key for PI errors
PI errors were reported with ILLEGAL_REQUEST sense key but there was actually no problem with the request. Target detected PI errors should be reported with aborted command sense key. Signed-off-by: Sagi Grimberg sa...@mellanox.com --- drivers/target/target_core_transport.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 923e69d..1847fdc 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2705,19 +2705,19 @@ static const struct sense_info sense_info_table[] = { .ascq = 0x00, }, [TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED] = { - .key = ILLEGAL_REQUEST, + .key = ABORTED_COMMAND, .asc = 0x10, .ascq = 0x01, /* LOGICAL BLOCK GUARD CHECK FAILED */ .add_sector_info = true, }, [TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED] = { - .key = ILLEGAL_REQUEST, + .key = ABORTED_COMMAND, .asc = 0x10, .ascq = 0x02, /* LOGICAL BLOCK APPLICATION TAG CHECK FAILED */ .add_sector_info = true, }, [TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED] = { - .key = ILLEGAL_REQUEST, + .key = ABORTED_COMMAND, .asc = 0x10, .ascq = 0x03, /* LOGICAL BLOCK REFERENCE TAG CHECK FAILED */ .add_sector_info = true, -- 1.8.4.3 -- 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 v4 3/5] scsi: Move sense handling routines to scsi_common
Sense data handling is also done in the target stack. Hence, move sense handling routines to scsi_common so the target will be able to use them as well. Signed-off-by: Sagi Grimberg sa...@mellanox.com Reviewed-by: Bart Van Assche bart.vanass...@sandisk.com Reviewed-by: Christoph Hellwig h...@lst.de --- drivers/scsi/scsi_common.c | 98 + drivers/scsi/scsi_error.c | 99 +- include/scsi/scsi_common.h | 5 +++ include/scsi/scsi_eh.h | 7 +--- 4 files changed, 105 insertions(+), 104 deletions(-) diff --git a/drivers/scsi/scsi_common.c b/drivers/scsi/scsi_common.c index 2ff0922..41432c1 100644 --- a/drivers/scsi/scsi_common.c +++ b/drivers/scsi/scsi_common.c @@ -5,6 +5,7 @@ #include linux/bug.h #include linux/kernel.h #include linux/string.h +#include asm/unaligned.h #include scsi/scsi_common.h /* NB: These are exposed through /proc/scsi/scsi and form part of the ABI. @@ -176,3 +177,100 @@ bool scsi_normalize_sense(const u8 *sense_buffer, int sb_len, return true; } EXPORT_SYMBOL(scsi_normalize_sense); + +/** + * scsi_sense_desc_find - search for a given descriptor type in descriptor sense data format. + * @sense_buffer: byte array of descriptor format sense data + * @sb_len:number of valid bytes in sense_buffer + * @desc_type: value of descriptor type to find + * (e.g. 0 - information) + * + * Notes: + * only valid when sense data is in descriptor format + * + * Return value: + * pointer to start of (first) descriptor if found else NULL + */ +const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len, + int desc_type) +{ + int add_sen_len, add_len, desc_len, k; + const u8 * descp; + + if ((sb_len 8) || (0 == (add_sen_len = sense_buffer[7]))) + return NULL; + if ((sense_buffer[0] 0x72) || (sense_buffer[0] 0x73)) + return NULL; + add_sen_len = (add_sen_len (sb_len - 8)) ? + add_sen_len : (sb_len - 8); + descp = sense_buffer[8]; + for (desc_len = 0, k = 0; k add_sen_len; k += desc_len) { + descp += desc_len; + add_len = (k (add_sen_len - 1)) ? descp[1]: -1; + desc_len = add_len + 2; + if (descp[0] == desc_type) + return descp; + if (add_len 0) // short descriptor ?? + break; + } + return NULL; +} +EXPORT_SYMBOL(scsi_sense_desc_find); + +/** + * scsi_build_sense_buffer - build sense data in a buffer + * @desc: Sense format (non zero == descriptor format, + * 0 == fixed format) + * @buf: Where to build sense data + * @key: Sense key + * @asc: Additional sense code + * @ascq: Additional sense code qualifier + * + **/ +void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq) +{ + if (desc) { + buf[0] = 0x72; /* descriptor, current */ + buf[1] = key; + buf[2] = asc; + buf[3] = ascq; + buf[7] = 0; + } else { + buf[0] = 0x70; /* fixed, current */ + buf[2] = key; + buf[7] = 0xa; + buf[12] = asc; + buf[13] = ascq; + } +} +EXPORT_SYMBOL(scsi_build_sense_buffer); + +/** + * scsi_set_sense_information - set the information field in a + * formatted sense data buffer + * @buf: Where to build sense data + * @info: 64-bit information value to be set + * + **/ +void scsi_set_sense_information(u8 *buf, u64 info) +{ + if ((buf[0] 0x7f) == 0x72) { + u8 *ucp, len; + + len = buf[7]; + ucp = (char *)scsi_sense_desc_find(buf, len + 8, 0); + if (!ucp) { + buf[7] = len + 0xa; + ucp = buf + 8 + len; + } + ucp[0] = 0; + ucp[1] = 0xa; + ucp[2] = 0x80; /* Valid bit */ + ucp[3] = 0; + put_unaligned_be64(info, ucp[4]); + } else if ((buf[0] 0x7f) == 0x70) { + buf[0] |= 0x80; + put_unaligned_be64(info, buf[3]); + } +} +EXPORT_SYMBOL(scsi_set_sense_information); diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 106884a..6e6b2d2 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -26,7 +26,6 @@ #include linux/blkdev.h #include linux/delay.h #include linux/jiffies.h -#include asm/unaligned.h #include scsi/scsi.h #include scsi/scsi_cmnd.h @@ -34,6 +33,7 @@ #include scsi/scsi_device.h #include scsi/scsi_driver.h #include scsi/scsi_eh.h +#include scsi/scsi_common.h #include scsi/scsi_transport.h #include scsi/scsi_host.h #include scsi/scsi_ioctl.h @@ -2408,45 +2408,6 @@ bool
[PATCH] lpfc: Destroy lpfc_hba_index IDR on module exit
Destroy lpfc_hba_index IDR on module exit, reclaiming the allocated memory. This was detected by the following semantic patch (written by Luis Rodriguez mcg...@suse.com) SmPL @ defines_module_init @ declarer name module_init, module_exit; declarer name DEFINE_IDR; identifier init; @@ module_init(init); @ defines_module_exit @ identifier exit; @@ module_exit(exit); @ declares_idr depends on defines_module_init defines_module_exit @ identifier idr; @@ DEFINE_IDR(idr); @ on_exit_calls_destroy depends on declares_idr defines_module_exit @ identifier declares_idr.idr, defines_module_exit.exit; @@ exit(void) { ... idr_destroy(idr); ... } @ missing_module_idr_destroy depends on declares_idr defines_module_exit !on_exit_calls_destroy @ identifier declares_idr.idr, defines_module_exit.exit; @@ exit(void) { ... +idr_destroy(idr); } /SmPL Signed-off-by: Johannes Thumshirn jthumsh...@suse.de --- drivers/scsi/lpfc/lpfc_init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index f962118..4bedb06 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -11477,6 +11477,7 @@ lpfc_exit(void) free_pages((unsigned long)_dump_buf_dif, _dump_buf_dif_order); } kfree(lpfc_used_cpu); + idr_destroy(lpfc_hba_index); } module_init(lpfc_init); -- 2.4.3 -- 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 v4 3/5] scsi: Move sense handling routines to scsi_common
On 7/8/2015 6:06 PM, Hannes Reinecke wrote: We're adding extra fields here, so we need to make sure to not overflow the buffer. You probably have to pass in the buffersize to avoid an overflow ... Yeah, I know, it's theoretical at the moment. But there's nothing which prevents anyone to add other fields to it, so this field might be the one causing the overflow. Since this patch is simply a movement of functions I don't think I should change any functionality here. Would it be acceptable to fix this in an incremental patch? -- 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] st: Destroy st_index_idr on module exit
Destroy st_index_idr on module exit, reclaiming the allocated memory. This was detected by the following semantic patch (written by Luis Rodriguez mcg...@suse.com) SmPL @ defines_module_init @ declarer name module_init, module_exit; declarer name DEFINE_IDR; identifier init; @@ module_init(init); @ defines_module_exit @ identifier exit; @@ module_exit(exit); @ declares_idr depends on defines_module_init defines_module_exit @ identifier idr; @@ DEFINE_IDR(idr); @ on_exit_calls_destroy depends on declares_idr defines_module_exit @ identifier declares_idr.idr, defines_module_exit.exit; @@ exit(void) { ... idr_destroy(idr); ... } @ missing_module_idr_destroy depends on declares_idr defines_module_exit !on_exit_calls_destroy @ identifier declares_idr.idr, defines_module_exit.exit; @@ exit(void) { ... +idr_destroy(idr); } /SmPL Signed-off-by: Johannes Thumshirn jthumsh...@suse.de --- drivers/scsi/st.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 3f25b8f..79ac024 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -4427,6 +4427,7 @@ static void __exit exit_st(void) unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0), ST_MAX_TAPE_ENTRIES); class_unregister(st_sysfs_class); + idr_destroy(st_index_idr); printk(KERN_INFO st: Unloaded.\n); } -- 2.4.3 -- 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 v4 3/5] scsi: Move sense handling routines to scsi_common
On 07/08/2015 04:58 PM, Sagi Grimberg wrote: Sense data handling is also done in the target stack. Hence, move sense handling routines to scsi_common so the target will be able to use them as well. Signed-off-by: Sagi Grimberg sa...@mellanox.com Reviewed-by: Bart Van Assche bart.vanass...@sandisk.com Reviewed-by: Christoph Hellwig h...@lst.de --- drivers/scsi/scsi_common.c | 98 + drivers/scsi/scsi_error.c | 99 +- include/scsi/scsi_common.h | 5 +++ include/scsi/scsi_eh.h | 7 +--- 4 files changed, 105 insertions(+), 104 deletions(-) diff --git a/drivers/scsi/scsi_common.c b/drivers/scsi/scsi_common.c index 2ff0922..41432c1 100644 --- a/drivers/scsi/scsi_common.c +++ b/drivers/scsi/scsi_common.c @@ -5,6 +5,7 @@ #include linux/bug.h #include linux/kernel.h #include linux/string.h +#include asm/unaligned.h #include scsi/scsi_common.h /* NB: These are exposed through /proc/scsi/scsi and form part of the ABI. @@ -176,3 +177,100 @@ bool scsi_normalize_sense(const u8 *sense_buffer, int sb_len, return true; } EXPORT_SYMBOL(scsi_normalize_sense); + +/** + * scsi_sense_desc_find - search for a given descriptor type in descriptor sense data format. + * @sense_buffer:byte array of descriptor format sense data + * @sb_len: number of valid bytes in sense_buffer + * @desc_type: value of descriptor type to find + * (e.g. 0 - information) + * + * Notes: + * only valid when sense data is in descriptor format + * + * Return value: + * pointer to start of (first) descriptor if found else NULL + */ +const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len, + int desc_type) +{ + int add_sen_len, add_len, desc_len, k; + const u8 * descp; + + if ((sb_len 8) || (0 == (add_sen_len = sense_buffer[7]))) + return NULL; + if ((sense_buffer[0] 0x72) || (sense_buffer[0] 0x73)) + return NULL; + add_sen_len = (add_sen_len (sb_len - 8)) ? + add_sen_len : (sb_len - 8); + descp = sense_buffer[8]; + for (desc_len = 0, k = 0; k add_sen_len; k += desc_len) { + descp += desc_len; + add_len = (k (add_sen_len - 1)) ? descp[1]: -1; + desc_len = add_len + 2; + if (descp[0] == desc_type) + return descp; + if (add_len 0) // short descriptor ?? + break; + } + return NULL; +} +EXPORT_SYMBOL(scsi_sense_desc_find); + +/** + * scsi_build_sense_buffer - build sense data in a buffer + * @desc:Sense format (non zero == descriptor format, + * 0 == fixed format) + * @buf: Where to build sense data + * @key: Sense key + * @asc: Additional sense code + * @ascq:Additional sense code qualifier + * + **/ +void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq) +{ + if (desc) { + buf[0] = 0x72; /* descriptor, current */ + buf[1] = key; + buf[2] = asc; + buf[3] = ascq; + buf[7] = 0; + } else { + buf[0] = 0x70; /* fixed, current */ + buf[2] = key; + buf[7] = 0xa; + buf[12] = asc; + buf[13] = ascq; + } +} +EXPORT_SYMBOL(scsi_build_sense_buffer); + +/** + * scsi_set_sense_information - set the information field in a + * formatted sense data buffer + * @buf: Where to build sense data + * @info:64-bit information value to be set + * + **/ +void scsi_set_sense_information(u8 *buf, u64 info) +{ + if ((buf[0] 0x7f) == 0x72) { + u8 *ucp, len; + + len = buf[7]; + ucp = (char *)scsi_sense_desc_find(buf, len + 8, 0); + if (!ucp) { + buf[7] = len + 0xa; + ucp = buf + 8 + len; + } We're adding extra fields here, so we need to make sure to not overflow the buffer. You probably have to pass in the buffersize to avoid an overflow ... Yeah, I know, it's theoretical at the moment. But there's nothing which prevents anyone to add other fields to it, so this field might be the one causing the overflow. 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
[PATCH v4 0/5] Target sense data handling modifications
This patch set modifies the target sense data handling. First, cleanup transport_send_check_condition_and_sense() by splitting the sense translation to a separate function. Second, convert sense reason the switch statement to a table driven code. Third, Use scsi common helpers to correctly set the sense buffer. Last, Fix sense key wrong setting of t10-pi errors. Changes from v2: - Removed wrong patch 5/5 for descriptor format sense data - Added a patch (5/5) that fixes wrong sense key for PI errors - Incorporate hch's comments - Added Reviewed-by tags Changes from v2: - Pass sense_reason_t to scsi_translate_sense() - Split patch 3: 1) move the helpers to scsi_common.c 2) use helpers in the target code 3) always use descriptor-type sense data for PI errors Changes from v1: - Added Reviewed-by tags for patches 1,2 - Fixed compilation error after testing patch #3 on scsi/for-next branch. Moved scsi_sense_desc_find() to scsi_common as well (dependency) and also moved asm/unaligned.h include to scsi_common.h Changes from v0: - Added Bart's patches and converted my patch to apply over his - Moved scsi sense helpers to scsi_common Bart Van Assche (2): target: Inline transport_get_sense_codes() target: Split transport_send_check_condition_and_sense() Sagi Grimberg (3): scsi: Move sense handling routines to scsi_common target: Use scsi helpers to build the sense data correctly target: Return ABORTED_COMMAND sense key for PI errors drivers/scsi/scsi_common.c | 98 drivers/scsi/scsi_error.c | 99 + drivers/target/target_core_spc.c | 31 +-- drivers/target/target_core_transport.c | 396 - include/scsi/scsi_common.h | 5 + include/scsi/scsi_eh.h | 7 +- 6 files changed, 252 insertions(+), 384 deletions(-) -- 1.8.4.3 -- 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 v4 1/5] target: Inline transport_get_sense_codes()
From: Bart Van Assche bart.vanass...@sandisk.com Inline this function in its call site since it performs a trivial task and since it is only called once. Signed-off-by: Bart Van Assche bart.vanass...@sandisk.com Signed-off-by: Sagi Grimberg sa...@mellanox.com Reviewed-by: Hannes Reinecke h...@suse.de Reviewed-by: Christoph Hellwig h...@lst.de --- drivers/target/target_core_transport.c | 16 ++-- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 1bc8378..e895156 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2620,17 +2620,6 @@ bool transport_wait_for_tasks(struct se_cmd *cmd) } EXPORT_SYMBOL(transport_wait_for_tasks); -static int transport_get_sense_codes( - struct se_cmd *cmd, - u8 *asc, - u8 *ascq) -{ - *asc = cmd-scsi_asc; - *ascq = cmd-scsi_ascq; - - return 0; -} - static void transport_err_sector_info(unsigned char *buffer, sector_t bad_sector) { @@ -2824,9 +2813,8 @@ transport_send_check_condition_and_sense(struct se_cmd *cmd, buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; /* Not Ready */ buffer[SPC_SENSE_KEY_OFFSET] = NOT_READY; - transport_get_sense_codes(cmd, asc, ascq); - buffer[SPC_ASC_KEY_OFFSET] = asc; - buffer[SPC_ASCQ_KEY_OFFSET] = ascq; + buffer[SPC_ASC_KEY_OFFSET] = cmd-scsi_asc; + buffer[SPC_ASCQ_KEY_OFFSET] = cmd-scsi_ascq; break; case TCM_MISCOMPARE_VERIFY: /* CURRENT ERROR */ -- 1.8.4.3 -- 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 v4 2/5] target: Split transport_send_check_condition_and_sense()
From: Bart Van Assche bart.vanass...@sandisk.com Move the code for translating a sense_reason_t code into a SCSI status ASC and ASCQ codes from transport_send_check_condition_and_sense() into the new function translate_sense_reason(). Convert the switch statement that performs the translation into table-driven code. Signed-off-by: Bart Van Assche bart.vanass...@sandisk.com Signed-off-by: Sagi Grimberg sa...@mellanox.com Reviewed-by: Hannes Reinecke h...@suse.de Reviewed-by: Christoph Hellwig h...@lst.de --- drivers/target/target_core_transport.c | 383 + 1 file changed, 148 insertions(+), 235 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index e895156..31373f3 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2633,13 +2633,155 @@ void transport_err_sector_info(unsigned char *buffer, sector_t bad_sector) put_unaligned_be64(bad_sector, buffer[12]); } +struct sense_info { + u8 key; + u8 asc; + u8 ascq; + bool add_sector_info; +}; + +static const struct sense_info sense_info_table[] = { + [TCM_NO_SENSE] = { + .key = NOT_READY + }, + [TCM_NON_EXISTENT_LUN] = { + .key = ILLEGAL_REQUEST, + .asc = 0x25 /* LOGICAL UNIT NOT SUPPORTED */ + }, + [TCM_UNSUPPORTED_SCSI_OPCODE] = { + .key = ILLEGAL_REQUEST, + .asc = 0x20, /* INVALID COMMAND OPERATION CODE */ + }, + [TCM_SECTOR_COUNT_TOO_MANY] = { + .key = ILLEGAL_REQUEST, + .asc = 0x20, /* INVALID COMMAND OPERATION CODE */ + }, + [TCM_UNKNOWN_MODE_PAGE] = { + .key = ILLEGAL_REQUEST, + .asc = 0x24, /* INVALID FIELD IN CDB */ + }, + [TCM_CHECK_CONDITION_ABORT_CMD] = { + .key = ABORTED_COMMAND, + .asc = 0x29, /* BUS DEVICE RESET FUNCTION OCCURRED */ + .ascq = 0x03, + }, + [TCM_INCORRECT_AMOUNT_OF_DATA] = { + .key = ABORTED_COMMAND, + .asc = 0x0c, /* WRITE ERROR */ + .ascq = 0x0d, /* NOT ENOUGH UNSOLICITED DATA */ + }, + [TCM_INVALID_CDB_FIELD] = { + .key = ILLEGAL_REQUEST, + .asc = 0x24, /* INVALID FIELD IN CDB */ + }, + [TCM_INVALID_PARAMETER_LIST] = { + .key = ILLEGAL_REQUEST, + .asc = 0x26, /* INVALID FIELD IN PARAMETER LIST */ + }, + [TCM_PARAMETER_LIST_LENGTH_ERROR] = { + .key = ILLEGAL_REQUEST, + .asc = 0x1a, /* PARAMETER LIST LENGTH ERROR */ + }, + [TCM_UNEXPECTED_UNSOLICITED_DATA] = { + .key = ILLEGAL_REQUEST, + .asc = 0x0c, /* WRITE ERROR */ + .ascq = 0x0c, /* UNEXPECTED_UNSOLICITED_DATA */ + }, + [TCM_SERVICE_CRC_ERROR] = { + .key = ABORTED_COMMAND, + .asc = 0x47, /* PROTOCOL SERVICE CRC ERROR */ + .ascq = 0x05, /* N/A */ + }, + [TCM_SNACK_REJECTED] = { + .key = ABORTED_COMMAND, + .asc = 0x11, /* READ ERROR */ + .ascq = 0x13, /* FAILED RETRANSMISSION REQUEST */ + }, + [TCM_WRITE_PROTECTED] = { + .key = DATA_PROTECT, + .asc = 0x27, /* WRITE PROTECTED */ + }, + [TCM_ADDRESS_OUT_OF_RANGE] = { + .key = ILLEGAL_REQUEST, + .asc = 0x21, /* LOGICAL BLOCK ADDRESS OUT OF RANGE */ + }, + [TCM_CHECK_CONDITION_UNIT_ATTENTION] = { + .key = UNIT_ATTENTION, + }, + [TCM_CHECK_CONDITION_NOT_READY] = { + .key = NOT_READY, + }, + [TCM_MISCOMPARE_VERIFY] = { + .key = MISCOMPARE, + .asc = 0x1d, /* MISCOMPARE DURING VERIFY OPERATION */ + .ascq = 0x00, + }, + [TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED] = { + .key = ILLEGAL_REQUEST, + .asc = 0x10, + .ascq = 0x01, /* LOGICAL BLOCK GUARD CHECK FAILED */ + .add_sector_info = true, + }, + [TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED] = { + .key = ILLEGAL_REQUEST, + .asc = 0x10, + .ascq = 0x02, /* LOGICAL BLOCK APPLICATION TAG CHECK FAILED */ + .add_sector_info = true, + }, + [TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED] = { + .key = ILLEGAL_REQUEST, + .asc = 0x10, + .ascq = 0x03, /* LOGICAL BLOCK REFERENCE TAG CHECK FAILED */ + .add_sector_info = true, + }, + [TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE] = { + /* +* Returning ILLEGAL REQUEST would cause immediate IO errors on +* Solaris initiators. Returning NOT READY instead means the +* operations will be retried
Re: [PATCH v4 5/5] target: Return ABORTED_COMMAND sense key for PI errors
On 07/08/2015 04:58 PM, Sagi Grimberg wrote: PI errors were reported with ILLEGAL_REQUEST sense key but there was actually no problem with the request. Target detected PI errors should be reported with aborted command sense key. Signed-off-by: Sagi Grimberg sa...@mellanox.com --- drivers/target/target_core_transport.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 923e69d..1847fdc 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2705,19 +2705,19 @@ static const struct sense_info sense_info_table[] = { .ascq = 0x00, }, [TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED] = { - .key = ILLEGAL_REQUEST, + .key = ABORTED_COMMAND, .asc = 0x10, .ascq = 0x01, /* LOGICAL BLOCK GUARD CHECK FAILED */ .add_sector_info = true, }, [TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED] = { - .key = ILLEGAL_REQUEST, + .key = ABORTED_COMMAND, .asc = 0x10, .ascq = 0x02, /* LOGICAL BLOCK APPLICATION TAG CHECK FAILED */ .add_sector_info = true, }, [TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED] = { - .key = ILLEGAL_REQUEST, + .key = ABORTED_COMMAND, .asc = 0x10, .ascq = 0x03, /* LOGICAL BLOCK REFERENCE TAG CHECK FAILED */ .add_sector_info = true, 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: [PATCH] [SCSI] FlashPoint: optimize string comparison
On 07/08/2015 01:12 AM, Frans Klaver wrote: On Wed, Jul 8, 2015 at 7:45 AM, Christophe JAILLET christophe.jail...@wanadoo.fr wrote: Le 07/07/2015 19:04, Khalid Aziz a écrit : On 07/07/2015 02:45 AM, Frans Klaver wrote: On Tue, Jul 7, 2015 at 7:39 AM, Christophe JAILLET christophe.jail...@wanadoo.fr wrote: Stop comparing the strings as soon as we know that they don't match. Signed-off-by: Christophe JAILLET christophe.jail...@wanadoo.fr --- drivers/scsi/FlashPoint.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c index 5c74e4c..24a4d1a 100644 --- a/drivers/scsi/FlashPoint.c +++ b/drivers/scsi/FlashPoint.c @@ -6280,8 +6280,10 @@ static unsigned char FPT_scmachid(unsigned char p_card, match = 1; for (k = 0; k ID_STRING_LENGTH; k++) { - if (p_id_string[k] != FPT_scamInfo[i].id_string[k]) + if (p_id_string[k] != FPT_scamInfo[i].id_string[k]) { match = 0; + break; + } } if (match) { Why doesn't this use strncmp? Thanks, Frans I suspect that is how this code came from Mylex many years ago. Using strncmp would indeed be a better way to clean this up. Also, further down in the same routine: if (FPT_scamInfo[match].state == ID_UNUSED) { for (k = 0; k ID_STRING_LENGTH; k++) { FPT_scamInfo[match].id_string[k] = p_id_string[k]; } This should use strncpy instead. There is another similar spot further down. Christophe, if you can send a new patch with these clean-ups, that would be great. Thanks, Khalid Hi, I'm sorry but I won't propose a new patch for that. I had the same reaction at first (why not use strncmp?) but it seems to be the way this driver is coded. Should we want to introduce strncmp here, then, as you have noticed, strcpy should be used to. memset could be also used in many places. Then looking elsewhere in the code, many things should, IMHO, also be fixed. (use consistently empty lines before/after code ; use consistently { }...) Another concern to me is the use of carriage return. In the following examples, things could be much more readable if not limited to 50 chars per line, or so. 80. Parts of the code are indented way too much, resulting in these unreadable lines. I have to say that this entire driver looks like something that (sh|w)ould be in staging right now. FlashPoint.c and BusLogic.c together make up the buslogic driver. I went through a massive clean up of BusLogic.c (addressing issues like the ones you guys are bringing up) when I took over maintenance of buslogic driver and made it 64-bit clean. I am very much in agreement with suggested clean ups, but this code has been in the kernel for a very long time and cleaning it up at this point for the sake of clean up is not a reason enough to destabilize a very stable driver. staging is for drivers under development and in experimental state. buslogic driver is most definitely not experimental. For now we either leave FlashPoint.c as it is or clean it up as part of a bigger effort to add new functionality or fix a major bug. Christophe's original patch fixes an inefficiency in the code, so my take on it is to either accept the very specific fix without modifying rest of the code or combine this fix with clean up of at least the entire FPT_scmachid() routine. Thanks, Khalid -- 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 v3 3/5] scsi: Move sense handling routines to scsi_common
Looks good, Reviewed-by: Christoph Hellwig h...@lst.de -- 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 v3 4/5] target: Use scsi helpers to build the sense data correctly
--- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -7,6 +7,7 @@ #include linux/blkdev.h #include linux/percpu_ida.h #include linux/t10-pi.h +#include scsi/scsi_common.h #include net/sock.h #include net/tcp.h Please only add the include in the files that need it. (And many of the existing includes should be fixed up the same way, but that's a different story). Otherwise looks good: Reviewed-by: Christoph Hellwig h...@lst.de -- 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] libiscsi: Fix host busy blocking during connection teardown
On Tue, Jun 23, 2015 at 6:11 PM, John Soni Jose sony.j...@avagotech.com wrote: Issue: In case of hw iscsi offload, an host can have N-number of active connections. There can be IO's running on some connections which make host-host_busy always TRUE. Now if logout from a connection is tried then the code gets into an infinite loop as host-host_busy is always TRUE. iscsi_conn_teardown() { . /* * Block until all in-progress commands for this connection * time out or fail. */ for (;;) { spin_lock_irqsave(session-host-host_lock, flags); if (!atomic_read(session-host-host_busy)) { /* OK for ERL == 0 */ spin_unlock_irqrestore(session-host-host_lock, flags); break; } spin_unlock_irqrestore(session-host-host_lock, flags); msleep_interruptible(500); iscsi_conn_printk(KERN_INFO, conn, iscsi conn_destroy(): host_busy %d host_failed %d\n, atomic_read(session-host-host_busy), session-host-host_failed); ... } } This is not an issue with software-iscsi/iser as each cxn is a separate host. Fix: Acquiring eh_mutex in iscsi_conn_teardown() before setting session-state = ISCSI_STATE_TERMINATE. Signed-off-by: John Soni Jose sony.j...@aavagotech.com --- drivers/scsi/libiscsi.c | 25 ++--- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 8053f24..98d9bb6 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -2941,10 +2941,10 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) { struct iscsi_conn *conn = cls_conn-dd_data; struct iscsi_session *session = conn-session; - unsigned long flags; del_timer_sync(conn-transport_timer); + mutex_lock(session-eh_mutex); spin_lock_bh(session-frwd_lock); conn-c_stage = ISCSI_CONN_CLEANUP_WAIT; if (session-leadconn == conn) { @@ -2956,28 +2956,6 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) } spin_unlock_bh(session-frwd_lock); - /* -* Block until all in-progress commands for this connection -* time out or fail. -*/ - for (;;) { - spin_lock_irqsave(session-host-host_lock, flags); - if (!atomic_read(session-host-host_busy)) { /* OK for ERL == 0 */ - spin_unlock_irqrestore(session-host-host_lock, flags); - break; - } - spin_unlock_irqrestore(session-host-host_lock, flags); - msleep_interruptible(500); - iscsi_conn_printk(KERN_INFO, conn, iscsi conn_destroy(): - host_busy %d host_failed %d\n, - atomic_read(session-host-host_busy), - session-host-host_failed); - /* -* force eh_abort() to unblock -*/ - wake_up(conn-ehwait); - } - /* flush queued up work because we free the connection below */ iscsi_suspend_tx(conn); @@ -2994,6 +2972,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) if (session-leadconn == conn) session-leadconn = NULL; spin_unlock_bh(session-frwd_lock); + mutex_unlock(session-eh_mutex); iscsi_destroy_conn(cls_conn); } -- Looks good to me, solid reasoning on why host_busy is the wrong thing to check. Reviewed-by: Chris Leech cle...@redhat.com -- 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] [SCSI] FlashPoint: optimize string comparison
On Wed, Jul 8, 2015 at 7:45 AM, Christophe JAILLET christophe.jail...@wanadoo.fr wrote: Le 07/07/2015 19:04, Khalid Aziz a écrit : On 07/07/2015 02:45 AM, Frans Klaver wrote: On Tue, Jul 7, 2015 at 7:39 AM, Christophe JAILLET christophe.jail...@wanadoo.fr wrote: Stop comparing the strings as soon as we know that they don't match. Signed-off-by: Christophe JAILLET christophe.jail...@wanadoo.fr --- drivers/scsi/FlashPoint.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c index 5c74e4c..24a4d1a 100644 --- a/drivers/scsi/FlashPoint.c +++ b/drivers/scsi/FlashPoint.c @@ -6280,8 +6280,10 @@ static unsigned char FPT_scmachid(unsigned char p_card, match = 1; for (k = 0; k ID_STRING_LENGTH; k++) { - if (p_id_string[k] != FPT_scamInfo[i].id_string[k]) + if (p_id_string[k] != FPT_scamInfo[i].id_string[k]) { match = 0; + break; + } } if (match) { Why doesn't this use strncmp? Thanks, Frans I suspect that is how this code came from Mylex many years ago. Using strncmp would indeed be a better way to clean this up. Also, further down in the same routine: if (FPT_scamInfo[match].state == ID_UNUSED) { for (k = 0; k ID_STRING_LENGTH; k++) { FPT_scamInfo[match].id_string[k] = p_id_string[k]; } This should use strncpy instead. There is another similar spot further down. Christophe, if you can send a new patch with these clean-ups, that would be great. Thanks, Khalid Hi, I'm sorry but I won't propose a new patch for that. I had the same reaction at first (why not use strncmp?) but it seems to be the way this driver is coded. Should we want to introduce strncmp here, then, as you have noticed, strcpy should be used to. memset could be also used in many places. Then looking elsewhere in the code, many things should, IMHO, also be fixed. (use consistently empty lines before/after code ; use consistently { }...) Another concern to me is the use of carriage return. In the following examples, things could be much more readable if not limited to 50 chars per line, or so. 80. Parts of the code are indented way too much, resulting in these unreadable lines. I have to say that this entire driver looks like something that (sh|w)ould be in staging right now. Frans -- 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 v3 1/3] megaraid : use dev_printk when possible
-Original Message- From: Bjorn Helgaas [mailto:bhelg...@google.com] Sent: Wednesday, July 08, 2015 2:22 AM To: Kashyap Desai; Uday Lingala; Sumit Saxena Cc: megaraidlinux@avagotech.com; linux-scsi@vger.kernel.org; James E.J. Bottomley; linux-ker...@vger.kernel.org; Joe Perches; Christoph Hellwig Subject: [PATCH v3 1/3] megaraid : use dev_printk when possible Use dev_printk() when possible to make messages more useful. Signed-off-by: Bjorn Helgaas bhelg...@google.com --- drivers/scsi/megaraid.c | 140 ++- 1 file changed, 66 insertions(+), 74 deletions(-) diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index bc7b34c..9d05302 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -268,8 +268,8 @@ mega_query_adapter(adapter_t *adapter) raw_mbox[2] = NC_SUBOP_PRODUCT_INFO;/* i.e. 0x0E */ if ((retval = issue_scb_block(adapter, raw_mbox))) - printk(KERN_WARNING - megaraid: Product_info cmd failed with error: %d\n, + dev_warn(adapter-dev-dev, + Product_info cmd failed with error: %d\n, retval); pci_unmap_single(adapter-dev, prod_info_dma_handle, @@ - 334,7 +334,7 @@ mega_query_adapter(adapter_t *adapter) adapter-bios_version[4] = 0; } - printk(KERN_NOTICE megaraid: [%s:%s] detected %d logical drives.\n, + dev_notice(adapter-dev-dev, [%s:%s] detected %d logical drives\n, adapter-fw_version, adapter-bios_version, adapter- numldrv); /* @@ -342,7 +342,7 @@ mega_query_adapter(adapter_t *adapter) */ adapter-support_ext_cdb = mega_support_ext_cdb(adapter); if (adapter-support_ext_cdb) - printk(KERN_NOTICE megaraid: supports extended CDBs.\n); + dev_notice(adapter-dev-dev, supports extended CDBs\n); return 0; @@ -678,11 +678,11 @@ mega_build_cmd(adapter_t *adapter, Scsi_Cmnd *cmd, int *busy) if(!(adapter-flag (1L cmd-device-channel))) { - printk(KERN_NOTICE - scsi%d: scanning scsi channel %d , + dev_notice(adapter-dev-dev, + scsi%d: scanning scsi channel %d + for logical drives\n, adapter-host-host_no, cmd-device-channel); - printk(for logical drives.\n); adapter-flag |= (1L cmd-device-channel); } @@ -983,11 +983,11 @@ mega_prepare_passthru(adapter_t *adapter, scb_t *scb, Scsi_Cmnd *cmd, case READ_CAPACITY: if(!(adapter-flag (1L cmd-device-channel))) { - printk(KERN_NOTICE - scsi%d: scanning scsi channel %d [P%d] , + dev_notice(adapter-dev-dev, + scsi%d: scanning scsi channel %d [P%d] + for physical devices\n, adapter-host-host_no, cmd-device-channel, channel); - printk(for physical devices.\n); adapter-flag |= (1L cmd-device-channel); } @@ -1045,11 +1045,11 @@ mega_prepare_extpassthru(adapter_t *adapter, scb_t *scb, Scsi_Cmnd *cmd, case READ_CAPACITY: if(!(adapter-flag (1L cmd-device-channel))) { - printk(KERN_NOTICE - scsi%d: scanning scsi channel %d [P%d] , + dev_notice(adapter-dev-dev, + scsi%d: scanning scsi channel %d [P%d] + for physical devices\n, adapter-host-host_no, cmd-device-channel, channel); - printk(for physical devices.\n); adapter-flag |= (1L cmd-device-channel); } @@ -1241,7 +1241,7 @@ issue_scb_block(adapter_t *adapter, u_char *raw_mbox) return mbox-m_in.status; bug_blocked_mailbox: - printk(KERN_WARNING megaraid: Blocked mailbox..!!\n); + dev_warn(adapter-dev-dev, Blocked mailbox..!!\n); udelay (1000); return -1; } @@ -1454,9 +1454,8 @@ mega_cmd_done(adapter_t *adapter, u8 completed[], int nstatus, int status) * Make sure f/w has completed a valid command */ if( !(scb-state SCB_ISSUED) || scb-cmd == NULL ) { - printk(KERN_CRIT - megaraid: invalid command ); -
[Bug 100921] Kernel cannot read partition table automatically.But use partprobe command can.
https://bugzilla.kernel.org/show_bug.cgi?id=100921 --- Comment #2 from Wallance ha...@126.com --- Oh,I have solved it. -- You are receiving this mail because: You are the assignee for the bug. -- 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