aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/iscsi_tcp.c2
-rw-r--r--drivers/scsi/libiscsi.c4
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c125
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);
1897struct iscsi_cls_session * 1897struct iscsi_cls_session *
1898iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, 1898iscsi_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}
317EXPORT_SYMBOL_GPL(iscsi_scan_finished); 316EXPORT_SYMBOL_GPL(iscsi_scan_finished);
318 317
319static int iscsi_user_scan(struct Scsi_Host *shost, uint channel, 318struct iscsi_scan_data {
320 uint id, uint lun) 319 unsigned int channel;
320 unsigned int id;
321 unsigned int lun;
322};
323
324static 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
362static 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
337static void iscsi_scan_session(struct work_struct *work) 375static 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);
354done:
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}
517EXPORT_SYMBOL_GPL(iscsi_alloc_session); 553EXPORT_SYMBOL_GPL(iscsi_alloc_session);
518 554
555static 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
519int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id) 572int 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