Limit overall SCSI EH runtime
Subsystems (3)
v3 cover Limit overall SCSI EH runtime
This patchset implements a new 'eh_deadline' attribute to the SCSI host. It will limit the overall SCSI EH runtime by a given timeout. If the timeout is reached all intermediate EH steps will be skipped and host reset will be scheduled immediately.
For this patch I've re-used the existing 'last_reset' field of the SCSI host to store the initial time SCSI EH started. Also the field 'resetting' has been removed as it never has been used as intended.
As 'last_reset' might be in use by transport-specific EH implementation I've disallowed eh_deadline setting there.
Changes from v2:
- Escalate to LUN reset if abort fails
Changes from the initial version:
- Add list_splice_init() calls to avoid stale commands
- Rename function to scsi_host_eh_past_deadline
Hannes Reinecke (8):
dpt_i2o: Remove DPTI_STATE_IOCTL
dpt_i2o: return SCSI_MLQUEUE_HOST_BUSY when in reset
advansys: Remove 'last_reset' references
tmscsim: Move 'last_reset' into host structure
dc395: Move 'last_reset' into internal host structure
scsi: remove check for 'resetting'
scsi: Add 'eh_deadline' to limit SCSI EH runtime
scsi_error: Escalate to LUN reset if abort fails
drivers/scsi/advansys.c | 8 +-- drivers/scsi/dc395x.c | 24 ++++---- drivers/scsi/dpt_i2o.c | 35 +++++------ drivers/scsi/dpti.h | 1 - drivers/scsi/hosts.c | 7 +++ drivers/scsi/scsi.c | 28 --------- drivers/scsi/scsi_error.c | 146 +++++++++++++++++++++++++++++++++++++++++----- drivers/scsi/scsi_sysfs.c | 37 ++++++++++++ drivers/scsi/tmscsim.c | 14 ++--- drivers/scsi/tmscsim.h | 1 + include/scsi/scsi_host.h | 4 +- 11 files changed, 217 insertions(+), 88 deletions(-)
Signature · 1 line
1.8.1.4
PATCH v3 1/8 dpt_i2o: Remove DPTI_STATE_IOCTL
scsi_block_host/scsi_unlock_host provides the required functionality.
--- drivers/scsi/dpt_i2o.c | 30 ++++++++++++------------------ drivers/scsi/dpti.h | 1 - 2 files changed, 12 insertions(+), 19 deletions(-)
drivers/scsi/dpt_i2o.c +12 -18
@@ -448,15 +448,7 @@ static int adpt_queue_lck(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd }rmb (); -/* -* TODO: I need to block here if I am processing ioctl cmds -* but if the outstanding cmds all finish before the ioctl, -* the scsi-core will not know to start sending cmds to me again. -* I need to a way to restart the scsi-cores queues or should I block -* calling scsi_done on the outstanding cmds instead -* for now we don't set the IOCTL state -*/ -if (((pHba->state) &DPTI_STATE_IOCTL ) || ((pHba->state) &DPTI_STATE_RESET )) { +if ((pHba->state) &DPTI_STATE_RESET ) { pHba->host->last_reset = jiffies; pHba->host->resetting =1 ;return 1 ;
@@ -1811,21 +1803,23 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg) }do { -if (pHba->host) +/* +* Stop any new commands from enterring the +* controller while processing the ioctl +*/ +if (pHba->host) { +scsi_block_requests (pHba->host);spin_lock_irqsave (pHba->host->host_lock, flags); -// This state stops any new commands from enterring the -// controller while processing the ioctl -// pHba->state |= DPTI_STATE_IOCTL; -// We can't set this now - The scsi subsystem sets host_blocked and -// the queue empties and stops. We need a way to restart the queue + } rcode =adpt_i2o_post_wait (pHba, msg, size,FOREVER );if (rcode !=0 )printk ("adpt_i2o_passthru: post wait failed %d %p\n" , rcode, reply); -// pHba->state &= ~DPTI_STATE_IOCTL; -if (pHba->host) +if (pHba->host) {spin_unlock_irqrestore (pHba->host->host_lock, flags); - }while (rcode == -ETIMEDOUT ); +scsi_unblock_requests (pHba->host); + } + }while (rcode == -ETIMEDOUT );if (rcode){ goto cleanup;
drivers/scsi/dpti.h +0 -1
@@ -202,7 +202,6 @@ struct adpt_channel {// HBA state flags #define DPTI_STATE_RESET (0x01) -#define DPTI_STATE_IOCTL (0x02) typedef struct _adpt_hba { struct _adpt_hba *next;
Signature · 1 line
1.8.1.4
PATCH v3 2/8 dpt_i2o: return SCSI_MLQUEUE_HOST_BUSY when in reset
In reply to Hannes ReineckeWhen the HBA is in reset we should be returning 'busy' and not rely on the obscure 'last_reset' feature.
--- drivers/scsi/dpt_i2o.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
drivers/scsi/dpt_i2o.c +2 -5
@@ -448,11 +448,8 @@ static int adpt_queue_lck(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd }rmb (); -if ((pHba->state) &DPTI_STATE_RESET ) { - pHba->host->last_reset = jiffies; - pHba->host->resetting =1 ; -return 1 ; - } +if ((pHba->state) &DPTI_STATE_RESET ) +return SCSI_MLQUEUE_HOST_BUSY ;// TODO if the cmd->device if offline then I may need to issue a bus rescan // followed by a get_lct to see if the device is there anymore
Signature · 1 line
1.8.1.4
PATCH v3 3/8 advansys: Remove 'last_reset' references
In reply to Hannes ReineckeServes no purpose whatsoever.
--- drivers/scsi/advansys.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/scsi/advansys.c +4 -4
@@ -2511,8 +2511,8 @@ static void asc_prt_scsi_host(struct Scsi_Host *s)struct asc_board *boardp =shost_priv (s);printk ("Scsi_Host at addr 0x%p, device %s\n" , s,dev_name (boardp->dev)); -printk (" host_busy %u, host_no %d, last_reset %d,\n" , - s->host_busy, s->host_no, (unsigned )s->last_reset); +printk (" host_busy %u, host_no %d,\n" , + s->host_busy, s->host_no);printk (" base 0x%lx, io_port 0x%lx, irq %d,\n" , (ulong )s->base, (ulong )s->io_port, boardp->irq);
@@ -3345,8 +3345,8 @@ static void asc_prt_driver_conf(struct seq_file *m, struct Scsi_Host *shost) shost->host_no);seq_printf (m, -" host_busy %u, last_reset %lu, max_id %u, max_lun %u, max_channel %u\n" , - shost->host_busy, shost->last_reset, shost->max_id, +" host_busy %u, max_id %u, max_lun %u, max_channel %u\n" , + shost->host_busy, shost->max_id, shost->max_lun, shost->max_channel); seq_printf(m,
Signature · 1 line
1.8.1.4
PATCH v3 4/8 tmscsim: Move 'last_reset' into host structure
In reply to Hannes ReineckeThe 'last_reset' value is only used internally, so move it into the internal host structure.
--- drivers/scsi/tmscsim.c | 14 +++++++------- drivers/scsi/tmscsim.h | 1 + 2 files changed, 8 insertions(+), 7 deletions(-)
drivers/scsi/tmscsim.c +7 -7
@@ -521,7 +521,7 @@ dc390_StartSCSI( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_sr pACB->SelConn++;return 1 ; } -if (time_before (jiffies, pACB->pScsiHost->last_reset)) +if (time_before (jiffies, pACB->last_reset)) {DEBUG0 (printk ("DC390: We were just reset and don't accept commands yet!\n" ));return 1 ;
@@ -1863,7 +1863,7 @@ dc390_ScsiRstDetect( struct dc390_acb* pACB )/* delay half a second */ udelay (1000 );DC390_write8 (ScsiCmd,CLEAR_FIFO_CMD ); - pACB->pScsiHost->last_reset = jiffies +5 *HZ /2 + pACB->last_reset = jiffies +5 *HZ /2 +HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY ]; pACB->Connected =0 ;
@@ -2048,9 +2048,9 @@ static int DC390_bus_reset (struct scsi_cmnd *cmd)dc390_ResetDevParam (pACB);mdelay (1 ); - pACB->pScsiHost->last_reset = jiffies +3 *HZ /2 + pACB->last_reset = jiffies +3 *HZ /2 +HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY ]; - +DC390_write8 (ScsiCmd,CLEAR_FIFO_CMD );DC390_read8 (INT_Status);/* Reset Pending INT */
@@ -2383,7 +2383,7 @@ static void dc390_init_hw(struct dc390_acb *pACB, u8 index)if (pACB->Gmode2 &RST_SCSI_BUS ) {dc390_ResetSCSIBus (pACB);udelay (1000 ); - shost->last_reset = jiffies +HZ /2 + + pACB->last_reset = jiffies +HZ /2 +HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY ]; }
@@ -2455,8 +2455,8 @@ static int dc390_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) shost->irq = pdev->irq; shost->base = io_port; shost->unique_id = io_port; - shost->last_reset = jiffies; - + + pACB->last_reset = jiffies; pACB->pScsiHost = shost; pACB->IOPortBase = (u16 ) io_port; pACB->IRQLevel = pdev->irq;
drivers/scsi/tmscsim.h +1 -0
@@ -143,6 +143,7 @@ u8 Ignore_IRQ; /* Not used */struct pci_dev *pdev; +unsigned long last_reset;unsigned long Cmds;u32 SelLost;u32 SelConn;
Signature · 1 line
1.8.1.4
PATCH v3 5/8 dc395: Move 'last_reset' into internal host structure
In reply to Hannes Reinecke'last_reset' is only used internally, so move it into the internal host structure.
--- drivers/scsi/dc395x.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-)
drivers/scsi/dc395x.c +13 -11
@@ -308,6 +308,8 @@ struct AdapterCtlBlk {struct timer_list waiting_timer;struct timer_list selto_timer; +unsigned long last_reset; +u16 srb_count;u8 sel_timeout;
@@ -860,9 +862,9 @@ static void waiting_set_timer(struct AdapterCtlBlk *acb, unsigned long to)init_timer (&acb->waiting_timer); acb->waiting_timer.function = waiting_timeout; acb->waiting_timer.data = (unsigned long ) acb; -if (time_before (jiffies + to, acb->scsi_host->last_reset -HZ /2 )) +if (time_before (jiffies + to, acb->last_reset -HZ /2 )) acb->waiting_timer.expires = - acb->scsi_host->last_reset -HZ /2 +1 ; + acb->last_reset -HZ /2 +1 ;else acb->waiting_timer.expires = jiffies + to +1 ;add_timer (&acb->waiting_timer);
@@ -1319,7 +1321,7 @@ static int __dc395x_eh_bus_reset(struct scsi_cmnd *cmd)udelay (500 );/* We may be in serious trouble. Wait some seconds */ - acb->scsi_host->last_reset = + acb->last_reset = jiffies +3 *HZ /2 +HZ * acb->eeprom.delay_time;
@@ -1462,9 +1464,9 @@ static void selto_timer(struct AdapterCtlBlk *acb) acb->selto_timer.function = selection_timeout_missed; acb->selto_timer.data = (unsigned long ) acb;if (time_before - (jiffies +HZ , acb->scsi_host->last_reset +HZ /2 )) + (jiffies +HZ , acb->last_reset +HZ /2 )) acb->selto_timer.expires = - acb->scsi_host->last_reset +HZ /2 +1 ; + acb->last_reset +HZ /2 +1 ;else acb->selto_timer.expires = jiffies +HZ +1 ;add_timer (&acb->selto_timer);
@@ -1535,7 +1537,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb, }/* Allow starting of SCSI commands half a second before we allow the mid-level * to queue them again after a reset */ -if (time_before (jiffies, acb->scsi_host->last_reset -HZ /2 )) { +if (time_before (jiffies, acb->last_reset -HZ /2 )) {dprintkdbg (DBG_KG ,"start_scsi: Refuse cmds (reset wait)\n" );return 1 ; }
@@ -3031,7 +3033,7 @@ static void disconnect(struct AdapterCtlBlk *acb)dprintkl (KERN_ERR ,"disconnect: No such device\n" );udelay (500 );/* Suspend queue for a while */ - acb->scsi_host->last_reset = + acb->last_reset = jiffies +HZ /2 +HZ * acb->eeprom.delay_time;clear_fifo (acb,"disconnectEx" );
@@ -3053,7 +3055,7 @@ static void disconnect(struct AdapterCtlBlk *acb)waiting_process_next (acb); }else if (srb->state &SRB_ABORT_SENT ) { dcb->flag &= ~ABORT_DEV_ ; - acb->scsi_host->last_reset = jiffies +HZ /2 +1 ; + acb->last_reset = jiffies +HZ /2 +1 ;dprintkl (KERN_ERR ,"disconnect: SRB_ABORT_SENT\n" );doing_srb_done (acb,DID_ABORT , srb->cmd,1 );waiting_process_next (acb);
@@ -3649,7 +3651,7 @@ static void scsi_reset_detect(struct AdapterCtlBlk *acb)/*DC395x_write8(acb, TRM_S1040_DMA_CONTROL,STOPDMAXFER); */ udelay (500 );/* Maybe we locked up the bus? Then lets wait even longer ... */ - acb->scsi_host->last_reset = + acb->last_reset = jiffies +5 *HZ /2 +HZ * acb->eeprom.delay_time;
@@ -4426,7 +4428,7 @@ static void adapter_init_scsi_host(struct Scsi_Host *host) host->dma_channel =-1 ; host->unique_id = acb->io_port_base; host->irq = acb->irq_level; - host->last_reset = jiffies; + acb->last_reset = jiffies; host->max_id =16 ;if (host->max_id -1 == eeprom->scsi_id)
@@ -4484,7 +4486,7 @@ static void adapter_init_chip(struct AdapterCtlBlk *acb)/*spin_unlock_irq (&io_request_lock); */ udelay (500 ); - acb->scsi_host->last_reset = + acb->last_reset = jiffies +HZ /2 +HZ * acb->eeprom.delay_time;
Signature · 1 line
1.8.1.4
PATCH v3 6/8 scsi: remove check for 'resetting'
In reply to Hannes ReineckeField is now unused, so this is dead code.
--- drivers/scsi/scsi.c | 28 ---------------------------- 1 file changed, 28 deletions(-)
drivers/scsi/scsi.c +0 -28
@@ -78,11 +78,6 @@ static void scsi_done(struct scsi_cmnd *cmd);* Definitions and constants. */ -#define MIN_RESET_DELAY (2*HZ) - -/* Do not call reset on error if we just did a reset within 15 sec. */ -#define MIN_RESET_PERIOD (15*HZ) -/* * Note - the initial logging level can be set here to log events at boot time. * After the system is up, you may enable logging via the /proc interface.
@@ -658,7 +653,6 @@ EXPORT_SYMBOL(scsi_cmd_get_serial);int scsi_dispatch_cmd (struct scsi_cmnd *cmd) {struct Scsi_Host *host = cmd->device->host; -unsigned long timeout;int rtn =0 ;atomic_inc (&cmd->device->iorequest_cnt);
@@ -704,28 +698,6 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) (cmd->device->lun <<5 &0xe0 ); } -/* -* We will wait MIN_RESET_DELAY clock ticks after the last reset so -* we can avoid the drive not being ready. -*/ - timeout = host->last_reset +MIN_RESET_DELAY ; - -if (host->resetting &&time_before (jiffies, timeout)) { -int ticks_remaining = timeout - jiffies; -/* -* NOTE: This may be executed from within an interrupt -* handler! This is bad, but for now, it'll do. The irq -* level of the interrupt handler has been masked out by the -* platform dependent interrupt handling code already, so the -* sti() here will not cause another call to the SCSI host's -* interrupt handler (assuming there is one irq-level per -* host). -*/ -while (--ticks_remaining >=0 ) -mdelay (1 +999 /HZ ); - host->resetting =0 ; - } -scsi_log_send (cmd);/*
Signature · 1 line
1.8.1.4
PATCH v3 7/8 scsi: Add 'eh_deadline' to limit SCSI EH runtime
In reply to Hannes ReineckeThis patchs adds an 'eh_deadline' sysfs attribute to the scsi host which limits the overall runtime of the SCSI EH. The 'eh_deadline' value is stored in the now obsolete field 'resetting'.
When a command is failed the start time of the EH is stored in 'last_reset'. If the overall runtime of the SCSI EH is longer than last_reset + eh_deadline, the EH is short-circuited and falls through to issue a host reset only.
--- drivers/scsi/hosts.c | 7 +++ drivers/scsi/scsi_error.c | 130 +++++++++++++++++++++++++++++++++++++++++++--- drivers/scsi/scsi_sysfs.c | 37 +++++++++++++ include/scsi/scsi_host.h | 4 +- 4 files changed, 170 insertions(+), 8 deletions(-)
drivers/scsi/hosts.c +7 -0
@@ -316,6 +316,12 @@ static void scsi_host_dev_release(struct device *dev)kfree (shost); } +static unsigned int shost_eh_deadline; + +module_param_named (eh_deadline, shost_eh_deadline, uint,S_IRUGO |S_IWUSR ); +MODULE_PARM_DESC (eh_deadline, +"SCSI EH timeout in seconds (should be between 1 and 2^32-1)" ); +static struct device_type scsi_host_type = { .name ="scsi_host" , .release = scsi_host_dev_release,
@@ -388,6 +394,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) shost->unchecked_isa_dma = sht->unchecked_isa_dma; shost->use_clustering = sht->use_clustering; shost->ordered_tag = sht->ordered_tag; + shost->eh_deadline = shost_eh_deadline *HZ ;if (sht->supported_mode ==MODE_UNKNOWN )/* means we didn't set it ... default to INITIATOR */
drivers/scsi/scsi_error.c +124 -6
244 lines not on this page · raw message
drivers/scsi/scsi_sysfs.c +37 -0
@@ -281,6 +281,42 @@ exit_store_host_reset: static DEVICE_ATTR(host_reset, S_IWUSR, NULL, store_host_reset); +static ssize_t +show_shost_eh_deadline (struct device *dev, +struct device_attribute *attr,char *buf) +{ +struct Scsi_Host *shost =class_to_shost (dev); + +return sprintf (buf,"%d\n" , shost->eh_deadline /HZ ); +} + +static ssize_t +store_shost_eh_deadline (struct device *dev,struct device_attribute *attr, +const char *buf,size_t count) +{ +struct Scsi_Host *shost =class_to_shost (dev); +int ret = -EINVAL ; +int deadline; +unsigned long flags; + +if (shost->transportt && shost->transportt->eh_strategy_handler) +return ret; + +if (sscanf (buf,"%d\n" , &deadline) ==1 ) { +spin_lock_irqsave (shost->host_lock, flags); +if (scsi_host_in_recovery (shost)) + ret = -EBUSY ; +else { + shost->eh_deadline = deadline *HZ ; + ret = count; + } +spin_unlock_irqrestore (shost->host_lock, flags); + } +return ret; +} + +static DEVICE_ATTR(eh_deadline, S_IRUGO | S_IWUSR, show_shost_eh_deadline, store_shost_eh_deadline); +shost_rd_attr (unique_id,"%u\n" );shost_rd_attr (host_busy,"%hu\n" );shost_rd_attr (cmd_per_lun,"%hd\n" );
@@ -308,6 +344,7 @@ static struct attribute *scsi_sysfs_shost_attrs[] = { &dev_attr_prot_capabilities.attr, &dev_attr_prot_guard_type.attr, &dev_attr_host_reset.attr, + &dev_attr_eh_deadline.attr, NULL };
include/scsi/scsi_host.h +2 -2
@@ -596,9 +596,9 @@ struct Scsi_Host {unsigned int host_busy;/* commands actually active on low-level */ unsigned int host_failed;/* commands that failed. */ unsigned int host_eh_scheduled;/* EH scheduled without command */ - +unsigned int host_no;/* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */ -int resetting;/* if set, it means that last_reset is a valid value */ +int eh_deadline;unsigned long last_reset;/*
Signature · 1 line
1.8.1.4
Re: [PATCH 7/8] scsi: Add 'eh_deadline' to limit SCSI EH runtime
Hi, Hannes:
Quoted 22 lines · Hannes Reinecke
This patchs adds an '
eh_deadline' sysfs attribute to the scsi host which limits the overall runtime of the SCSI EH. The 'eh_deadline' value is stored in the now obsolete field 'resetting'.
When a command is failed the start time of the EH is stored in 'last_reset'. If the overall runtime of the SCSI EH is longer thanlast_reset+eh_deadline, the EH is short-circuited and falls through to issue a host reset only.Signed-off-by Hannes Reinecke<[email protected]>--- drivers/scsi/hosts.c | 7 +++ drivers/scsi/scsi_error.c | 130 +++++++++++++++++++++++++++++++++++++++++++--- drivers/scsi/scsi_sysfs.c | 37 +++++++++++++ include/scsi/scsi_host.h | 4 +- 4 files changed, 170 insertions(+), 8 deletions(-)drivers/scsi/hosts.c +0
-0
drivers/scsi/hosts.c static void scsi_host_dev_release(struct device *dev) · line 323
Quoted 8 lines
drivers/scsi/hosts.c +5
-0@@ -316,6 +316,12 @@ static void scsi_host_dev_release(struct device *dev)kfree (shost); } +static unsigned int shost_eh_deadline; + +module_param_named (eh_deadline, shost_eh_deadline, uint,S_IRUGO |S_IWUSR ); +MODULE_PARM_DESC (eh_deadline, +"SCSI EH timeout in seconds (should be between 1 and 2^32-1)" );
Sorry, didn't consider '0' as the minimum valid value as we talked on Oct 9?
Thanks,
Ren
<snip>
Quoted 4 lines
drivers/scsi/hosts.c +1
-0+int eh_deadline;unsigned long last_reset;/*
Re: [PATCH 7/8] scsi: Add 'eh_deadline' to limit SCSI EH runtime
In reply to Hannes ReineckeHi, Hannes:
Quoted 2 lines · Hannes Reinecke
This patchs adds an '
eh_deadline' sysfs attribute to the scsi host which limits the overall runtime of the SCSI EH.
As you known, adding to scsi host means such interface has also been added to the SATA and USB controllers. But to users, I think it is possible that there are 3 confusing points below:
1) There should not be this sysfs interface for SATA controllers, for such interface will not work under SATA's own EH policy;
2) There should not be this sysfs interface for USB controllers, because probably they will not consider EH recovery to USB ones;
3) They are not willing to affect SATA/USB controllers(even if their sysfs interfaces) while setting global interafce by assigning scsi module parameter.
I was thinking how to mask SATA/USB controllers, but havn't a perfect solution so far, for it seems that it is not clever enough to mask them in each controller driver. Do you have any idea about above?
Thanks,
Ren
Re: [PATCH 7/8] scsi: Add 'eh_deadline' to limit SCSI EH runtime
Quoted 18 lines · Ren Mingxin
Hi, Hannes:
Quoted 2 lines · Hannes Reinecke
This patchs adds an '
eh_deadline' sysfs attribute to the scsi host which limits the overall runtime of the SCSI EH.As you known, adding to scsi host means such interface has also been added to the SATA and USB controllers. But to users, I think it is possible that there are 3 confusing points below:
1) There should not be this sysfs interface for SATA controllers, for such interface will not work under SATA's own EH policy;
2) There should not be this sysfs interface for USB controllers, because probably they will not consider EH recovery to USB ones;
3) They are not willing to affect SATA/USB controllers(even if their sysfs interfaces) while setting global interafce by assigning scsi module parameter.
Quoted 4 lines
I was thinking how to mask SATA/USB controllers, but havn't a perfect solution so far, for it seems that it is not clever enough to mask them in each controller driver. Do you have any idea about above?
Yes, I have.
I've send a patchset titled 'Display EVPD pages in sysfs', which introduces the ability to mask individual (device) attributes. The same mechanism can easily be used for host attributes.
James B indicated that those patches might be okay for inclusion, but so far nothing has happened with them.
I'll ping him again.
Cheers,
Hannes
Signature · 8 lines
Dr. Hannes Reinecke zSeries & Storage [email protected] +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 [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v3 8/8 scsi_error: Escalate to LUN reset if abort fails
In reply to Hannes ReineckeIf a command abort fails there is a fair chance that all other aborts will be failing, too.
So we should be calling LUN reset directly after the first failed abort and skip aborting the remaining commands.
--- drivers/scsi/scsi_error.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
drivers/scsi/scsi_error.c +9 -7
@@ -1192,18 +1192,20 @@ static int scsi_eh_abort_cmds(struct list_head *work_q,"0x%p\n" , current->comm, scmd)); rtn =scsi_try_to_abort_cmd (shost->hostt, scmd); -if (rtn ==SUCCESS || rtn ==FAST_IO_FAIL ) { - scmd->eh_eflags &= ~SCSI_EH_CANCEL_CMD ; -if (rtn ==FAST_IO_FAIL ) -scsi_eh_finish_cmd (scmd, done_q); -else -list_move_tail (&scmd->eh_entry, &check_list); - }else +if (rtn ==FAILED ) {SCSI_LOG_ERROR_RECOVERY (3 ,printk ("%s: aborting" " cmd failed:" "0x%p\n" , current->comm, scmd)); +list_splice_init (&check_list, work_q); +return list_empty (work_q); + } + scmd->eh_eflags &= ~SCSI_EH_CANCEL_CMD ; +if (rtn ==FAST_IO_FAIL ) +scsi_eh_finish_cmd (scmd, done_q); +else +list_move_tail (&scmd->eh_entry, &check_list); }return scsi_eh_test_devices (&check_list, work_q, done_q,0 );
Signature · 1 line
1.8.1.4
Re: [PATCH 8/8] scsi_error: Escalate to LUN reset if abort fails
Quoted 32 lines · Hannes Reinecke
If a command abort fails there is a fair chance that all other aborts will be failing, too.
So we should be calling LUN reset directly after the first failed abort and skip aborting the remaining commands.Signed-off-by Hannes Reinecke <[email protected]>--- drivers/scsi/scsi_error.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)drivers/scsi/scsi_error.c +2
-7@@ -1192,18 +1192,20 @@ static int scsi_eh_abort_cmds(struct list_head *work_q,"0x%p\n" , current->comm, scmd)); rtn =scsi_try_to_abort_cmd (shost->hostt, scmd); -if (rtn ==SUCCESS || rtn ==FAST_IO_FAIL ) { - scmd->eh_eflags &= ~SCSI_EH_CANCEL_CMD ; -if (rtn ==FAST_IO_FAIL ) -scsi_eh_finish_cmd (scmd, done_q); -else -list_move_tail (&scmd->eh_entry, &check_list); - }else +if (rtn ==FAILED ) {SCSI_LOG_ERROR_RECOVERY (3 ,printk ("%s: aborting" " cmd failed:" "0x%p\n" , current->comm, scmd)); +list_splice_init (&check_list, work_q);
drivers/scsi/scsi_error.c static int scsi_eh_abort_cmds(struct list_head *work_q, · line 1211
Quoted 10 lines
drivers/scsi/scsi_error.c +7
-0+return list_empty (work_q); + } + scmd->eh_eflags &= ~SCSI_EH_CANCEL_CMD ; +if (rtn ==FAST_IO_FAIL ) +scsi_eh_finish_cmd (scmd, done_q); +else +list_move_tail (&scmd->eh_entry, &check_list); }return scsi_eh_test_devices (&check_list, work_q, done_q,0 );
This looks like it should be OK, assuming that we do in fact want to stop issuing aborts once a call to ->eh_abort_handler() returns FAILED. I guess it depends upon whether drivers might occasionally return FAILED due to some temporary condition as opposed to e.g. loss of link.
(I've been having a discussion with the vmw_pvscsi driver maintainer regarding their implementation of ->eh_abort_handler(), which might have to change to return FAILED if the hypervisor side doesn't respond to the abort request fast enough, instead of returning SUCCESS and then later completing the request when the abort actually completes. So I think that a temporary condition that results in returning FAILED is possible...)
Note that this portion of the patch set would change the behavior regardless of whether eh_deadline was enabled.
-Ewan