From 24669f75a3231fa37444977c92d1f4838bec1233 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 16 Jan 2006 10:31:18 -0500 Subject: [SCSI] SCSI core kmalloc2kzalloc Change the core SCSI code to use kzalloc rather than kmalloc+memset where possible. Signed-off-by: Jes Sorensen Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_fc.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/scsi/scsi_transport_fc.c') diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index f2c9acf11bd0..56012b2694d2 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -1115,15 +1115,13 @@ static int fc_user_scan(struct Scsi_Host *shost, uint channel, struct scsi_transport_template * fc_attach_transport(struct fc_function_template *ft) { - struct fc_internal *i = kmalloc(sizeof(struct fc_internal), - GFP_KERNEL); int count; + struct fc_internal *i = kzalloc(sizeof(struct fc_internal), + GFP_KERNEL); if (unlikely(!i)) return NULL; - memset(i, 0, sizeof(struct fc_internal)); - i->t.target_attrs.ac.attrs = &i->starget_attrs[0]; i->t.target_attrs.ac.class = &fc_transport_class.class; i->t.target_attrs.ac.match = fc_target_match; @@ -1305,12 +1303,11 @@ fc_rport_create(struct Scsi_Host *shost, int channel, size_t size; size = (sizeof(struct fc_rport) + fci->f->dd_fcrport_size); - rport = kmalloc(size, GFP_KERNEL); + rport = kzalloc(size, GFP_KERNEL); if (unlikely(!rport)) { printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__); return NULL; } - memset(rport, 0, size); rport->maxframe_size = -1; rport->supported_classes = FC_COS_UNSPECIFIED; -- cgit v1.2.3 From ad139a2f56e5789aa8a9f74e3600a7f854a38de9 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Thu, 9 Mar 2006 16:37:49 +0100 Subject: [SCSI] scsi_transport_fc: fix FC_HOST_NUM_ATTRS In the past I added an host attribute but unfortunately I forgot to increase FC_HOST_NUM_ATTRS. This is fixed with the patch. Otherwise an fibre channel lld might run into BUG_ON(count > FC_HOST_NUM_ATTRS); in fc_attach_transport(). Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_fc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi/scsi_transport_fc.c') diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 929032e370db..13ea64119b73 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -223,7 +223,7 @@ static void fc_rport_terminate(struct fc_rport *rport); */ #define FC_STARGET_NUM_ATTRS 3 #define FC_RPORT_NUM_ATTRS 9 -#define FC_HOST_NUM_ATTRS 16 +#define FC_HOST_NUM_ATTRS 17 struct fc_internal { struct scsi_transport_template t; -- cgit v1.2.3 From c829c394165f981d49f05a9be228404d7a9398d4 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 13 Mar 2006 08:28:57 -0500 Subject: [SCSI] FC transport : Avoid device offline cases by stalling aborts until device unblocked This moves the eh_timed_out functionality from the scsi_host_template to the transport_template. Given that this is now a transport function, the EH_RESET_TIMER case no longer caps the timer reschedulings. The transport guarantees that this is not an infinite condition. Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 9 +++------ drivers/scsi/scsi_transport_fc.c | 37 +++++++++++++++++++++++++++++++++++++ include/scsi/scsi_host.h | 14 -------------- include/scsi/scsi_transport.h | 11 +++++++++++ 4 files changed, 51 insertions(+), 20 deletions(-) (limited to 'drivers/scsi/scsi_transport_fc.c') diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 5cc97b721661..9cf020622134 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -163,16 +164,12 @@ void scsi_times_out(struct scsi_cmnd *scmd) { scsi_log_completion(scmd, TIMEOUT_ERROR); - if (scmd->device->host->hostt->eh_timed_out) - switch (scmd->device->host->hostt->eh_timed_out(scmd)) { + if (scmd->device->host->transportt->eh_timed_out) + switch (scmd->device->host->transportt->eh_timed_out(scmd)) { case EH_HANDLED: __scsi_done(scmd); return; case EH_RESET_TIMER: - /* This allows a single retry even of a command - * with allowed == 0 */ - if (scmd->retries++ > scmd->allowed) - break; scsi_add_timer(scmd, scmd->timeout_per_command, scsi_times_out); return; diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 56012b2694d2..3c3baa9f5f28 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "scsi_priv.h" /* @@ -1090,6 +1091,40 @@ static int fc_rport_match(struct attribute_container *cont, } +/** + * fc_timed_out - FC Transport I/O timeout intercept handler + * + * @scmd: The SCSI command which timed out + * + * This routine protects against error handlers getting invoked while a + * rport is in a blocked state, typically due to a temporarily loss of + * connectivity. If the error handlers are allowed to proceed, requests + * to abort i/o, reset the target, etc will likely fail as there is no way + * to communicate with the device to perform the requested function. These + * failures may result in the midlayer taking the device offline, requiring + * manual intervention to restore operation. + * + * This routine, called whenever an i/o times out, validates the state of + * the underlying rport. If the rport is blocked, it returns + * EH_RESET_TIMER, which will continue to reschedule the timeout. + * Eventually, either the device will return, or devloss_tmo will fire, + * and when the timeout then fires, it will be handled normally. + * If the rport is not blocked, normal error handling continues. + * + * Notes: + * This routine assumes no locks are held on entry. + **/ +static enum scsi_eh_timer_return +fc_timed_out(struct scsi_cmnd *scmd) +{ + struct fc_rport *rport = starget_to_rport(scsi_target(scmd->device)); + + if (rport->port_state == FC_PORTSTATE_BLOCKED) + return EH_RESET_TIMER; + + return EH_NOT_HANDLED; +} + /* * Must be called with shost->host_lock held */ @@ -1146,6 +1181,8 @@ fc_attach_transport(struct fc_function_template *ft) /* Transport uses the shost workq for scsi scanning */ i->t.create_work_queue = 1; + i->t.eh_timed_out = fc_timed_out; + i->t.user_scan = fc_user_scan; /* diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 827992949c4b..a6cf3e535c0b 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -146,20 +146,6 @@ struct scsi_host_template { int (* eh_bus_reset_handler)(struct scsi_cmnd *); int (* eh_host_reset_handler)(struct scsi_cmnd *); - /* - * This is an optional routine to notify the host that the scsi - * timer just fired. The returns tell the timer routine what to - * do about this: - * - * EH_HANDLED: I fixed the error, please complete the command - * EH_RESET_TIMER: I need more time, reset the timer and - * begin counting again - * EH_NOT_HANDLED Begin normal error recovery - * - * Status: OPTIONAL - */ - enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *); - /* * Before the mid layer attempts to scan for a new device where none * currently exists, it will call this entry in your driver. Should diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h index e7b1054adf86..b3657f111937 100644 --- a/include/scsi/scsi_transport.h +++ b/include/scsi/scsi_transport.h @@ -48,6 +48,17 @@ struct scsi_transport_template { * True if the transport wants to use a host-based work-queue */ unsigned int create_work_queue : 1; + + /* + * This is an optional routine that allows the transport to become + * involved when a scsi io timer fires. The return value tells the + * timer routine how to finish the io timeout handling: + * EH_HANDLED: I fixed the error, please complete the command + * EH_RESET_TIMER: I need more time, reset the timer and + * begin counting again + * EH_NOT_HANDLED Begin normal error recovery + */ + enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *); }; #define transport_class_to_shost(tc) \ -- cgit v1.2.3