On Wed, 8 Jan 2014, James Bottomley wrote:
> OK, Agreed, but that means modifying the 1/2 patch with the below. This
> should make the proposed diff to 2/2 correct.
>
> James
>
> ---
> diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
> index ef3f958..5fad646 100644
> --- a/drivers/scsi/scsi_scan.c
> +++ b/drivers/scsi/scsi_scan.c
> @@ -417,7 +417,7 @@ static struct scsi_target *scsi_alloc_target(struct
> device *parent,
> + shost->transportt->target_size;
> struct scsi_target *starget;
> struct scsi_target *found_target;
> - int error;
> + int error, ref_got;
>
> starget = kzalloc(size, GFP_KERNEL);
> if (!starget) {
> @@ -466,15 +466,15 @@ static struct scsi_target *scsi_alloc_target(struct
> device *parent,
> return starget;
>
> found:
> - if (!kref_get_unless_zero(&found_target->reap_ref))
> - /*
> - * release routine already fired. Target is dead, but
> - * STARGET_DEL may not yet be set (set in the release
> - * routine), so set here as well, just in case
> - */
> - found_target->state = STARGET_DEL;
> + /*
> + * release routine already fired if kref is zero, so if we can still
> + * take the reference, the target must be alive. If we can't, it must
> + * be dying and we need to wait for a new target
> + */
> + ref_got = kref_get_unless_zero(&found_target->reap_ref);
> +
> spin_unlock_irqrestore(shost->host_lock, flags);
> - if (found_target->state != STARGET_DEL) {
> + if (ref_got) {
> put_device(dev);
> return found_target;
> }
> @@ -482,8 +482,8 @@ static struct scsi_target *scsi_alloc_target(struct
> device *parent,
> * Unfortunately, we found a dying target; need to wait until it's
> * dead before we can get a new one. There is an anomaly here. We
> * *should* call scsi_target_reap() to balance the kref_get() of the
> - * reap_ref above. However, since the target is in state STARGET_DEL,
> - * it's already invisible and the reap_ref is irrelevant. If we call
> + * reap_ref above. However, since the target being released, it's
> + * already invisible and the reap_ref is irrelevant. If we call
> * scsi_target_reap() we might spuriously do another device_del() on
> * an already invisible target.
> */
In fact, most of this comment (everything after the first sentence) is
no longer needed. If the target is dying then kref_get_unless_zero
must have failed, so there is no need to worry about unbalanced
refcounts.
Otherwise this looks good.
Alan Stern
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html