Commit 643eb2d932c97a0583381629d632d486934cf7ee

Authored by James Bottomley
1 parent f7120a4f75

[SCSI] rework scsi_target allocation

The current target allocation code registeres each possible target
with sysfs; it will be deleted again if no useable LUN on this target
was found. This results in a string of 'target add/target remove' uevents.

Based on a patch by Hannes Reinecke <hare@suse.de> this patch reworks
the target allocation code so that only uevents for existing targets
are sent. The sysfs registration is split off from the existing
scsi_target_alloc() into a in a new scsi_add_target() function, which
should be called whenever an existing target is found. Only then a
uevent is sent, so we'll be generating events for existing targets
only.

Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>

Showing 3 changed files with 63 additions and 39 deletions Side-by-side Diff

drivers/scsi/scsi_scan.c
... ... @@ -322,6 +322,21 @@
322 322 return NULL;
323 323 }
324 324  
  325 +static void scsi_target_destroy(struct scsi_target *starget)
  326 +{
  327 + struct device *dev = &starget->dev;
  328 + struct Scsi_Host *shost = dev_to_shost(dev->parent);
  329 + unsigned long flags;
  330 +
  331 + transport_destroy_device(dev);
  332 + spin_lock_irqsave(shost->host_lock, flags);
  333 + if (shost->hostt->target_destroy)
  334 + shost->hostt->target_destroy(starget);
  335 + list_del_init(&starget->siblings);
  336 + spin_unlock_irqrestore(shost->host_lock, flags);
  337 + put_device(dev);
  338 +}
  339 +
325 340 static void scsi_target_dev_release(struct device *dev)
326 341 {
327 342 struct device *parent = dev->parent;
... ... @@ -406,7 +421,7 @@
406 421 starget->channel = channel;
407 422 INIT_LIST_HEAD(&starget->siblings);
408 423 INIT_LIST_HEAD(&starget->devices);
409   - starget->state = STARGET_RUNNING;
  424 + starget->state = STARGET_CREATED;
410 425 starget->scsi_level = SCSI_2;
411 426 retry:
412 427 spin_lock_irqsave(shost->host_lock, flags);
... ... @@ -419,18 +434,6 @@
419 434 spin_unlock_irqrestore(shost->host_lock, flags);
420 435 /* allocate and add */
421 436 transport_setup_device(dev);
422   - error = device_add(dev);
423   - if (error) {
424   - dev_err(dev, "target device_add failed, error %d\n", error);
425   - spin_lock_irqsave(shost->host_lock, flags);
426   - list_del_init(&starget->siblings);
427   - spin_unlock_irqrestore(shost->host_lock, flags);
428   - transport_destroy_device(dev);
429   - put_device(parent);
430   - kfree(starget);
431   - return NULL;
432   - }
433   - transport_add_device(dev);
434 437 if (shost->hostt->target_alloc) {
435 438 error = shost->hostt->target_alloc(starget);
436 439  
... ... @@ -438,9 +441,7 @@
438 441 dev_printk(KERN_ERR, dev, "target allocation failed, error %d\n", error);
439 442 /* don't want scsi_target_reap to do the final
440 443 * put because it will be under the host lock */
441   - get_device(dev);
442   - scsi_target_reap(starget);
443   - put_device(dev);
  444 + scsi_target_destroy(starget);
444 445 return NULL;
445 446 }
446 447 }
447 448  
... ... @@ -467,18 +468,10 @@
467 468 {
468 469 struct scsi_target *starget =
469 470 container_of(work, struct scsi_target, ew.work);
470   - struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
471   - unsigned long flags;
472 471  
473 472 transport_remove_device(&starget->dev);
474 473 device_del(&starget->dev);
475   - transport_destroy_device(&starget->dev);
476   - spin_lock_irqsave(shost->host_lock, flags);
477   - if (shost->hostt->target_destroy)
478   - shost->hostt->target_destroy(starget);
479   - list_del_init(&starget->siblings);
480   - spin_unlock_irqrestore(shost->host_lock, flags);
481   - put_device(&starget->dev);
  474 + scsi_target_destroy(starget);
482 475 }
483 476  
484 477 /**
485 478  
486 479  
487 480  
... ... @@ -493,21 +486,25 @@
493 486 {
494 487 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
495 488 unsigned long flags;
  489 + enum scsi_target_state state;
  490 + int empty;
496 491  
497 492 spin_lock_irqsave(shost->host_lock, flags);
  493 + state = starget->state;
  494 + empty = --starget->reap_ref == 0 &&
  495 + list_empty(&starget->devices) ? 1 : 0;
  496 + spin_unlock_irqrestore(shost->host_lock, flags);
498 497  
499   - if (--starget->reap_ref == 0 && list_empty(&starget->devices)) {
500   - BUG_ON(starget->state == STARGET_DEL);
501   - starget->state = STARGET_DEL;
502   - spin_unlock_irqrestore(shost->host_lock, flags);
503   - execute_in_process_context(scsi_target_reap_usercontext,
504   - &starget->ew);
  498 + if (!empty)
505 499 return;
506 500  
507   - }
508   - spin_unlock_irqrestore(shost->host_lock, flags);
509   -
510   - return;
  501 + BUG_ON(state == STARGET_DEL);
  502 + starget->state = STARGET_DEL;
  503 + if (state == STARGET_CREATED)
  504 + scsi_target_destroy(starget);
  505 + else
  506 + execute_in_process_context(scsi_target_reap_usercontext,
  507 + &starget->ew);
511 508 }
512 509  
513 510 /**
514 511  
... ... @@ -1056,8 +1053,9 @@
1056 1053 scsi_inq_str(vend, result, 8, 16),
1057 1054 scsi_inq_str(mod, result, 16, 32));
1058 1055 });
  1056 +
1059 1057 }
1060   -
  1058 +
1061 1059 res = SCSI_SCAN_TARGET_PRESENT;
1062 1060 goto out_free_result;
1063 1061 }
... ... @@ -1497,7 +1495,6 @@
1497 1495 if (scsi_host_scan_allowed(shost))
1498 1496 scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata);
1499 1497 mutex_unlock(&shost->scan_mutex);
1500   - transport_configure_device(&starget->dev);
1501 1498 scsi_target_reap(starget);
1502 1499 put_device(&starget->dev);
1503 1500  
... ... @@ -1578,7 +1575,6 @@
1578 1575 out_reap:
1579 1576 /* now determine if the target has any children at all
1580 1577 * and if not, nuke it */
1581   - transport_configure_device(&starget->dev);
1582 1578 scsi_target_reap(starget);
1583 1579  
1584 1580 put_device(&starget->dev);
drivers/scsi/scsi_sysfs.c
... ... @@ -809,6 +809,27 @@
809 809 return count;
810 810 }
811 811  
  812 +static int scsi_target_add(struct scsi_target *starget)
  813 +{
  814 + int error;
  815 +
  816 + if (starget->state != STARGET_CREATED)
  817 + return 0;
  818 +
  819 + error = device_add(&starget->dev);
  820 + if (error) {
  821 + dev_err(&starget->dev, "target device_add failed, error %d\n", error);
  822 + get_device(&starget->dev);
  823 + scsi_target_reap(starget);
  824 + put_device(&starget->dev);
  825 + return error;
  826 + }
  827 + transport_add_device(&starget->dev);
  828 + starget->state = STARGET_RUNNING;
  829 +
  830 + return 0;
  831 +}
  832 +
812 833 static struct device_attribute sdev_attr_queue_type_rw =
813 834 __ATTR(queue_type, S_IRUGO | S_IWUSR, show_queue_type_field,
814 835 sdev_store_queue_type_rw);
815 836  
... ... @@ -824,10 +845,16 @@
824 845 {
825 846 int error, i;
826 847 struct request_queue *rq = sdev->request_queue;
  848 + struct scsi_target *starget = sdev->sdev_target;
827 849  
828 850 if ((error = scsi_device_set_state(sdev, SDEV_RUNNING)) != 0)
829 851 return error;
830 852  
  853 + error = scsi_target_add(starget);
  854 + if (error)
  855 + return error;
  856 +
  857 + transport_configure_device(&starget->dev);
831 858 error = device_add(&sdev->sdev_gendev);
832 859 if (error) {
833 860 put_device(sdev->sdev_gendev.parent);
include/scsi/scsi_device.h
... ... @@ -181,7 +181,8 @@
181 181 sdev_printk(prefix, (scmd)->device, fmt, ##a)
182 182  
183 183 enum scsi_target_state {
184   - STARGET_RUNNING = 1,
  184 + STARGET_CREATED = 1,
  185 + STARGET_RUNNING,
185 186 STARGET_DEL,
186 187 };
187 188