aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2008-05-21 16:54:12 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-07-12 09:22:20 -0400
commit7970634b81a6e3561954517bca42615542c4535b (patch)
treee8a6aea24c5db8c1198173b75945746333cdbd4d
parent2261ec3d686e35c1a6088ab7f00a1d02b528b994 (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>
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.c2
-rw-r--r--drivers/scsi/iscsi_tcp.c2
-rw-r--r--drivers/scsi/libiscsi.c4
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c125
-rw-r--r--include/scsi/libiscsi.h2
-rw-r--r--include/scsi/scsi_transport_iscsi.h6
6 files changed, 104 insertions, 37 deletions
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index 86d9c42f0d33..3a89039e9a96 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -437,7 +437,7 @@ iscsi_iser_session_create(struct Scsi_Host *shost,
437 cls_session = iscsi_session_setup(&iscsi_iser_transport, shost, 437 cls_session = iscsi_session_setup(&iscsi_iser_transport, shost,
438 ISCSI_DEF_XMIT_CMDS_MAX, 438 ISCSI_DEF_XMIT_CMDS_MAX,
439 sizeof(struct iscsi_iser_task), 439 sizeof(struct iscsi_iser_task),
440 initial_cmdsn); 440 initial_cmdsn, 0);
441 if (!cls_session) 441 if (!cls_session)
442 goto remove_host; 442 goto remove_host;
443 session = cls_session->dd_data; 443 session = cls_session->dd_data;
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
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index 176353c117b6..13c92d7ba969 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -331,7 +331,7 @@ extern void iscsi_host_free(struct Scsi_Host *shost);
331 */ 331 */
332extern struct iscsi_cls_session * 332extern struct iscsi_cls_session *
333iscsi_session_setup(struct iscsi_transport *, struct Scsi_Host *shost, 333iscsi_session_setup(struct iscsi_transport *, struct Scsi_Host *shost,
334 uint16_t, int, uint32_t); 334 uint16_t, int, uint32_t, unsigned int);
335extern void iscsi_session_teardown(struct iscsi_cls_session *); 335extern void iscsi_session_teardown(struct iscsi_cls_session *);
336extern void iscsi_session_recovery_timedout(struct iscsi_cls_session *); 336extern void iscsi_session_recovery_timedout(struct iscsi_cls_session *);
337extern int iscsi_set_param(struct iscsi_cls_conn *cls_conn, 337extern int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index 0553240796e9..d6b823195563 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -161,9 +161,10 @@ enum {
161 ISCSI_SESSION_FREE, 161 ISCSI_SESSION_FREE,
162}; 162};
163 163
164#define ISCSI_MAX_TARGET -1
165
164struct iscsi_cls_session { 166struct iscsi_cls_session {
165 struct list_head sess_list; /* item in session_list */ 167 struct list_head sess_list; /* item in session_list */
166 struct list_head host_list;
167 struct iscsi_transport *transport; 168 struct iscsi_transport *transport;
168 spinlock_t lock; 169 spinlock_t lock;
169 struct work_struct block_work; 170 struct work_struct block_work;
@@ -175,7 +176,7 @@ struct iscsi_cls_session {
175 int recovery_tmo; 176 int recovery_tmo;
176 struct delayed_work recovery_work; 177 struct delayed_work recovery_work;
177 178
178 int target_id; 179 unsigned int target_id;
179 180
180 int state; 181 int state;
181 int sid; /* session id */ 182 int sid; /* session id */
@@ -193,7 +194,6 @@ struct iscsi_cls_session {
193 iscsi_dev_to_session(_stgt->dev.parent) 194 iscsi_dev_to_session(_stgt->dev.parent)
194 195
195struct iscsi_cls_host { 196struct iscsi_cls_host {
196 struct list_head sessions;
197 atomic_t nr_scans; 197 atomic_t nr_scans;
198 struct mutex mutex; 198 struct mutex mutex;
199 struct workqueue_struct *scan_workq; 199 struct workqueue_struct *scan_workq;