diff options
-rw-r--r-- | drivers/scsi/scsi_transport_iscsi.c | 37 | ||||
-rw-r--r-- | include/scsi/scsi_transport_iscsi.h | 7 |
2 files changed, 34 insertions, 10 deletions
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index f876b0ae521a..af88955d0ec1 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c | |||
@@ -128,11 +128,11 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev, | |||
128 | INIT_LIST_HEAD(&ihost->sessions); | 128 | INIT_LIST_HEAD(&ihost->sessions); |
129 | mutex_init(&ihost->mutex); | 129 | mutex_init(&ihost->mutex); |
130 | 130 | ||
131 | snprintf(ihost->unbind_workq_name, KOBJ_NAME_LEN, "iscsi_unbind_%d", | 131 | snprintf(ihost->scan_workq_name, KOBJ_NAME_LEN, "iscsi_scan_%d", |
132 | shost->host_no); | 132 | shost->host_no); |
133 | ihost->unbind_workq = create_singlethread_workqueue( | 133 | ihost->scan_workq = create_singlethread_workqueue( |
134 | ihost->unbind_workq_name); | 134 | ihost->scan_workq_name); |
135 | if (!ihost->unbind_workq) | 135 | if (!ihost->scan_workq) |
136 | return -ENOMEM; | 136 | return -ENOMEM; |
137 | return 0; | 137 | return 0; |
138 | } | 138 | } |
@@ -143,7 +143,7 @@ static int iscsi_remove_host(struct transport_container *tc, struct device *dev, | |||
143 | struct Scsi_Host *shost = dev_to_shost(dev); | 143 | struct Scsi_Host *shost = dev_to_shost(dev); |
144 | struct iscsi_host *ihost = shost->shost_data; | 144 | struct iscsi_host *ihost = shost->shost_data; |
145 | 145 | ||
146 | destroy_workqueue(ihost->unbind_workq); | 146 | destroy_workqueue(ihost->scan_workq); |
147 | return 0; | 147 | return 0; |
148 | } | 148 | } |
149 | 149 | ||
@@ -302,6 +302,23 @@ static int iscsi_user_scan(struct Scsi_Host *shost, uint channel, | |||
302 | return 0; | 302 | return 0; |
303 | } | 303 | } |
304 | 304 | ||
305 | static void iscsi_scan_session(struct work_struct *work) | ||
306 | { | ||
307 | struct iscsi_cls_session *session = | ||
308 | container_of(work, struct iscsi_cls_session, scan_work); | ||
309 | unsigned long flags; | ||
310 | |||
311 | spin_lock_irqsave(&session->lock, flags); | ||
312 | if (session->state != ISCSI_SESSION_LOGGED_IN) { | ||
313 | spin_unlock_irqrestore(&session->lock, flags); | ||
314 | return; | ||
315 | } | ||
316 | spin_unlock_irqrestore(&session->lock, flags); | ||
317 | |||
318 | scsi_scan_target(&session->dev, 0, session->target_id, | ||
319 | SCAN_WILD_CARD, 1); | ||
320 | } | ||
321 | |||
305 | static void session_recovery_timedout(struct work_struct *work) | 322 | static void session_recovery_timedout(struct work_struct *work) |
306 | { | 323 | { |
307 | struct iscsi_cls_session *session = | 324 | struct iscsi_cls_session *session = |
@@ -340,6 +357,8 @@ void __iscsi_unblock_session(struct iscsi_cls_session *session) | |||
340 | 357 | ||
341 | void iscsi_unblock_session(struct iscsi_cls_session *session) | 358 | void iscsi_unblock_session(struct iscsi_cls_session *session) |
342 | { | 359 | { |
360 | struct Scsi_Host *shost = iscsi_session_to_shost(session); | ||
361 | struct iscsi_host *ihost = shost->shost_data; | ||
343 | unsigned long flags; | 362 | unsigned long flags; |
344 | 363 | ||
345 | spin_lock_irqsave(&session->lock, flags); | 364 | spin_lock_irqsave(&session->lock, flags); |
@@ -347,6 +366,7 @@ void iscsi_unblock_session(struct iscsi_cls_session *session) | |||
347 | spin_unlock_irqrestore(&session->lock, flags); | 366 | spin_unlock_irqrestore(&session->lock, flags); |
348 | 367 | ||
349 | __iscsi_unblock_session(session); | 368 | __iscsi_unblock_session(session); |
369 | queue_work(ihost->scan_workq, &session->scan_work); | ||
350 | } | 370 | } |
351 | EXPORT_SYMBOL_GPL(iscsi_unblock_session); | 371 | EXPORT_SYMBOL_GPL(iscsi_unblock_session); |
352 | 372 | ||
@@ -390,7 +410,7 @@ static int iscsi_unbind_session(struct iscsi_cls_session *session) | |||
390 | struct Scsi_Host *shost = iscsi_session_to_shost(session); | 410 | struct Scsi_Host *shost = iscsi_session_to_shost(session); |
391 | struct iscsi_host *ihost = shost->shost_data; | 411 | struct iscsi_host *ihost = shost->shost_data; |
392 | 412 | ||
393 | return queue_work(ihost->unbind_workq, &session->unbind_work); | 413 | return queue_work(ihost->scan_workq, &session->unbind_work); |
394 | } | 414 | } |
395 | 415 | ||
396 | struct iscsi_cls_session * | 416 | struct iscsi_cls_session * |
@@ -411,6 +431,7 @@ iscsi_alloc_session(struct Scsi_Host *shost, | |||
411 | INIT_LIST_HEAD(&session->host_list); | 431 | INIT_LIST_HEAD(&session->host_list); |
412 | INIT_LIST_HEAD(&session->sess_list); | 432 | INIT_LIST_HEAD(&session->sess_list); |
413 | INIT_WORK(&session->unbind_work, __iscsi_unbind_session); | 433 | INIT_WORK(&session->unbind_work, __iscsi_unbind_session); |
434 | INIT_WORK(&session->scan_work, iscsi_scan_session); | ||
414 | spin_lock_init(&session->lock); | 435 | spin_lock_init(&session->lock); |
415 | 436 | ||
416 | /* this is released in the dev's release function */ | 437 | /* this is released in the dev's release function */ |
@@ -530,13 +551,15 @@ void iscsi_remove_session(struct iscsi_cls_session *session) | |||
530 | spin_unlock_irqrestore(&session->lock, flags); | 551 | spin_unlock_irqrestore(&session->lock, flags); |
531 | __iscsi_unblock_session(session); | 552 | __iscsi_unblock_session(session); |
532 | iscsi_unbind_session(session); | 553 | iscsi_unbind_session(session); |
554 | |||
555 | /* flush running scans */ | ||
556 | flush_workqueue(ihost->scan_workq); | ||
533 | /* | 557 | /* |
534 | * If the session dropped while removing devices then we need to make | 558 | * If the session dropped while removing devices then we need to make |
535 | * sure it is not blocked | 559 | * sure it is not blocked |
536 | */ | 560 | */ |
537 | if (!cancel_delayed_work(&session->recovery_work)) | 561 | if (!cancel_delayed_work(&session->recovery_work)) |
538 | flush_workqueue(iscsi_eh_timer_workq); | 562 | flush_workqueue(iscsi_eh_timer_workq); |
539 | flush_workqueue(ihost->unbind_workq); | ||
540 | 563 | ||
541 | /* hw iscsi may not have removed all connections from session */ | 564 | /* hw iscsi may not have removed all connections from session */ |
542 | err = device_for_each_child(&session->dev, NULL, | 565 | err = device_for_each_child(&session->dev, NULL, |
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 0e869d9a3856..1f0ec46b4f87 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h | |||
@@ -177,11 +177,12 @@ struct iscsi_cls_session { | |||
177 | struct list_head host_list; | 177 | struct list_head host_list; |
178 | struct iscsi_transport *transport; | 178 | struct iscsi_transport *transport; |
179 | spinlock_t lock; | 179 | spinlock_t lock; |
180 | struct work_struct scan_work; | ||
181 | struct work_struct unbind_work; | ||
180 | 182 | ||
181 | /* recovery fields */ | 183 | /* recovery fields */ |
182 | int recovery_tmo; | 184 | int recovery_tmo; |
183 | struct delayed_work recovery_work; | 185 | struct delayed_work recovery_work; |
184 | struct work_struct unbind_work; | ||
185 | 186 | ||
186 | int target_id; | 187 | int target_id; |
187 | 188 | ||
@@ -203,8 +204,8 @@ struct iscsi_cls_session { | |||
203 | struct iscsi_host { | 204 | struct iscsi_host { |
204 | struct list_head sessions; | 205 | struct list_head sessions; |
205 | struct mutex mutex; | 206 | struct mutex mutex; |
206 | struct workqueue_struct *unbind_workq; | 207 | struct workqueue_struct *scan_workq; |
207 | char unbind_workq_name[KOBJ_NAME_LEN]; | 208 | char scan_workq_name[KOBJ_NAME_LEN]; |
208 | }; | 209 | }; |
209 | 210 | ||
210 | /* | 211 | /* |