aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2008-01-31 14:36:46 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-02-07 19:02:35 -0500
commitbd976f62cd6c6dda1ce57bf3e84447e94844868a (patch)
tree560e9fd29f0af7d6cb1a89b49e6f2091832c987b /drivers/scsi
parent7fb1921b07a83f71a77f806a2a7d2dd721ea641b (diff)
[SCSI] iscsi class: add session scanning
This just adds iscsi session scanning which works like fc rport scanning. The future patches will hook the drivers into Mathew Wilcox's async scanning infrastructure, so userspace does not have to special case iscsi and so userspace does not have to make a extra special case for hardware iscsi root scanning. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c37
1 files changed, 30 insertions, 7 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,