diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2008-05-21 16:54:12 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-07-12 09:22:20 -0400 |
commit | 7970634b81a6e3561954517bca42615542c4535b (patch) | |
tree | e8a6aea24c5db8c1198173b75945746333cdbd4d /drivers/scsi | |
parent | 2261ec3d686e35c1a6088ab7f00a1d02b528b994 (diff) |
[SCSI] iscsi class: user device_for_each_child instead of duplicating session list
Currently we duplicate the list of sessions, because we were using the
test for if a session was on the host list to indicate if the session
was bound or unbound. We can instead use the target_id and fix up
the class so that drivers like bnx2i do not have to manage the target id
space.
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/iscsi_tcp.c | 2 | ||||
-rw-r--r-- | drivers/scsi/libiscsi.c | 4 | ||||
-rw-r--r-- | drivers/scsi/scsi_transport_iscsi.c | 125 |
3 files changed, 99 insertions, 32 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 33cd0ca7cc8d..aa3c7f0c550d 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c | |||
@@ -1868,7 +1868,7 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max, | |||
1868 | 1868 | ||
1869 | cls_session = iscsi_session_setup(&iscsi_tcp_transport, shost, cmds_max, | 1869 | cls_session = iscsi_session_setup(&iscsi_tcp_transport, shost, cmds_max, |
1870 | sizeof(struct iscsi_tcp_task), | 1870 | sizeof(struct iscsi_tcp_task), |
1871 | initial_cmdsn); | 1871 | initial_cmdsn, 0); |
1872 | if (!cls_session) | 1872 | if (!cls_session) |
1873 | goto remove_host; | 1873 | goto remove_host; |
1874 | session = cls_session->dd_data; | 1874 | session = cls_session->dd_data; |
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 92ee6d94aaf9..e88b726ab2e0 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -1897,7 +1897,7 @@ EXPORT_SYMBOL_GPL(iscsi_host_free); | |||
1897 | struct iscsi_cls_session * | 1897 | struct iscsi_cls_session * |
1898 | iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, | 1898 | iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, |
1899 | uint16_t scsi_cmds_max, int cmd_task_size, | 1899 | uint16_t scsi_cmds_max, int cmd_task_size, |
1900 | uint32_t initial_cmdsn) | 1900 | uint32_t initial_cmdsn, unsigned int id) |
1901 | { | 1901 | { |
1902 | struct iscsi_session *session; | 1902 | struct iscsi_session *session; |
1903 | struct iscsi_cls_session *cls_session; | 1903 | struct iscsi_cls_session *cls_session; |
@@ -1957,7 +1957,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, | |||
1957 | if (!try_module_get(iscsit->owner)) | 1957 | if (!try_module_get(iscsit->owner)) |
1958 | goto module_get_fail; | 1958 | goto module_get_fail; |
1959 | 1959 | ||
1960 | if (iscsi_add_session(cls_session, 0)) | 1960 | if (iscsi_add_session(cls_session, id)) |
1961 | goto cls_session_fail; | 1961 | goto cls_session_fail; |
1962 | return cls_session; | 1962 | return cls_session; |
1963 | 1963 | ||
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 6b8516a0970b..ac9d298f54e7 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c | |||
@@ -119,9 +119,8 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev, | |||
119 | struct iscsi_cls_host *ihost = shost->shost_data; | 119 | struct iscsi_cls_host *ihost = shost->shost_data; |
120 | 120 | ||
121 | memset(ihost, 0, sizeof(*ihost)); | 121 | memset(ihost, 0, sizeof(*ihost)); |
122 | INIT_LIST_HEAD(&ihost->sessions); | ||
123 | mutex_init(&ihost->mutex); | ||
124 | atomic_set(&ihost->nr_scans, 0); | 122 | atomic_set(&ihost->nr_scans, 0); |
123 | mutex_init(&ihost->mutex); | ||
125 | 124 | ||
126 | snprintf(ihost->scan_workq_name, KOBJ_NAME_LEN, "iscsi_scan_%d", | 125 | snprintf(ihost->scan_workq_name, KOBJ_NAME_LEN, "iscsi_scan_%d", |
127 | shost->host_no); | 126 | shost->host_no); |
@@ -316,42 +315,76 @@ int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time) | |||
316 | } | 315 | } |
317 | EXPORT_SYMBOL_GPL(iscsi_scan_finished); | 316 | EXPORT_SYMBOL_GPL(iscsi_scan_finished); |
318 | 317 | ||
319 | static int iscsi_user_scan(struct Scsi_Host *shost, uint channel, | 318 | struct iscsi_scan_data { |
320 | uint id, uint lun) | 319 | unsigned int channel; |
320 | unsigned int id; | ||
321 | unsigned int lun; | ||
322 | }; | ||
323 | |||
324 | static int iscsi_user_scan_session(struct device *dev, void *data) | ||
321 | { | 325 | { |
322 | struct iscsi_cls_host *ihost = shost->shost_data; | 326 | struct iscsi_scan_data *scan_data = data; |
323 | struct iscsi_cls_session *session; | 327 | struct iscsi_cls_session *session; |
328 | struct Scsi_Host *shost; | ||
329 | struct iscsi_cls_host *ihost; | ||
330 | unsigned long flags; | ||
331 | unsigned int id; | ||
332 | |||
333 | if (!iscsi_is_session_dev(dev)) | ||
334 | return 0; | ||
335 | |||
336 | session = iscsi_dev_to_session(dev); | ||
337 | shost = iscsi_session_to_shost(session); | ||
338 | ihost = shost->shost_data; | ||
324 | 339 | ||
325 | mutex_lock(&ihost->mutex); | 340 | mutex_lock(&ihost->mutex); |
326 | list_for_each_entry(session, &ihost->sessions, host_list) { | 341 | spin_lock_irqsave(&session->lock, flags); |
327 | if ((channel == SCAN_WILD_CARD || channel == 0) && | 342 | if (session->state != ISCSI_SESSION_LOGGED_IN) { |
328 | (id == SCAN_WILD_CARD || id == session->target_id)) | 343 | spin_unlock_irqrestore(&session->lock, flags); |
329 | scsi_scan_target(&session->dev, 0, | 344 | mutex_unlock(&ihost->mutex); |
330 | session->target_id, lun, 1); | 345 | return 0; |
331 | } | 346 | } |
332 | mutex_unlock(&ihost->mutex); | 347 | id = session->target_id; |
348 | spin_unlock_irqrestore(&session->lock, flags); | ||
333 | 349 | ||
350 | if (id != ISCSI_MAX_TARGET) { | ||
351 | if ((scan_data->channel == SCAN_WILD_CARD || | ||
352 | scan_data->channel == 0) && | ||
353 | (scan_data->id == SCAN_WILD_CARD || | ||
354 | scan_data->id == id)) | ||
355 | scsi_scan_target(&session->dev, 0, id, | ||
356 | scan_data->lun, 1); | ||
357 | } | ||
358 | mutex_unlock(&ihost->mutex); | ||
334 | return 0; | 359 | return 0; |
335 | } | 360 | } |
336 | 361 | ||
362 | static int iscsi_user_scan(struct Scsi_Host *shost, uint channel, | ||
363 | uint id, uint lun) | ||
364 | { | ||
365 | struct iscsi_scan_data scan_data; | ||
366 | |||
367 | scan_data.channel = channel; | ||
368 | scan_data.id = id; | ||
369 | scan_data.lun = lun; | ||
370 | |||
371 | return device_for_each_child(&shost->shost_gendev, &scan_data, | ||
372 | iscsi_user_scan_session); | ||
373 | } | ||
374 | |||
337 | static void iscsi_scan_session(struct work_struct *work) | 375 | static void iscsi_scan_session(struct work_struct *work) |
338 | { | 376 | { |
339 | struct iscsi_cls_session *session = | 377 | struct iscsi_cls_session *session = |
340 | container_of(work, struct iscsi_cls_session, scan_work); | 378 | container_of(work, struct iscsi_cls_session, scan_work); |
341 | struct Scsi_Host *shost = iscsi_session_to_shost(session); | 379 | struct Scsi_Host *shost = iscsi_session_to_shost(session); |
342 | struct iscsi_cls_host *ihost = shost->shost_data; | 380 | struct iscsi_cls_host *ihost = shost->shost_data; |
343 | unsigned long flags; | 381 | struct iscsi_scan_data scan_data; |
344 | 382 | ||
345 | spin_lock_irqsave(&session->lock, flags); | 383 | scan_data.channel = 0; |
346 | if (session->state != ISCSI_SESSION_LOGGED_IN) { | 384 | scan_data.id = SCAN_WILD_CARD; |
347 | spin_unlock_irqrestore(&session->lock, flags); | 385 | scan_data.lun = SCAN_WILD_CARD; |
348 | goto done; | ||
349 | } | ||
350 | spin_unlock_irqrestore(&session->lock, flags); | ||
351 | 386 | ||
352 | scsi_scan_target(&session->dev, 0, session->target_id, | 387 | iscsi_user_scan_session(&session->dev, &scan_data); |
353 | SCAN_WILD_CARD, 1); | ||
354 | done: | ||
355 | atomic_dec(&ihost->nr_scans); | 388 | atomic_dec(&ihost->nr_scans); |
356 | } | 389 | } |
357 | 390 | ||
@@ -460,14 +493,18 @@ static void __iscsi_unbind_session(struct work_struct *work) | |||
460 | unbind_work); | 493 | unbind_work); |
461 | struct Scsi_Host *shost = iscsi_session_to_shost(session); | 494 | struct Scsi_Host *shost = iscsi_session_to_shost(session); |
462 | struct iscsi_cls_host *ihost = shost->shost_data; | 495 | struct iscsi_cls_host *ihost = shost->shost_data; |
496 | unsigned long flags; | ||
463 | 497 | ||
464 | /* Prevent new scans and make sure scanning is not in progress */ | 498 | /* Prevent new scans and make sure scanning is not in progress */ |
465 | mutex_lock(&ihost->mutex); | 499 | mutex_lock(&ihost->mutex); |
466 | if (list_empty(&session->host_list)) { | 500 | spin_lock_irqsave(&session->lock, flags); |
501 | if (session->target_id == ISCSI_MAX_TARGET) { | ||
502 | spin_unlock_irqrestore(&session->lock, flags); | ||
467 | mutex_unlock(&ihost->mutex); | 503 | mutex_unlock(&ihost->mutex); |
468 | return; | 504 | return; |
469 | } | 505 | } |
470 | list_del_init(&session->host_list); | 506 | session->target_id = ISCSI_MAX_TARGET; |
507 | spin_unlock_irqrestore(&session->lock, flags); | ||
471 | mutex_unlock(&ihost->mutex); | 508 | mutex_unlock(&ihost->mutex); |
472 | 509 | ||
473 | scsi_remove_target(&session->dev); | 510 | scsi_remove_target(&session->dev); |
@@ -497,7 +534,6 @@ iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport, | |||
497 | session->recovery_tmo = 120; | 534 | session->recovery_tmo = 120; |
498 | session->state = ISCSI_SESSION_FREE; | 535 | session->state = ISCSI_SESSION_FREE; |
499 | INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout); | 536 | INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout); |
500 | INIT_LIST_HEAD(&session->host_list); | ||
501 | INIT_LIST_HEAD(&session->sess_list); | 537 | INIT_LIST_HEAD(&session->sess_list); |
502 | INIT_WORK(&session->unblock_work, __iscsi_unblock_session); | 538 | INIT_WORK(&session->unblock_work, __iscsi_unblock_session); |
503 | INIT_WORK(&session->block_work, __iscsi_block_session); | 539 | INIT_WORK(&session->block_work, __iscsi_block_session); |
@@ -516,16 +552,51 @@ iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport, | |||
516 | } | 552 | } |
517 | EXPORT_SYMBOL_GPL(iscsi_alloc_session); | 553 | EXPORT_SYMBOL_GPL(iscsi_alloc_session); |
518 | 554 | ||
555 | static int iscsi_get_next_target_id(struct device *dev, void *data) | ||
556 | { | ||
557 | struct iscsi_cls_session *session; | ||
558 | unsigned long flags; | ||
559 | int err = 0; | ||
560 | |||
561 | if (!iscsi_is_session_dev(dev)) | ||
562 | return 0; | ||
563 | |||
564 | session = iscsi_dev_to_session(dev); | ||
565 | spin_lock_irqsave(&session->lock, flags); | ||
566 | if (*((unsigned int *) data) == session->target_id) | ||
567 | err = -EEXIST; | ||
568 | spin_unlock_irqrestore(&session->lock, flags); | ||
569 | return err; | ||
570 | } | ||
571 | |||
519 | int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id) | 572 | int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id) |
520 | { | 573 | { |
521 | struct Scsi_Host *shost = iscsi_session_to_shost(session); | 574 | struct Scsi_Host *shost = iscsi_session_to_shost(session); |
522 | struct iscsi_cls_host *ihost; | 575 | struct iscsi_cls_host *ihost; |
523 | unsigned long flags; | 576 | unsigned long flags; |
577 | unsigned int id = target_id; | ||
524 | int err; | 578 | int err; |
525 | 579 | ||
526 | ihost = shost->shost_data; | 580 | ihost = shost->shost_data; |
527 | session->sid = atomic_add_return(1, &iscsi_session_nr); | 581 | session->sid = atomic_add_return(1, &iscsi_session_nr); |
528 | session->target_id = target_id; | 582 | |
583 | if (id == ISCSI_MAX_TARGET) { | ||
584 | for (id = 0; id < ISCSI_MAX_TARGET; id++) { | ||
585 | err = device_for_each_child(&shost->shost_gendev, &id, | ||
586 | iscsi_get_next_target_id); | ||
587 | if (!err) | ||
588 | break; | ||
589 | } | ||
590 | |||
591 | if (id == ISCSI_MAX_TARGET) { | ||
592 | iscsi_cls_session_printk(KERN_ERR, session, | ||
593 | "Too many iscsi targets. Max " | ||
594 | "number of targets is %d.\n", | ||
595 | ISCSI_MAX_TARGET - 1); | ||
596 | goto release_host; | ||
597 | } | ||
598 | } | ||
599 | session->target_id = id; | ||
529 | 600 | ||
530 | snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", | 601 | snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", |
531 | session->sid); | 602 | session->sid); |
@@ -541,10 +612,6 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id) | |||
541 | list_add(&session->sess_list, &sesslist); | 612 | list_add(&session->sess_list, &sesslist); |
542 | spin_unlock_irqrestore(&sesslock, flags); | 613 | spin_unlock_irqrestore(&sesslock, flags); |
543 | 614 | ||
544 | mutex_lock(&ihost->mutex); | ||
545 | list_add(&session->host_list, &ihost->sessions); | ||
546 | mutex_unlock(&ihost->mutex); | ||
547 | |||
548 | iscsi_session_event(session, ISCSI_KEVENT_CREATE_SESSION); | 615 | iscsi_session_event(session, ISCSI_KEVENT_CREATE_SESSION); |
549 | return 0; | 616 | return 0; |
550 | 617 | ||