aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJody McIntyre <scjody@steamballoon.com>2005-09-30 14:59:06 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-30 15:41:18 -0400
commitabd559b1052e28d8b9c28aabde241f18fa89090b (patch)
tree8720378a6a4e57b4e80969348fe9aa67ae899461
parent105d7b38b08f85c9abc3fd31e5cfa7ee4cf0a402 (diff)
[PATCH] sbp2: fix deadlocks and delays on device removal/rmmod
Fixes for deadlocks of the ieee1394 and scsi subsystems and long delays in futile error recovery attempts when SBP-2 devices are removed or drivers are unloaded. - Complete commands quickly with DID_NO_CONNECT if the 1394 node is gone or if the 1394 low-level driver was unloaded. - Skip unnecessary work in the eh_abort_handler and eh_device_reset_handler if the node or 1394 low-level driver is gone. - Let scsi's high-level shut down gracefully when sbp2 is being unloaded or detached from the 1394 unit. A call to scsi_remove_device is added for this purpose, which requires us to store a scsi_device pointer. - scsi_device pointer is obtained from slave_alloc hook and cleared by slave_destroy. This avoids usage of the pointer after the scsi device was deleted e.g. by the user via scsi_mod's sysfs interface. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> Signed-off-by: Jody McIntyre <scjody@steamballoon.com> Cc: Ben Collins <bcollins@debian.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/ieee1394/sbp2.c96
1 files changed, 58 insertions, 38 deletions
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index de88218ef7cc..5d86b03979ec 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -596,6 +596,14 @@ static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_i
596 spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); 596 spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
597} 597}
598 598
599/*
600 * Is scsi_id valid? Is the 1394 node still present?
601 */
602static inline int sbp2util_node_is_available(struct scsi_id_instance_data *scsi_id)
603{
604 return scsi_id && scsi_id->ne && !scsi_id->ne->in_limbo;
605}
606
599 607
600 608
601/********************************************* 609/*********************************************
@@ -631,11 +639,23 @@ static int sbp2_remove(struct device *dev)
631{ 639{
632 struct unit_directory *ud; 640 struct unit_directory *ud;
633 struct scsi_id_instance_data *scsi_id; 641 struct scsi_id_instance_data *scsi_id;
642 struct scsi_device *sdev;
634 643
635 SBP2_DEBUG("sbp2_remove"); 644 SBP2_DEBUG("sbp2_remove");
636 645
637 ud = container_of(dev, struct unit_directory, device); 646 ud = container_of(dev, struct unit_directory, device);
638 scsi_id = ud->device.driver_data; 647 scsi_id = ud->device.driver_data;
648 if (!scsi_id)
649 return 0;
650
651 /* Trigger shutdown functions in scsi's highlevel. */
652 if (scsi_id->scsi_host)
653 scsi_unblock_requests(scsi_id->scsi_host);
654 sdev = scsi_id->sdev;
655 if (sdev) {
656 scsi_id->sdev = NULL;
657 scsi_remove_device(sdev);
658 }
639 659
640 sbp2_logout_device(scsi_id); 660 sbp2_logout_device(scsi_id);
641 sbp2_remove_device(scsi_id); 661 sbp2_remove_device(scsi_id);
@@ -2473,37 +2493,26 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
2473 struct scsi_id_instance_data *scsi_id = 2493 struct scsi_id_instance_data *scsi_id =
2474 (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0]; 2494 (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
2475 struct sbp2scsi_host_info *hi; 2495 struct sbp2scsi_host_info *hi;
2496 int result = DID_NO_CONNECT << 16;
2476 2497
2477 SBP2_DEBUG("sbp2scsi_queuecommand"); 2498 SBP2_DEBUG("sbp2scsi_queuecommand");
2478 2499
2479 /* 2500 if (!sbp2util_node_is_available(scsi_id))
2480 * If scsi_id is null, it means there is no device in this slot, 2501 goto done;
2481 * so we should return selection timeout.
2482 */
2483 if (!scsi_id) {
2484 SCpnt->result = DID_NO_CONNECT << 16;
2485 done (SCpnt);
2486 return 0;
2487 }
2488 2502
2489 hi = scsi_id->hi; 2503 hi = scsi_id->hi;
2490 2504
2491 if (!hi) { 2505 if (!hi) {
2492 SBP2_ERR("sbp2scsi_host_info is NULL - this is bad!"); 2506 SBP2_ERR("sbp2scsi_host_info is NULL - this is bad!");
2493 SCpnt->result = DID_NO_CONNECT << 16; 2507 goto done;
2494 done (SCpnt);
2495 return(0);
2496 } 2508 }
2497 2509
2498 /* 2510 /*
2499 * Until we handle multiple luns, just return selection time-out 2511 * Until we handle multiple luns, just return selection time-out
2500 * to any IO directed at non-zero LUNs 2512 * to any IO directed at non-zero LUNs
2501 */ 2513 */
2502 if (SCpnt->device->lun) { 2514 if (SCpnt->device->lun)
2503 SCpnt->result = DID_NO_CONNECT << 16; 2515 goto done;
2504 done (SCpnt);
2505 return(0);
2506 }
2507 2516
2508 /* 2517 /*
2509 * Check for request sense command, and handle it here 2518 * Check for request sense command, and handle it here
@@ -2514,7 +2523,7 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
2514 memcpy(SCpnt->request_buffer, SCpnt->sense_buffer, SCpnt->request_bufflen); 2523 memcpy(SCpnt->request_buffer, SCpnt->sense_buffer, SCpnt->request_bufflen);
2515 memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer)); 2524 memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));
2516 sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_GOOD, SCpnt, done); 2525 sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_GOOD, SCpnt, done);
2517 return(0); 2526 return 0;
2518 } 2527 }
2519 2528
2520 /* 2529 /*
@@ -2522,9 +2531,8 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
2522 */ 2531 */
2523 if (!hpsb_node_entry_valid(scsi_id->ne)) { 2532 if (!hpsb_node_entry_valid(scsi_id->ne)) {
2524 SBP2_ERR("Bus reset in progress - rejecting command"); 2533 SBP2_ERR("Bus reset in progress - rejecting command");
2525 SCpnt->result = DID_BUS_BUSY << 16; 2534 result = DID_BUS_BUSY << 16;
2526 done (SCpnt); 2535 goto done;
2527 return(0);
2528 } 2536 }
2529 2537
2530 /* 2538 /*
@@ -2535,8 +2543,12 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
2535 sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_SELECTION_TIMEOUT, 2543 sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_SELECTION_TIMEOUT,
2536 SCpnt, done); 2544 SCpnt, done);
2537 } 2545 }
2546 return 0;
2538 2547
2539 return(0); 2548done:
2549 SCpnt->result = result;
2550 done(SCpnt);
2551 return 0;
2540} 2552}
2541 2553
2542/* 2554/*
@@ -2683,14 +2695,27 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
2683} 2695}
2684 2696
2685 2697
2686static int sbp2scsi_slave_configure (struct scsi_device *sdev) 2698static int sbp2scsi_slave_alloc(struct scsi_device *sdev)
2687{ 2699{
2688 blk_queue_dma_alignment(sdev->request_queue, (512 - 1)); 2700 ((struct scsi_id_instance_data *)sdev->host->hostdata[0])->sdev = sdev;
2701 return 0;
2702}
2703
2689 2704
2705static int sbp2scsi_slave_configure(struct scsi_device *sdev)
2706{
2707 blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
2690 return 0; 2708 return 0;
2691} 2709}
2692 2710
2693 2711
2712static void sbp2scsi_slave_destroy(struct scsi_device *sdev)
2713{
2714 ((struct scsi_id_instance_data *)sdev->host->hostdata[0])->sdev = NULL;
2715 return;
2716}
2717
2718
2694/* 2719/*
2695 * Called by scsi stack when something has really gone wrong. Usually 2720 * Called by scsi stack when something has really gone wrong. Usually
2696 * called when a command has timed-out for some reason. 2721 * called when a command has timed-out for some reason.
@@ -2705,7 +2730,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
2705 SBP2_ERR("aborting sbp2 command"); 2730 SBP2_ERR("aborting sbp2 command");
2706 scsi_print_command(SCpnt); 2731 scsi_print_command(SCpnt);
2707 2732
2708 if (scsi_id) { 2733 if (sbp2util_node_is_available(scsi_id)) {
2709 2734
2710 /* 2735 /*
2711 * Right now, just return any matching command structures 2736 * Right now, just return any matching command structures
@@ -2742,31 +2767,24 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
2742/* 2767/*
2743 * Called by scsi stack when something has really gone wrong. 2768 * Called by scsi stack when something has really gone wrong.
2744 */ 2769 */
2745static int __sbp2scsi_reset(struct scsi_cmnd *SCpnt) 2770static int sbp2scsi_reset(struct scsi_cmnd *SCpnt)
2746{ 2771{
2747 struct scsi_id_instance_data *scsi_id = 2772 struct scsi_id_instance_data *scsi_id =
2748 (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0]; 2773 (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
2774 unsigned long flags;
2749 2775
2750 SBP2_ERR("reset requested"); 2776 SBP2_ERR("reset requested");
2751 2777
2752 if (scsi_id) { 2778 spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
2779
2780 if (sbp2util_node_is_available(scsi_id)) {
2753 SBP2_ERR("Generating sbp2 fetch agent reset"); 2781 SBP2_ERR("Generating sbp2 fetch agent reset");
2754 sbp2_agent_reset(scsi_id, 0); 2782 sbp2_agent_reset(scsi_id, 0);
2755 } 2783 }
2756 2784
2757 return(SUCCESS);
2758}
2759
2760static int sbp2scsi_reset(struct scsi_cmnd *SCpnt)
2761{
2762 unsigned long flags;
2763 int rc;
2764
2765 spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
2766 rc = __sbp2scsi_reset(SCpnt);
2767 spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags); 2785 spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
2768 2786
2769 return rc; 2787 return SUCCESS;
2770} 2788}
2771 2789
2772static const char *sbp2scsi_info (struct Scsi_Host *host) 2790static const char *sbp2scsi_info (struct Scsi_Host *host)
@@ -2817,7 +2835,9 @@ static struct scsi_host_template scsi_driver_template = {
2817 .eh_device_reset_handler = sbp2scsi_reset, 2835 .eh_device_reset_handler = sbp2scsi_reset,
2818 .eh_bus_reset_handler = sbp2scsi_reset, 2836 .eh_bus_reset_handler = sbp2scsi_reset,
2819 .eh_host_reset_handler = sbp2scsi_reset, 2837 .eh_host_reset_handler = sbp2scsi_reset,
2838 .slave_alloc = sbp2scsi_slave_alloc,
2820 .slave_configure = sbp2scsi_slave_configure, 2839 .slave_configure = sbp2scsi_slave_configure,
2840 .slave_destroy = sbp2scsi_slave_destroy,
2821 .this_id = -1, 2841 .this_id = -1,
2822 .sg_tablesize = SG_ALL, 2842 .sg_tablesize = SG_ALL,
2823 .use_clustering = ENABLE_CLUSTERING, 2843 .use_clustering = ENABLE_CLUSTERING,