From: David S. Miller Date: Wed, 18 Jun 2008 06:53:22 +0000 (-0700) Subject: [SCSI] esp: Fix OOPS in esp_reset_cleanup(). X-Git-Tag: v2.6.26-rc9~80^2~1 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=eadc49b1a8d09480f14caea292142f103a89c77a;p=linux-2.6 [SCSI] esp: Fix OOPS in esp_reset_cleanup(). OOPS reported by Friedrich Oslage The problem here is that tp->starget is set every time a lun is allocated for a particular target so we can catch the sdev_target parent value. The reset handler uses the NULL'ness of this value to determine which targets are active. But esp_slave_destroy() does not NULL out this value when appropriate. So for every target that doesn't respond, the SCSI bus scan causes a stale pointer to be left here, with ensuing crashes like you're seeing. Signed-off-by: David S. Miller Cc: Stable Tree Signed-off-by: James Bottomley --- diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c index a0b6d41495..305eddef5c 100644 --- a/drivers/scsi/esp_scsi.c +++ b/drivers/scsi/esp_scsi.c @@ -2371,6 +2371,7 @@ static int esp_slave_alloc(struct scsi_device *dev) dev->hostdata = lp; tp->starget = dev->sdev_target; + tp->starget_ref++; spi_min_period(tp->starget) = esp->min_period; spi_max_offset(tp->starget) = 15; @@ -2425,10 +2426,17 @@ static int esp_slave_configure(struct scsi_device *dev) static void esp_slave_destroy(struct scsi_device *dev) { + struct esp *esp = shost_priv(dev->host); + struct esp_target_data *tp = &esp->target[dev->id]; struct esp_lun_data *lp = dev->hostdata; kfree(lp); dev->hostdata = NULL; + + BUG_ON(tp->starget_ref <= 0); + + if (!--tp->starget_ref) + tp->starget = NULL; } static int esp_eh_abort_handler(struct scsi_cmnd *cmd) diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h index bb43a13881..655e0b2240 100644 --- a/drivers/scsi/esp_scsi.h +++ b/drivers/scsi/esp_scsi.h @@ -322,6 +322,7 @@ struct esp_target_data { u8 nego_goal_tags; struct scsi_target *starget; + int starget_ref; }; struct esp_event_ent {