aboutsummaryrefslogtreecommitdiffstats
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
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>
-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/*