aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c309
-rw-r--r--include/scsi/iscsi_if.h23
-rw-r--r--include/scsi/scsi_transport_iscsi.h3
3 files changed, 235 insertions, 100 deletions
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 7963c0538de5..7b9e8fa1a4e0 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -413,11 +413,59 @@ int iscsi_destroy_session(struct iscsi_cls_session *session)
413} 413}
414EXPORT_SYMBOL_GPL(iscsi_destroy_session); 414EXPORT_SYMBOL_GPL(iscsi_destroy_session);
415 415
416static void mempool_zone_destroy(struct mempool_zone *zp)
417{
418 mempool_destroy(zp->pool);
419 kfree(zp);
420}
421
422static void*
423mempool_zone_alloc_skb(gfp_t gfp_mask, void *pool_data)
424{
425 struct mempool_zone *zone = pool_data;
426
427 return alloc_skb(zone->size, gfp_mask);
428}
429
430static void
431mempool_zone_free_skb(void *element, void *pool_data)
432{
433 kfree_skb(element);
434}
435
436static struct mempool_zone *
437mempool_zone_init(unsigned max, unsigned size, unsigned hiwat)
438{
439 struct mempool_zone *zp;
440
441 zp = kzalloc(sizeof(*zp), GFP_KERNEL);
442 if (!zp)
443 return NULL;
444
445 zp->size = size;
446 zp->hiwat = hiwat;
447 INIT_LIST_HEAD(&zp->freequeue);
448 spin_lock_init(&zp->freelock);
449 atomic_set(&zp->allocated, 0);
450
451 zp->pool = mempool_create(max, mempool_zone_alloc_skb,
452 mempool_zone_free_skb, zp);
453 if (!zp->pool) {
454 kfree(zp);
455 return NULL;
456 }
457
458 return zp;
459}
460
416static void iscsi_conn_release(struct device *dev) 461static void iscsi_conn_release(struct device *dev)
417{ 462{
418 struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev); 463 struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev);
419 struct device *parent = conn->dev.parent; 464 struct device *parent = conn->dev.parent;
420 465
466 mempool_zone_destroy(conn->z_pdu);
467 mempool_zone_destroy(conn->z_error);
468
421 kfree(conn); 469 kfree(conn);
422 put_device(parent); 470 put_device(parent);
423} 471}
@@ -427,6 +475,31 @@ static int iscsi_is_conn_dev(const struct device *dev)
427 return dev->release == iscsi_conn_release; 475 return dev->release == iscsi_conn_release;
428} 476}
429 477
478static int iscsi_create_event_pools(struct iscsi_cls_conn *conn)
479{
480 conn->z_pdu = mempool_zone_init(Z_MAX_PDU,
481 NLMSG_SPACE(sizeof(struct iscsi_uevent) +
482 sizeof(struct iscsi_hdr) +
483 DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH),
484 Z_HIWAT_PDU);
485 if (!conn->z_pdu) {
486 dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
487 "pdu zone for new conn\n");
488 return -ENOMEM;
489 }
490
491 conn->z_error = mempool_zone_init(Z_MAX_ERROR,
492 NLMSG_SPACE(sizeof(struct iscsi_uevent)),
493 Z_HIWAT_ERROR);
494 if (!conn->z_error) {
495 dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
496 "error zone for new conn\n");
497 mempool_zone_destroy(conn->z_pdu);
498 return -ENOMEM;
499 }
500 return 0;
501}
502
430/** 503/**
431 * iscsi_create_conn - create iscsi class connection 504 * iscsi_create_conn - create iscsi class connection
432 * @session: iscsi cls session 505 * @session: iscsi cls session
@@ -459,9 +532,12 @@ iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid)
459 conn->transport = transport; 532 conn->transport = transport;
460 conn->cid = cid; 533 conn->cid = cid;
461 534
535 if (iscsi_create_event_pools(conn))
536 goto free_conn;
537
462 /* this is released in the dev's release function */ 538 /* this is released in the dev's release function */
463 if (!get_device(&session->dev)) 539 if (!get_device(&session->dev))
464 goto free_conn; 540 goto free_conn_pools;
465 541
466 snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u", 542 snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
467 session->sid, cid); 543 session->sid, cid);
@@ -478,6 +554,8 @@ iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid)
478 554
479release_parent_ref: 555release_parent_ref:
480 put_device(&session->dev); 556 put_device(&session->dev);
557free_conn_pools:
558
481free_conn: 559free_conn:
482 kfree(conn); 560 kfree(conn);
483 return NULL; 561 return NULL;
@@ -525,20 +603,6 @@ static inline struct list_head *skb_to_lh(struct sk_buff *skb)
525 return (struct list_head *)&skb->cb; 603 return (struct list_head *)&skb->cb;
526} 604}
527 605
528static void*
529mempool_zone_alloc_skb(gfp_t gfp_mask, void *pool_data)
530{
531 struct mempool_zone *zone = pool_data;
532
533 return alloc_skb(zone->size, gfp_mask);
534}
535
536static void
537mempool_zone_free_skb(void *element, void *pool_data)
538{
539 kfree_skb(element);
540}
541
542static void 606static void
543mempool_zone_complete(struct mempool_zone *zone) 607mempool_zone_complete(struct mempool_zone *zone)
544{ 608{
@@ -558,37 +622,6 @@ mempool_zone_complete(struct mempool_zone *zone)
558 spin_unlock_irqrestore(&zone->freelock, flags); 622 spin_unlock_irqrestore(&zone->freelock, flags);
559} 623}
560 624
561static struct mempool_zone *
562mempool_zone_init(unsigned max, unsigned size, unsigned hiwat)
563{
564 struct mempool_zone *zp;
565
566 zp = kzalloc(sizeof(*zp), GFP_KERNEL);
567 if (!zp)
568 return NULL;
569
570 zp->size = size;
571 zp->hiwat = hiwat;
572 INIT_LIST_HEAD(&zp->freequeue);
573 spin_lock_init(&zp->freelock);
574 atomic_set(&zp->allocated, 0);
575
576 zp->pool = mempool_create(max, mempool_zone_alloc_skb,
577 mempool_zone_free_skb, zp);
578 if (!zp->pool) {
579 kfree(zp);
580 return NULL;
581 }
582
583 return zp;
584}
585
586static void mempool_zone_destroy(struct mempool_zone *zp)
587{
588 mempool_destroy(zp->pool);
589 kfree(zp);
590}
591
592static struct sk_buff* 625static struct sk_buff*
593mempool_zone_get_skb(struct mempool_zone *zone) 626mempool_zone_get_skb(struct mempool_zone *zone)
594{ 627{
@@ -601,6 +634,27 @@ mempool_zone_get_skb(struct mempool_zone *zone)
601} 634}
602 635
603static int 636static int
637iscsi_broadcast_skb(struct mempool_zone *zone, struct sk_buff *skb)
638{
639 unsigned long flags;
640 int rc;
641
642 skb_get(skb);
643 rc = netlink_broadcast(nls, skb, 0, 1, GFP_KERNEL);
644 if (rc < 0) {
645 mempool_free(skb, zone->pool);
646 printk(KERN_ERR "iscsi: can not broadcast skb (%d)\n", rc);
647 return rc;
648 }
649
650 spin_lock_irqsave(&zone->freelock, flags);
651 INIT_LIST_HEAD(skb_to_lh(skb));
652 list_add(skb_to_lh(skb), &zone->freequeue);
653 spin_unlock_irqrestore(&zone->freelock, flags);
654 return 0;
655}
656
657static int
604iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb, int pid) 658iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb, int pid)
605{ 659{
606 unsigned long flags; 660 unsigned long flags;
@@ -695,7 +749,7 @@ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
695 ev->r.connerror.cid = conn->cid; 749 ev->r.connerror.cid = conn->cid;
696 ev->r.connerror.sid = iscsi_conn_get_sid(conn); 750 ev->r.connerror.sid = iscsi_conn_get_sid(conn);
697 751
698 iscsi_unicast_skb(conn->z_error, skb, priv->daemon_pid); 752 iscsi_broadcast_skb(conn->z_error, skb);
699 753
700 dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n", 754 dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n",
701 error); 755 error);
@@ -796,6 +850,131 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
796 return err; 850 return err;
797} 851}
798 852
853/**
854 * iscsi_if_destroy_session_done - send session destr. completion event
855 * @conn: last connection for session
856 *
857 * This is called by HW iscsi LLDs to notify userpsace that its HW has
858 * removed a session.
859 **/
860int iscsi_if_destroy_session_done(struct iscsi_cls_conn *conn)
861{
862 struct iscsi_internal *priv;
863 struct iscsi_cls_session *session;
864 struct Scsi_Host *shost;
865 struct iscsi_uevent *ev;
866 struct sk_buff *skb;
867 struct nlmsghdr *nlh;
868 unsigned long flags;
869 int rc, len = NLMSG_SPACE(sizeof(*ev));
870
871 priv = iscsi_if_transport_lookup(conn->transport);
872 if (!priv)
873 return -EINVAL;
874
875 session = iscsi_dev_to_session(conn->dev.parent);
876 shost = iscsi_session_to_shost(session);
877
878 mempool_zone_complete(conn->z_pdu);
879
880 skb = mempool_zone_get_skb(conn->z_pdu);
881 if (!skb) {
882 dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
883 "session creation event\n");
884 return -ENOMEM;
885 }
886
887 nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
888 ev = NLMSG_DATA(nlh);
889 ev->transport_handle = iscsi_handle(conn->transport);
890 ev->type = ISCSI_KEVENT_DESTROY_SESSION;
891 ev->r.d_session.host_no = shost->host_no;
892 ev->r.d_session.sid = session->sid;
893
894 /*
895 * this will occur if the daemon is not up, so we just warn
896 * the user and when the daemon is restarted it will handle it
897 */
898 rc = iscsi_broadcast_skb(conn->z_pdu, skb);
899 if (rc < 0)
900 dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
901 "session destruction event. Check iscsi daemon\n");
902
903 spin_lock_irqsave(&sesslock, flags);
904 list_del(&session->sess_list);
905 spin_unlock_irqrestore(&sesslock, flags);
906
907 spin_lock_irqsave(&connlock, flags);
908 conn->active = 0;
909 list_del(&conn->conn_list);
910 spin_unlock_irqrestore(&connlock, flags);
911
912 return rc;
913}
914EXPORT_SYMBOL_GPL(iscsi_if_destroy_session_done);
915
916/**
917 * iscsi_if_create_session_done - send session creation completion event
918 * @conn: leading connection for session
919 *
920 * This is called by HW iscsi LLDs to notify userpsace that its HW has
921 * created a session or a existing session is back in the logged in state.
922 **/
923int iscsi_if_create_session_done(struct iscsi_cls_conn *conn)
924{
925 struct iscsi_internal *priv;
926 struct iscsi_cls_session *session;
927 struct Scsi_Host *shost;
928 struct iscsi_uevent *ev;
929 struct sk_buff *skb;
930 struct nlmsghdr *nlh;
931 unsigned long flags;
932 int rc, len = NLMSG_SPACE(sizeof(*ev));
933
934 priv = iscsi_if_transport_lookup(conn->transport);
935 if (!priv)
936 return -EINVAL;
937
938 session = iscsi_dev_to_session(conn->dev.parent);
939 shost = iscsi_session_to_shost(session);
940
941 mempool_zone_complete(conn->z_pdu);
942
943 skb = mempool_zone_get_skb(conn->z_pdu);
944 if (!skb) {
945 dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
946 "session creation event\n");
947 return -ENOMEM;
948 }
949
950 nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
951 ev = NLMSG_DATA(nlh);
952 ev->transport_handle = iscsi_handle(conn->transport);
953 ev->type = ISCSI_UEVENT_CREATE_SESSION;
954 ev->r.c_session_ret.host_no = shost->host_no;
955 ev->r.c_session_ret.sid = session->sid;
956
957 /*
958 * this will occur if the daemon is not up, so we just warn
959 * the user and when the daemon is restarted it will handle it
960 */
961 rc = iscsi_broadcast_skb(conn->z_pdu, skb);
962 if (rc < 0)
963 dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
964 "session creation event. Check iscsi daemon\n");
965
966 spin_lock_irqsave(&sesslock, flags);
967 list_add(&session->sess_list, &sesslist);
968 spin_unlock_irqrestore(&sesslock, flags);
969
970 spin_lock_irqsave(&connlock, flags);
971 list_add(&conn->conn_list, &connlist);
972 conn->active = 1;
973 spin_unlock_irqrestore(&connlock, flags);
974 return rc;
975}
976EXPORT_SYMBOL_GPL(iscsi_if_create_session_done);
977
799static int 978static int
800iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev) 979iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
801{ 980{
@@ -841,26 +1020,6 @@ iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
841 return -ENOMEM; 1020 return -ENOMEM;
842 } 1021 }
843 1022
844 conn->z_pdu = mempool_zone_init(Z_MAX_PDU,
845 NLMSG_SPACE(sizeof(struct iscsi_uevent) +
846 sizeof(struct iscsi_hdr) +
847 DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH),
848 Z_HIWAT_PDU);
849 if (!conn->z_pdu) {
850 dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
851 "pdu zone for new conn\n");
852 goto destroy_conn;
853 }
854
855 conn->z_error = mempool_zone_init(Z_MAX_ERROR,
856 NLMSG_SPACE(sizeof(struct iscsi_uevent)),
857 Z_HIWAT_ERROR);
858 if (!conn->z_error) {
859 dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
860 "error zone for new conn\n");
861 goto free_pdu_pool;
862 }
863
864 ev->r.c_conn_ret.sid = session->sid; 1023 ev->r.c_conn_ret.sid = session->sid;
865 ev->r.c_conn_ret.cid = conn->cid; 1024 ev->r.c_conn_ret.cid = conn->cid;
866 1025
@@ -870,13 +1029,6 @@ iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
870 spin_unlock_irqrestore(&connlock, flags); 1029 spin_unlock_irqrestore(&connlock, flags);
871 1030
872 return 0; 1031 return 0;
873
874free_pdu_pool:
875 mempool_zone_destroy(conn->z_pdu);
876destroy_conn:
877 if (transport->destroy_conn)
878 transport->destroy_conn(conn->dd_data);
879 return -ENOMEM;
880} 1032}
881 1033
882static int 1034static int
@@ -884,7 +1036,6 @@ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev
884{ 1036{
885 unsigned long flags; 1037 unsigned long flags;
886 struct iscsi_cls_conn *conn; 1038 struct iscsi_cls_conn *conn;
887 struct mempool_zone *z_error, *z_pdu;
888 1039
889 conn = iscsi_conn_lookup(ev->u.d_conn.sid, ev->u.d_conn.cid); 1040 conn = iscsi_conn_lookup(ev->u.d_conn.sid, ev->u.d_conn.cid);
890 if (!conn) 1041 if (!conn)
@@ -894,15 +1045,8 @@ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev
894 list_del(&conn->conn_list); 1045 list_del(&conn->conn_list);
895 spin_unlock_irqrestore(&connlock, flags); 1046 spin_unlock_irqrestore(&connlock, flags);
896 1047
897 z_pdu = conn->z_pdu;
898 z_error = conn->z_error;
899
900 if (transport->destroy_conn) 1048 if (transport->destroy_conn)
901 transport->destroy_conn(conn); 1049 transport->destroy_conn(conn);
902
903 mempool_zone_destroy(z_pdu);
904 mempool_zone_destroy(z_error);
905
906 return 0; 1050 return 0;
907} 1051}
908 1052
@@ -1331,6 +1475,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
1331 if (!priv) 1475 if (!priv)
1332 return NULL; 1476 return NULL;
1333 INIT_LIST_HEAD(&priv->list); 1477 INIT_LIST_HEAD(&priv->list);
1478 priv->daemon_pid = -1;
1334 priv->iscsi_transport = tt; 1479 priv->iscsi_transport = tt;
1335 priv->t.user_scan = iscsi_user_scan; 1480 priv->t.user_scan = iscsi_user_scan;
1336 1481
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
index 8813f0f4c624..55ebf035e620 100644
--- a/include/scsi/iscsi_if.h
+++ b/include/scsi/iscsi_if.h
@@ -53,6 +53,7 @@ enum iscsi_uevent_e {
53 ISCSI_KEVENT_RECV_PDU = KEVENT_BASE + 1, 53 ISCSI_KEVENT_RECV_PDU = KEVENT_BASE + 1,
54 ISCSI_KEVENT_CONN_ERROR = KEVENT_BASE + 2, 54 ISCSI_KEVENT_CONN_ERROR = KEVENT_BASE + 2,
55 ISCSI_KEVENT_IF_ERROR = KEVENT_BASE + 3, 55 ISCSI_KEVENT_IF_ERROR = KEVENT_BASE + 3,
56 ISCSI_KEVENT_DESTROY_SESSION = KEVENT_BASE + 4,
56}; 57};
57 58
58enum iscsi_tgt_dscvr { 59enum iscsi_tgt_dscvr {
@@ -157,27 +158,13 @@ struct iscsi_uevent {
157 uint32_t cid; 158 uint32_t cid;
158 uint32_t error; /* enum iscsi_err */ 159 uint32_t error; /* enum iscsi_err */
159 } connerror; 160 } connerror;
161 struct msg_session_destroyed {
162 uint32_t host_no;
163 uint32_t sid;
164 } d_session;
160 struct msg_transport_connect_ret { 165 struct msg_transport_connect_ret {
161 uint64_t handle; 166 uint64_t handle;
162 } ep_connect_ret; 167 } ep_connect_ret;
163 struct msg_tgt_dscvr_ret {
164 /*
165 * session/connection pair used to reference
166 * the connection to server
167 */
168 uint32_t sid;
169 uint32_t cid;
170 union {
171 struct isns {
172 /* port # for conn to iSNS server */
173 uint16_t isns_port;
174 /* listening port to receive SCNs */
175 uint16_t scn_port;
176 /* listening port to receive ESIs */
177 uint16_t esi_port;
178 } isns_attrib;
179 } u;
180 } tgt_dscvr_ret;
181 } r; 168 } r;
182} __attribute__ ((aligned (sizeof(uint64_t)))); 169} __attribute__ ((aligned (sizeof(uint64_t))));
183 170
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index f7b0db5f2f5b..5a3df1d7085f 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -214,6 +214,8 @@ extern struct iscsi_cls_session *iscsi_alloc_session(struct Scsi_Host *shost,
214 struct iscsi_transport *transport); 214 struct iscsi_transport *transport);
215extern int iscsi_add_session(struct iscsi_cls_session *session, 215extern int iscsi_add_session(struct iscsi_cls_session *session,
216 unsigned int target_id); 216 unsigned int target_id);
217extern int iscsi_if_create_session_done(struct iscsi_cls_conn *conn);
218extern int iscsi_if_destroy_session_done(struct iscsi_cls_conn *conn);
217extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost, 219extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost,
218 struct iscsi_transport *t, 220 struct iscsi_transport *t,
219 unsigned int target_id); 221 unsigned int target_id);
@@ -226,4 +228,5 @@ extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn);
226extern void iscsi_unblock_session(struct iscsi_cls_session *session); 228extern void iscsi_unblock_session(struct iscsi_cls_session *session);
227extern void iscsi_block_session(struct iscsi_cls_session *session); 229extern void iscsi_block_session(struct iscsi_cls_session *session);
228 230
231
229#endif 232#endif