aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c37
-rw-r--r--include/scsi/scsi_transport_iscsi.h7
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
305static 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
305static void session_recovery_timedout(struct work_struct *work) 322static 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
341void iscsi_unblock_session(struct iscsi_cls_session *session) 358void 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}
351EXPORT_SYMBOL_GPL(iscsi_unblock_session); 371EXPORT_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
396struct iscsi_cls_session * 416struct 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 {
203struct iscsi_host { 204struct 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/*