aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2006-02-01 22:06:49 -0500
committer <jejb@mulgrave.il.steeleye.com>2006-02-04 17:17:03 -0500
commit7b7232f3fb5ecd7c30cb52df368070cc5f5ca614 (patch)
treec7430280a69e587575bba336259e11a7aec8674e /drivers/scsi
parentbb08f92ebd75704e07d69bb9d8ee234d1a500b98 (diff)
[SCSI] iscsi update: cleanup iscsi class interface
From: michaelc@cs.wisc.edu fujita.tomonori@lab.ntt.co.jp da-x@monatomic.org and err path fixup from: ogerlitz@voltaire.com This patch cleans up that interface by having the lld and class pass a iscsi_cls_session or iscsi_cls_conn between each other when the function is used by HW and SW iscsi llds. This way the lld does not have to remember if it has to send a handle or pointer and a handle or pointer to connection, session or host. This also has the class verify the session handle that gets passed from userspace instead of using the pointer passed into the kernel directly. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: Alex Aizman <itn780@yahoo.com> Signed-off-by: Dmitry Yusupov <dmitry_yus@yahoo.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/iscsi_tcp.c70
-rw-r--r--drivers/scsi/iscsi_tcp.h3
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c221
3 files changed, 154 insertions, 140 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 780bfcc67096..d07d309ac026 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -146,7 +146,7 @@ iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
146 spin_unlock_irqrestore(&session->lock, flags); 146 spin_unlock_irqrestore(&session->lock, flags);
147 set_bit(SUSPEND_BIT, &conn->suspend_tx); 147 set_bit(SUSPEND_BIT, &conn->suspend_tx);
148 set_bit(SUSPEND_BIT, &conn->suspend_rx); 148 set_bit(SUSPEND_BIT, &conn->suspend_rx);
149 iscsi_conn_error(iscsi_handle(conn), err); 149 iscsi_conn_error(conn->cls_conn, err);
150} 150}
151 151
152static inline int 152static inline int
@@ -689,7 +689,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
689 break; 689 break;
690 690
691 if (!conn->in.datalen) { 691 if (!conn->in.datalen) {
692 rc = iscsi_recv_pdu(iscsi_handle(conn), hdr, 692 rc = iscsi_recv_pdu(conn->cls_conn, hdr,
693 NULL, 0); 693 NULL, 0);
694 if (conn->login_mtask != mtask) { 694 if (conn->login_mtask != mtask) {
695 spin_lock(&session->lock); 695 spin_lock(&session->lock);
@@ -737,7 +737,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
737 if (!conn->in.datalen) { 737 if (!conn->in.datalen) {
738 struct iscsi_mgmt_task *mtask; 738 struct iscsi_mgmt_task *mtask;
739 739
740 rc = iscsi_recv_pdu(iscsi_handle(conn), hdr, 740 rc = iscsi_recv_pdu(conn->cls_conn, hdr,
741 NULL, 0); 741 NULL, 0);
742 mtask = (struct iscsi_mgmt_task *) 742 mtask = (struct iscsi_mgmt_task *)
743 session->mgmt_cmds[conn->in.itt - 743 session->mgmt_cmds[conn->in.itt -
@@ -761,7 +761,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
761 rc = iscsi_check_assign_cmdsn(session, 761 rc = iscsi_check_assign_cmdsn(session,
762 (struct iscsi_nopin*)hdr); 762 (struct iscsi_nopin*)hdr);
763 if (!rc && hdr->ttt != ISCSI_RESERVED_TAG) 763 if (!rc && hdr->ttt != ISCSI_RESERVED_TAG)
764 rc = iscsi_recv_pdu(iscsi_handle(conn), 764 rc = iscsi_recv_pdu(conn->cls_conn,
765 hdr, NULL, 0); 765 hdr, NULL, 0);
766 } else 766 } else
767 rc = ISCSI_ERR_PROTO; 767 rc = ISCSI_ERR_PROTO;
@@ -1044,7 +1044,7 @@ iscsi_data_recv(struct iscsi_conn *conn)
1044 goto exit; 1044 goto exit;
1045 } 1045 }
1046 1046
1047 rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr, 1047 rc = iscsi_recv_pdu(conn->cls_conn, conn->in.hdr,
1048 conn->data, conn->in.datalen); 1048 conn->data, conn->in.datalen);
1049 1049
1050 if (!rc && conn->datadgst_en && 1050 if (!rc && conn->datadgst_en &&
@@ -2428,19 +2428,20 @@ iscsi_pool_free(struct iscsi_queue *q, void **items)
2428} 2428}
2429 2429
2430static struct iscsi_cls_conn * 2430static struct iscsi_cls_conn *
2431iscsi_conn_create(struct Scsi_Host *shost, uint32_t conn_idx) 2431iscsi_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
2432{ 2432{
2433 struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
2433 struct iscsi_session *session = iscsi_hostdata(shost->hostdata); 2434 struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
2434 struct iscsi_conn *conn; 2435 struct iscsi_conn *conn;
2435 struct iscsi_cls_conn *cls_conn; 2436 struct iscsi_cls_conn *cls_conn;
2436 2437
2437 cls_conn = iscsi_create_conn(hostdata_session(shost->hostdata), 2438 cls_conn = iscsi_create_conn(cls_session, conn_idx);
2438 conn_idx);
2439 if (!cls_conn) 2439 if (!cls_conn)
2440 return NULL; 2440 return NULL;
2441 conn = cls_conn->dd_data; 2441 conn = cls_conn->dd_data;
2442 memset(conn, 0, sizeof(*conn));
2442 2443
2443 memset(conn, 0, sizeof(struct iscsi_conn)); 2444 conn->cls_conn = cls_conn;
2444 conn->c_stage = ISCSI_CONN_INITIAL_STAGE; 2445 conn->c_stage = ISCSI_CONN_INITIAL_STAGE;
2445 conn->in_progress = IN_PROGRESS_WAIT_HEADER; 2446 conn->in_progress = IN_PROGRESS_WAIT_HEADER;
2446 conn->id = conn_idx; 2447 conn->id = conn_idx;
@@ -2625,11 +2626,13 @@ iscsi_conn_destroy(struct iscsi_cls_conn *cls_conn)
2625} 2626}
2626 2627
2627static int 2628static int
2628iscsi_conn_bind(iscsi_sessionh_t sessionh, iscsi_connh_t connh, 2629iscsi_conn_bind(struct iscsi_cls_session *cls_session,
2629 uint32_t transport_fd, int is_leading) 2630 struct iscsi_cls_conn *cls_conn, uint32_t transport_fd,
2631 int is_leading)
2630{ 2632{
2631 struct iscsi_session *session = iscsi_ptr(sessionh); 2633 struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
2632 struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = iscsi_ptr(connh); 2634 struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
2635 struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = cls_conn->dd_data;
2633 struct sock *sk; 2636 struct sock *sk;
2634 struct socket *sock; 2637 struct socket *sock;
2635 int err; 2638 int err;
@@ -2703,9 +2706,9 @@ iscsi_conn_bind(iscsi_sessionh_t sessionh, iscsi_connh_t connh,
2703} 2706}
2704 2707
2705static int 2708static int
2706iscsi_conn_start(iscsi_connh_t connh) 2709iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
2707{ 2710{
2708 struct iscsi_conn *conn = iscsi_ptr(connh); 2711 struct iscsi_conn *conn = cls_conn->dd_data;
2709 struct iscsi_session *session = conn->session; 2712 struct iscsi_session *session = conn->session;
2710 struct sock *sk; 2713 struct sock *sk;
2711 2714
@@ -2754,9 +2757,9 @@ iscsi_conn_start(iscsi_connh_t connh)
2754} 2757}
2755 2758
2756static void 2759static void
2757iscsi_conn_stop(iscsi_connh_t connh, int flag) 2760iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
2758{ 2761{
2759 struct iscsi_conn *conn = iscsi_ptr(connh); 2762 struct iscsi_conn *conn = cls_conn->dd_data;
2760 struct iscsi_session *session = conn->session; 2763 struct iscsi_session *session = conn->session;
2761 struct sock *sk; 2764 struct sock *sk;
2762 unsigned long flags; 2765 unsigned long flags;
@@ -3253,9 +3256,9 @@ static struct scsi_host_template iscsi_sht = {
3253 3256
3254static struct iscsi_transport iscsi_tcp_transport; 3257static struct iscsi_transport iscsi_tcp_transport;
3255 3258
3256static struct Scsi_Host * 3259static struct iscsi_cls_session *
3257iscsi_session_create(struct scsi_transport_template *scsit, 3260iscsi_session_create(struct scsi_transport_template *scsit,
3258 uint32_t initial_cmdsn) 3261 uint32_t initial_cmdsn, uint32_t *sid)
3259{ 3262{
3260 struct Scsi_Host *shost; 3263 struct Scsi_Host *shost;
3261 struct iscsi_session *session; 3264 struct iscsi_session *session;
@@ -3275,6 +3278,7 @@ iscsi_session_create(struct scsi_transport_template *scsit,
3275 session->exp_cmdsn = initial_cmdsn + 1; 3278 session->exp_cmdsn = initial_cmdsn + 1;
3276 session->max_cmdsn = initial_cmdsn + 1; 3279 session->max_cmdsn = initial_cmdsn + 1;
3277 session->max_r2t = 1; 3280 session->max_r2t = 1;
3281 *sid = shost->host_no;
3278 3282
3279 /* initialize SCSI PDU commands pool */ 3283 /* initialize SCSI PDU commands pool */
3280 if (iscsi_pool_init(&session->cmdpool, session->cmds_max, 3284 if (iscsi_pool_init(&session->cmdpool, session->cmds_max,
@@ -3311,7 +3315,7 @@ iscsi_session_create(struct scsi_transport_template *scsit,
3311 if (iscsi_r2tpool_alloc(session)) 3315 if (iscsi_r2tpool_alloc(session))
3312 goto r2tpool_alloc_fail; 3316 goto r2tpool_alloc_fail;
3313 3317
3314 return shost; 3318 return hostdata_session(shost->hostdata);
3315 3319
3316r2tpool_alloc_fail: 3320r2tpool_alloc_fail:
3317 for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) 3321 for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++)
@@ -3321,12 +3325,14 @@ immdata_alloc_fail:
3321mgmtpool_alloc_fail: 3325mgmtpool_alloc_fail:
3322 iscsi_pool_free(&session->cmdpool, (void**)session->cmds); 3326 iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
3323cmdpool_alloc_fail: 3327cmdpool_alloc_fail:
3328 iscsi_transport_destroy_session(shost);
3324 return NULL; 3329 return NULL;
3325} 3330}
3326 3331
3327static void 3332static void
3328iscsi_session_destroy(struct Scsi_Host *shost) 3333iscsi_session_destroy(struct iscsi_cls_session *cls_session)
3329{ 3334{
3335 struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
3330 struct iscsi_session *session = iscsi_hostdata(shost->hostdata); 3336 struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
3331 int cmd_i; 3337 int cmd_i;
3332 struct iscsi_data_task *dtask, *n; 3338 struct iscsi_data_task *dtask, *n;
@@ -3350,10 +3356,10 @@ iscsi_session_destroy(struct Scsi_Host *shost)
3350} 3356}
3351 3357
3352static int 3358static int
3353iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param, 3359iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
3354 uint32_t value) 3360 uint32_t value)
3355{ 3361{
3356 struct iscsi_conn *conn = iscsi_ptr(connh); 3362 struct iscsi_conn *conn = cls_conn->dd_data;
3357 struct iscsi_session *session = conn->session; 3363 struct iscsi_session *session = conn->session;
3358 3364
3359 spin_lock_bh(&session->lock); 3365 spin_lock_bh(&session->lock);
@@ -3495,9 +3501,10 @@ iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param,
3495} 3501}
3496 3502
3497static int 3503static int
3498iscsi_session_get_param(struct Scsi_Host *shost, 3504iscsi_session_get_param(struct iscsi_cls_session *cls_session,
3499 enum iscsi_param param, uint32_t *value) 3505 enum iscsi_param param, uint32_t *value)
3500{ 3506{
3507 struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
3501 struct iscsi_session *session = iscsi_hostdata(shost->hostdata); 3508 struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
3502 3509
3503 switch(param) { 3510 switch(param) {
@@ -3539,9 +3546,10 @@ iscsi_session_get_param(struct Scsi_Host *shost,
3539} 3546}
3540 3547
3541static int 3548static int
3542iscsi_conn_get_param(void *data, enum iscsi_param param, uint32_t *value) 3549iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
3550 enum iscsi_param param, uint32_t *value)
3543{ 3551{
3544 struct iscsi_conn *conn = data; 3552 struct iscsi_conn *conn = cls_conn->dd_data;
3545 3553
3546 switch(param) { 3554 switch(param) {
3547 case ISCSI_PARAM_MAX_RECV_DLENGTH: 3555 case ISCSI_PARAM_MAX_RECV_DLENGTH:
@@ -3564,9 +3572,9 @@ iscsi_conn_get_param(void *data, enum iscsi_param param, uint32_t *value)
3564} 3572}
3565 3573
3566static void 3574static void
3567iscsi_conn_get_stats(iscsi_connh_t connh, struct iscsi_stats *stats) 3575iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats)
3568{ 3576{
3569 struct iscsi_conn *conn = iscsi_ptr(connh); 3577 struct iscsi_conn *conn = cls_conn->dd_data;
3570 3578
3571 stats->txdata_octets = conn->txdata_octets; 3579 stats->txdata_octets = conn->txdata_octets;
3572 stats->rxdata_octets = conn->rxdata_octets; 3580 stats->rxdata_octets = conn->rxdata_octets;
@@ -3587,10 +3595,10 @@ iscsi_conn_get_stats(iscsi_connh_t connh, struct iscsi_stats *stats)
3587} 3595}
3588 3596
3589static int 3597static int
3590iscsi_conn_send_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr, char *data, 3598iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
3591 uint32_t data_size) 3599 char *data, uint32_t data_size)
3592{ 3600{
3593 struct iscsi_conn *conn = iscsi_ptr(connh); 3601 struct iscsi_conn *conn = cls_conn->dd_data;
3594 int rc; 3602 int rc;
3595 3603
3596 mutex_lock(&conn->xmitmutex); 3604 mutex_lock(&conn->xmitmutex);
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
index f95e61b76f70..6766b817db2d 100644
--- a/drivers/scsi/iscsi_tcp.h
+++ b/drivers/scsi/iscsi_tcp.h
@@ -113,7 +113,10 @@ struct iscsi_tcp_recv {
113 int datadgst; 113 int datadgst;
114}; 114};
115 115
116struct iscsi_cls_conn;
117
116struct iscsi_conn { 118struct iscsi_conn {
119 struct iscsi_cls_conn *cls_conn; /* ptr to class connection */
117 struct iscsi_hdr hdr; /* header placeholder */ 120 struct iscsi_hdr hdr; /* header placeholder */
118 char hdrext[4*sizeof(__u16) + 121 char hdrext[4*sizeof(__u16) +
119 sizeof(__u32)]; 122 sizeof(__u32)];
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 59a1c9d9d3bd..b61868587dca 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -164,9 +164,43 @@ static struct mempool_zone *z_reply;
164#define Z_MAX_ERROR 16 164#define Z_MAX_ERROR 16
165#define Z_HIWAT_ERROR 12 165#define Z_HIWAT_ERROR 12
166 166
167static LIST_HEAD(sesslist);
168static DEFINE_SPINLOCK(sesslock);
167static LIST_HEAD(connlist); 169static LIST_HEAD(connlist);
168static DEFINE_SPINLOCK(connlock); 170static DEFINE_SPINLOCK(connlock);
169 171
172static struct iscsi_cls_session *iscsi_session_lookup(uint64_t handle)
173{
174 unsigned long flags;
175 struct iscsi_cls_session *sess;
176
177 spin_lock_irqsave(&sesslock, flags);
178 list_for_each_entry(sess, &sesslist, sess_list) {
179 if (sess == iscsi_ptr(handle)) {
180 spin_unlock_irqrestore(&sesslock, flags);
181 return sess;
182 }
183 }
184 spin_unlock_irqrestore(&sesslock, flags);
185 return NULL;
186}
187
188static struct iscsi_cls_conn *iscsi_conn_lookup(uint64_t handle)
189{
190 unsigned long flags;
191 struct iscsi_cls_conn *conn;
192
193 spin_lock_irqsave(&connlock, flags);
194 list_for_each_entry(conn, &connlist, conn_list) {
195 if (conn == iscsi_ptr(handle)) {
196 spin_unlock_irqrestore(&connlock, flags);
197 return conn;
198 }
199 }
200 spin_unlock_irqrestore(&connlock, flags);
201 return NULL;
202}
203
170/* 204/*
171 * The following functions can be used by LLDs that allocate 205 * The following functions can be used by LLDs that allocate
172 * their own scsi_hosts or by software iscsi LLDs 206 * their own scsi_hosts or by software iscsi LLDs
@@ -365,6 +399,7 @@ iscsi_transport_create_session(struct scsi_transport_template *scsit,
365{ 399{
366 struct iscsi_cls_session *session; 400 struct iscsi_cls_session *session;
367 struct Scsi_Host *shost; 401 struct Scsi_Host *shost;
402 unsigned long flags;
368 403
369 shost = scsi_host_alloc(transport->host_template, 404 shost = scsi_host_alloc(transport->host_template,
370 hostdata_privsize(transport)); 405 hostdata_privsize(transport));
@@ -389,6 +424,9 @@ iscsi_transport_create_session(struct scsi_transport_template *scsit,
389 goto remove_host; 424 goto remove_host;
390 425
391 *(unsigned long*)shost->hostdata = (unsigned long)session; 426 *(unsigned long*)shost->hostdata = (unsigned long)session;
427 spin_lock_irqsave(&sesslock, flags);
428 list_add(&session->sess_list, &sesslist);
429 spin_unlock_irqrestore(&sesslock, flags);
392 return shost; 430 return shost;
393 431
394remove_host: 432remove_host:
@@ -410,9 +448,13 @@ EXPORT_SYMBOL_GPL(iscsi_transport_create_session);
410int iscsi_transport_destroy_session(struct Scsi_Host *shost) 448int iscsi_transport_destroy_session(struct Scsi_Host *shost)
411{ 449{
412 struct iscsi_cls_session *session; 450 struct iscsi_cls_session *session;
451 unsigned long flags;
413 452
414 scsi_remove_host(shost); 453 scsi_remove_host(shost);
415 session = hostdata_session(shost->hostdata); 454 session = hostdata_session(shost->hostdata);
455 spin_lock_irqsave(&sesslock, flags);
456 list_del(&session->sess_list);
457 spin_unlock_irqrestore(&sesslock, flags);
416 iscsi_destroy_session(session); 458 iscsi_destroy_session(session);
417 /* ref from host alloc */ 459 /* ref from host alloc */
418 scsi_host_put(shost); 460 scsi_host_put(shost);
@@ -424,22 +466,6 @@ EXPORT_SYMBOL_GPL(iscsi_transport_destroy_session);
424/* 466/*
425 * iscsi interface functions 467 * iscsi interface functions
426 */ 468 */
427static struct iscsi_cls_conn*
428iscsi_if_find_conn(uint64_t key)
429{
430 unsigned long flags;
431 struct iscsi_cls_conn *conn;
432
433 spin_lock_irqsave(&connlock, flags);
434 list_for_each_entry(conn, &connlist, conn_list)
435 if (conn->connh == key) {
436 spin_unlock_irqrestore(&connlock, flags);
437 return conn;
438 }
439 spin_unlock_irqrestore(&connlock, flags);
440 return NULL;
441}
442
443static struct iscsi_internal * 469static struct iscsi_internal *
444iscsi_if_transport_lookup(struct iscsi_transport *tt) 470iscsi_if_transport_lookup(struct iscsi_transport *tt)
445{ 471{
@@ -559,25 +585,21 @@ iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb)
559 return 0; 585 return 0;
560} 586}
561 587
562int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr, 588int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
563 char *data, uint32_t data_size) 589 char *data, uint32_t data_size)
564{ 590{
565 struct nlmsghdr *nlh; 591 struct nlmsghdr *nlh;
566 struct sk_buff *skb; 592 struct sk_buff *skb;
567 struct iscsi_uevent *ev; 593 struct iscsi_uevent *ev;
568 struct iscsi_cls_conn *conn;
569 char *pdu; 594 char *pdu;
570 int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) + 595 int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) +
571 data_size); 596 data_size);
572 597
573 conn = iscsi_if_find_conn(connh);
574 BUG_ON(!conn);
575
576 mempool_zone_complete(conn->z_pdu); 598 mempool_zone_complete(conn->z_pdu);
577 599
578 skb = mempool_zone_get_skb(conn->z_pdu); 600 skb = mempool_zone_get_skb(conn->z_pdu);
579 if (!skb) { 601 if (!skb) {
580 iscsi_conn_error(connh, ISCSI_ERR_CONN_FAILED); 602 iscsi_conn_error(conn, ISCSI_ERR_CONN_FAILED);
581 dev_printk(KERN_ERR, &conn->dev, "iscsi: can not deliver " 603 dev_printk(KERN_ERR, &conn->dev, "iscsi: can not deliver "
582 "control PDU: OOM\n"); 604 "control PDU: OOM\n");
583 return -ENOMEM; 605 return -ENOMEM;
@@ -590,7 +612,7 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
590 ev->type = ISCSI_KEVENT_RECV_PDU; 612 ev->type = ISCSI_KEVENT_RECV_PDU;
591 if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat) 613 if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
592 ev->iferror = -ENOMEM; 614 ev->iferror = -ENOMEM;
593 ev->r.recv_req.conn_handle = connh; 615 ev->r.recv_req.conn_handle = iscsi_handle(conn);
594 pdu = (char*)ev + sizeof(*ev); 616 pdu = (char*)ev + sizeof(*ev);
595 memcpy(pdu, hdr, sizeof(struct iscsi_hdr)); 617 memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
596 memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size); 618 memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
@@ -599,17 +621,13 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
599} 621}
600EXPORT_SYMBOL_GPL(iscsi_recv_pdu); 622EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
601 623
602void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error) 624void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
603{ 625{
604 struct nlmsghdr *nlh; 626 struct nlmsghdr *nlh;
605 struct sk_buff *skb; 627 struct sk_buff *skb;
606 struct iscsi_uevent *ev; 628 struct iscsi_uevent *ev;
607 struct iscsi_cls_conn *conn;
608 int len = NLMSG_SPACE(sizeof(*ev)); 629 int len = NLMSG_SPACE(sizeof(*ev));
609 630
610 conn = iscsi_if_find_conn(connh);
611 BUG_ON(!conn);
612
613 mempool_zone_complete(conn->z_error); 631 mempool_zone_complete(conn->z_error);
614 632
615 skb = mempool_zone_get_skb(conn->z_error); 633 skb = mempool_zone_get_skb(conn->z_error);
@@ -626,7 +644,7 @@ void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error)
626 if (atomic_read(&conn->z_error->allocated) >= conn->z_error->hiwat) 644 if (atomic_read(&conn->z_error->allocated) >= conn->z_error->hiwat)
627 ev->iferror = -ENOMEM; 645 ev->iferror = -ENOMEM;
628 ev->r.connerror.error = error; 646 ev->r.connerror.error = error;
629 ev->r.connerror.conn_handle = connh; 647 ev->r.connerror.conn_handle = iscsi_handle(conn);
630 648
631 iscsi_unicast_skb(conn->z_error, skb); 649 iscsi_unicast_skb(conn->z_error, skb);
632 650
@@ -677,7 +695,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
677 ISCSI_STATS_CUSTOM_MAX); 695 ISCSI_STATS_CUSTOM_MAX);
678 int err = 0; 696 int err = 0;
679 697
680 conn = iscsi_if_find_conn(ev->u.get_stats.conn_handle); 698 conn = iscsi_conn_lookup(ev->u.get_stats.conn_handle);
681 if (!conn) 699 if (!conn)
682 return -EEXIST; 700 return -EEXIST;
683 701
@@ -707,7 +725,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
707 ((char*)evstat + sizeof(*evstat)); 725 ((char*)evstat + sizeof(*evstat));
708 memset(stats, 0, sizeof(*stats)); 726 memset(stats, 0, sizeof(*stats));
709 727
710 transport->get_stats(ev->u.get_stats.conn_handle, stats); 728 transport->get_stats(conn, stats);
711 actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) + 729 actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) +
712 sizeof(struct iscsi_stats) + 730 sizeof(struct iscsi_stats) +
713 sizeof(struct iscsi_stats_custom) * 731 sizeof(struct iscsi_stats_custom) *
@@ -727,58 +745,34 @@ static int
727iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev) 745iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
728{ 746{
729 struct iscsi_transport *transport = priv->iscsi_transport; 747 struct iscsi_transport *transport = priv->iscsi_transport;
730 struct Scsi_Host *shost; 748 struct iscsi_cls_session *session;
731 749 uint32_t sid;
732 if (!transport->create_session)
733 return -EINVAL;
734 750
735 shost = transport->create_session(&priv->t, 751 session = transport->create_session(&priv->t,
736 ev->u.c_session.initial_cmdsn); 752 ev->u.c_session.initial_cmdsn,
737 if (!shost) 753 &sid);
754 if (!session)
738 return -ENOMEM; 755 return -ENOMEM;
739 756
740 ev->r.c_session_ret.session_handle = iscsi_handle(iscsi_hostdata(shost->hostdata)); 757 ev->r.c_session_ret.session_handle = iscsi_handle(session);
741 ev->r.c_session_ret.sid = shost->host_no; 758 ev->r.c_session_ret.sid = sid;
742 return 0; 759 return 0;
743} 760}
744 761
745static int 762static int
746iscsi_if_destroy_session(struct iscsi_internal *priv, struct iscsi_uevent *ev) 763iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
747{ 764{
748 struct iscsi_transport *transport = priv->iscsi_transport;
749
750 struct Scsi_Host *shost;
751
752 if (!transport->destroy_session)
753 return -EINVAL;
754
755 shost = scsi_host_lookup(ev->u.d_session.sid);
756 if (shost == ERR_PTR(-ENXIO))
757 return -EEXIST;
758
759 if (transport->destroy_session)
760 transport->destroy_session(shost);
761 /* ref from host lookup */
762 scsi_host_put(shost);
763 return 0;
764}
765
766static int
767iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev){
768 struct Scsi_Host *shost;
769 struct iscsi_cls_conn *conn; 765 struct iscsi_cls_conn *conn;
766 struct iscsi_cls_session *session;
770 unsigned long flags; 767 unsigned long flags;
771 768
772 if (!transport->create_conn) 769 session = iscsi_session_lookup(ev->u.c_conn.session_handle);
770 if (!session)
773 return -EINVAL; 771 return -EINVAL;
774 772
775 shost = scsi_host_lookup(ev->u.c_conn.sid); 773 conn = transport->create_conn(session, ev->u.c_conn.cid);
776 if (shost == ERR_PTR(-ENXIO))
777 return -EEXIST;
778
779 conn = transport->create_conn(shost, ev->u.c_conn.cid);
780 if (!conn) 774 if (!conn)
781 goto release_ref; 775 return -ENOMEM;
782 776
783 conn->z_pdu = mempool_zone_init(Z_MAX_PDU, 777 conn->z_pdu = mempool_zone_init(Z_MAX_PDU,
784 NLMSG_SPACE(sizeof(struct iscsi_uevent) + 778 NLMSG_SPACE(sizeof(struct iscsi_uevent) +
@@ -800,14 +794,13 @@ iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
800 goto free_pdu_pool; 794 goto free_pdu_pool;
801 } 795 }
802 796
803 ev->r.handle = conn->connh = iscsi_handle(conn->dd_data); 797 ev->r.handle = iscsi_handle(conn);
804 798
805 spin_lock_irqsave(&connlock, flags); 799 spin_lock_irqsave(&connlock, flags);
806 list_add(&conn->conn_list, &connlist); 800 list_add(&conn->conn_list, &connlist);
807 conn->active = 1; 801 conn->active = 1;
808 spin_unlock_irqrestore(&connlock, flags); 802 spin_unlock_irqrestore(&connlock, flags);
809 803
810 scsi_host_put(shost);
811 return 0; 804 return 0;
812 805
813free_pdu_pool: 806free_pdu_pool:
@@ -815,8 +808,6 @@ free_pdu_pool:
815destroy_conn: 808destroy_conn:
816 if (transport->destroy_conn) 809 if (transport->destroy_conn)
817 transport->destroy_conn(conn->dd_data); 810 transport->destroy_conn(conn->dd_data);
818release_ref:
819 scsi_host_put(shost);
820 return -ENOMEM; 811 return -ENOMEM;
821} 812}
822 813
@@ -827,13 +818,9 @@ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev
827 struct iscsi_cls_conn *conn; 818 struct iscsi_cls_conn *conn;
828 struct mempool_zone *z_error, *z_pdu; 819 struct mempool_zone *z_error, *z_pdu;
829 820
830 conn = iscsi_if_find_conn(ev->u.d_conn.conn_handle); 821 conn = iscsi_conn_lookup(ev->u.d_conn.conn_handle);
831 if (!conn) 822 if (!conn)
832 return -EEXIST;
833
834 if (!transport->destroy_conn)
835 return -EINVAL; 823 return -EINVAL;
836
837 spin_lock_irqsave(&connlock, flags); 824 spin_lock_irqsave(&connlock, flags);
838 conn->active = 0; 825 conn->active = 0;
839 list_del(&conn->conn_list); 826 list_del(&conn->conn_list);
@@ -858,6 +845,8 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
858 struct iscsi_uevent *ev = NLMSG_DATA(nlh); 845 struct iscsi_uevent *ev = NLMSG_DATA(nlh);
859 struct iscsi_transport *transport = NULL; 846 struct iscsi_transport *transport = NULL;
860 struct iscsi_internal *priv; 847 struct iscsi_internal *priv;
848 struct iscsi_cls_session *session;
849 struct iscsi_cls_conn *conn;
861 850
862 if (NETLINK_CREDS(skb)->uid) 851 if (NETLINK_CREDS(skb)->uid)
863 return -EPERM; 852 return -EPERM;
@@ -867,6 +856,9 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
867 return -EINVAL; 856 return -EINVAL;
868 transport = priv->iscsi_transport; 857 transport = priv->iscsi_transport;
869 858
859 if (!try_module_get(transport->owner))
860 return -EINVAL;
861
870 daemon_pid = NETLINK_CREDS(skb)->pid; 862 daemon_pid = NETLINK_CREDS(skb)->pid;
871 863
872 switch (nlh->nlmsg_type) { 864 switch (nlh->nlmsg_type) {
@@ -874,7 +866,11 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
874 err = iscsi_if_create_session(priv, ev); 866 err = iscsi_if_create_session(priv, ev);
875 break; 867 break;
876 case ISCSI_UEVENT_DESTROY_SESSION: 868 case ISCSI_UEVENT_DESTROY_SESSION:
877 err = iscsi_if_destroy_session(priv, ev); 869 session = iscsi_session_lookup(ev->u.d_session.session_handle);
870 if (session)
871 transport->destroy_session(session);
872 else
873 err = -EINVAL;
878 break; 874 break;
879 case ISCSI_UEVENT_CREATE_CONN: 875 case ISCSI_UEVENT_CREATE_CONN:
880 err = iscsi_if_create_conn(transport, ev); 876 err = iscsi_if_create_conn(transport, ev);
@@ -883,41 +879,48 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
883 err = iscsi_if_destroy_conn(transport, ev); 879 err = iscsi_if_destroy_conn(transport, ev);
884 break; 880 break;
885 case ISCSI_UEVENT_BIND_CONN: 881 case ISCSI_UEVENT_BIND_CONN:
886 if (!iscsi_if_find_conn(ev->u.b_conn.conn_handle)) 882 session = iscsi_session_lookup(ev->u.b_conn.session_handle);
887 return -EEXIST; 883 conn = iscsi_conn_lookup(ev->u.b_conn.conn_handle);
888 ev->r.retcode = transport->bind_conn( 884
889 ev->u.b_conn.session_handle, 885 if (session && conn)
890 ev->u.b_conn.conn_handle, 886 ev->r.retcode = transport->bind_conn(session, conn,
891 ev->u.b_conn.transport_fd, 887 ev->u.b_conn.transport_fd,
892 ev->u.b_conn.is_leading); 888 ev->u.b_conn.is_leading);
889 else
890 err = -EINVAL;
893 break; 891 break;
894 case ISCSI_UEVENT_SET_PARAM: 892 case ISCSI_UEVENT_SET_PARAM:
895 if (!iscsi_if_find_conn(ev->u.set_param.conn_handle)) 893 conn = iscsi_conn_lookup(ev->u.set_param.conn_handle);
896 return -EEXIST; 894 if (conn)
897 ev->r.retcode = transport->set_param( 895 ev->r.retcode = transport->set_param(conn,
898 ev->u.set_param.conn_handle, 896 ev->u.set_param.param, ev->u.set_param.value);
899 ev->u.set_param.param, ev->u.set_param.value); 897 else
898 err = -EINVAL;
900 break; 899 break;
901 case ISCSI_UEVENT_START_CONN: 900 case ISCSI_UEVENT_START_CONN:
902 if (!iscsi_if_find_conn(ev->u.start_conn.conn_handle)) 901 conn = iscsi_conn_lookup(ev->u.start_conn.conn_handle);
903 return -EEXIST; 902 if (conn)
904 ev->r.retcode = transport->start_conn( 903 ev->r.retcode = transport->start_conn(conn);
905 ev->u.start_conn.conn_handle); 904 else
905 err = -EINVAL;
906
906 break; 907 break;
907 case ISCSI_UEVENT_STOP_CONN: 908 case ISCSI_UEVENT_STOP_CONN:
908 if (!iscsi_if_find_conn(ev->u.stop_conn.conn_handle)) 909 conn = iscsi_conn_lookup(ev->u.stop_conn.conn_handle);
909 return -EEXIST; 910 if (conn)
910 transport->stop_conn(ev->u.stop_conn.conn_handle, 911 transport->stop_conn(conn, ev->u.stop_conn.flag);
911 ev->u.stop_conn.flag); 912 else
913 err = -EINVAL;
912 break; 914 break;
913 case ISCSI_UEVENT_SEND_PDU: 915 case ISCSI_UEVENT_SEND_PDU:
914 if (!iscsi_if_find_conn(ev->u.send_pdu.conn_handle)) 916 conn = iscsi_conn_lookup(ev->u.send_pdu.conn_handle);
915 return -EEXIST; 917 if (conn)
916 ev->r.retcode = transport->send_pdu( 918 ev->r.retcode = transport->send_pdu(conn,
917 ev->u.send_pdu.conn_handle, 919 (struct iscsi_hdr*)((char*)ev + sizeof(*ev)),
918 (struct iscsi_hdr*)((char*)ev + sizeof(*ev)), 920 (char*)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size,
919 (char*)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size, 921 ev->u.send_pdu.data_size);
920 ev->u.send_pdu.data_size); 922 else
923 err = -EINVAL;
921 break; 924 break;
922 case ISCSI_UEVENT_GET_STATS: 925 case ISCSI_UEVENT_GET_STATS:
923 err = iscsi_if_get_stats(transport, skb, nlh); 926 err = iscsi_if_get_stats(transport, skb, nlh);
@@ -927,6 +930,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
927 break; 930 break;
928 } 931 }
929 932
933 module_put(transport->owner);
930 return err; 934 return err;
931} 935}
932 936
@@ -997,7 +1001,7 @@ show_conn_int_param_##param(struct class_device *cdev, char *buf) \
997 struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \ 1001 struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \
998 struct iscsi_transport *t = conn->transport; \ 1002 struct iscsi_transport *t = conn->transport; \
999 \ 1003 \
1000 t->get_conn_param(conn->dd_data, param, &value); \ 1004 t->get_conn_param(conn, param, &value); \
1001 return snprintf(buf, 20, format"\n", value); \ 1005 return snprintf(buf, 20, format"\n", value); \
1002} 1006}
1003 1007
@@ -1024,10 +1028,9 @@ show_session_int_param_##param(struct class_device *cdev, char *buf) \
1024{ \ 1028{ \
1025 uint32_t value = 0; \ 1029 uint32_t value = 0; \
1026 struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \ 1030 struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
1027 struct Scsi_Host *shost = iscsi_session_to_shost(session); \
1028 struct iscsi_transport *t = session->transport; \ 1031 struct iscsi_transport *t = session->transport; \
1029 \ 1032 \
1030 t->get_session_param(shost, param, &value); \ 1033 t->get_session_param(session, param, &value); \
1031 return snprintf(buf, 20, format"\n", value); \ 1034 return snprintf(buf, 20, format"\n", value); \
1032} 1035}
1033 1036