aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_transport_iscsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_transport_iscsi.c')
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c663
1 files changed, 370 insertions, 293 deletions
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 5569fdcfd621..7b0019cccce3 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -34,6 +34,7 @@
34#define ISCSI_SESSION_ATTRS 11 34#define ISCSI_SESSION_ATTRS 11
35#define ISCSI_CONN_ATTRS 11 35#define ISCSI_CONN_ATTRS 11
36#define ISCSI_HOST_ATTRS 0 36#define ISCSI_HOST_ATTRS 0
37#define ISCSI_TRANSPORT_VERSION "2.0-685"
37 38
38struct iscsi_internal { 39struct iscsi_internal {
39 int daemon_pid; 40 int daemon_pid;
@@ -228,14 +229,11 @@ static struct iscsi_cls_conn *iscsi_conn_lookup(uint32_t sid, uint32_t cid)
228static void iscsi_session_release(struct device *dev) 229static void iscsi_session_release(struct device *dev)
229{ 230{
230 struct iscsi_cls_session *session = iscsi_dev_to_session(dev); 231 struct iscsi_cls_session *session = iscsi_dev_to_session(dev);
231 struct iscsi_transport *transport = session->transport;
232 struct Scsi_Host *shost; 232 struct Scsi_Host *shost;
233 233
234 shost = iscsi_session_to_shost(session); 234 shost = iscsi_session_to_shost(session);
235 scsi_host_put(shost); 235 scsi_host_put(shost);
236 kfree(session->targetname);
237 kfree(session); 236 kfree(session);
238 module_put(transport->owner);
239} 237}
240 238
241static int iscsi_is_session_dev(const struct device *dev) 239static int iscsi_is_session_dev(const struct device *dev)
@@ -251,10 +249,9 @@ static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
251 249
252 mutex_lock(&ihost->mutex); 250 mutex_lock(&ihost->mutex);
253 list_for_each_entry(session, &ihost->sessions, host_list) { 251 list_for_each_entry(session, &ihost->sessions, host_list) {
254 if ((channel == SCAN_WILD_CARD || 252 if ((channel == SCAN_WILD_CARD || channel == 0) &&
255 channel == session->channel) &&
256 (id == SCAN_WILD_CARD || id == session->target_id)) 253 (id == SCAN_WILD_CARD || id == session->target_id))
257 scsi_scan_target(&session->dev, session->channel, 254 scsi_scan_target(&session->dev, 0,
258 session->target_id, lun, 1); 255 session->target_id, lun, 1);
259 } 256 }
260 mutex_unlock(&ihost->mutex); 257 mutex_unlock(&ihost->mutex);
@@ -291,80 +288,92 @@ void iscsi_block_session(struct iscsi_cls_session *session)
291} 288}
292EXPORT_SYMBOL_GPL(iscsi_block_session); 289EXPORT_SYMBOL_GPL(iscsi_block_session);
293 290
294/**
295 * iscsi_create_session - create iscsi class session
296 * @shost: scsi host
297 * @transport: iscsi transport
298 *
299 * This can be called from a LLD or iscsi_transport.
300 **/
301struct iscsi_cls_session * 291struct iscsi_cls_session *
302iscsi_create_session(struct Scsi_Host *shost, 292iscsi_alloc_session(struct Scsi_Host *shost,
303 struct iscsi_transport *transport, int channel) 293 struct iscsi_transport *transport)
304{ 294{
305 struct iscsi_host *ihost;
306 struct iscsi_cls_session *session; 295 struct iscsi_cls_session *session;
307 int err;
308
309 if (!try_module_get(transport->owner))
310 return NULL;
311 296
312 session = kzalloc(sizeof(*session) + transport->sessiondata_size, 297 session = kzalloc(sizeof(*session) + transport->sessiondata_size,
313 GFP_KERNEL); 298 GFP_KERNEL);
314 if (!session) 299 if (!session)
315 goto module_put; 300 return NULL;
301
316 session->transport = transport; 302 session->transport = transport;
317 session->recovery_tmo = 120; 303 session->recovery_tmo = 120;
318 INIT_WORK(&session->recovery_work, session_recovery_timedout, session); 304 INIT_WORK(&session->recovery_work, session_recovery_timedout, session);
319 INIT_LIST_HEAD(&session->host_list); 305 INIT_LIST_HEAD(&session->host_list);
320 INIT_LIST_HEAD(&session->sess_list); 306 INIT_LIST_HEAD(&session->sess_list);
321 307
308 /* this is released in the dev's release function */
309 scsi_host_get(shost);
310 session->dev.parent = &shost->shost_gendev;
311 session->dev.release = iscsi_session_release;
312 device_initialize(&session->dev);
322 if (transport->sessiondata_size) 313 if (transport->sessiondata_size)
323 session->dd_data = &session[1]; 314 session->dd_data = &session[1];
315 return session;
316}
317EXPORT_SYMBOL_GPL(iscsi_alloc_session);
324 318
325 /* this is released in the dev's release function */ 319int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
326 scsi_host_get(shost); 320{
327 ihost = shost->shost_data; 321 struct Scsi_Host *shost = iscsi_session_to_shost(session);
322 struct iscsi_host *ihost;
323 int err;
328 324
325 ihost = shost->shost_data;
329 session->sid = iscsi_session_nr++; 326 session->sid = iscsi_session_nr++;
330 session->channel = channel; 327 session->target_id = target_id;
331 session->target_id = ihost->next_target_id++;
332 328
333 snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", 329 snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u",
334 session->sid); 330 session->sid);
335 session->dev.parent = &shost->shost_gendev; 331 err = device_add(&session->dev);
336 session->dev.release = iscsi_session_release;
337 err = device_register(&session->dev);
338 if (err) { 332 if (err) {
339 dev_printk(KERN_ERR, &session->dev, "iscsi: could not " 333 dev_printk(KERN_ERR, &session->dev, "iscsi: could not "
340 "register session's dev\n"); 334 "register session's dev\n");
341 goto free_session; 335 goto release_host;
342 } 336 }
343 transport_register_device(&session->dev); 337 transport_register_device(&session->dev);
344 338
345 mutex_lock(&ihost->mutex); 339 mutex_lock(&ihost->mutex);
346 list_add(&session->host_list, &ihost->sessions); 340 list_add(&session->host_list, &ihost->sessions);
347 mutex_unlock(&ihost->mutex); 341 mutex_unlock(&ihost->mutex);
342 return 0;
348 343
349 return session; 344release_host:
350 345 scsi_host_put(shost);
351free_session: 346 return err;
352 kfree(session);
353module_put:
354 module_put(transport->owner);
355 return NULL;
356} 347}
357 348EXPORT_SYMBOL_GPL(iscsi_add_session);
358EXPORT_SYMBOL_GPL(iscsi_create_session);
359 349
360/** 350/**
361 * iscsi_destroy_session - destroy iscsi session 351 * iscsi_create_session - create iscsi class session
362 * @session: iscsi_session 352 * @shost: scsi host
353 * @transport: iscsi transport
363 * 354 *
364 * Can be called by a LLD or iscsi_transport. There must not be 355 * This can be called from a LLD or iscsi_transport.
365 * any running connections.
366 **/ 356 **/
367int iscsi_destroy_session(struct iscsi_cls_session *session) 357struct iscsi_cls_session *
358iscsi_create_session(struct Scsi_Host *shost,
359 struct iscsi_transport *transport,
360 unsigned int target_id)
361{
362 struct iscsi_cls_session *session;
363
364 session = iscsi_alloc_session(shost, transport);
365 if (!session)
366 return NULL;
367
368 if (iscsi_add_session(session, target_id)) {
369 iscsi_free_session(session);
370 return NULL;
371 }
372 return session;
373}
374EXPORT_SYMBOL_GPL(iscsi_create_session);
375
376void iscsi_remove_session(struct iscsi_cls_session *session)
368{ 377{
369 struct Scsi_Host *shost = iscsi_session_to_shost(session); 378 struct Scsi_Host *shost = iscsi_session_to_shost(session);
370 struct iscsi_host *ihost = shost->shost_data; 379 struct iscsi_host *ihost = shost->shost_data;
@@ -376,19 +385,88 @@ int iscsi_destroy_session(struct iscsi_cls_session *session)
376 list_del(&session->host_list); 385 list_del(&session->host_list);
377 mutex_unlock(&ihost->mutex); 386 mutex_unlock(&ihost->mutex);
378 387
388 scsi_remove_target(&session->dev);
389
379 transport_unregister_device(&session->dev); 390 transport_unregister_device(&session->dev);
380 device_unregister(&session->dev); 391 device_del(&session->dev);
381 return 0; 392}
393EXPORT_SYMBOL_GPL(iscsi_remove_session);
394
395void iscsi_free_session(struct iscsi_cls_session *session)
396{
397 put_device(&session->dev);
382} 398}
383 399
400EXPORT_SYMBOL_GPL(iscsi_free_session);
401
402/**
403 * iscsi_destroy_session - destroy iscsi session
404 * @session: iscsi_session
405 *
406 * Can be called by a LLD or iscsi_transport. There must not be
407 * any running connections.
408 **/
409int iscsi_destroy_session(struct iscsi_cls_session *session)
410{
411 iscsi_remove_session(session);
412 iscsi_free_session(session);
413 return 0;
414}
384EXPORT_SYMBOL_GPL(iscsi_destroy_session); 415EXPORT_SYMBOL_GPL(iscsi_destroy_session);
385 416
417static void mempool_zone_destroy(struct mempool_zone *zp)
418{
419 mempool_destroy(zp->pool);
420 kfree(zp);
421}
422
423static void*
424mempool_zone_alloc_skb(gfp_t gfp_mask, void *pool_data)
425{
426 struct mempool_zone *zone = pool_data;
427
428 return alloc_skb(zone->size, gfp_mask);
429}
430
431static void
432mempool_zone_free_skb(void *element, void *pool_data)
433{
434 kfree_skb(element);
435}
436
437static struct mempool_zone *
438mempool_zone_init(unsigned max, unsigned size, unsigned hiwat)
439{
440 struct mempool_zone *zp;
441
442 zp = kzalloc(sizeof(*zp), GFP_KERNEL);
443 if (!zp)
444 return NULL;
445
446 zp->size = size;
447 zp->hiwat = hiwat;
448 INIT_LIST_HEAD(&zp->freequeue);
449 spin_lock_init(&zp->freelock);
450 atomic_set(&zp->allocated, 0);
451
452 zp->pool = mempool_create(max, mempool_zone_alloc_skb,
453 mempool_zone_free_skb, zp);
454 if (!zp->pool) {
455 kfree(zp);
456 return NULL;
457 }
458
459 return zp;
460}
461
386static void iscsi_conn_release(struct device *dev) 462static void iscsi_conn_release(struct device *dev)
387{ 463{
388 struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev); 464 struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev);
389 struct device *parent = conn->dev.parent; 465 struct device *parent = conn->dev.parent;
390 466
391 kfree(conn->persistent_address); 467 mempool_zone_destroy(conn->z_pdu);
468 mempool_zone_destroy(conn->z_error);
469
392 kfree(conn); 470 kfree(conn);
393 put_device(parent); 471 put_device(parent);
394} 472}
@@ -398,6 +476,31 @@ static int iscsi_is_conn_dev(const struct device *dev)
398 return dev->release == iscsi_conn_release; 476 return dev->release == iscsi_conn_release;
399} 477}
400 478
479static int iscsi_create_event_pools(struct iscsi_cls_conn *conn)
480{
481 conn->z_pdu = mempool_zone_init(Z_MAX_PDU,
482 NLMSG_SPACE(sizeof(struct iscsi_uevent) +
483 sizeof(struct iscsi_hdr) +
484 DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH),
485 Z_HIWAT_PDU);
486 if (!conn->z_pdu) {
487 dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
488 "pdu zone for new conn\n");
489 return -ENOMEM;
490 }
491
492 conn->z_error = mempool_zone_init(Z_MAX_ERROR,
493 NLMSG_SPACE(sizeof(struct iscsi_uevent)),
494 Z_HIWAT_ERROR);
495 if (!conn->z_error) {
496 dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
497 "error zone for new conn\n");
498 mempool_zone_destroy(conn->z_pdu);
499 return -ENOMEM;
500 }
501 return 0;
502}
503
401/** 504/**
402 * iscsi_create_conn - create iscsi class connection 505 * iscsi_create_conn - create iscsi class connection
403 * @session: iscsi cls session 506 * @session: iscsi cls session
@@ -430,9 +533,12 @@ iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid)
430 conn->transport = transport; 533 conn->transport = transport;
431 conn->cid = cid; 534 conn->cid = cid;
432 535
536 if (iscsi_create_event_pools(conn))
537 goto free_conn;
538
433 /* this is released in the dev's release function */ 539 /* this is released in the dev's release function */
434 if (!get_device(&session->dev)) 540 if (!get_device(&session->dev))
435 goto free_conn; 541 goto free_conn_pools;
436 542
437 snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u", 543 snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
438 session->sid, cid); 544 session->sid, cid);
@@ -449,6 +555,8 @@ iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid)
449 555
450release_parent_ref: 556release_parent_ref:
451 put_device(&session->dev); 557 put_device(&session->dev);
558free_conn_pools:
559
452free_conn: 560free_conn:
453 kfree(conn); 561 kfree(conn);
454 return NULL; 562 return NULL;
@@ -496,20 +604,6 @@ static inline struct list_head *skb_to_lh(struct sk_buff *skb)
496 return (struct list_head *)&skb->cb; 604 return (struct list_head *)&skb->cb;
497} 605}
498 606
499static void*
500mempool_zone_alloc_skb(gfp_t gfp_mask, void *pool_data)
501{
502 struct mempool_zone *zone = pool_data;
503
504 return alloc_skb(zone->size, gfp_mask);
505}
506
507static void
508mempool_zone_free_skb(void *element, void *pool_data)
509{
510 kfree_skb(element);
511}
512
513static void 607static void
514mempool_zone_complete(struct mempool_zone *zone) 608mempool_zone_complete(struct mempool_zone *zone)
515{ 609{
@@ -529,37 +623,6 @@ mempool_zone_complete(struct mempool_zone *zone)
529 spin_unlock_irqrestore(&zone->freelock, flags); 623 spin_unlock_irqrestore(&zone->freelock, flags);
530} 624}
531 625
532static struct mempool_zone *
533mempool_zone_init(unsigned max, unsigned size, unsigned hiwat)
534{
535 struct mempool_zone *zp;
536
537 zp = kzalloc(sizeof(*zp), GFP_KERNEL);
538 if (!zp)
539 return NULL;
540
541 zp->size = size;
542 zp->hiwat = hiwat;
543 INIT_LIST_HEAD(&zp->freequeue);
544 spin_lock_init(&zp->freelock);
545 atomic_set(&zp->allocated, 0);
546
547 zp->pool = mempool_create(max, mempool_zone_alloc_skb,
548 mempool_zone_free_skb, zp);
549 if (!zp->pool) {
550 kfree(zp);
551 return NULL;
552 }
553
554 return zp;
555}
556
557static void mempool_zone_destroy(struct mempool_zone *zp)
558{
559 mempool_destroy(zp->pool);
560 kfree(zp);
561}
562
563static struct sk_buff* 626static struct sk_buff*
564mempool_zone_get_skb(struct mempool_zone *zone) 627mempool_zone_get_skb(struct mempool_zone *zone)
565{ 628{
@@ -572,6 +635,27 @@ mempool_zone_get_skb(struct mempool_zone *zone)
572} 635}
573 636
574static int 637static int
638iscsi_broadcast_skb(struct mempool_zone *zone, struct sk_buff *skb, gfp_t gfp)
639{
640 unsigned long flags;
641 int rc;
642
643 skb_get(skb);
644 rc = netlink_broadcast(nls, skb, 0, 1, gfp);
645 if (rc < 0) {
646 mempool_free(skb, zone->pool);
647 printk(KERN_ERR "iscsi: can not broadcast skb (%d)\n", rc);
648 return rc;
649 }
650
651 spin_lock_irqsave(&zone->freelock, flags);
652 INIT_LIST_HEAD(skb_to_lh(skb));
653 list_add(skb_to_lh(skb), &zone->freequeue);
654 spin_unlock_irqrestore(&zone->freelock, flags);
655 return 0;
656}
657
658static int
575iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb, int pid) 659iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb, int pid)
576{ 660{
577 unsigned long flags; 661 unsigned long flags;
@@ -666,7 +750,7 @@ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
666 ev->r.connerror.cid = conn->cid; 750 ev->r.connerror.cid = conn->cid;
667 ev->r.connerror.sid = iscsi_conn_get_sid(conn); 751 ev->r.connerror.sid = iscsi_conn_get_sid(conn);
668 752
669 iscsi_unicast_skb(conn->z_error, skb, priv->daemon_pid); 753 iscsi_broadcast_skb(conn->z_error, skb, GFP_ATOMIC);
670 754
671 dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n", 755 dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n",
672 error); 756 error);
@@ -767,6 +851,131 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
767 return err; 851 return err;
768} 852}
769 853
854/**
855 * iscsi_if_destroy_session_done - send session destr. completion event
856 * @conn: last connection for session
857 *
858 * This is called by HW iscsi LLDs to notify userpsace that its HW has
859 * removed a session.
860 **/
861int iscsi_if_destroy_session_done(struct iscsi_cls_conn *conn)
862{
863 struct iscsi_internal *priv;
864 struct iscsi_cls_session *session;
865 struct Scsi_Host *shost;
866 struct iscsi_uevent *ev;
867 struct sk_buff *skb;
868 struct nlmsghdr *nlh;
869 unsigned long flags;
870 int rc, len = NLMSG_SPACE(sizeof(*ev));
871
872 priv = iscsi_if_transport_lookup(conn->transport);
873 if (!priv)
874 return -EINVAL;
875
876 session = iscsi_dev_to_session(conn->dev.parent);
877 shost = iscsi_session_to_shost(session);
878
879 mempool_zone_complete(conn->z_pdu);
880
881 skb = mempool_zone_get_skb(conn->z_pdu);
882 if (!skb) {
883 dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
884 "session creation event\n");
885 return -ENOMEM;
886 }
887
888 nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
889 ev = NLMSG_DATA(nlh);
890 ev->transport_handle = iscsi_handle(conn->transport);
891 ev->type = ISCSI_KEVENT_DESTROY_SESSION;
892 ev->r.d_session.host_no = shost->host_no;
893 ev->r.d_session.sid = session->sid;
894
895 /*
896 * this will occur if the daemon is not up, so we just warn
897 * the user and when the daemon is restarted it will handle it
898 */
899 rc = iscsi_broadcast_skb(conn->z_pdu, skb, GFP_KERNEL);
900 if (rc < 0)
901 dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
902 "session destruction event. Check iscsi daemon\n");
903
904 spin_lock_irqsave(&sesslock, flags);
905 list_del(&session->sess_list);
906 spin_unlock_irqrestore(&sesslock, flags);
907
908 spin_lock_irqsave(&connlock, flags);
909 conn->active = 0;
910 list_del(&conn->conn_list);
911 spin_unlock_irqrestore(&connlock, flags);
912
913 return rc;
914}
915EXPORT_SYMBOL_GPL(iscsi_if_destroy_session_done);
916
917/**
918 * iscsi_if_create_session_done - send session creation completion event
919 * @conn: leading connection for session
920 *
921 * This is called by HW iscsi LLDs to notify userpsace that its HW has
922 * created a session or a existing session is back in the logged in state.
923 **/
924int iscsi_if_create_session_done(struct iscsi_cls_conn *conn)
925{
926 struct iscsi_internal *priv;
927 struct iscsi_cls_session *session;
928 struct Scsi_Host *shost;
929 struct iscsi_uevent *ev;
930 struct sk_buff *skb;
931 struct nlmsghdr *nlh;
932 unsigned long flags;
933 int rc, len = NLMSG_SPACE(sizeof(*ev));
934
935 priv = iscsi_if_transport_lookup(conn->transport);
936 if (!priv)
937 return -EINVAL;
938
939 session = iscsi_dev_to_session(conn->dev.parent);
940 shost = iscsi_session_to_shost(session);
941
942 mempool_zone_complete(conn->z_pdu);
943
944 skb = mempool_zone_get_skb(conn->z_pdu);
945 if (!skb) {
946 dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
947 "session creation event\n");
948 return -ENOMEM;
949 }
950
951 nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
952 ev = NLMSG_DATA(nlh);
953 ev->transport_handle = iscsi_handle(conn->transport);
954 ev->type = ISCSI_UEVENT_CREATE_SESSION;
955 ev->r.c_session_ret.host_no = shost->host_no;
956 ev->r.c_session_ret.sid = session->sid;
957
958 /*
959 * this will occur if the daemon is not up, so we just warn
960 * the user and when the daemon is restarted it will handle it
961 */
962 rc = iscsi_broadcast_skb(conn->z_pdu, skb, GFP_KERNEL);
963 if (rc < 0)
964 dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
965 "session creation event. Check iscsi daemon\n");
966
967 spin_lock_irqsave(&sesslock, flags);
968 list_add(&session->sess_list, &sesslist);
969 spin_unlock_irqrestore(&sesslock, flags);
970
971 spin_lock_irqsave(&connlock, flags);
972 list_add(&conn->conn_list, &connlist);
973 conn->active = 1;
974 spin_unlock_irqrestore(&connlock, flags);
975 return rc;
976}
977EXPORT_SYMBOL_GPL(iscsi_if_create_session_done);
978
770static int 979static int
771iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev) 980iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
772{ 981{
@@ -812,26 +1021,6 @@ iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
812 return -ENOMEM; 1021 return -ENOMEM;
813 } 1022 }
814 1023
815 conn->z_pdu = mempool_zone_init(Z_MAX_PDU,
816 NLMSG_SPACE(sizeof(struct iscsi_uevent) +
817 sizeof(struct iscsi_hdr) +
818 DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH),
819 Z_HIWAT_PDU);
820 if (!conn->z_pdu) {
821 dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
822 "pdu zone for new conn\n");
823 goto destroy_conn;
824 }
825
826 conn->z_error = mempool_zone_init(Z_MAX_ERROR,
827 NLMSG_SPACE(sizeof(struct iscsi_uevent)),
828 Z_HIWAT_ERROR);
829 if (!conn->z_error) {
830 dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
831 "error zone for new conn\n");
832 goto free_pdu_pool;
833 }
834
835 ev->r.c_conn_ret.sid = session->sid; 1024 ev->r.c_conn_ret.sid = session->sid;
836 ev->r.c_conn_ret.cid = conn->cid; 1025 ev->r.c_conn_ret.cid = conn->cid;
837 1026
@@ -841,13 +1030,6 @@ iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
841 spin_unlock_irqrestore(&connlock, flags); 1030 spin_unlock_irqrestore(&connlock, flags);
842 1031
843 return 0; 1032 return 0;
844
845free_pdu_pool:
846 mempool_zone_destroy(conn->z_pdu);
847destroy_conn:
848 if (transport->destroy_conn)
849 transport->destroy_conn(conn->dd_data);
850 return -ENOMEM;
851} 1033}
852 1034
853static int 1035static int
@@ -855,7 +1037,6 @@ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev
855{ 1037{
856 unsigned long flags; 1038 unsigned long flags;
857 struct iscsi_cls_conn *conn; 1039 struct iscsi_cls_conn *conn;
858 struct mempool_zone *z_error, *z_pdu;
859 1040
860 conn = iscsi_conn_lookup(ev->u.d_conn.sid, ev->u.d_conn.cid); 1041 conn = iscsi_conn_lookup(ev->u.d_conn.sid, ev->u.d_conn.cid);
861 if (!conn) 1042 if (!conn)
@@ -865,35 +1046,18 @@ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev
865 list_del(&conn->conn_list); 1046 list_del(&conn->conn_list);
866 spin_unlock_irqrestore(&connlock, flags); 1047 spin_unlock_irqrestore(&connlock, flags);
867 1048
868 z_pdu = conn->z_pdu;
869 z_error = conn->z_error;
870
871 if (transport->destroy_conn) 1049 if (transport->destroy_conn)
872 transport->destroy_conn(conn); 1050 transport->destroy_conn(conn);
873
874 mempool_zone_destroy(z_pdu);
875 mempool_zone_destroy(z_error);
876
877 return 0; 1051 return 0;
878} 1052}
879 1053
880static void
881iscsi_copy_param(struct iscsi_uevent *ev, uint32_t *value, char *data)
882{
883 if (ev->u.set_param.len != sizeof(uint32_t))
884 BUG();
885 memcpy(value, data, min_t(uint32_t, sizeof(uint32_t),
886 ev->u.set_param.len));
887}
888
889static int 1054static int
890iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev) 1055iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
891{ 1056{
892 char *data = (char*)ev + sizeof(*ev); 1057 char *data = (char*)ev + sizeof(*ev);
893 struct iscsi_cls_conn *conn; 1058 struct iscsi_cls_conn *conn;
894 struct iscsi_cls_session *session; 1059 struct iscsi_cls_session *session;
895 int err = 0; 1060 int err = 0, value = 0;
896 uint32_t value = 0;
897 1061
898 session = iscsi_session_lookup(ev->u.set_param.sid); 1062 session = iscsi_session_lookup(ev->u.set_param.sid);
899 conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid); 1063 conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid);
@@ -902,42 +1066,13 @@ iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
902 1066
903 switch (ev->u.set_param.param) { 1067 switch (ev->u.set_param.param) {
904 case ISCSI_PARAM_SESS_RECOVERY_TMO: 1068 case ISCSI_PARAM_SESS_RECOVERY_TMO:
905 iscsi_copy_param(ev, &value, data); 1069 sscanf(data, "%d", &value);
906 if (value != 0) 1070 if (value != 0)
907 session->recovery_tmo = value; 1071 session->recovery_tmo = value;
908 break; 1072 break;
909 case ISCSI_PARAM_TARGET_NAME:
910 /* this should not change between logins */
911 if (session->targetname)
912 return 0;
913
914 session->targetname = kstrdup(data, GFP_KERNEL);
915 if (!session->targetname)
916 return -ENOMEM;
917 break;
918 case ISCSI_PARAM_TPGT:
919 iscsi_copy_param(ev, &value, data);
920 session->tpgt = value;
921 break;
922 case ISCSI_PARAM_PERSISTENT_PORT:
923 iscsi_copy_param(ev, &value, data);
924 conn->persistent_port = value;
925 break;
926 case ISCSI_PARAM_PERSISTENT_ADDRESS:
927 /*
928 * this is the address returned in discovery so it should
929 * not change between logins.
930 */
931 if (conn->persistent_address)
932 return 0;
933
934 conn->persistent_address = kstrdup(data, GFP_KERNEL);
935 if (!conn->persistent_address)
936 return -ENOMEM;
937 break;
938 default: 1073 default:
939 iscsi_copy_param(ev, &value, data); 1074 err = transport->set_param(conn, ev->u.set_param.param,
940 err = transport->set_param(conn, ev->u.set_param.param, value); 1075 data, ev->u.set_param.len);
941 } 1076 }
942 1077
943 return err; 1078 return err;
@@ -978,6 +1113,21 @@ iscsi_if_transport_ep(struct iscsi_transport *transport,
978} 1113}
979 1114
980static int 1115static int
1116iscsi_tgt_dscvr(struct iscsi_transport *transport,
1117 struct iscsi_uevent *ev)
1118{
1119 struct sockaddr *dst_addr;
1120
1121 if (!transport->tgt_dscvr)
1122 return -EINVAL;
1123
1124 dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
1125 return transport->tgt_dscvr(ev->u.tgt_dscvr.type,
1126 ev->u.tgt_dscvr.host_no,
1127 ev->u.tgt_dscvr.enable, dst_addr);
1128}
1129
1130static int
981iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) 1131iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
982{ 1132{
983 int err = 0; 1133 int err = 0;
@@ -1065,6 +1215,9 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
1065 case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT: 1215 case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
1066 err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type); 1216 err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type);
1067 break; 1217 break;
1218 case ISCSI_UEVENT_TGT_DSCVR:
1219 err = iscsi_tgt_dscvr(transport, ev);
1220 break;
1068 default: 1221 default:
1069 err = -EINVAL; 1222 err = -EINVAL;
1070 break; 1223 break;
@@ -1147,49 +1300,31 @@ struct class_device_attribute class_device_attr_##_prefix##_##_name = \
1147/* 1300/*
1148 * iSCSI connection attrs 1301 * iSCSI connection attrs
1149 */ 1302 */
1150#define iscsi_conn_int_attr_show(param, format) \ 1303#define iscsi_conn_attr_show(param) \
1151static ssize_t \
1152show_conn_int_param_##param(struct class_device *cdev, char *buf) \
1153{ \
1154 uint32_t value = 0; \
1155 struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \
1156 struct iscsi_transport *t = conn->transport; \
1157 \
1158 t->get_conn_param(conn, param, &value); \
1159 return snprintf(buf, 20, format"\n", value); \
1160}
1161
1162#define iscsi_conn_int_attr(field, param, format) \
1163 iscsi_conn_int_attr_show(param, format) \
1164static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_int_param_##param, \
1165 NULL);
1166
1167iscsi_conn_int_attr(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH, "%u");
1168iscsi_conn_int_attr(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH, "%u");
1169iscsi_conn_int_attr(header_digest, ISCSI_PARAM_HDRDGST_EN, "%d");
1170iscsi_conn_int_attr(data_digest, ISCSI_PARAM_DATADGST_EN, "%d");
1171iscsi_conn_int_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN, "%d");
1172iscsi_conn_int_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN, "%d");
1173iscsi_conn_int_attr(persistent_port, ISCSI_PARAM_PERSISTENT_PORT, "%d");
1174iscsi_conn_int_attr(port, ISCSI_PARAM_CONN_PORT, "%d");
1175iscsi_conn_int_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN, "%u");
1176
1177#define iscsi_conn_str_attr_show(param) \
1178static ssize_t \ 1304static ssize_t \
1179show_conn_str_param_##param(struct class_device *cdev, char *buf) \ 1305show_conn_param_##param(struct class_device *cdev, char *buf) \
1180{ \ 1306{ \
1181 struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \ 1307 struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \
1182 struct iscsi_transport *t = conn->transport; \ 1308 struct iscsi_transport *t = conn->transport; \
1183 return t->get_conn_str_param(conn, param, buf); \ 1309 return t->get_conn_param(conn, param, buf); \
1184} 1310}
1185 1311
1186#define iscsi_conn_str_attr(field, param) \ 1312#define iscsi_conn_attr(field, param) \
1187 iscsi_conn_str_attr_show(param) \ 1313 iscsi_conn_attr_show(param) \
1188static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_str_param_##param, \ 1314static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_param_##param, \
1189 NULL); 1315 NULL);
1190 1316
1191iscsi_conn_str_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS); 1317iscsi_conn_attr(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH);
1192iscsi_conn_str_attr(address, ISCSI_PARAM_CONN_ADDRESS); 1318iscsi_conn_attr(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH);
1319iscsi_conn_attr(header_digest, ISCSI_PARAM_HDRDGST_EN);
1320iscsi_conn_attr(data_digest, ISCSI_PARAM_DATADGST_EN);
1321iscsi_conn_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN);
1322iscsi_conn_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN);
1323iscsi_conn_attr(persistent_port, ISCSI_PARAM_PERSISTENT_PORT);
1324iscsi_conn_attr(port, ISCSI_PARAM_CONN_PORT);
1325iscsi_conn_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN);
1326iscsi_conn_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS);
1327iscsi_conn_attr(address, ISCSI_PARAM_CONN_ADDRESS);
1193 1328
1194#define iscsi_cdev_to_session(_cdev) \ 1329#define iscsi_cdev_to_session(_cdev) \
1195 iscsi_dev_to_session(_cdev->dev) 1330 iscsi_dev_to_session(_cdev->dev)
@@ -1197,61 +1332,36 @@ iscsi_conn_str_attr(address, ISCSI_PARAM_CONN_ADDRESS);
1197/* 1332/*
1198 * iSCSI session attrs 1333 * iSCSI session attrs
1199 */ 1334 */
1200#define iscsi_session_int_attr_show(param, format) \ 1335#define iscsi_session_attr_show(param) \
1201static ssize_t \
1202show_session_int_param_##param(struct class_device *cdev, char *buf) \
1203{ \
1204 uint32_t value = 0; \
1205 struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
1206 struct iscsi_transport *t = session->transport; \
1207 \
1208 t->get_session_param(session, param, &value); \
1209 return snprintf(buf, 20, format"\n", value); \
1210}
1211
1212#define iscsi_session_int_attr(field, param, format) \
1213 iscsi_session_int_attr_show(param, format) \
1214static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_int_param_##param, \
1215 NULL);
1216
1217iscsi_session_int_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN, "%d");
1218iscsi_session_int_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T, "%hu");
1219iscsi_session_int_attr(immediate_data, ISCSI_PARAM_IMM_DATA_EN, "%d");
1220iscsi_session_int_attr(first_burst_len, ISCSI_PARAM_FIRST_BURST, "%u");
1221iscsi_session_int_attr(max_burst_len, ISCSI_PARAM_MAX_BURST, "%u");
1222iscsi_session_int_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN, "%d");
1223iscsi_session_int_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN, "%d");
1224iscsi_session_int_attr(erl, ISCSI_PARAM_ERL, "%d");
1225iscsi_session_int_attr(tpgt, ISCSI_PARAM_TPGT, "%d");
1226
1227#define iscsi_session_str_attr_show(param) \
1228static ssize_t \ 1336static ssize_t \
1229show_session_str_param_##param(struct class_device *cdev, char *buf) \ 1337show_session_param_##param(struct class_device *cdev, char *buf) \
1230{ \ 1338{ \
1231 struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \ 1339 struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
1232 struct iscsi_transport *t = session->transport; \ 1340 struct iscsi_transport *t = session->transport; \
1233 return t->get_session_str_param(session, param, buf); \ 1341 return t->get_session_param(session, param, buf); \
1234} 1342}
1235 1343
1236#define iscsi_session_str_attr(field, param) \ 1344#define iscsi_session_attr(field, param) \
1237 iscsi_session_str_attr_show(param) \ 1345 iscsi_session_attr_show(param) \
1238static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_str_param_##param, \ 1346static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_param_##param, \
1239 NULL); 1347 NULL);
1240 1348
1241iscsi_session_str_attr(targetname, ISCSI_PARAM_TARGET_NAME); 1349iscsi_session_attr(targetname, ISCSI_PARAM_TARGET_NAME);
1350iscsi_session_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN);
1351iscsi_session_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T);
1352iscsi_session_attr(immediate_data, ISCSI_PARAM_IMM_DATA_EN);
1353iscsi_session_attr(first_burst_len, ISCSI_PARAM_FIRST_BURST);
1354iscsi_session_attr(max_burst_len, ISCSI_PARAM_MAX_BURST);
1355iscsi_session_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN);
1356iscsi_session_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN);
1357iscsi_session_attr(erl, ISCSI_PARAM_ERL);
1358iscsi_session_attr(tpgt, ISCSI_PARAM_TPGT);
1242 1359
1243/*
1244 * Private session and conn attrs. userspace uses several iscsi values
1245 * to identify each session between reboots. Some of these values may not
1246 * be present in the iscsi_transport/LLD driver becuase userspace handles
1247 * login (and failback for login redirect) so for these type of drivers
1248 * the class manages the attrs and values for the iscsi_transport/LLD
1249 */
1250#define iscsi_priv_session_attr_show(field, format) \ 1360#define iscsi_priv_session_attr_show(field, format) \
1251static ssize_t \ 1361static ssize_t \
1252show_priv_session_##field(struct class_device *cdev, char *buf) \ 1362show_priv_session_##field(struct class_device *cdev, char *buf) \
1253{ \ 1363{ \
1254 struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \ 1364 struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev);\
1255 return sprintf(buf, format"\n", session->field); \ 1365 return sprintf(buf, format"\n", session->field); \
1256} 1366}
1257 1367
@@ -1259,31 +1369,15 @@ show_priv_session_##field(struct class_device *cdev, char *buf) \
1259 iscsi_priv_session_attr_show(field, format) \ 1369 iscsi_priv_session_attr_show(field, format) \
1260static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO, show_priv_session_##field, \ 1370static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO, show_priv_session_##field, \
1261 NULL) 1371 NULL)
1262iscsi_priv_session_attr(targetname, "%s");
1263iscsi_priv_session_attr(tpgt, "%d");
1264iscsi_priv_session_attr(recovery_tmo, "%d"); 1372iscsi_priv_session_attr(recovery_tmo, "%d");
1265 1373
1266#define iscsi_priv_conn_attr_show(field, format) \
1267static ssize_t \
1268show_priv_conn_##field(struct class_device *cdev, char *buf) \
1269{ \
1270 struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \
1271 return sprintf(buf, format"\n", conn->field); \
1272}
1273
1274#define iscsi_priv_conn_attr(field, format) \
1275 iscsi_priv_conn_attr_show(field, format) \
1276static ISCSI_CLASS_ATTR(priv_conn, field, S_IRUGO, show_priv_conn_##field, \
1277 NULL)
1278iscsi_priv_conn_attr(persistent_address, "%s");
1279iscsi_priv_conn_attr(persistent_port, "%d");
1280
1281#define SETUP_PRIV_SESSION_RD_ATTR(field) \ 1374#define SETUP_PRIV_SESSION_RD_ATTR(field) \
1282do { \ 1375do { \
1283 priv->session_attrs[count] = &class_device_attr_priv_sess_##field; \ 1376 priv->session_attrs[count] = &class_device_attr_priv_sess_##field; \
1284 count++; \ 1377 count++; \
1285} while (0) 1378} while (0)
1286 1379
1380
1287#define SETUP_SESSION_RD_ATTR(field, param_flag) \ 1381#define SETUP_SESSION_RD_ATTR(field, param_flag) \
1288do { \ 1382do { \
1289 if (tt->param_mask & param_flag) { \ 1383 if (tt->param_mask & param_flag) { \
@@ -1292,12 +1386,6 @@ do { \
1292 } \ 1386 } \
1293} while (0) 1387} while (0)
1294 1388
1295#define SETUP_PRIV_CONN_RD_ATTR(field) \
1296do { \
1297 priv->conn_attrs[count] = &class_device_attr_priv_conn_##field; \
1298 count++; \
1299} while (0)
1300
1301#define SETUP_CONN_RD_ATTR(field, param_flag) \ 1389#define SETUP_CONN_RD_ATTR(field, param_flag) \
1302do { \ 1390do { \
1303 if (tt->param_mask & param_flag) { \ 1391 if (tt->param_mask & param_flag) { \
@@ -1388,6 +1476,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
1388 if (!priv) 1476 if (!priv)
1389 return NULL; 1477 return NULL;
1390 INIT_LIST_HEAD(&priv->list); 1478 INIT_LIST_HEAD(&priv->list);
1479 priv->daemon_pid = -1;
1391 priv->iscsi_transport = tt; 1480 priv->iscsi_transport = tt;
1392 priv->t.user_scan = iscsi_user_scan; 1481 priv->t.user_scan = iscsi_user_scan;
1393 1482
@@ -1424,16 +1513,8 @@ iscsi_register_transport(struct iscsi_transport *tt)
1424 SETUP_CONN_RD_ATTR(address, ISCSI_CONN_ADDRESS); 1513 SETUP_CONN_RD_ATTR(address, ISCSI_CONN_ADDRESS);
1425 SETUP_CONN_RD_ATTR(port, ISCSI_CONN_PORT); 1514 SETUP_CONN_RD_ATTR(port, ISCSI_CONN_PORT);
1426 SETUP_CONN_RD_ATTR(exp_statsn, ISCSI_EXP_STATSN); 1515 SETUP_CONN_RD_ATTR(exp_statsn, ISCSI_EXP_STATSN);
1427 1516 SETUP_CONN_RD_ATTR(persistent_address, ISCSI_PERSISTENT_ADDRESS);
1428 if (tt->param_mask & ISCSI_PERSISTENT_ADDRESS) 1517 SETUP_CONN_RD_ATTR(persistent_port, ISCSI_PERSISTENT_PORT);
1429 SETUP_CONN_RD_ATTR(persistent_address, ISCSI_PERSISTENT_ADDRESS);
1430 else
1431 SETUP_PRIV_CONN_RD_ATTR(persistent_address);
1432
1433 if (tt->param_mask & ISCSI_PERSISTENT_PORT)
1434 SETUP_CONN_RD_ATTR(persistent_port, ISCSI_PERSISTENT_PORT);
1435 else
1436 SETUP_PRIV_CONN_RD_ATTR(persistent_port);
1437 1518
1438 BUG_ON(count > ISCSI_CONN_ATTRS); 1519 BUG_ON(count > ISCSI_CONN_ATTRS);
1439 priv->conn_attrs[count] = NULL; 1520 priv->conn_attrs[count] = NULL;
@@ -1453,18 +1534,10 @@ iscsi_register_transport(struct iscsi_transport *tt)
1453 SETUP_SESSION_RD_ATTR(data_pdu_in_order, ISCSI_PDU_INORDER_EN); 1534 SETUP_SESSION_RD_ATTR(data_pdu_in_order, ISCSI_PDU_INORDER_EN);
1454 SETUP_SESSION_RD_ATTR(data_seq_in_order, ISCSI_DATASEQ_INORDER_EN); 1535 SETUP_SESSION_RD_ATTR(data_seq_in_order, ISCSI_DATASEQ_INORDER_EN);
1455 SETUP_SESSION_RD_ATTR(erl, ISCSI_ERL); 1536 SETUP_SESSION_RD_ATTR(erl, ISCSI_ERL);
1537 SETUP_SESSION_RD_ATTR(targetname, ISCSI_TARGET_NAME);
1538 SETUP_SESSION_RD_ATTR(tpgt, ISCSI_TPGT);
1456 SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo); 1539 SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo);
1457 1540
1458 if (tt->param_mask & ISCSI_TARGET_NAME)
1459 SETUP_SESSION_RD_ATTR(targetname, ISCSI_TARGET_NAME);
1460 else
1461 SETUP_PRIV_SESSION_RD_ATTR(targetname);
1462
1463 if (tt->param_mask & ISCSI_TPGT)
1464 SETUP_SESSION_RD_ATTR(tpgt, ISCSI_TPGT);
1465 else
1466 SETUP_PRIV_SESSION_RD_ATTR(tpgt);
1467
1468 BUG_ON(count > ISCSI_SESSION_ATTRS); 1541 BUG_ON(count > ISCSI_SESSION_ATTRS);
1469 priv->session_attrs[count] = NULL; 1542 priv->session_attrs[count] = NULL;
1470 1543
@@ -1541,6 +1614,9 @@ static __init int iscsi_transport_init(void)
1541{ 1614{
1542 int err; 1615 int err;
1543 1616
1617 printk(KERN_INFO "Loading iSCSI transport class v%s.",
1618 ISCSI_TRANSPORT_VERSION);
1619
1544 err = class_register(&iscsi_transport_class); 1620 err = class_register(&iscsi_transport_class);
1545 if (err) 1621 if (err)
1546 return err; 1622 return err;
@@ -1606,3 +1682,4 @@ MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>, "
1606 "Alex Aizman <itn780@yahoo.com>"); 1682 "Alex Aizman <itn780@yahoo.com>");
1607MODULE_DESCRIPTION("iSCSI Transport Interface"); 1683MODULE_DESCRIPTION("iSCSI Transport Interface");
1608MODULE_LICENSE("GPL"); 1684MODULE_LICENSE("GPL");
1685MODULE_VERSION(ISCSI_TRANSPORT_VERSION);