scsi_dh: fix reference counting in scsi_dh_activate error path
PATCH RESEND 1/1 scsi_dh: fix reference counting in scsi_dh_activate error path
Commit db422318cbca55168cf965f655471dbf8be82433 ([SCSI] scsi_dh:
propagate SCSI device deletion) introduced a regression where the device reference is not dropped prior to scsi_dh_activate's early return from the error path.
Signed-off-by Mike Snitzer <[email protected]>
Cc [email protected] # 2.6.38
--- drivers/scsi/device_handler/scsi_dh.c | 9 ++++++--- 1 files changed, 6 insertions(+), 3 deletions(-)
(I embedded this fix in another scsi_dh_emc thread on 3/21 so figured I'd resend to get it back on the radar)
drivers/scsi/device_handler/scsi_dh.c +6 -3
@@ -394,12 +394,14 @@ int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data)unsigned long flags;struct scsi_device *sdev;struct scsi_device_handler *scsi_dh =NULL ; +struct device *dev =NULL ;spin_lock_irqsave (q->queue_lock, flags); sdev = q->queuedata;if (sdev && sdev->scsi_dh_data) scsi_dh = sdev->scsi_dh_data->scsi_dh; -if (!scsi_dh || !get_device (&sdev->sdev_gendev) || + dev =get_device (&sdev->sdev_gendev); +if (!scsi_dh || !dev || sdev->sdev_state ==SDEV_CANCEL || sdev->sdev_state ==SDEV_DEL ) err =SCSI_DH_NOSYS ;
@@ -410,12 +412,13 @@ int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data)if (err) {if (fn)fn (data, err); -return err; + goto out; }if (scsi_dh->activate) err = scsi_dh->activate (sdev, fn, data); -put_device (&sdev->sdev_gendev); +out: +put_device (dev);return err; }EXPORT_SYMBOL_GPL (scsi_dh_activate);
Quoted 27 lines · Mike Snitzer
drivers/scsi/device_handler/scsi_dh.c +4
-2@@ -394,12 +394,14 @@ int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data)unsigned long flags;struct scsi_device *sdev;struct scsi_device_handler *scsi_dh =NULL ; +struct device *dev =NULL ;spin_lock_irqsave (q->queue_lock, flags); sdev = q->queuedata;if (sdev&& sdev->scsi_dh_data) scsi_dh = sdev->scsi_dh_data->scsi_dh; -if (!scsi_dh || !get_device (&sdev->sdev_gendev) || + dev =get_device (&sdev->sdev_gendev); +if (!scsi_dh || !dev || sdev->sdev_state ==SDEV_CANCEL || sdev->sdev_state ==SDEV_DEL ) err =SCSI_DH_NOSYS ;@@ -410,12 +412,13 @@ int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data)if (err) {if (fn)fn (data, err); -return err; + goto out;
drivers/scsi/device_handler/scsi_dh.c int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data) · line 424
Quoted 10 lines
drivers/scsi/device_handler/scsi_dh.c +2
-1}if (scsi_dh->activate) err = scsi_dh->activate (sdev, fn, data); -put_device (&sdev->sdev_gendev); +out: +put_device (dev);return err; }EXPORT_SYMBOL_GPL (scsi_dh_activate);
Looks correct to me.
Reviewed-by Mike Christie <[email protected]>