aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <JBottomley@Parallels.com>2014-01-21 10:00:50 -0500
committerJames Bottomley <JBottomley@Parallels.com>2014-03-15 13:18:59 -0400
commite63ed0d7a98014fdfc2cfeb3f6dada313dcabb59 (patch)
tree64f3dd3c794d009538993445d8039f04407dc593
parent81b86d4d275244ad7e134e95cbcfee49198da854 (diff)
[SCSI] fix our current target reap infrastructure
This patch eliminates the reap_ref and replaces it with a proper kref. On last put of this kref, the target is removed from visibility in sysfs. The final call to scsi_target_reap() for the device is done from __scsi_remove_device() and only if the device was made visible. This ensures that the target disappears as soon as the last device is gone rather than waiting until final release of the device (which is often too long). Reviewed-by: Alan Stern <stern@rowland.harvard.edu> Tested-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Cc: stable@vger.kernel.org # delay backport by 2 months for field testing Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/scsi_scan.c99
-rw-r--r--drivers/scsi/scsi_sysfs.c20
-rw-r--r--include/scsi/scsi_device.h3
3 files changed, 75 insertions, 47 deletions
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 307a81137607..5fad646ee6e5 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -371,6 +371,31 @@ static struct scsi_target *__scsi_find_target(struct device *parent,
371} 371}
372 372
373/** 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 */
382static 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
393static void scsi_target_reap_ref_put(struct scsi_target *starget)
394{
395 kref_put(&starget->reap_ref, scsi_target_reap_ref_release);
396}
397
398/**
374 * scsi_alloc_target - allocate a new or find an existing target 399 * scsi_alloc_target - allocate a new or find an existing target
375 * @parent: parent of the target (need not be a scsi host) 400 * @parent: parent of the target (need not be a scsi host)
376 * @channel: target channel number (zero if no channels) 401 * @channel: target channel number (zero if no channels)
@@ -392,7 +417,7 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
392 + shost->transportt->target_size; 417 + shost->transportt->target_size;
393 struct scsi_target *starget; 418 struct scsi_target *starget;
394 struct scsi_target *found_target; 419 struct scsi_target *found_target;
395 int error; 420 int error, ref_got;
396 421
397 starget = kzalloc(size, GFP_KERNEL); 422 starget = kzalloc(size, GFP_KERNEL);
398 if (!starget) { 423 if (!starget) {
@@ -401,7 +426,7 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
401 } 426 }
402 dev = &starget->dev; 427 dev = &starget->dev;
403 device_initialize(dev); 428 device_initialize(dev);
404 starget->reap_ref = 1; 429 kref_init(&starget->reap_ref);
405 dev->parent = get_device(parent); 430 dev->parent = get_device(parent);
406 dev_set_name(dev, "target%d:%d:%d", shost->host_no, channel, id); 431 dev_set_name(dev, "target%d:%d:%d", shost->host_no, channel, id);
407 dev->bus = &scsi_bus_type; 432 dev->bus = &scsi_bus_type;
@@ -441,29 +466,36 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
441 return starget; 466 return starget;
442 467
443 found: 468 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
445 spin_unlock_irqrestore(shost->host_lock, flags); 476 spin_unlock_irqrestore(shost->host_lock, flags);
446 if (found_target->state != STARGET_DEL) { 477 if (ref_got) {
447 put_device(dev); 478 put_device(dev);
448 return found_target; 479 return found_target;
449 } 480 }
450 /* Unfortunately, we found a dying target; need to 481 /*
451 * wait until it's dead before we can get a new one */ 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 */
452 put_device(&found_target->dev); 490 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);
454 goto retry; 496 goto retry;
455} 497}
456 498
457static 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
467/** 499/**
468 * scsi_target_reap - check to see if target is in use and destroy if not 500 * scsi_target_reap - check to see if target is in use and destroy if not
469 * @starget: target to be checked 501 * @starget: target to be checked
@@ -474,28 +506,11 @@ static void scsi_target_reap_usercontext(struct work_struct *work)
474 */ 506 */
475void scsi_target_reap(struct scsi_target *starget) 507void scsi_target_reap(struct scsi_target *starget)
476{ 508{
477 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 509 BUG_ON(starget->state == STARGET_DEL);
478 unsigned long flags; 510 if (starget->state == STARGET_CREATED)
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)
495 scsi_target_destroy(starget); 511 scsi_target_destroy(starget);
496 else 512 else
497 execute_in_process_context(scsi_target_reap_usercontext, 513 scsi_target_reap_ref_put(starget);
498 &starget->ew);
499} 514}
500 515
501/** 516/**
@@ -1532,6 +1547,10 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
1532 } 1547 }
1533 mutex_unlock(&shost->scan_mutex); 1548 mutex_unlock(&shost->scan_mutex);
1534 scsi_autopm_put_target(starget); 1549 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 */
1535 scsi_target_reap(starget); 1554 scsi_target_reap(starget);
1536 put_device(&starget->dev); 1555 put_device(&starget->dev);
1537 1556
@@ -1612,8 +1631,10 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel,
1612 1631
1613 out_reap: 1632 out_reap:
1614 scsi_autopm_put_target(starget); 1633 scsi_autopm_put_target(starget);
1615 /* now determine if the target has any children at all 1634 /*
1616 * and if not, nuke it */ 1635 * paired with scsi_alloc_target(): determine if the target has
1636 * any children at all and if not, nuke it
1637 */
1617 scsi_target_reap(starget); 1638 scsi_target_reap(starget);
1618 1639
1619 put_device(&starget->dev); 1640 put_device(&starget->dev);
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 9117d0bf408e..665acbf83693 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -383,17 +383,14 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work)
383{ 383{
384 struct scsi_device *sdev; 384 struct scsi_device *sdev;
385 struct device *parent; 385 struct device *parent;
386 struct scsi_target *starget;
387 struct list_head *this, *tmp; 386 struct list_head *this, *tmp;
388 unsigned long flags; 387 unsigned long flags;
389 388
390 sdev = container_of(work, struct scsi_device, ew.work); 389 sdev = container_of(work, struct scsi_device, ew.work);
391 390
392 parent = sdev->sdev_gendev.parent; 391 parent = sdev->sdev_gendev.parent;
393 starget = to_scsi_target(parent);
394 392
395 spin_lock_irqsave(sdev->host->host_lock, flags); 393 spin_lock_irqsave(sdev->host->host_lock, flags);
396 starget->reap_ref++;
397 list_del(&sdev->siblings); 394 list_del(&sdev->siblings);
398 list_del(&sdev->same_target_siblings); 395 list_del(&sdev->same_target_siblings);
399 list_del(&sdev->starved_entry); 396 list_del(&sdev->starved_entry);
@@ -413,8 +410,6 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work)
413 /* NULL queue means the device can't be used */ 410 /* NULL queue means the device can't be used */
414 sdev->request_queue = NULL; 411 sdev->request_queue = NULL;
415 412
416 scsi_target_reap(scsi_target(sdev));
417
418 kfree(sdev->inquiry); 413 kfree(sdev->inquiry);
419 kfree(sdev); 414 kfree(sdev);
420 415
@@ -1071,6 +1066,13 @@ void __scsi_remove_device(struct scsi_device *sdev)
1071 sdev->host->hostt->slave_destroy(sdev); 1066 sdev->host->hostt->slave_destroy(sdev);
1072 transport_destroy_device(dev); 1067 transport_destroy_device(dev);
1073 1068
1069 /*
1070 * Paired with the kref_get() in scsi_sysfs_initialize(). We have
1071 * remoed sysfs visibility from the device, so make the target
1072 * invisible if this was the last device underneath it.
1073 */
1074 scsi_target_reap(scsi_target(sdev));
1075
1074 put_device(dev); 1076 put_device(dev);
1075} 1077}
1076 1078
@@ -1133,7 +1135,7 @@ void scsi_remove_target(struct device *dev)
1133 continue; 1135 continue;
1134 if (starget->dev.parent == dev || &starget->dev == dev) { 1136 if (starget->dev.parent == dev || &starget->dev == dev) {
1135 /* assuming new targets arrive at the end */ 1137 /* assuming new targets arrive at the end */
1136 starget->reap_ref++; 1138 kref_get(&starget->reap_ref);
1137 spin_unlock_irqrestore(shost->host_lock, flags); 1139 spin_unlock_irqrestore(shost->host_lock, flags);
1138 if (last) 1140 if (last)
1139 scsi_target_reap(last); 1141 scsi_target_reap(last);
@@ -1217,6 +1219,12 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev)
1217 list_add_tail(&sdev->same_target_siblings, &starget->devices); 1219 list_add_tail(&sdev->same_target_siblings, &starget->devices);
1218 list_add_tail(&sdev->siblings, &shost->__devices); 1220 list_add_tail(&sdev->siblings, &shost->__devices);
1219 spin_unlock_irqrestore(shost->host_lock, flags); 1221 spin_unlock_irqrestore(shost->host_lock, flags);
1222 /*
1223 * device can now only be removed via __scsi_remove_device() so hold
1224 * the target. Target will be held in CREATED state until something
1225 * beneath it becomes visible (in which case it moves to RUNNING)
1226 */
1227 kref_get(&starget->reap_ref);
1220} 1228}
1221 1229
1222int scsi_is_sdev_device(const struct device *dev) 1230int scsi_is_sdev_device(const struct device *dev)
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 622e100561d2..ccabdc1c27ca 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -269,7 +269,7 @@ struct scsi_target {
269 struct list_head siblings; 269 struct list_head siblings;
270 struct list_head devices; 270 struct list_head devices;
271 struct device dev; 271 struct device dev;
272 unsigned int reap_ref; /* protected by the host lock */ 272 struct kref reap_ref; /* last put renders target invisible */
273 unsigned int channel; 273 unsigned int channel;
274 unsigned int id; /* target id ... replace 274 unsigned int id; /* target id ... replace
275 * scsi_device.id eventually */ 275 * scsi_device.id eventually */
@@ -296,7 +296,6 @@ struct scsi_target {
296#define SCSI_DEFAULT_TARGET_BLOCKED 3 296#define SCSI_DEFAULT_TARGET_BLOCKED 3
297 297
298 char scsi_level; 298 char scsi_level;
299 struct execute_work ew;
300 enum scsi_target_state state; 299 enum scsi_target_state state;
301 void *hostdata; /* available to low-level driver */ 300 void *hostdata; /* available to low-level driver */
302 unsigned long starget_data[0]; /* for the transport */ 301 unsigned long starget_data[0]; /* for the transport */