Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Mike Christie and committed by
James Bottomley
5d9fb5cc 1b8d2620

+41 -34
+2 -1
drivers/scsi/mpt2sas/mpt2sas_base.h
··· 1158 1158 extern int scsi_internal_device_block(struct scsi_device *sdev); 1159 1159 extern u8 mpt2sas_stm_zero_smid_handler(struct MPT2SAS_ADAPTER *ioc, 1160 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 1164 #endif /* MPT2SAS_BASE_H_INCLUDED */
+2 -2
drivers/scsi/mpt2sas/mpt2sas_scsih.c
··· 2904 2904 dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_running, " 2905 2905 "handle(0x%04x)\n", 2906 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 2933 "sas address(0x%016llx)\n", ioc->name, 2934 2934 (unsigned long long)sas_address)); 2935 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 }
+23 -17
drivers/scsi/scsi_lib.c
··· 2444 2444 /** 2445 2445 * scsi_internal_device_unblock - resume a device after a block request 2446 2446 * @sdev: device to resume 2447 + * @new_state: state to set devices to after unblocking 2447 2448 * 2448 2449 * Called by scsi lld's or the midlayer to restart the device queue 2449 2450 * for the previously suspended scsi device. Called from interrupt or ··· 2454 2453 * 2455 2454 * Notes: 2456 2455 * This routine transitions the device to the SDEV_RUNNING state 2457 - * (which must be a legal transition) allowing the midlayer to 2458 - * goose the queue for this device. This routine assumes the 2459 - * host_lock is held upon entry. 2456 + * or to one of the offline states (which must be a legal transition) 2457 + * allowing the midlayer to goose the queue for this device. This 2458 + * routine assumes the host_lock is held upon entry. 2460 2459 */ 2461 2460 int 2462 - scsi_internal_device_unblock(struct scsi_device *sdev) 2461 + scsi_internal_device_unblock(struct scsi_device *sdev, 2462 + enum scsi_device_state new_state) 2463 2463 { 2464 2464 struct request_queue *q = sdev->request_queue; 2465 2465 unsigned long flags; 2466 - 2467 - /* 2468 - * Try to transition the scsi device to SDEV_RUNNING 2469 - * and goose the device queue if successful. 2466 + 2467 + /* 2468 + * Try to transition the scsi device to SDEV_RUNNING or one of the 2469 + * offlined states and goose the device queue if successful. 2470 2470 */ 2471 2471 if (sdev->sdev_state == SDEV_BLOCK) 2472 - sdev->sdev_state = SDEV_RUNNING; 2473 - else if (sdev->sdev_state == SDEV_CREATED_BLOCK) 2474 - sdev->sdev_state = SDEV_CREATED; 2475 - else if (sdev->sdev_state != SDEV_CANCEL && 2472 + sdev->sdev_state = new_state; 2473 + else if (sdev->sdev_state == SDEV_CREATED_BLOCK) { 2474 + if (new_state == SDEV_TRANSPORT_OFFLINE || 2475 + new_state == SDEV_OFFLINE) 2476 + sdev->sdev_state = new_state; 2477 + else 2478 + sdev->sdev_state = SDEV_CREATED; 2479 + } else if (sdev->sdev_state != SDEV_CANCEL && 2476 2480 sdev->sdev_state != SDEV_OFFLINE) 2477 2481 return -EINVAL; 2478 2482 ··· 2518 2512 static void 2519 2513 device_unblock(struct scsi_device *sdev, void *data) 2520 2514 { 2521 - scsi_internal_device_unblock(sdev); 2515 + scsi_internal_device_unblock(sdev, *(enum scsi_device_state *)data); 2522 2516 } 2523 2517 2524 2518 static int 2525 2519 target_unblock(struct device *dev, void *data) 2526 2520 { 2527 2521 if (scsi_is_target_device(dev)) 2528 - starget_for_each_device(to_scsi_target(dev), NULL, 2522 + starget_for_each_device(to_scsi_target(dev), data, 2529 2523 device_unblock); 2530 2524 return 0; 2531 2525 } 2532 2526 2533 2527 void 2534 - scsi_target_unblock(struct device *dev) 2528 + scsi_target_unblock(struct device *dev, enum scsi_device_state new_state) 2535 2529 { 2536 2530 if (scsi_is_target_device(dev)) 2537 - starget_for_each_device(to_scsi_target(dev), NULL, 2531 + starget_for_each_device(to_scsi_target(dev), &new_state, 2538 2532 device_unblock); 2539 2533 else 2540 - device_for_each_child(dev, NULL, target_unblock); 2534 + device_for_each_child(dev, &new_state, target_unblock); 2541 2535 } 2542 2536 EXPORT_SYMBOL_GPL(scsi_target_unblock); 2543 2537
+3 -1
drivers/scsi/scsi_priv.h
··· 2 2 #define _SCSI_PRIV_H 3 3 4 4 #include <linux/device.h> 5 + #include <scsi/scsi_device.h> 5 6 6 7 struct request_queue; 7 8 struct request; ··· 173 172 174 173 #define SCSI_DEVICE_BLOCK_MAX_TIMEOUT 600 /* units in seconds */ 175 174 extern int scsi_internal_device_block(struct scsi_device *sdev); 176 - extern int scsi_internal_device_unblock(struct scsi_device *sdev); 175 + extern int scsi_internal_device_unblock(struct scsi_device *sdev, 176 + enum scsi_device_state new_state); 177 177 178 178 #endif /* _SCSI_PRIV_H */
+7 -9
drivers/scsi/scsi_transport_fc.c
··· 2495 2495 i->f->terminate_rport_io(rport); 2496 2496 2497 2497 /* 2498 - * must unblock to flush queued IO. The caller will have set 2499 - * the port_state or flags, so that fc_remote_port_chkready will 2500 - * fail IO. 2498 + * Must unblock to flush queued IO. scsi-ml will fail incoming reqs. 2501 2499 */ 2502 - scsi_target_unblock(&rport->dev); 2500 + scsi_target_unblock(&rport->dev, SDEV_TRANSPORT_OFFLINE); 2503 2501 } 2504 2502 2505 2503 /** ··· 2828 2830 2829 2831 /* if target, initiate a scan */ 2830 2832 if (rport->scsi_target_id != -1) { 2831 - scsi_target_unblock(&rport->dev); 2832 - 2833 + scsi_target_unblock(&rport->dev, 2834 + SDEV_RUNNING); 2833 2835 spin_lock_irqsave(shost->host_lock, 2834 2836 flags); 2835 2837 rport->flags |= FC_RPORT_SCAN_PENDING; ··· 2898 2900 spin_unlock_irqrestore(shost->host_lock, flags); 2899 2901 2900 2902 if (ids->roles & FC_PORT_ROLE_FCP_TARGET) { 2901 - scsi_target_unblock(&rport->dev); 2903 + scsi_target_unblock(&rport->dev, SDEV_RUNNING); 2902 2904 2903 2905 /* initiate a scan of the target */ 2904 2906 spin_lock_irqsave(shost->host_lock, flags); ··· 3103 3105 /* ensure any stgt delete functions are done */ 3104 3106 fc_flush_work(shost); 3105 3107 3106 - scsi_target_unblock(&rport->dev); 3108 + scsi_target_unblock(&rport->dev, SDEV_RUNNING); 3107 3109 /* initiate a scan of the target */ 3108 3110 spin_lock_irqsave(shost->host_lock, flags); 3109 3111 rport->flags |= FC_RPORT_SCAN_PENDING; ··· 3147 3149 "blocked FC remote port time out: no longer" 3148 3150 " a FCP target, removing starget\n"); 3149 3151 spin_unlock_irqrestore(shost->host_lock, flags); 3150 - scsi_target_unblock(&rport->dev); 3152 + scsi_target_unblock(&rport->dev, SDEV_TRANSPORT_OFFLINE); 3151 3153 fc_queue_work(shost, &rport->stgt_delete_work); 3152 3154 return; 3153 3155 }
+3 -3
drivers/scsi/scsi_transport_iscsi.c
··· 907 907 session->transport->session_recovery_timedout(session); 908 908 909 909 ISCSI_DBG_TRANS_SESSION(session, "Unblocking SCSI target\n"); 910 - scsi_target_unblock(&session->dev); 910 + scsi_target_unblock(&session->dev, SDEV_TRANSPORT_OFFLINE); 911 911 ISCSI_DBG_TRANS_SESSION(session, "Completed unblocking SCSI target\n"); 912 912 } 913 913 ··· 930 930 session->state = ISCSI_SESSION_LOGGED_IN; 931 931 spin_unlock_irqrestore(&session->lock, flags); 932 932 /* start IO */ 933 - scsi_target_unblock(&session->dev); 933 + scsi_target_unblock(&session->dev, SDEV_RUNNING); 934 934 /* 935 935 * Only do kernel scanning if the driver is properly hooked into 936 936 * the async scanning code (drivers like iscsi_tcp do login and ··· 1180 1180 session->state = ISCSI_SESSION_FREE; 1181 1181 spin_unlock_irqrestore(&session->lock, flags); 1182 1182 1183 - scsi_target_unblock(&session->dev); 1183 + scsi_target_unblock(&session->dev, SDEV_TRANSPORT_OFFLINE); 1184 1184 /* flush running scans then delete devices */ 1185 1185 scsi_flush_work(shost); 1186 1186 __iscsi_unbind_session(&session->unbind_work);
+1 -1
include/scsi/scsi_device.h
··· 374 374 unsigned int id, unsigned int lun, int rescan); 375 375 extern void scsi_target_reap(struct scsi_target *); 376 376 extern void scsi_target_block(struct device *); 377 - extern void scsi_target_unblock(struct device *); 377 + extern void scsi_target_unblock(struct device *, enum scsi_device_state); 378 378 extern void scsi_remove_target(struct device *); 379 379 extern void int_to_scsilun(unsigned int, struct scsi_lun *); 380 380 extern int scsilun_to_int(struct scsi_lun *);