aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_transport_iscsi.c
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2006-04-06 22:13:33 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-04-14 15:02:43 -0400
commitb5c7a12dc29ae0990d9e867749bdd717a3160325 (patch)
tree66bb4b7fd02e5a8a89f385aadf80a666ac941fbe /drivers/scsi/scsi_transport_iscsi.c
parent13f7e5acc8b329080672c13f05f252ace5b79825 (diff)
[SCSI] iscsi: rm kernel iscsi handles usage for session and connection
from hare@suse.de and michaelc@cs.wisc.edu hw iscsi like qla4xxx does not allocate a host per session and for userspace it is difficult to restart iscsid using the "iscsi handles" for the session and connection, so this patch just has the class or userspace allocate the id for the session and connection. Note: this breaks userspace and requires users to upgrade to the newest open-iscsi tools. Sorry about his but open-iscsi is still too new to say we have a stable user-kernel api and we were not good nough designers to know that other hw iscsi drivers and iscsid itself would need such changes. Actually we sorta did but at the time we did not have the HW available to us so we could only guess. Luckily, the only tools hooking into the class are the open-iscsi ones or other tools like iscsitart hook into the open-iscsi engine from userspace or prgroams like anaconda call our tools so they are not affected. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/scsi_transport_iscsi.c')
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c106
1 files changed, 73 insertions, 33 deletions
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 2730d507e585..10ff0f0210ba 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -56,6 +56,8 @@ struct iscsi_internal {
56 struct class_device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1]; 56 struct class_device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1];
57}; 57};
58 58
59static int iscsi_session_nr; /* sysfs session id for next new session */
60
59/* 61/*
60 * list of registered transports and lock that must 62 * list of registered transports and lock that must
61 * be held while accessing list. The iscsi_transport_lock must 63 * be held while accessing list. The iscsi_transport_lock must
@@ -165,14 +167,23 @@ static DEFINE_SPINLOCK(sesslock);
165static LIST_HEAD(connlist); 167static LIST_HEAD(connlist);
166static DEFINE_SPINLOCK(connlock); 168static DEFINE_SPINLOCK(connlock);
167 169
168static struct iscsi_cls_session *iscsi_session_lookup(uint64_t handle) 170static uint32_t iscsi_conn_get_sid(struct iscsi_cls_conn *conn)
171{
172 struct iscsi_cls_session *sess = iscsi_dev_to_session(conn->dev.parent);
173 return sess->sid;
174}
175
176/*
177 * Returns the matching session to a given sid
178 */
179static struct iscsi_cls_session *iscsi_session_lookup(uint32_t sid)
169{ 180{
170 unsigned long flags; 181 unsigned long flags;
171 struct iscsi_cls_session *sess; 182 struct iscsi_cls_session *sess;
172 183
173 spin_lock_irqsave(&sesslock, flags); 184 spin_lock_irqsave(&sesslock, flags);
174 list_for_each_entry(sess, &sesslist, sess_list) { 185 list_for_each_entry(sess, &sesslist, sess_list) {
175 if (sess == iscsi_ptr(handle)) { 186 if (sess->sid == sid) {
176 spin_unlock_irqrestore(&sesslock, flags); 187 spin_unlock_irqrestore(&sesslock, flags);
177 return sess; 188 return sess;
178 } 189 }
@@ -181,14 +192,17 @@ static struct iscsi_cls_session *iscsi_session_lookup(uint64_t handle)
181 return NULL; 192 return NULL;
182} 193}
183 194
184static struct iscsi_cls_conn *iscsi_conn_lookup(uint64_t handle) 195/*
196 * Returns the matching connection to a given sid / cid tuple
197 */
198static struct iscsi_cls_conn *iscsi_conn_lookup(uint32_t sid, uint32_t cid)
185{ 199{
186 unsigned long flags; 200 unsigned long flags;
187 struct iscsi_cls_conn *conn; 201 struct iscsi_cls_conn *conn;
188 202
189 spin_lock_irqsave(&connlock, flags); 203 spin_lock_irqsave(&connlock, flags);
190 list_for_each_entry(conn, &connlist, conn_list) { 204 list_for_each_entry(conn, &connlist, conn_list) {
191 if (conn == iscsi_ptr(handle)) { 205 if ((conn->cid == cid) && (iscsi_conn_get_sid(conn) == sid)) {
192 spin_unlock_irqrestore(&connlock, flags); 206 spin_unlock_irqrestore(&connlock, flags);
193 return conn; 207 return conn;
194 } 208 }
@@ -223,7 +237,7 @@ static int iscsi_is_session_dev(const struct device *dev)
223 * @shost: scsi host 237 * @shost: scsi host
224 * @transport: iscsi transport 238 * @transport: iscsi transport
225 * 239 *
226 * This can be called from a LLD or iscsi_transport 240 * This can be called from a LLD or iscsi_transport.
227 **/ 241 **/
228struct iscsi_cls_session * 242struct iscsi_cls_session *
229iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport) 243iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport)
@@ -234,14 +248,20 @@ iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport)
234 if (!try_module_get(transport->owner)) 248 if (!try_module_get(transport->owner))
235 return NULL; 249 return NULL;
236 250
237 session = kzalloc(sizeof(*session), GFP_KERNEL); 251 session = kzalloc(sizeof(*session) + transport->sessiondata_size,
252 GFP_KERNEL);
238 if (!session) 253 if (!session)
239 goto module_put; 254 goto module_put;
240 session->transport = transport; 255 session->transport = transport;
241 256
257 if (transport->sessiondata_size)
258 session->dd_data = &session[1];
259
242 /* this is released in the dev's release function */ 260 /* this is released in the dev's release function */
243 scsi_host_get(shost); 261 scsi_host_get(shost);
244 snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", shost->host_no); 262 session->sid = iscsi_session_nr++;
263 snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u",
264 session->sid);
245 session->dev.parent = &shost->shost_gendev; 265 session->dev.parent = &shost->shost_gendev;
246 session->dev.release = iscsi_session_release; 266 session->dev.release = iscsi_session_release;
247 err = device_register(&session->dev); 267 err = device_register(&session->dev);
@@ -301,12 +321,16 @@ static int iscsi_is_conn_dev(const struct device *dev)
301 * This can be called from a LLD or iscsi_transport. The connection 321 * This can be called from a LLD or iscsi_transport. The connection
302 * is child of the session so cid must be unique for all connections 322 * is child of the session so cid must be unique for all connections
303 * on the session. 323 * on the session.
324 *
325 * Since we do not support MCS, cid will normally be zero. In some cases
326 * for software iscsi we could be trying to preallocate a connection struct
327 * in which case there could be two connection structs and cid would be
328 * non-zero.
304 **/ 329 **/
305struct iscsi_cls_conn * 330struct iscsi_cls_conn *
306iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid) 331iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid)
307{ 332{
308 struct iscsi_transport *transport = session->transport; 333 struct iscsi_transport *transport = session->transport;
309 struct Scsi_Host *shost = iscsi_session_to_shost(session);
310 struct iscsi_cls_conn *conn; 334 struct iscsi_cls_conn *conn;
311 int err; 335 int err;
312 336
@@ -319,12 +343,14 @@ iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid)
319 343
320 INIT_LIST_HEAD(&conn->conn_list); 344 INIT_LIST_HEAD(&conn->conn_list);
321 conn->transport = transport; 345 conn->transport = transport;
346 conn->cid = cid;
322 347
323 /* this is released in the dev's release function */ 348 /* this is released in the dev's release function */
324 if (!get_device(&session->dev)) 349 if (!get_device(&session->dev))
325 goto free_conn; 350 goto free_conn;
351
326 snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u", 352 snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
327 shost->host_no, cid); 353 session->sid, cid);
328 conn->dev.parent = &session->dev; 354 conn->dev.parent = &session->dev;
329 conn->dev.release = iscsi_conn_release; 355 conn->dev.release = iscsi_conn_release;
330 err = device_register(&conn->dev); 356 err = device_register(&conn->dev);
@@ -607,7 +633,8 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
607 ev->type = ISCSI_KEVENT_RECV_PDU; 633 ev->type = ISCSI_KEVENT_RECV_PDU;
608 if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat) 634 if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
609 ev->iferror = -ENOMEM; 635 ev->iferror = -ENOMEM;
610 ev->r.recv_req.conn_handle = iscsi_handle(conn); 636 ev->r.recv_req.cid = conn->cid;
637 ev->r.recv_req.sid = iscsi_conn_get_sid(conn);
611 pdu = (char*)ev + sizeof(*ev); 638 pdu = (char*)ev + sizeof(*ev);
612 memcpy(pdu, hdr, sizeof(struct iscsi_hdr)); 639 memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
613 memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size); 640 memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
@@ -639,7 +666,8 @@ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
639 if (atomic_read(&conn->z_error->allocated) >= conn->z_error->hiwat) 666 if (atomic_read(&conn->z_error->allocated) >= conn->z_error->hiwat)
640 ev->iferror = -ENOMEM; 667 ev->iferror = -ENOMEM;
641 ev->r.connerror.error = error; 668 ev->r.connerror.error = error;
642 ev->r.connerror.conn_handle = iscsi_handle(conn); 669 ev->r.connerror.cid = conn->cid;
670 ev->r.connerror.sid = iscsi_conn_get_sid(conn);
643 671
644 iscsi_unicast_skb(conn->z_error, skb); 672 iscsi_unicast_skb(conn->z_error, skb);
645 673
@@ -689,7 +717,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
689 ISCSI_STATS_CUSTOM_MAX); 717 ISCSI_STATS_CUSTOM_MAX);
690 int err = 0; 718 int err = 0;
691 719
692 conn = iscsi_conn_lookup(ev->u.get_stats.conn_handle); 720 conn = iscsi_conn_lookup(ev->u.get_stats.sid, ev->u.get_stats.cid);
693 if (!conn) 721 if (!conn)
694 return -EEXIST; 722 return -EEXIST;
695 723
@@ -713,8 +741,10 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
713 evstat->type = nlh->nlmsg_type; 741 evstat->type = nlh->nlmsg_type;
714 if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat) 742 if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
715 evstat->iferror = -ENOMEM; 743 evstat->iferror = -ENOMEM;
716 evstat->u.get_stats.conn_handle = 744 evstat->u.get_stats.cid =
717 ev->u.get_stats.conn_handle; 745 ev->u.get_stats.cid;
746 evstat->u.get_stats.sid =
747 ev->u.get_stats.sid;
718 stats = (struct iscsi_stats *) 748 stats = (struct iscsi_stats *)
719 ((char*)evstat + sizeof(*evstat)); 749 ((char*)evstat + sizeof(*evstat));
720 memset(stats, 0, sizeof(*stats)); 750 memset(stats, 0, sizeof(*stats));
@@ -740,16 +770,16 @@ iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
740{ 770{
741 struct iscsi_transport *transport = priv->iscsi_transport; 771 struct iscsi_transport *transport = priv->iscsi_transport;
742 struct iscsi_cls_session *session; 772 struct iscsi_cls_session *session;
743 uint32_t sid; 773 uint32_t hostno;
744 774
745 session = transport->create_session(&priv->t, 775 session = transport->create_session(&priv->t,
746 ev->u.c_session.initial_cmdsn, 776 ev->u.c_session.initial_cmdsn,
747 &sid); 777 &hostno);
748 if (!session) 778 if (!session)
749 return -ENOMEM; 779 return -ENOMEM;
750 780
751 ev->r.c_session_ret.session_handle = iscsi_handle(session); 781 ev->r.c_session_ret.host_no = hostno;
752 ev->r.c_session_ret.sid = sid; 782 ev->r.c_session_ret.sid = session->sid;
753 return 0; 783 return 0;
754} 784}
755 785
@@ -760,13 +790,20 @@ iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
760 struct iscsi_cls_session *session; 790 struct iscsi_cls_session *session;
761 unsigned long flags; 791 unsigned long flags;
762 792
763 session = iscsi_session_lookup(ev->u.c_conn.session_handle); 793 session = iscsi_session_lookup(ev->u.c_conn.sid);
764 if (!session) 794 if (!session) {
795 printk(KERN_ERR "iscsi: invalid session %d\n",
796 ev->u.c_conn.sid);
765 return -EINVAL; 797 return -EINVAL;
798 }
766 799
767 conn = transport->create_conn(session, ev->u.c_conn.cid); 800 conn = transport->create_conn(session, ev->u.c_conn.cid);
768 if (!conn) 801 if (!conn) {
802 printk(KERN_ERR "iscsi: couldn't create a new "
803 "connection for session %d\n",
804 session->sid);
769 return -ENOMEM; 805 return -ENOMEM;
806 }
770 807
771 conn->z_pdu = mempool_zone_init(Z_MAX_PDU, 808 conn->z_pdu = mempool_zone_init(Z_MAX_PDU,
772 NLMSG_SPACE(sizeof(struct iscsi_uevent) + 809 NLMSG_SPACE(sizeof(struct iscsi_uevent) +
@@ -788,7 +825,8 @@ iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
788 goto free_pdu_pool; 825 goto free_pdu_pool;
789 } 826 }
790 827
791 ev->r.handle = iscsi_handle(conn); 828 ev->r.c_conn_ret.sid = session->sid;
829 ev->r.c_conn_ret.cid = conn->cid;
792 830
793 spin_lock_irqsave(&connlock, flags); 831 spin_lock_irqsave(&connlock, flags);
794 list_add(&conn->conn_list, &connlist); 832 list_add(&conn->conn_list, &connlist);
@@ -812,7 +850,7 @@ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev
812 struct iscsi_cls_conn *conn; 850 struct iscsi_cls_conn *conn;
813 struct mempool_zone *z_error, *z_pdu; 851 struct mempool_zone *z_error, *z_pdu;
814 852
815 conn = iscsi_conn_lookup(ev->u.d_conn.conn_handle); 853 conn = iscsi_conn_lookup(ev->u.d_conn.sid, ev->u.d_conn.cid);
816 if (!conn) 854 if (!conn)
817 return -EINVAL; 855 return -EINVAL;
818 spin_lock_irqsave(&connlock, flags); 856 spin_lock_irqsave(&connlock, flags);
@@ -855,7 +893,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
855 err = iscsi_if_create_session(priv, ev); 893 err = iscsi_if_create_session(priv, ev);
856 break; 894 break;
857 case ISCSI_UEVENT_DESTROY_SESSION: 895 case ISCSI_UEVENT_DESTROY_SESSION:
858 session = iscsi_session_lookup(ev->u.d_session.session_handle); 896 session = iscsi_session_lookup(ev->u.d_session.sid);
859 if (session) 897 if (session)
860 transport->destroy_session(session); 898 transport->destroy_session(session);
861 else 899 else
@@ -868,8 +906,8 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
868 err = iscsi_if_destroy_conn(transport, ev); 906 err = iscsi_if_destroy_conn(transport, ev);
869 break; 907 break;
870 case ISCSI_UEVENT_BIND_CONN: 908 case ISCSI_UEVENT_BIND_CONN:
871 session = iscsi_session_lookup(ev->u.b_conn.session_handle); 909 session = iscsi_session_lookup(ev->u.b_conn.sid);
872 conn = iscsi_conn_lookup(ev->u.b_conn.conn_handle); 910 conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid);
873 911
874 if (session && conn) 912 if (session && conn)
875 ev->r.retcode = transport->bind_conn(session, conn, 913 ev->r.retcode = transport->bind_conn(session, conn,
@@ -879,7 +917,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
879 err = -EINVAL; 917 err = -EINVAL;
880 break; 918 break;
881 case ISCSI_UEVENT_SET_PARAM: 919 case ISCSI_UEVENT_SET_PARAM:
882 conn = iscsi_conn_lookup(ev->u.set_param.conn_handle); 920 conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid);
883 if (conn) 921 if (conn)
884 ev->r.retcode = transport->set_param(conn, 922 ev->r.retcode = transport->set_param(conn,
885 ev->u.set_param.param, ev->u.set_param.value); 923 ev->u.set_param.param, ev->u.set_param.value);
@@ -887,7 +925,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
887 err = -EINVAL; 925 err = -EINVAL;
888 break; 926 break;
889 case ISCSI_UEVENT_START_CONN: 927 case ISCSI_UEVENT_START_CONN:
890 conn = iscsi_conn_lookup(ev->u.start_conn.conn_handle); 928 conn = iscsi_conn_lookup(ev->u.start_conn.sid, ev->u.start_conn.cid);
891 if (conn) 929 if (conn)
892 ev->r.retcode = transport->start_conn(conn); 930 ev->r.retcode = transport->start_conn(conn);
893 else 931 else
@@ -895,14 +933,14 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
895 933
896 break; 934 break;
897 case ISCSI_UEVENT_STOP_CONN: 935 case ISCSI_UEVENT_STOP_CONN:
898 conn = iscsi_conn_lookup(ev->u.stop_conn.conn_handle); 936 conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ev->u.stop_conn.cid);
899 if (conn) 937 if (conn)
900 transport->stop_conn(conn, ev->u.stop_conn.flag); 938 transport->stop_conn(conn, ev->u.stop_conn.flag);
901 else 939 else
902 err = -EINVAL; 940 err = -EINVAL;
903 break; 941 break;
904 case ISCSI_UEVENT_SEND_PDU: 942 case ISCSI_UEVENT_SEND_PDU:
905 conn = iscsi_conn_lookup(ev->u.send_pdu.conn_handle); 943 conn = iscsi_conn_lookup(ev->u.send_pdu.sid, ev->u.send_pdu.cid);
906 if (conn) 944 if (conn)
907 ev->r.retcode = transport->send_pdu(conn, 945 ev->r.retcode = transport->send_pdu(conn,
908 (struct iscsi_hdr*)((char*)ev + sizeof(*ev)), 946 (struct iscsi_hdr*)((char*)ev + sizeof(*ev)),
@@ -923,9 +961,11 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
923 return err; 961 return err;
924} 962}
925 963
926/* Get message from skb (based on rtnetlink_rcv_skb). Each message is 964/*
927 * processed by iscsi_if_recv_msg. Malformed skbs with wrong length are 965 * Get message from skb (based on rtnetlink_rcv_skb). Each message is
928 * or invalid creds discarded silently. */ 966 * processed by iscsi_if_recv_msg. Malformed skbs with wrong lengths or
967 * invalid creds are discarded silently.
968 */
929static void 969static void
930iscsi_if_rx(struct sock *sk, int len) 970iscsi_if_rx(struct sock *sk, int len)
931{ 971{