diff options
| author | Mike Christie <michaelc@cs.wisc.edu> | 2012-05-18 00:56:57 -0400 |
|---|---|---|
| committer | James Bottomley <JBottomley@Parallels.com> | 2012-07-20 03:58:22 -0400 |
| commit | 5d9fb5cc1b88277bb28a2a54e51b34cacaa123c2 (patch) | |
| tree | 9067ba87ee1455850d97984608daa717f381e0d8 | |
| parent | 1b8d26206134458044b0689f48194af00c96d406 (diff) | |
[SCSI] core, classes, mpt2sas: have scsi_internal_device_unblock take new state
This has scsi_internal_device_unblock/scsi_target_unblock take
the new state to set the devices as an argument instead of
always setting to running. The patch also converts users of these
functions.
This allows the FC and iSCSI class to transition devices from blocked
to transport-offline, so that when fast_io_fail/replacement_timeout
has fired we do not set the devices back to running. Instead, we
set them to SDEV_TRANSPORT_OFFLINE.
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
| -rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_base.h | 3 | ||||
| -rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_scsih.c | 4 | ||||
| -rw-r--r-- | drivers/scsi/scsi_lib.c | 40 | ||||
| -rw-r--r-- | drivers/scsi/scsi_priv.h | 4 | ||||
| -rw-r--r-- | drivers/scsi/scsi_transport_fc.c | 16 | ||||
| -rw-r--r-- | drivers/scsi/scsi_transport_iscsi.c | 6 | ||||
| -rw-r--r-- | include/scsi/scsi_device.h | 2 |
7 files changed, 41 insertions, 34 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index b6dd3a5de7f9..b3a1a30055d6 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h | |||
| @@ -1158,6 +1158,7 @@ extern struct scsi_transport_template *mpt2sas_transport_template; | |||
| 1158 | extern int scsi_internal_device_block(struct scsi_device *sdev); | 1158 | extern int scsi_internal_device_block(struct scsi_device *sdev); |
| 1159 | extern u8 mpt2sas_stm_zero_smid_handler(struct MPT2SAS_ADAPTER *ioc, | 1159 | extern u8 mpt2sas_stm_zero_smid_handler(struct MPT2SAS_ADAPTER *ioc, |
| 1160 | u8 msix_index, u32 reply); | 1160 | u8 msix_index, u32 reply); |
| 1161 | extern int scsi_internal_device_unblock(struct scsi_device *sdev); | 1161 | extern int scsi_internal_device_unblock(struct scsi_device *sdev, |
| 1162 | enum scsi_device_state new_state); | ||
| 1162 | 1163 | ||
| 1163 | #endif /* MPT2SAS_BASE_H_INCLUDED */ | 1164 | #endif /* MPT2SAS_BASE_H_INCLUDED */ |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 76973e8ca4ba..b1ebd6f8dab3 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c | |||
| @@ -2904,7 +2904,7 @@ _scsih_ublock_io_all_device(struct MPT2SAS_ADAPTER *ioc) | |||
| 2904 | dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_running, " | 2904 | dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_running, " |
| 2905 | "handle(0x%04x)\n", | 2905 | "handle(0x%04x)\n", |
| 2906 | sas_device_priv_data->sas_target->handle)); | 2906 | sas_device_priv_data->sas_target->handle)); |
| 2907 | scsi_internal_device_unblock(sdev); | 2907 | scsi_internal_device_unblock(sdev, SDEV_RUNNING); |
| 2908 | } | 2908 | } |
| 2909 | } | 2909 | } |
| 2910 | /** | 2910 | /** |
| @@ -2933,7 +2933,7 @@ _scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u64 sas_address) | |||
| 2933 | "sas address(0x%016llx)\n", ioc->name, | 2933 | "sas address(0x%016llx)\n", ioc->name, |
| 2934 | (unsigned long long)sas_address)); | 2934 | (unsigned long long)sas_address)); |
| 2935 | sas_device_priv_data->block = 0; | 2935 | sas_device_priv_data->block = 0; |
| 2936 | scsi_internal_device_unblock(sdev); | 2936 | scsi_internal_device_unblock(sdev, SDEV_RUNNING); |
| 2937 | } | 2937 | } |
| 2938 | } | 2938 | } |
| 2939 | } | 2939 | } |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 340c569d4535..36521a0ac54b 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
| @@ -2444,6 +2444,7 @@ EXPORT_SYMBOL_GPL(scsi_internal_device_block); | |||
| 2444 | /** | 2444 | /** |
| 2445 | * scsi_internal_device_unblock - resume a device after a block request | 2445 | * scsi_internal_device_unblock - resume a device after a block request |
| 2446 | * @sdev: device to resume | 2446 | * @sdev: device to resume |
| 2447 | * @new_state: state to set devices to after unblocking | ||
| 2447 | * | 2448 | * |
| 2448 | * Called by scsi lld's or the midlayer to restart the device queue | 2449 | * Called by scsi lld's or the midlayer to restart the device queue |
| 2449 | * for the previously suspended scsi device. Called from interrupt or | 2450 | * for the previously suspended scsi device. Called from interrupt or |
| @@ -2453,25 +2454,30 @@ EXPORT_SYMBOL_GPL(scsi_internal_device_block); | |||
| 2453 | * | 2454 | * |
| 2454 | * Notes: | 2455 | * Notes: |
| 2455 | * This routine transitions the device to the SDEV_RUNNING state | 2456 | * This routine transitions the device to the SDEV_RUNNING state |
| 2456 | * (which must be a legal transition) allowing the midlayer to | 2457 | * or to one of the offline states (which must be a legal transition) |
| 2457 | * goose the queue for this device. This routine assumes the | 2458 | * allowing the midlayer to goose the queue for this device. This |
| 2458 | * host_lock is held upon entry. | 2459 | * routine assumes the host_lock is held upon entry. |
| 2459 | */ | 2460 | */ |
| 2460 | int | 2461 | int |
| 2461 | scsi_internal_device_unblock(struct scsi_device *sdev) | 2462 | scsi_internal_device_unblock(struct scsi_device *sdev, |
| 2463 | enum scsi_device_state new_state) | ||
| 2462 | { | 2464 | { |
| 2463 | struct request_queue *q = sdev->request_queue; | 2465 | struct request_queue *q = sdev->request_queue; |
| 2464 | unsigned long flags; | 2466 | unsigned long flags; |
| 2465 | 2467 | ||
| 2466 | /* | 2468 | /* |
| 2467 | * Try to transition the scsi device to SDEV_RUNNING | 2469 | * Try to transition the scsi device to SDEV_RUNNING or one of the |
| 2468 | * and goose the device queue if successful. | 2470 | * offlined states and goose the device queue if successful. |
| 2469 | */ | 2471 | */ |
| 2470 | if (sdev->sdev_state == SDEV_BLOCK) | 2472 | if (sdev->sdev_state == SDEV_BLOCK) |
| 2471 | sdev->sdev_state = SDEV_RUNNING; | 2473 | sdev->sdev_state = new_state; |
| 2472 | else if (sdev->sdev_state == SDEV_CREATED_BLOCK) | 2474 | else if (sdev->sdev_state == SDEV_CREATED_BLOCK) { |
| 2473 | sdev->sdev_state = SDEV_CREATED; | 2475 | if (new_state == SDEV_TRANSPORT_OFFLINE || |
| 2474 | else if (sdev->sdev_state != SDEV_CANCEL && | 2476 | new_state == SDEV_OFFLINE) |
| 2477 | sdev->sdev_state = new_state; | ||
| 2478 | else | ||
| 2479 | sdev->sdev_state = SDEV_CREATED; | ||
| 2480 | } else if (sdev->sdev_state != SDEV_CANCEL && | ||
| 2475 | sdev->sdev_state != SDEV_OFFLINE) | 2481 | sdev->sdev_state != SDEV_OFFLINE) |
| 2476 | return -EINVAL; | 2482 | return -EINVAL; |
| 2477 | 2483 | ||
| @@ -2512,26 +2518,26 @@ EXPORT_SYMBOL_GPL(scsi_target_block); | |||
| 2512 | static void | 2518 | static void |
| 2513 | device_unblock(struct scsi_device *sdev, void *data) | 2519 | device_unblock(struct scsi_device *sdev, void *data) |
| 2514 | { | 2520 | { |
| 2515 | scsi_internal_device_unblock(sdev); | 2521 | scsi_internal_device_unblock(sdev, *(enum scsi_device_state *)data); |
| 2516 | } | 2522 | } |
| 2517 | 2523 | ||
| 2518 | static int | 2524 | static int |
| 2519 | target_unblock(struct device *dev, void *data) | 2525 | target_unblock(struct device *dev, void *data) |
| 2520 | { | 2526 | { |
| 2521 | if (scsi_is_target_device(dev)) | 2527 | if (scsi_is_target_device(dev)) |
| 2522 | starget_for_each_device(to_scsi_target(dev), NULL, | 2528 | starget_for_each_device(to_scsi_target(dev), data, |
| 2523 | device_unblock); | 2529 | device_unblock); |
| 2524 | return 0; | 2530 | return 0; |
| 2525 | } | 2531 | } |
| 2526 | 2532 | ||
| 2527 | void | 2533 | void |
| 2528 | scsi_target_unblock(struct device *dev) | 2534 | scsi_target_unblock(struct device *dev, enum scsi_device_state new_state) |
| 2529 | { | 2535 | { |
| 2530 | if (scsi_is_target_device(dev)) | 2536 | if (scsi_is_target_device(dev)) |
| 2531 | starget_for_each_device(to_scsi_target(dev), NULL, | 2537 | starget_for_each_device(to_scsi_target(dev), &new_state, |
| 2532 | device_unblock); | 2538 | device_unblock); |
| 2533 | else | 2539 | else |
| 2534 | device_for_each_child(dev, NULL, target_unblock); | 2540 | device_for_each_child(dev, &new_state, target_unblock); |
| 2535 | } | 2541 | } |
| 2536 | EXPORT_SYMBOL_GPL(scsi_target_unblock); | 2542 | EXPORT_SYMBOL_GPL(scsi_target_unblock); |
| 2537 | 2543 | ||
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 07ce3f51701d..cbfe5df24a3b 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | #define _SCSI_PRIV_H | 2 | #define _SCSI_PRIV_H |
| 3 | 3 | ||
| 4 | #include <linux/device.h> | 4 | #include <linux/device.h> |
| 5 | #include <scsi/scsi_device.h> | ||
| 5 | 6 | ||
| 6 | struct request_queue; | 7 | struct request_queue; |
| 7 | struct request; | 8 | struct request; |
| @@ -172,6 +173,7 @@ extern struct list_head scsi_sd_probe_domain; | |||
| 172 | 173 | ||
| 173 | #define SCSI_DEVICE_BLOCK_MAX_TIMEOUT 600 /* units in seconds */ | 174 | #define SCSI_DEVICE_BLOCK_MAX_TIMEOUT 600 /* units in seconds */ |
| 174 | extern int scsi_internal_device_block(struct scsi_device *sdev); | 175 | extern int scsi_internal_device_block(struct scsi_device *sdev); |
| 175 | extern int scsi_internal_device_unblock(struct scsi_device *sdev); | 176 | extern int scsi_internal_device_unblock(struct scsi_device *sdev, |
| 177 | enum scsi_device_state new_state); | ||
| 176 | 178 | ||
| 177 | #endif /* _SCSI_PRIV_H */ | 179 | #endif /* _SCSI_PRIV_H */ |
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 2fded793997c..2d1e68db9b3f 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c | |||
| @@ -2495,11 +2495,9 @@ static void fc_terminate_rport_io(struct fc_rport *rport) | |||
| 2495 | i->f->terminate_rport_io(rport); | 2495 | i->f->terminate_rport_io(rport); |
| 2496 | 2496 | ||
| 2497 | /* | 2497 | /* |
| 2498 | * must unblock to flush queued IO. The caller will have set | 2498 | * Must unblock to flush queued IO. scsi-ml will fail incoming reqs. |
| 2499 | * the port_state or flags, so that fc_remote_port_chkready will | ||
| 2500 | * fail IO. | ||
| 2501 | */ | 2499 | */ |
| 2502 | scsi_target_unblock(&rport->dev); | 2500 | scsi_target_unblock(&rport->dev, SDEV_TRANSPORT_OFFLINE); |
| 2503 | } | 2501 | } |
| 2504 | 2502 | ||
| 2505 | /** | 2503 | /** |
| @@ -2830,8 +2828,8 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel, | |||
| 2830 | |||
