aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2008-01-31 14:36:48 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-02-07 19:02:35 -0500
commit8aae18adb240a9eb1999b8245c56522cbefc9047 (patch)
treea859a89c4385fc3639733db4b56735e26797feba
parent568d303b5b3f0f6432ae8f56ecdb0beb2341288e (diff)
[SCSI] iscsi class: add async scan helper
In qla4xxx's probe it will call the iscsi session setup functions for session that got setup on the initial start. This then makes it easy for the iscsi class to export a helper which indicates when those scans are done. 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.c38
-rw-r--r--include/scsi/scsi_transport_iscsi.h3
2 files changed, 37 insertions, 4 deletions
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index af88955d0ec1..af1799723e7b 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -127,6 +127,7 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
127 memset(ihost, 0, sizeof(*ihost)); 127 memset(ihost, 0, sizeof(*ihost));
128 INIT_LIST_HEAD(&ihost->sessions); 128 INIT_LIST_HEAD(&ihost->sessions);
129 mutex_init(&ihost->mutex); 129 mutex_init(&ihost->mutex);
130 atomic_set(&ihost->nr_scans, 0);
130 131
131 snprintf(ihost->scan_workq_name, KOBJ_NAME_LEN, "iscsi_scan_%d", 132 snprintf(ihost->scan_workq_name, KOBJ_NAME_LEN, "iscsi_scan_%d",
132 shost->host_no); 133 shost->host_no);
@@ -284,6 +285,25 @@ static int iscsi_is_session_dev(const struct device *dev)
284 return dev->release == iscsi_session_release; 285 return dev->release == iscsi_session_release;
285} 286}
286 287
288/**
289 * iscsi_scan_finished - helper to report when running scans are done
290 * @shost: scsi host
291 * @time: scan run time
292 *
293 * This function can be used by drives like qla4xxx to report to the scsi
294 * layer when the scans it kicked off at module load time are done.
295 */
296int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time)
297{
298 struct iscsi_host *ihost = shost->shost_data;
299 /*
300 * qla4xxx will have kicked off some session unblocks before calling
301 * scsi_scan_host, so just wait for them to complete.
302 */
303 return !atomic_read(&ihost->nr_scans);
304}
305EXPORT_SYMBOL_GPL(iscsi_scan_finished);
306
287static int iscsi_user_scan(struct Scsi_Host *shost, uint channel, 307static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
288 uint id, uint lun) 308 uint id, uint lun)
289{ 309{
@@ -306,17 +326,21 @@ static void iscsi_scan_session(struct work_struct *work)
306{ 326{
307 struct iscsi_cls_session *session = 327 struct iscsi_cls_session *session =
308 container_of(work, struct iscsi_cls_session, scan_work); 328 container_of(work, struct iscsi_cls_session, scan_work);
329 struct Scsi_Host *shost = iscsi_session_to_shost(session);
330 struct iscsi_host *ihost = shost->shost_data;
309 unsigned long flags; 331 unsigned long flags;
310 332
311 spin_lock_irqsave(&session->lock, flags); 333 spin_lock_irqsave(&session->lock, flags);
312 if (session->state != ISCSI_SESSION_LOGGED_IN) { 334 if (session->state != ISCSI_SESSION_LOGGED_IN) {
313 spin_unlock_irqrestore(&session->lock, flags); 335 spin_unlock_irqrestore(&session->lock, flags);
314 return; 336 goto done;
315 } 337 }
316 spin_unlock_irqrestore(&session->lock, flags); 338 spin_unlock_irqrestore(&session->lock, flags);
317 339
318 scsi_scan_target(&session->dev, 0, session->target_id, 340 scsi_scan_target(&session->dev, 0, session->target_id,
319 SCAN_WILD_CARD, 1); 341 SCAN_WILD_CARD, 1);
342done:
343 atomic_dec(&ihost->nr_scans);
320} 344}
321 345
322static void session_recovery_timedout(struct work_struct *work) 346static void session_recovery_timedout(struct work_struct *work)
@@ -366,7 +390,15 @@ void iscsi_unblock_session(struct iscsi_cls_session *session)
366 spin_unlock_irqrestore(&session->lock, flags); 390 spin_unlock_irqrestore(&session->lock, flags);
367 391
368 __iscsi_unblock_session(session); 392 __iscsi_unblock_session(session);
369 queue_work(ihost->scan_workq, &session->scan_work); 393 /*
394 * Only do kernel scanning if the driver is properly hooked into
395 * the async scanning code (drivers like iscsi_tcp do login and
396 * scanning from userspace).
397 */
398 if (shost->hostt->scan_finished) {
399 if (queue_work(ihost->scan_workq, &session->scan_work))
400 atomic_inc(&ihost->nr_scans);
401 }
370} 402}
371EXPORT_SYMBOL_GPL(iscsi_unblock_session); 403EXPORT_SYMBOL_GPL(iscsi_unblock_session);
372 404
@@ -550,7 +582,7 @@ void iscsi_remove_session(struct iscsi_cls_session *session)
550 session->state = ISCSI_SESSION_FREE; 582 session->state = ISCSI_SESSION_FREE;
551 spin_unlock_irqrestore(&session->lock, flags); 583 spin_unlock_irqrestore(&session->lock, flags);
552 __iscsi_unblock_session(session); 584 __iscsi_unblock_session(session);
553 iscsi_unbind_session(session); 585 __iscsi_unbind_session(&session->unbind_work);
554 586
555 /* flush running scans */ 587 /* flush running scans */
556 flush_workqueue(ihost->scan_workq); 588 flush_workqueue(ihost->scan_workq);
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index 1f0ec46b4f87..83693ba09c29 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -203,6 +203,7 @@ struct iscsi_cls_session {
203 203
204struct iscsi_host { 204struct iscsi_host {
205 struct list_head sessions; 205 struct list_head sessions;
206 atomic_t nr_scans;
206 struct mutex mutex; 207 struct mutex mutex;
207 struct workqueue_struct *scan_workq; 208 struct workqueue_struct *scan_workq;
208 char scan_workq_name[KOBJ_NAME_LEN]; 209 char scan_workq_name[KOBJ_NAME_LEN];
@@ -229,6 +230,6 @@ extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess,
229extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn); 230extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn);
230extern void iscsi_unblock_session(struct iscsi_cls_session *session); 231extern void iscsi_unblock_session(struct iscsi_cls_session *session);
231extern void iscsi_block_session(struct iscsi_cls_session *session); 232extern void iscsi_block_session(struct iscsi_cls_session *session);
232 233extern int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time);
233 234
234#endif 235#endif