@@ -370,6 +370,31 @@ static struct scsi_target *__scsi_find_target(struct device *parent,
370370 return found_starget ;
371371}
372372
373+ /**
374+ * scsi_target_reap_ref_release - remove target from visibility
375+ * @kref: the reap_ref in the target being released
376+ *
377+ * Called on last put of reap_ref, which is the indication that no device
378+ * under this target is visible anymore, so render the target invisible in
379+ * sysfs. Note: we have to be in user context here because the target reaps
380+ * should be done in places where the scsi device visibility is being removed.
381+ */
382+ static void scsi_target_reap_ref_release (struct kref * kref )
383+ {
384+ struct scsi_target * starget
385+ = container_of (kref , struct scsi_target , reap_ref );
386+
387+ transport_remove_device (& starget -> dev );
388+ device_del (& starget -> dev );
389+ starget -> state = STARGET_DEL ;
390+ scsi_target_destroy (starget );
391+ }
392+
393+ static void scsi_target_reap_ref_put (struct scsi_target * starget )
394+ {
395+ kref_put (& starget -> reap_ref , scsi_target_reap_ref_release );
396+ }
397+
373398/**
374399 * scsi_alloc_target - allocate a new or find an existing target
375400 * @parent: parent of the target (need not be a scsi host)
@@ -392,7 +417,7 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
392417 + shost -> transportt -> target_size ;
393418 struct scsi_target * starget ;
394419 struct scsi_target * found_target ;
395- int error ;
420+ int error , ref_got ;
396421
397422 starget = kzalloc (size , GFP_KERNEL );
398423 if (!starget ) {
@@ -401,7 +426,7 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
401426 }
402427 dev = & starget -> dev ;
403428 device_initialize (dev );
404- starget -> reap_ref = 1 ;
429+ kref_init ( & starget -> reap_ref ) ;
405430 dev -> parent = get_device (parent );
406431 dev_set_name (dev , "target%d:%d:%d" , shost -> host_no , channel , id );
407432 dev -> bus = & scsi_bus_type ;
@@ -441,29 +466,36 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
441466 return starget ;
442467
443468 found :
444- found_target -> reap_ref ++ ;
469+ /*
470+ * release routine already fired if kref is zero, so if we can still
471+ * take the reference, the target must be alive. If we can't, it must
472+ * be dying and we need to wait for a new target
473+ */
474+ ref_got = kref_get_unless_zero (& found_target -> reap_ref );
475+
445476 spin_unlock_irqrestore (shost -> host_lock , flags );
446- if (found_target -> state != STARGET_DEL ) {
477+ if (ref_got ) {
447478 put_device (dev );
448479 return found_target ;
449480 }
450- /* Unfortunately, we found a dying target; need to
451- * wait until it's dead before we can get a new one */
481+ /*
482+ * Unfortunately, we found a dying target; need to wait until it's
483+ * dead before we can get a new one. There is an anomaly here. We
484+ * *should* call scsi_target_reap() to balance the kref_get() of the
485+ * reap_ref above. However, since the target being released, it's
486+ * already invisible and the reap_ref is irrelevant. If we call
487+ * scsi_target_reap() we might spuriously do another device_del() on
488+ * an already invisible target.
489+ */
452490 put_device (& found_target -> dev );
453- flush_scheduled_work ();
491+ /*
492+ * length of time is irrelevant here, we just want to yield the CPU
493+ * for a tick to avoid busy waiting for the target to die.
494+ */
495+ msleep (1 );
454496 goto retry ;
455497}
456498
457- static void scsi_target_reap_usercontext (struct work_struct * work )
458- {
459- struct scsi_target * starget =
460- container_of (work , struct scsi_target , ew .work );
461-
462- transport_remove_device (& starget -> dev );
463- device_del (& starget -> dev );
464- scsi_target_destroy (starget );
465- }
466-
467499/**
468500 * scsi_target_reap - check to see if target is in use and destroy if not
469501 * @starget: target to be checked
@@ -474,28 +506,11 @@ static void scsi_target_reap_usercontext(struct work_struct *work)
474506 */
475507void scsi_target_reap (struct scsi_target * starget )
476508{
477- struct Scsi_Host * shost = dev_to_shost (starget -> dev .parent );
478- unsigned long flags ;
479- enum scsi_target_state state ;
480- int empty = 0 ;
481-
482- spin_lock_irqsave (shost -> host_lock , flags );
483- state = starget -> state ;
484- if (-- starget -> reap_ref == 0 && list_empty (& starget -> devices )) {
485- empty = 1 ;
486- starget -> state = STARGET_DEL ;
487- }
488- spin_unlock_irqrestore (shost -> host_lock , flags );
489-
490- if (!empty )
491- return ;
492-
493- BUG_ON (state == STARGET_DEL );
494- if (state == STARGET_CREATED )
509+ BUG_ON (starget -> state == STARGET_DEL );
510+ if (starget -> state == STARGET_CREATED )
495511 scsi_target_destroy (starget );
496512 else
497- execute_in_process_context (scsi_target_reap_usercontext ,
498- & starget -> ew );
513+ scsi_target_reap_ref_put (starget );
499514}
500515
501516/**
@@ -1532,6 +1547,10 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
15321547 }
15331548 mutex_unlock (& shost -> scan_mutex );
15341549 scsi_autopm_put_target (starget );
1550+ /*
1551+ * paired with scsi_alloc_target(). Target will be destroyed unless
1552+ * scsi_probe_and_add_lun made an underlying device visible
1553+ */
15351554 scsi_target_reap (starget );
15361555 put_device (& starget -> dev );
15371556
@@ -1612,8 +1631,10 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel,
16121631
16131632 out_reap :
16141633 scsi_autopm_put_target (starget );
1615- /* now determine if the target has any children at all
1616- * and if not, nuke it */
1634+ /*
1635+ * paired with scsi_alloc_target(): determine if the target has
1636+ * any children at all and if not, nuke it
1637+ */
16171638 scsi_target_reap (starget );
16181639
16191640 put_device (& starget -> dev );
0 commit comments