aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2006-01-13 19:05:50 -0500
committerJames Bottomley <jejb@mulgrave.(none)>2006-01-14 11:55:20 -0500
commit7b8631b53bea286b68847a939b87135198335b66 (patch)
tree69a3d47f4d00f98771c4eb3cb6bc11fde0a6e0a1 /drivers/scsi
parent7cae5159dd2623300cf9820865bfbf6dcdb7c1b9 (diff)
[SCSI] iscsi: seperate iscsi interface from setup functions
This is the second version of the patch to address Christoph's comments. Instead of doing the lib, I just kept everything in scsi_trnapsort_iscsi.c like the FC and SPI class. This was becuase the driver model and sysfs class is tied to the session and connection setup so separating did not buy very much at this time. The reason for this patch was becuase HW iscsi LLDs like qla4xxx cannot use the iscsi class becuase the scsi_host was tied to the interface and class code. This patch just seperates the session from scsi host so that LLDs that allocate the host per some resource like pci device can still use the class. This is also fixes a couple refcount bugs that can be triggered when users have a sysfs file open, close the session, then read or write to the file. Signed-off-by: Alex Aizman <itn780@yahoo.com> Signed-off-by: Dmitry Yusupov <dmitry_yus@yahoo.com> Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/iscsi_tcp.c118
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c845
2 files changed, 510 insertions, 453 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 0acc4b235d9b..e31d350e6b67 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -2435,17 +2435,20 @@ iscsi_pool_free(struct iscsi_queue *q, void **items)
2435 kfree(items); 2435 kfree(items);
2436} 2436}
2437 2437
2438static iscsi_connh_t 2438static struct iscsi_cls_conn *
2439iscsi_conn_create(iscsi_sessionh_t sessionh, uint32_t conn_idx) 2439iscsi_conn_create(struct Scsi_Host *shost, uint32_t conn_idx)
2440{ 2440{
2441 struct iscsi_session *session = iscsi_ptr(sessionh); 2441 struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
2442 struct iscsi_conn *conn = NULL; 2442 struct iscsi_conn *conn;
2443 struct iscsi_cls_conn *cls_conn;
2443 2444
2444 conn = kmalloc(sizeof(struct iscsi_conn), GFP_KERNEL); 2445 cls_conn = iscsi_create_conn(hostdata_session(shost->hostdata),
2445 if (conn == NULL) 2446 conn_idx);
2446 goto conn_alloc_fail; 2447 if (!cls_conn)
2447 memset(conn, 0, sizeof(struct iscsi_conn)); 2448 return NULL;
2449 conn = cls_conn->dd_data;
2448 2450
2451 memset(conn, 0, sizeof(struct iscsi_conn));
2449 conn->c_stage = ISCSI_CONN_INITIAL_STAGE; 2452 conn->c_stage = ISCSI_CONN_INITIAL_STAGE;
2450 conn->in_progress = IN_PROGRESS_WAIT_HEADER; 2453 conn->in_progress = IN_PROGRESS_WAIT_HEADER;
2451 conn->id = conn_idx; 2454 conn->id = conn_idx;
@@ -2507,7 +2510,7 @@ iscsi_conn_create(iscsi_sessionh_t sessionh, uint32_t conn_idx)
2507 mutex_init(&conn->xmitmutex); 2510 mutex_init(&conn->xmitmutex);
2508 init_waitqueue_head(&conn->ehwait); 2511 init_waitqueue_head(&conn->ehwait);
2509 2512
2510 return iscsi_handle(conn); 2513 return cls_conn;
2511 2514
2512max_recv_dlenght_alloc_fail: 2515max_recv_dlenght_alloc_fail:
2513 spin_lock_bh(&session->lock); 2516 spin_lock_bh(&session->lock);
@@ -2523,15 +2526,14 @@ immqueue_alloc_fail:
2523writequeue_alloc_fail: 2526writequeue_alloc_fail:
2524 kfifo_free(conn->xmitqueue); 2527 kfifo_free(conn->xmitqueue);
2525xmitqueue_alloc_fail: 2528xmitqueue_alloc_fail:
2526 kfree(conn); 2529 iscsi_destroy_conn(cls_conn);
2527conn_alloc_fail: 2530 return NULL;
2528 return iscsi_handle(NULL);
2529} 2531}
2530 2532
2531static void 2533static void
2532iscsi_conn_destroy(iscsi_connh_t connh) 2534iscsi_conn_destroy(struct iscsi_cls_conn *cls_conn)
2533{ 2535{
2534 struct iscsi_conn *conn = iscsi_ptr(connh); 2536 struct iscsi_conn *conn = cls_conn->dd_data;
2535 struct iscsi_session *session = conn->session; 2537 struct iscsi_session *session = conn->session;
2536 unsigned long flags; 2538 unsigned long flags;
2537 2539
@@ -2626,7 +2628,8 @@ iscsi_conn_destroy(iscsi_connh_t connh)
2626 kfifo_free(conn->writequeue); 2628 kfifo_free(conn->writequeue);
2627 kfifo_free(conn->immqueue); 2629 kfifo_free(conn->immqueue);
2628 kfifo_free(conn->mgmtqueue); 2630 kfifo_free(conn->mgmtqueue);
2629 kfree(conn); 2631
2632 iscsi_destroy_conn(cls_conn);
2630} 2633}
2631 2634
2632static int 2635static int
@@ -3257,17 +3260,23 @@ static struct scsi_host_template iscsi_sht = {
3257 .this_id = -1, 3260 .this_id = -1,
3258}; 3261};
3259 3262
3260static iscsi_sessionh_t 3263static struct iscsi_transport iscsi_tcp_transport;
3261iscsi_session_create(uint32_t initial_cmdsn, struct Scsi_Host *host) 3264
3265static struct Scsi_Host *
3266iscsi_session_create(struct scsi_transport_template *scsit,
3267 uint32_t initial_cmdsn)
3262{ 3268{
3263 int cmd_i; 3269 struct Scsi_Host *shost;
3264 struct iscsi_session *session; 3270 struct iscsi_session *session;
3271 int cmd_i;
3265 3272
3266 session = iscsi_hostdata(host->hostdata); 3273 shost = iscsi_transport_create_session(scsit, &iscsi_tcp_transport);
3267 memset(session, 0, sizeof(struct iscsi_session)); 3274 if (!shost)
3275 return NULL;
3268 3276
3269 session->host = host; 3277 session = iscsi_hostdata(shost->hostdata);
3270 session->id = host->host_no; 3278 memset(session, 0, sizeof(struct iscsi_session));
3279 session->host = shost;
3271 session->state = ISCSI_STATE_LOGGED_IN; 3280 session->state = ISCSI_STATE_LOGGED_IN;
3272 session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX; 3281 session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
3273 session->cmds_max = ISCSI_XMIT_CMDS_MAX; 3282 session->cmds_max = ISCSI_XMIT_CMDS_MAX;
@@ -3311,7 +3320,7 @@ iscsi_session_create(uint32_t initial_cmdsn, struct Scsi_Host *host)
3311 if (iscsi_r2tpool_alloc(session)) 3320 if (iscsi_r2tpool_alloc(session))
3312 goto r2tpool_alloc_fail; 3321 goto r2tpool_alloc_fail;
3313 3322
3314 return iscsi_handle(session); 3323 return shost;
3315 3324
3316r2tpool_alloc_fail: 3325r2tpool_alloc_fail:
3317 for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) 3326 for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++)
@@ -3321,15 +3330,15 @@ immdata_alloc_fail:
3321mgmtpool_alloc_fail: 3330mgmtpool_alloc_fail:
3322 iscsi_pool_free(&session->cmdpool, (void**)session->cmds); 3331 iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
3323cmdpool_alloc_fail: 3332cmdpool_alloc_fail:
3324 return iscsi_handle(NULL); 3333 return NULL;
3325} 3334}
3326 3335
3327static void 3336static void
3328iscsi_session_destroy(iscsi_sessionh_t sessionh) 3337iscsi_session_destroy(struct Scsi_Host *shost)
3329{ 3338{
3339 struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
3330 int cmd_i; 3340 int cmd_i;
3331 struct iscsi_data_task *dtask, *n; 3341 struct iscsi_data_task *dtask, *n;
3332 struct iscsi_session *session = iscsi_ptr(sessionh);
3333 3342
3334 for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { 3343 for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
3335 struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; 3344 struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
@@ -3345,6 +3354,8 @@ iscsi_session_destroy(iscsi_sessionh_t sessionh)
3345 iscsi_r2tpool_free(session); 3354 iscsi_r2tpool_free(session);
3346 iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); 3355 iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
3347 iscsi_pool_free(&session->cmdpool, (void**)session->cmds); 3356 iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
3357
3358 iscsi_transport_destroy_session(shost);
3348} 3359}
3349 3360
3350static int 3361static int
@@ -3493,25 +3504,12 @@ iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param,
3493} 3504}
3494 3505
3495static int 3506static int
3496iscsi_conn_get_param(iscsi_connh_t connh, enum iscsi_param param, 3507iscsi_session_get_param(struct Scsi_Host *shost,
3497 uint32_t *value) 3508 enum iscsi_param param, uint32_t *value)
3498{ 3509{
3499 struct iscsi_conn *conn = iscsi_ptr(connh); 3510 struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
3500 struct iscsi_session *session = conn->session;
3501 3511
3502 switch(param) { 3512 switch(param) {
3503 case ISCSI_PARAM_MAX_RECV_DLENGTH:
3504 *value = conn->max_recv_dlength;
3505 break;
3506 case ISCSI_PARAM_MAX_XMIT_DLENGTH:
3507 *value = conn->max_xmit_dlength;
3508 break;
3509 case ISCSI_PARAM_HDRDGST_EN:
3510 *value = conn->hdrdgst_en;
3511 break;
3512 case ISCSI_PARAM_DATADGST_EN:
3513 *value = conn->datadgst_en;
3514 break;
3515 case ISCSI_PARAM_INITIAL_R2T_EN: 3513 case ISCSI_PARAM_INITIAL_R2T_EN:
3516 *value = session->initial_r2t_en; 3514 *value = session->initial_r2t_en;
3517 break; 3515 break;
@@ -3549,6 +3547,31 @@ iscsi_conn_get_param(iscsi_connh_t connh, enum iscsi_param param,
3549 return 0; 3547 return 0;
3550} 3548}
3551 3549
3550static int
3551iscsi_conn_get_param(void *data, enum iscsi_param param, uint32_t *value)
3552{
3553 struct iscsi_conn *conn = data;
3554
3555 switch(param) {
3556 case ISCSI_PARAM_MAX_RECV_DLENGTH:
3557 *value = conn->max_recv_dlength;
3558 break;
3559 case ISCSI_PARAM_MAX_XMIT_DLENGTH:
3560 *value = conn->max_xmit_dlength;
3561 break;
3562 case ISCSI_PARAM_HDRDGST_EN:
3563 *value = conn->hdrdgst_en;
3564 break;
3565 case ISCSI_PARAM_DATADGST_EN:
3566 *value = conn->datadgst_en;
3567 break;
3568 default:
3569 return ISCSI_ERR_PARAM_NOT_FOUND;
3570 }
3571
3572 return 0;
3573}
3574
3552static void 3575static void
3553iscsi_conn_get_stats(iscsi_connh_t connh, struct iscsi_stats *stats) 3576iscsi_conn_get_stats(iscsi_connh_t connh, struct iscsi_stats *stats)
3554{ 3577{
@@ -3593,6 +3616,7 @@ static struct iscsi_transport iscsi_tcp_transport = {
3593 | CAP_DATADGST, 3616 | CAP_DATADGST,
3594 .host_template = &iscsi_sht, 3617 .host_template = &iscsi_sht,
3595 .hostdata_size = sizeof(struct iscsi_session), 3618 .hostdata_size = sizeof(struct iscsi_session),
3619 .conndata_size = sizeof(struct iscsi_conn),
3596 .max_conn = 1, 3620 .max_conn = 1,
3597 .max_cmd_len = ISCSI_TCP_MAX_CMD_LEN, 3621 .max_cmd_len = ISCSI_TCP_MAX_CMD_LEN,
3598 .create_session = iscsi_session_create, 3622 .create_session = iscsi_session_create,
@@ -3601,7 +3625,8 @@ static struct iscsi_transport iscsi_tcp_transport = {
3601 .bind_conn = iscsi_conn_bind, 3625 .bind_conn = iscsi_conn_bind,
3602 .destroy_conn = iscsi_conn_destroy, 3626 .destroy_conn = iscsi_conn_destroy,
3603 .set_param = iscsi_conn_set_param, 3627 .set_param = iscsi_conn_set_param,
3604 .get_param = iscsi_conn_get_param, 3628 .get_conn_param = iscsi_conn_get_param,
3629 .get_session_param = iscsi_session_get_param,
3605 .start_conn = iscsi_conn_start, 3630 .start_conn = iscsi_conn_start,
3606 .stop_conn = iscsi_conn_stop, 3631 .stop_conn = iscsi_conn_stop,
3607 .send_pdu = iscsi_conn_send_pdu, 3632 .send_pdu = iscsi_conn_send_pdu,
@@ -3611,8 +3636,6 @@ static struct iscsi_transport iscsi_tcp_transport = {
3611static int __init 3636static int __init
3612iscsi_tcp_init(void) 3637iscsi_tcp_init(void)
3613{ 3638{
3614 int error;
3615
3616 if (iscsi_max_lun < 1) { 3639 if (iscsi_max_lun < 1) {
3617 printk(KERN_ERR "Invalid max_lun value of %u\n", iscsi_max_lun); 3640 printk(KERN_ERR "Invalid max_lun value of %u\n", iscsi_max_lun);
3618 return -EINVAL; 3641 return -EINVAL;
@@ -3625,11 +3648,10 @@ iscsi_tcp_init(void)
3625 if (!taskcache) 3648 if (!taskcache)
3626 return -ENOMEM; 3649 return -ENOMEM;
3627 3650
3628 error = iscsi_register_transport(&iscsi_tcp_transport); 3651 if (!iscsi_register_transport(&iscsi_tcp_transport))
3629 if (error)
3630 kmem_cache_destroy(taskcache); 3652 kmem_cache_destroy(taskcache);
3631 3653
3632 return error; 3654 return 0;
3633} 3655}
3634 3656
3635static void __exit 3657static void __exit
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 50ed88f98f46..45e31635a595 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -21,12 +21,9 @@
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */ 22 */
23#include <linux/module.h> 23#include <linux/module.h>
24#include <linux/string.h>
25#include <linux/slab.h>
26#include <linux/mempool.h> 24#include <linux/mempool.h>
27#include <linux/mutex.h> 25#include <linux/mutex.h>
28#include <net/tcp.h> 26#include <net/tcp.h>
29
30#include <scsi/scsi.h> 27#include <scsi/scsi.h>
31#include <scsi/scsi_host.h> 28#include <scsi/scsi_host.h>
32#include <scsi/scsi_device.h> 29#include <scsi/scsi_device.h>
@@ -46,11 +43,6 @@ struct iscsi_internal {
46 */ 43 */
47 struct list_head sessions; 44 struct list_head sessions;
48 /* 45 /*
49 * lock to serialize access to the sessions list which must
50 * be taken after the rx_queue_mutex
51 */
52 spinlock_t session_lock;
53 /*
54 * based on transport capabilities, at register time we set these 46 * based on transport capabilities, at register time we set these
55 * bits to tell the transport class it wants attributes displayed 47 * bits to tell the transport class it wants attributes displayed
56 * in sysfs or that it can support different iSCSI Data-Path 48 * in sysfs or that it can support different iSCSI Data-Path
@@ -157,7 +149,7 @@ struct mempool_zone {
157 spinlock_t freelock; 149 spinlock_t freelock;
158}; 150};
159 151
160static struct mempool_zone z_reply; 152static struct mempool_zone *z_reply;
161 153
162/* 154/*
163 * Z_MAX_* - actual mempool size allocated at the mempool_zone_init() time 155 * Z_MAX_* - actual mempool size allocated at the mempool_zone_init() time
@@ -172,50 +164,270 @@ static struct mempool_zone z_reply;
172#define Z_MAX_ERROR 16 164#define Z_MAX_ERROR 16
173#define Z_HIWAT_ERROR 12 165#define Z_HIWAT_ERROR 12
174 166
175struct iscsi_if_conn { 167static LIST_HEAD(connlist);
176 struct list_head conn_list; /* item in connlist */ 168static DEFINE_SPINLOCK(connlock);
177 struct list_head session_list; /* item in session->connections */
178 iscsi_connh_t connh;
179 int active; /* must be accessed with the connlock */
180 struct Scsi_Host *host; /* originated shost */
181 struct device dev; /* sysfs transport/container device */
182 struct iscsi_transport *transport;
183 struct mempool_zone z_error;
184 struct mempool_zone z_pdu;
185 struct list_head freequeue;
186};
187 169
188#define iscsi_dev_to_if_conn(_dev) \ 170/*
189 container_of(_dev, struct iscsi_if_conn, dev) 171 * The following functions can be used by LLDs that allocate
172 * their own scsi_hosts or by software iscsi LLDs
173 */
174static void iscsi_session_release(struct device *dev)
175{
176 struct iscsi_cls_session *session = iscsi_dev_to_session(dev);
177 struct iscsi_transport *transport = session->transport;
178 struct Scsi_Host *shost;
190 179
191#define iscsi_cdev_to_if_conn(_cdev) \ 180 shost = iscsi_session_to_shost(session);
192 iscsi_dev_to_if_conn(_cdev->dev) 181 scsi_host_put(shost);
182 kfree(session);
183 module_put(transport->owner);
184}
193 185
194static LIST_HEAD(connlist); 186static int iscsi_is_session_dev(const struct device *dev)
195static DEFINE_SPINLOCK(connlock); 187{
188 return dev->release == iscsi_session_release;
189}
196 190
197struct iscsi_if_session { 191/**
198 struct list_head list; /* item in session_list */ 192 * iscsi_create_session - create iscsi class session
199 struct list_head connections; 193 * @shost: scsi host
200 iscsi_sessionh_t sessionh; 194 * @transport: iscsi transport
201 struct iscsi_transport *transport; 195 *
202 struct device dev; /* sysfs transport/container device */ 196 * This can be called from a LLD or iscsi_transport
203}; 197 **/
198struct iscsi_cls_session *
199iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport)
200{
201 struct iscsi_cls_session *session;
202 int err;
203
204 if (!try_module_get(transport->owner))
205 return NULL;
206
207 session = kzalloc(sizeof(*session), GFP_KERNEL);
208 if (!session)
209 goto module_put;
210 session->transport = transport;
211
212 /* this is released in the dev's release function */
213 scsi_host_get(shost);
214 snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", shost->host_no);
215 session->dev.parent = &shost->shost_gendev;
216 session->dev.release = iscsi_session_release;
217 err = device_register(&session->dev);
218 if (err) {
219 dev_printk(KERN_ERR, &session->dev, "iscsi: could not "
220 "register session's dev\n");
221 goto free_session;
222 }
223 transport_register_device(&session->dev);
224
225 return session;
226
227free_session:
228 kfree(session);
229module_put:
230 module_put(transport->owner);
231 return NULL;
232}
233
234EXPORT_SYMBOL_GPL(iscsi_create_session);
235
236/**
237 * iscsi_destroy_session - destroy iscsi session
238 * @session: iscsi_session
239 *
240 * Can be called by a LLD or iscsi_transport. There must not be
241 * any running connections.
242 **/
243int iscsi_destroy_session(struct iscsi_cls_session *session)
244{
245 transport_unregister_device(&session->dev);
246 device_unregister(&session->dev);
247 return 0;
248}
249
250EXPORT_SYMBOL_GPL(iscsi_destroy_session);
251
252static void iscsi_conn_release(struct device *dev)
253{
254 struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev);
255 struct device *parent = conn->dev.parent;
256
257 kfree(conn);
258 put_device(parent);
259}
260
261static int iscsi_is_conn_dev(const struct device *dev)
262{
263 return dev->release == iscsi_conn_release;
264}
265
266/**
267 * iscsi_create_conn - create iscsi class connection
268 * @session: iscsi cls session
269 * @cid: connection id
270 *
271 * This can be called from a LLD or iscsi_transport. The connection
272 * is child of the session so cid must be unique for all connections
273 * on the session.
274 **/
275struct iscsi_cls_conn *
276iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid)
277{
278 struct iscsi_transport *transport = session->transport;
279 struct Scsi_Host *shost = iscsi_session_to_shost(session);
280 struct iscsi_cls_conn *conn;
281 int err;
282
283 conn = kzalloc(sizeof(*conn) + transport->conndata_size, GFP_KERNEL);
284 if (!conn)
285 return NULL;
286
287 if (transport->conndata_size)
288 conn->dd_data = &conn[1];
289
290 INIT_LIST_HEAD(&conn->conn_list);
291 conn->transport = transport;
292
293 /* this is released in the dev's release function */
294 if (!get_device(&session->dev))
295 goto free_conn;
296 snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
297 shost->host_no, cid);
298 conn->dev.parent = &session->dev;
299 conn->dev.release = iscsi_conn_release;
300 err = device_register(&conn->dev);
301 if (err) {
302 dev_printk(KERN_ERR, &conn->dev, "iscsi: could not register "
303 "connection's dev\n");
304 goto release_parent_ref;
305 }
306 transport_register_device(&conn->dev);
307 return conn;
308
309release_parent_ref:
310 put_device(&session->dev);
311free_conn:
312 kfree(conn);
313 return NULL;
314}
315
316EXPORT_SYMBOL_GPL(iscsi_create_conn);
317
318/**
319 * iscsi_destroy_conn - destroy iscsi class connection
320 * @session: iscsi cls session
321 *
322 * This can be called from a LLD or iscsi_transport.
323 **/
324int iscsi_destroy_conn(struct iscsi_cls_conn *conn)
325{
326 transport_unregister_device(&conn->dev);
327 device_unregister(&conn->dev);
328 return 0;
329}
330
331EXPORT_SYMBOL_GPL(iscsi_destroy_conn);
332
333/*
334 * These functions are used only by software iscsi_transports
335 * which do not allocate and more their scsi_hosts since this
336 * is initiated from userspace.
337 */
338
339/*
340 * iSCSI Session's hostdata organization:
341 *
342 * *------------------* <== hostdata_session(host->hostdata)
343 * | ptr to class sess|
344 * |------------------| <== iscsi_hostdata(host->hostdata)
345 * | transport's data |
346 * *------------------*
347 */
348
349#define hostdata_privsize(_t) (sizeof(unsigned long) + _t->hostdata_size + \
350 _t->hostdata_size % sizeof(unsigned long))
351
352#define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata))
353
354/**
355 * iscsi_transport_create_session - create iscsi cls session and host
356 * scsit: scsi transport template
357 * transport: iscsi transport template
358 *
359 * This can be used by software iscsi_transports that allocate
360 * a session per scsi host.
361 **/
362struct Scsi_Host *
363iscsi_transport_create_session(struct scsi_transport_template *scsit,
364 struct iscsi_transport *transport)
365{
366 struct iscsi_cls_session *session;
367 struct Scsi_Host *shost;
368
369 shost = scsi_host_alloc(transport->host_template,
370 hostdata_privsize(transport));
371 if (!shost) {
372 printk(KERN_ERR "iscsi: can not allocate SCSI host for "
373 "session\n");
374 return NULL;
375 }
376
377 shost->max_id = 1;
378 shost->max_channel = 0;
379 shost->max_lun = transport->max_lun;
380 shost->max_cmd_len = transport->max_cmd_len;
381 shost->transportt = scsit;
382
383 if (scsi_add_host(shost, NULL))
384 goto free_host;
385
386 session = iscsi_create_session(shost, transport);
387 if (!session)
388 goto remove_host;
204 389
205#define iscsi_dev_to_if_session(_dev) \ 390 *(unsigned long*)shost->hostdata = (unsigned long)session;
206 container_of(_dev, struct iscsi_if_session, dev) 391 return shost;
392
393remove_host:
394 scsi_remove_host(shost);
395free_host:
396 scsi_host_put(shost);
397 return NULL;
398}
207 399
208#define iscsi_cdev_to_if_session(_cdev) \ 400EXPORT_SYMBOL_GPL(iscsi_transport_create_session);
209 iscsi_dev_to_if_session(_cdev->dev)
210 401
211#define iscsi_if_session_to_shost(_session) \ 402/**
212 dev_to_shost(_session->dev.parent) 403 * iscsi_transport_destroy_session - destroy session and scsi host
404 * shost: scsi host
405 *
406 * This can be used by software iscsi_transports that allocate
407 * a session per scsi host.
408 **/
409int iscsi_transport_destroy_session(struct Scsi_Host *shost)
410{
411 struct iscsi_cls_session *session;
213 412
214static struct iscsi_if_conn* 413 scsi_remove_host(shost);
414 session = hostdata_session(shost->hostdata);
415 iscsi_destroy_session(session);
416 /* ref from host alloc */
417 scsi_host_put(shost);
418 return 0;
419}
420
421EXPORT_SYMBOL_GPL(iscsi_transport_destroy_session);
422
423/*
424 * iscsi interface functions
425 */
426static struct iscsi_cls_conn*
215iscsi_if_find_conn(uint64_t key) 427iscsi_if_find_conn(uint64_t key)
216{ 428{
217 unsigned long flags; 429 unsigned long flags;
218 struct iscsi_if_conn *conn; 430 struct iscsi_cls_conn *conn;
219 431
220 spin_lock_irqsave(&connlock, flags); 432 spin_lock_irqsave(&connlock, flags);
221 list_for_each_entry(conn, &connlist, conn_list) 433 list_for_each_entry(conn, &connlist, conn_list)
@@ -250,7 +462,7 @@ static inline struct list_head *skb_to_lh(struct sk_buff *skb)
250} 462}
251 463
252static void* 464static void*
253mempool_zone_alloc_skb(gfp_t gfp_mask, void *pool_data) 465mempool_zone_alloc_skb(unsigned int gfp_mask, void *pool_data)
254{ 466{
255 struct mempool_zone *zone = pool_data; 467 struct mempool_zone *zone = pool_data;
256 468
@@ -282,14 +494,21 @@ mempool_zone_complete(struct mempool_zone *zone)
282 spin_unlock_irqrestore(&zone->freelock, flags); 494 spin_unlock_irqrestore(&zone->freelock, flags);
283} 495}
284 496
285static int 497static struct mempool_zone *
286mempool_zone_init(struct mempool_zone *zp, unsigned max, unsigned size, 498mempool_zone_init(unsigned max, unsigned size, unsigned hiwat)
287 unsigned hiwat)
288{ 499{
500 struct mempool_zone *zp;
501
502 zp = kzalloc(sizeof(*zp), GFP_KERNEL);
503 if (!zp)
504 return NULL;
505
289 zp->pool = mempool_create(max, mempool_zone_alloc_skb, 506 zp->pool = mempool_create(max, mempool_zone_alloc_skb,
290 mempool_zone_free_skb, zp); 507 mempool_zone_free_skb, zp);
291 if (!zp->pool) 508 if (!zp->pool) {
292 return -ENOMEM; 509 kfree(zp);
510 return NULL;
511 }
293 512
294 zp->size = size; 513 zp->size = size;
295 zp->hiwat = hiwat; 514 zp->hiwat = hiwat;
@@ -298,9 +517,14 @@ mempool_zone_init(struct mempool_zone *zp, unsigned max, unsigned size,
298 spin_lock_init(&zp->freelock); 517 spin_lock_init(&zp->freelock);
299 atomic_set(&zp->allocated, 0); 518 atomic_set(&zp->allocated, 0);
300 519
301 return 0; 520 return zp;
302} 521}
303 522
523static void mempool_zone_destroy(struct mempool_zone *zp)
524{
525 mempool_destroy(zp->pool);
526 kfree(zp);
527}
304 528
305static struct sk_buff* 529static struct sk_buff*
306mempool_zone_get_skb(struct mempool_zone *zone) 530mempool_zone_get_skb(struct mempool_zone *zone)
@@ -340,7 +564,7 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
340 struct nlmsghdr *nlh; 564 struct nlmsghdr *nlh;
341 struct sk_buff *skb; 565 struct sk_buff *skb;
342 struct iscsi_uevent *ev; 566 struct iscsi_uevent *ev;
343 struct iscsi_if_conn *conn; 567 struct iscsi_cls_conn *conn;
344 char *pdu; 568 char *pdu;
345 int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) + 569 int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) +
346 data_size); 570 data_size);
@@ -348,13 +572,13 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
348 conn = iscsi_if_find_conn(connh); 572 conn = iscsi_if_find_conn(connh);
349 BUG_ON(!conn); 573 BUG_ON(!conn);
350 574
351 mempool_zone_complete(&conn->z_pdu); 575 mempool_zone_complete(conn->z_pdu);
352 576
353 skb = mempool_zone_get_skb(&conn->z_pdu); 577 skb = mempool_zone_get_skb(conn->z_pdu);
354 if (!skb) { 578 if (!skb) {
355 iscsi_conn_error(connh, ISCSI_ERR_CONN_FAILED); 579 iscsi_conn_error(connh, ISCSI_ERR_CONN_FAILED);
356 printk(KERN_ERR "iscsi%d: can not deliver control PDU: OOM\n", 580 dev_printk(KERN_ERR, &conn->dev, "iscsi: can not deliver "
357 conn->host->host_no); 581 "control PDU: OOM\n");
358 return -ENOMEM; 582 return -ENOMEM;
359 } 583 }
360 584
@@ -363,14 +587,14 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
363 memset(ev, 0, sizeof(*ev)); 587 memset(ev, 0, sizeof(*ev));
364 ev->transport_handle = iscsi_handle(conn->transport); 588 ev->transport_handle = iscsi_handle(conn->transport);
365 ev->type = ISCSI_KEVENT_RECV_PDU; 589 ev->type = ISCSI_KEVENT_RECV_PDU;
366 if (atomic_read(&conn->z_pdu.allocated) >= conn->z_pdu.hiwat) 590 if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
367 ev->iferror = -ENOMEM; 591 ev->iferror = -ENOMEM;
368 ev->r.recv_req.conn_handle = connh; 592 ev->r.recv_req.conn_handle = connh;
369 pdu = (char*)ev + sizeof(*ev); 593 pdu = (char*)ev + sizeof(*ev);
370 memcpy(pdu, hdr, sizeof(struct iscsi_hdr)); 594 memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
371 memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size); 595 memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
372 596
373 return iscsi_unicast_skb(&conn->z_pdu, skb); 597 return iscsi_unicast_skb(conn->z_pdu, skb);
374} 598}
375EXPORT_SYMBOL_GPL(iscsi_recv_pdu); 599EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
376 600
@@ -379,18 +603,18 @@ void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error)
379 struct nlmsghdr *nlh; 603 struct nlmsghdr *nlh;
380 struct sk_buff *skb; 604 struct sk_buff *skb;
381 struct iscsi_uevent *ev; 605 struct iscsi_uevent *ev;
382 struct iscsi_if_conn *conn; 606 struct iscsi_cls_conn *conn;
383 int len = NLMSG_SPACE(sizeof(*ev)); 607 int len = NLMSG_SPACE(sizeof(*ev));
384 608
385 conn = iscsi_if_find_conn(connh); 609 conn = iscsi_if_find_conn(connh);
386 BUG_ON(!conn); 610 BUG_ON(!conn);
387 611
388 mempool_zone_complete(&conn->z_error); 612 mempool_zone_complete(conn->z_error);
389 613
390 skb = mempool_zone_get_skb(&conn->z_error); 614 skb = mempool_zone_get_skb(conn->z_error);
391 if (!skb) { 615 if (!skb) {
392 printk(KERN_ERR "iscsi%d: gracefully ignored conn error (%d)\n", 616 dev_printk(KERN_ERR, &conn->dev, "iscsi: gracefully ignored "
393 conn->host->host_no, error); 617 "conn error (%d)\n", error);
394 return; 618 return;
395 } 619 }
396 620
@@ -398,15 +622,15 @@ void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error)
398 ev = NLMSG_DATA(nlh); 622 ev = NLMSG_DATA(nlh);
399 ev->transport_handle = iscsi_handle(conn->transport); 623 ev->transport_handle = iscsi_handle(conn->transport);
400 ev->type = ISCSI_KEVENT_CONN_ERROR; 624 ev->type = ISCSI_KEVENT_CONN_ERROR;
401 if (atomic_read(&conn->z_error.allocated) >= conn->z_error.hiwat) 625 if (atomic_read(&conn->z_error->allocated) >= conn->z_error->hiwat)
402 ev->iferror = -ENOMEM; 626 ev->iferror = -ENOMEM;
403 ev->r.connerror.error = error; 627 ev->r.connerror.error = error;
404 ev->r.connerror.conn_handle = connh; 628 ev->r.connerror.conn_handle = connh;
405 629
406 iscsi_unicast_skb(&conn->z_error, skb); 630 iscsi_unicast_skb(conn->z_error, skb);
407 631
408 printk(KERN_INFO "iscsi%d: detected conn error (%d)\n", 632 dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n",
409 conn->host->host_no, error); 633 error);
410} 634}
411EXPORT_SYMBOL_GPL(iscsi_conn_error); 635EXPORT_SYMBOL_GPL(iscsi_conn_error);
412 636
@@ -420,9 +644,9 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi,
420 int flags = multi ? NLM_F_MULTI : 0; 644 int flags = multi ? NLM_F_MULTI : 0;
421 int t = done ? NLMSG_DONE : type; 645 int t = done ? NLMSG_DONE : type;
422 646
423 mempool_zone_complete(&z_reply); 647 mempool_zone_complete(z_reply);
424 648
425 skb = mempool_zone_get_skb(&z_reply); 649 skb = mempool_zone_get_skb(z_reply);
426 /* 650 /*
427 * FIXME: 651 * FIXME:
428 * user is supposed to react on iferror == -ENOMEM; 652 * user is supposed to react on iferror == -ENOMEM;
@@ -433,366 +657,197 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi,
433 nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0); 657 nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0);
434 nlh->nlmsg_flags = flags; 658 nlh->nlmsg_flags = flags;
435 memcpy(NLMSG_DATA(nlh), payload, size); 659 memcpy(NLMSG_DATA(nlh), payload, size);
436 return iscsi_unicast_skb(&z_reply, skb); 660 return iscsi_unicast_skb(z_reply, skb);
437} 661}
438 662
439/* 663static int
440 * iSCSI Session's hostdata organization: 664iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
441 * 665 struct nlmsghdr *nlh)
442 * *------------------* <== host->hostdata 666{
443 * | transport | 667 struct iscsi_uevent *ev = NLMSG_DATA(nlh);
444 * |------------------| <== iscsi_hostdata(host->hostdata) 668 struct iscsi_stats *stats;
445 * | transport's data | 669 struct sk_buff *skbstat;
446 * |------------------| <== hostdata_session(host->hostdata) 670 struct iscsi_cls_conn *conn;
447 * | interface's data | 671 struct nlmsghdr *nlhstat;
448 * *------------------* 672 struct iscsi_uevent *evstat;
449 */ 673 int len = NLMSG_SPACE(sizeof(*ev) +
674 sizeof(struct iscsi_stats) +
675 sizeof(struct iscsi_stats_custom) *
676 ISCSI_STATS_CUSTOM_MAX);
677 int err = 0;
450 678
451#define hostdata_privsize(_t) (sizeof(unsigned long) + _t->hostdata_size + \ 679 conn = iscsi_if_find_conn(ev->u.get_stats.conn_handle);
452 _t->hostdata_size % sizeof(unsigned long) + \ 680 if (!conn)
453 sizeof(struct iscsi_if_session)) 681 return -EEXIST;
454 682
455#define hostdata_session(_hostdata) ((void*)_hostdata + sizeof(unsigned long) + \ 683 do {
456 ((struct iscsi_transport *) \ 684 int actual_size;
457 iscsi_ptr(*(uint64_t *)_hostdata))->hostdata_size)
458 685
459static void iscsi_if_session_dev_release(struct device *dev) 686 mempool_zone_complete(conn->z_pdu);
460{
461 struct iscsi_if_session *session = iscsi_dev_to_if_session(dev);
462 struct iscsi_transport *transport = session->transport;
463 struct Scsi_Host *shost = iscsi_if_session_to_shost(session);
464 struct iscsi_if_conn *conn, *tmp;
465 unsigned long flags;
466 687
467 /* now free connections */ 688 skbstat = mempool_zone_get_skb(conn->z_pdu);
468 spin_lock_irqsave(&connlock, flags); 689 if (!skbstat) {
469 list_for_each_entry_safe(conn, tmp, &session->connections, 690 dev_printk(KERN_ERR, &conn->dev, "iscsi: can not "
470 session_list) { 691 "deliver stats: OOM\n");
471 list_del(&conn->session_list); 692 return -ENOMEM;
472 mempool_destroy(conn->z_pdu.pool); 693 }
473 mempool_destroy(conn->z_error.pool); 694
474 kfree(conn); 695 nlhstat = __nlmsg_put(skbstat, daemon_pid, 0, 0,
475 } 696 (len - sizeof(*nlhstat)), 0);
476 spin_unlock_irqrestore(&connlock, flags); 697 evstat = NLMSG_DATA(nlhstat);
477 scsi_host_put(shost); 698 memset(evstat, 0, sizeof(*evstat));
478 module_put(transport->owner); 699 evstat->transport_handle = iscsi_handle(conn->transport);
700 evstat->type = nlh->nlmsg_type;
701 if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
702 evstat->iferror = -ENOMEM;
703 evstat->u.get_stats.conn_handle =
704 ev->u.get_stats.conn_handle;
705 stats = (struct iscsi_stats *)
706 ((char*)evstat + sizeof(*evstat));
707 memset(stats, 0, sizeof(*stats));
708
709 transport->get_stats(ev->u.get_stats.conn_handle, stats);
710 actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) +
711 sizeof(struct iscsi_stats) +
712 sizeof(struct iscsi_stats_custom) *
713 stats->custom_length);
714 actual_size -= sizeof(*nlhstat);
715 actual_size = NLMSG_LENGTH(actual_size);
716 skb_trim(skb, NLMSG_ALIGN(actual_size));
717 nlhstat->nlmsg_len = actual_size;
718
719 err = iscsi_unicast_skb(conn->z_pdu, skbstat);
720 } while (err < 0 && err != -ECONNREFUSED);
721
722 return err;
479} 723}
480 724
481static int 725static int
482iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev) 726iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
483{ 727{
484 struct iscsi_transport *transport = priv->iscsi_transport; 728 struct iscsi_transport *transport = priv->iscsi_transport;
485 struct iscsi_if_session *session;
486 struct Scsi_Host *shost; 729 struct Scsi_Host *shost;
487 unsigned long flags;
488 int error;
489
490 if (!try_module_get(transport->owner))
491 return -EPERM;
492 730
493 shost = scsi_host_alloc(transport->host_template, 731 if (!transport->create_session)
494 hostdata_privsize(transport)); 732 return -EINVAL;
495 if (!shost) {
496 ev->r.c_session_ret.session_handle = iscsi_handle(NULL);
497 printk(KERN_ERR "iscsi: can not allocate SCSI host for "
498 "session\n");
499 error = -ENOMEM;
500 goto out_module_put;
501 }
502 shost->max_id = 1;
503 shost->max_channel = 0;
504 shost->max_lun = transport->max_lun;
505 shost->max_cmd_len = transport->max_cmd_len;
506 shost->transportt = &priv->t;
507
508 /* store struct iscsi_transport in hostdata */
509 *(uint64_t*)shost->hostdata = ev->transport_handle;
510 733
511 ev->r.c_session_ret.session_handle = transport->create_session( 734 shost = transport->create_session(&priv->t,
512 ev->u.c_session.initial_cmdsn, shost); 735 ev->u.c_session.initial_cmdsn);
513 if (ev->r.c_session_ret.session_handle == iscsi_handle(NULL)) { 736 if (!shost)
514 error = 0; 737 return -ENOMEM;
515 goto out_host_put;
516 }
517 738
518 /* host_no becomes assigned SID */ 739 ev->r.c_session_ret.session_handle = iscsi_handle(iscsi_hostdata(shost->hostdata));
519 ev->r.c_session_ret.sid = shost->host_no; 740 ev->r.c_session_ret.sid = shost->host_no;
520 /* initialize session */
521 session = hostdata_session(shost->hostdata);
522 INIT_LIST_HEAD(&session->connections);
523 INIT_LIST_HEAD(&session->list);
524 session->sessionh = ev->r.c_session_ret.session_handle;
525 session->transport = transport;
526
527 error = scsi_add_host(shost, NULL);
528 if (error)
529 goto out_destroy_session;
530
531 /*
532 * this is released in the dev's release function)
533 */
534 scsi_host_get(shost);
535 snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", shost->host_no);
536 session->dev.parent = &shost->shost_gendev;
537 session->dev.release = iscsi_if_session_dev_release;
538 error = device_register(&session->dev);
539 if (error) {
540 printk(KERN_ERR "iscsi: could not register session%d's dev\n",
541 shost->host_no);
542 goto out_remove_host;
543 }
544 transport_register_device(&session->dev);
545
546 /* add this session to the list of active sessions */
547 spin_lock_irqsave(&priv->session_lock, flags);
548 list_add(&session->list, &priv->sessions);
549 spin_unlock_irqrestore(&priv->session_lock, flags);
550
551 return 0; 741 return 0;
552
553out_remove_host:
554 scsi_remove_host(shost);
555out_destroy_session:
556 transport->destroy_session(ev->r.c_session_ret.session_handle);
557 ev->r.c_session_ret.session_handle = iscsi_handle(NULL);
558out_host_put:
559 scsi_host_put(shost);
560out_module_put:
561 module_put(transport->owner);
562 return error;
563} 742}
564 743
565static int 744static int
566iscsi_if_destroy_session(struct iscsi_internal *priv, struct iscsi_uevent *ev) 745iscsi_if_destroy_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
567{ 746{
568 struct iscsi_transport *transport = priv->iscsi_transport; 747 struct iscsi_transport *transport = priv->iscsi_transport;
748
569 struct Scsi_Host *shost; 749 struct Scsi_Host *shost;
570 struct iscsi_if_session *session; 750
571 unsigned long flags; 751 if (!transport->destroy_session)
572 struct iscsi_if_conn *conn; 752 return -EINVAL;
573 int error = 0;
574 753
575 shost = scsi_host_lookup(ev->u.d_session.sid); 754 shost = scsi_host_lookup(ev->u.d_session.sid);
576 if (shost == ERR_PTR(-ENXIO)) 755 if (shost == ERR_PTR(-ENXIO))
577 return -EEXIST; 756 return -EEXIST;
578 session = hostdata_session(shost->hostdata);
579 757
580 /* check if we have active connections */ 758 if (transport->destroy_session)
581 spin_lock_irqsave(&connlock, flags); 759 transport->destroy_session(shost);
582 list_for_each_entry(conn, &session->connections, session_list) { 760 /* ref from host lookup */
583 if (conn->active) { 761 scsi_host_put(shost);
584 printk(KERN_ERR "iscsi%d: can not destroy session: " 762 return 0;
585 "has active connection (%p)\n",
586 shost->host_no, iscsi_ptr(conn->connh));
587 spin_unlock_irqrestore(&connlock, flags);
588 error = EIO;
589 goto out_release_ref;
590 }
591 }
592 spin_unlock_irqrestore(&connlock, flags);
593
594 scsi_remove_host(shost);
595 transport->destroy_session(ev->u.d_session.session_handle);
596 transport_unregister_device(&session->dev);
597 device_unregister(&session->dev);
598
599 /* remove this session from the list of active sessions */
600 spin_lock_irqsave(&priv->session_lock, flags);
601 list_del(&session->list);
602 spin_unlock_irqrestore(&priv->session_lock, flags);
603
604 /* ref from host alloc */
605 scsi_host_put(shost);
606out_release_ref:
607 /* ref from host lookup */
608 scsi_host_put(shost);
609 return error;
610}
611
612static void iscsi_if_conn_dev_release(struct device *dev)
613{
614 struct iscsi_if_conn *conn = iscsi_dev_to_if_conn(dev);
615 struct Scsi_Host *shost = conn->host;
616
617 scsi_host_put(shost);
618} 763}
619 764
620static int 765static int
621iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev) 766iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev){
622{
623 struct iscsi_if_session *session;
624 struct Scsi_Host *shost; 767 struct Scsi_Host *shost;
625 struct iscsi_if_conn *conn; 768 struct iscsi_cls_conn *conn;
626 unsigned long flags; 769 unsigned long flags;
627 int error; 770
771 if (!transport->create_conn)
772 return -EINVAL;
628 773
629 shost = scsi_host_lookup(ev->u.c_conn.sid); 774 shost = scsi_host_lookup(ev->u.c_conn.sid);
630 if (shost == ERR_PTR(-ENXIO)) 775 if (shost == ERR_PTR(-ENXIO))
631 return -EEXIST; 776 return -EEXIST;
632 session = hostdata_session(shost->hostdata);
633 777
634 conn = kmalloc(sizeof(struct iscsi_if_conn), GFP_KERNEL); 778 conn = transport->create_conn(shost, ev->u.c_conn.cid);
635 if (!conn) { 779 if (!conn)
636 error = -ENOMEM; 780 goto release_ref;
637 goto out_release_ref;
638 }
639 memset(conn, 0, sizeof(struct iscsi_if_conn));
640 INIT_LIST_HEAD(&conn->session_list);
641 INIT_LIST_HEAD(&conn->conn_list);
642 conn->host = shost;
643 conn->transport = transport;
644 781
645 error = mempool_zone_init(&conn->z_pdu, Z_MAX_PDU, 782 conn->z_pdu = mempool_zone_init(Z_MAX_PDU,
646 NLMSG_SPACE(sizeof(struct iscsi_uevent) + 783 NLMSG_SPACE(sizeof(struct iscsi_uevent) +
647 sizeof(struct iscsi_hdr) + 784 sizeof(struct iscsi_hdr) +
648 DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH), 785 DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH),
649 Z_HIWAT_PDU); 786 Z_HIWAT_PDU);
650 if (error) { 787 if (!conn->z_pdu) {
651 printk(KERN_ERR "iscsi%d: can not allocate pdu zone for new " 788 dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
652 "conn\n", shost->host_no); 789 "pdu zone for new conn\n");
653 goto out_free_conn; 790 goto destroy_conn;
654 } 791 }
655 error = mempool_zone_init(&conn->z_error, Z_MAX_ERROR, 792
793 conn->z_error = mempool_zone_init(Z_MAX_ERROR,
656 NLMSG_SPACE(sizeof(struct iscsi_uevent)), 794 NLMSG_SPACE(sizeof(struct iscsi_uevent)),
657 Z_HIWAT_ERROR); 795 Z_HIWAT_ERROR);
658 if (error) { 796 if (!conn->z_error) {
659 printk(KERN_ERR "iscsi%d: can not allocate error zone for " 797 dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
660 "new conn\n", shost->host_no); 798 "error zone for new conn\n");
661 goto out_free_pdu_pool; 799 goto free_pdu_pool;
662 }
663
664 ev->r.handle = transport->create_conn(ev->u.c_conn.session_handle,
665 ev->u.c_conn.cid);
666 if (!ev->r.handle) {
667 error = -ENODEV;
668 goto out_free_error_pool;
669 } 800 }
670 801
671 conn->connh = ev->r.handle; 802 ev->r.handle = conn->connh = iscsi_handle(conn->dd_data);
672
673 /*
674 * this is released in the dev's release function
675 */
676 if (!scsi_host_get(shost))
677 goto out_destroy_conn;
678 snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
679 shost->host_no, ev->u.c_conn.cid);
680 conn->dev.parent = &session->dev;
681 conn->dev.release = iscsi_if_conn_dev_release;
682 error = device_register(&conn->dev);
683 if (error) {
684 printk(KERN_ERR "iscsi%d: could not register connections%u "
685 "dev\n", shost->host_no, ev->u.c_conn.cid);
686 goto out_release_parent_ref;
687 }
688 transport_register_device(&conn->dev);
689 803
690 spin_lock_irqsave(&connlock, flags); 804 spin_lock_irqsave(&connlock, flags);
691 list_add(&conn->conn_list, &connlist); 805 list_add(&conn->conn_list, &connlist);
692 list_add(&conn->session_list, &session->connections);
693 conn->active = 1; 806 conn->active = 1;
694 spin_unlock_irqrestore(&connlock, flags); 807 spin_unlock_irqrestore(&connlock, flags);
695 808
696 scsi_host_put(shost); 809 scsi_host_put(shost);
697 return 0; 810 return 0;
698 811
699out_release_parent_ref: 812free_pdu_pool:
813 mempool_zone_destroy(conn->z_pdu);
814destroy_conn:
815 if (transport->destroy_conn)
816 transport->destroy_conn(conn->dd_data);
817release_ref:
700 scsi_host_put(shost); 818 scsi_host_put(shost);
701out_destroy_conn: 819 return -ENOMEM;
702 transport->destroy_conn(ev->r.handle);
703out_free_error_pool:
704 mempool_destroy(conn->z_error.pool);
705out_free_pdu_pool:
706 mempool_destroy(conn->z_pdu.pool);
707out_free_conn:
708 kfree(conn);
709out_release_ref:
710 scsi_host_put(shost);
711 return error;
712} 820}
713 821
714static int 822static int
715iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev) 823iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
716{ 824{
717 unsigned long flags; 825 unsigned long flags;
718 struct iscsi_if_conn *conn; 826 struct iscsi_cls_conn *conn;
827 struct mempool_zone *z_error, *z_pdu;
719 828
720 conn = iscsi_if_find_conn(ev->u.d_conn.conn_handle); 829 conn = iscsi_if_find_conn(ev->u.d_conn.conn_handle);
721 if (!conn) 830 if (!conn)
722 return -EEXIST; 831 return -EEXIST;
723 832
724 transport->destroy_conn(ev->u.d_conn.conn_handle); 833 if (!transport->destroy_conn)
834 return -EINVAL;
725 835
726 spin_lock_irqsave(&connlock, flags); 836 spin_lock_irqsave(&connlock, flags);
727 conn->active = 0; 837 conn->active = 0;
728 list_del(&conn->conn_list); 838 list_del(&conn->conn_list);
729 spin_unlock_irqrestore(&connlock, flags); 839 spin_unlock_irqrestore(&connlock, flags);
730 840
731 transport_unregister_device(&conn->dev); 841 z_pdu = conn->z_pdu;
732 device_unregister(&conn->dev); 842 z_error = conn->z_error;
733 return 0;
734}
735
736static int
737iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
738 struct nlmsghdr *nlh)
739{
740 struct iscsi_uevent *ev = NLMSG_DATA(nlh);
741 struct iscsi_stats *stats;
742 struct sk_buff *skbstat;
743 struct iscsi_if_conn *conn;
744 struct nlmsghdr *nlhstat;
745 struct iscsi_uevent *evstat;
746 int len = NLMSG_SPACE(sizeof(*ev) +
747 sizeof(struct iscsi_stats) +
748 sizeof(struct iscsi_stats_custom) *
749 ISCSI_STATS_CUSTOM_MAX);
750 int err = 0;
751
752 conn = iscsi_if_find_conn(ev->u.get_stats.conn_handle);
753 if (!conn)
754 return -EEXIST;
755
756 do {
757 int actual_size;
758
759 mempool_zone_complete(&conn->z_pdu);
760
761 skbstat = mempool_zone_get_skb(&conn->z_pdu);
762 if (!skbstat) {
763 printk(KERN_ERR "iscsi%d: can not deliver stats: OOM\n",
764 conn->host->host_no);
765 return -ENOMEM;
766 }
767
768 nlhstat = __nlmsg_put(skbstat, daemon_pid, 0, 0,
769 (len - sizeof(*nlhstat)), 0);
770 evstat = NLMSG_DATA(nlhstat);
771 memset(evstat, 0, sizeof(*evstat));
772 evstat->transport_handle = iscsi_handle(conn->transport);
773 evstat->type = nlh->nlmsg_type;
774 if (atomic_read(&conn->z_pdu.allocated) >= conn->z_pdu.hiwat)
775 evstat->iferror = -ENOMEM;
776 evstat->u.get_stats.conn_handle =
777 ev->u.get_stats.conn_handle;
778 stats = (struct iscsi_stats *)
779 ((char*)evstat + sizeof(*evstat));
780 memset(stats, 0, sizeof(*stats));
781 843
782 transport->get_stats(ev->u.get_stats.conn_handle, stats); 844 if (transport->destroy_conn)
783 actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) + 845 transport->destroy_conn(conn);
784 sizeof(struct iscsi_stats) +
785 sizeof(struct iscsi_stats_custom) *
786 stats->custom_length);
787 actual_size -= sizeof(*nlhstat);
788 actual_size = NLMSG_LENGTH(actual_size);
789 skb_trim(skb, NLMSG_ALIGN(actual_size));
790 nlhstat->nlmsg_len = actual_size;
791 846
792 err = iscsi_unicast_skb(&conn->z_pdu, skbstat); 847 mempool_zone_destroy(z_pdu);
793 } while (err < 0 && err != -ECONNREFUSED); 848 mempool_zone_destroy(z_error);
794 849
795 return err; 850 return 0;
796} 851}
797 852
798static int 853static int
@@ -916,8 +971,8 @@ iscsi_if_rx(struct sock *sk, int len)
916 err = iscsi_if_send_reply( 971 err = iscsi_if_send_reply(
917 NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq, 972 NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq,
918 nlh->nlmsg_type, 0, 0, ev, sizeof(*ev)); 973 nlh->nlmsg_type, 0, 0, ev, sizeof(*ev));
919 if (atomic_read(&z_reply.allocated) >= 974 if (atomic_read(&z_reply->allocated) >=
920 z_reply.hiwat) 975 z_reply->hiwat)
921 ev->iferror = -ENOMEM; 976 ev->iferror = -ENOMEM;
922 } while (err < 0 && err != -ECONNREFUSED); 977 } while (err < 0 && err != -ECONNREFUSED);
923 skb_pull(skb, rlen); 978 skb_pull(skb, rlen);
@@ -927,6 +982,9 @@ iscsi_if_rx(struct sock *sk, int len)
927 mutex_unlock(&rx_queue_mutex); 982 mutex_unlock(&rx_queue_mutex);
928} 983}
929 984
985#define iscsi_cdev_to_conn(_cdev) \
986 iscsi_dev_to_conn(_cdev->dev)
987
930/* 988/*
931 * iSCSI connection attrs 989 * iSCSI connection attrs
932 */ 990 */
@@ -935,12 +993,10 @@ static ssize_t \
935show_conn_int_param_##param(struct class_device *cdev, char *buf) \ 993show_conn_int_param_##param(struct class_device *cdev, char *buf) \
936{ \ 994{ \
937 uint32_t value = 0; \ 995 uint32_t value = 0; \
938 struct iscsi_if_conn *conn = iscsi_cdev_to_if_conn(cdev); \ 996 struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \
939 struct iscsi_internal *priv; \ 997 struct iscsi_transport *t = conn->transport; \
940 \ 998 \
941 priv = to_iscsi_internal(conn->host->transportt); \ 999 t->get_conn_param(conn->dd_data, param, &value); \
942 if (priv->param_mask & (1 << param)) \
943 priv->iscsi_transport->get_param(conn->connh, param, &value); \
944 return snprintf(buf, 20, format"\n", value); \ 1000 return snprintf(buf, 20, format"\n", value); \
945} 1001}
946 1002
@@ -955,6 +1011,9 @@ iscsi_conn_int_attr(data_digest, ISCSI_PARAM_DATADGST_EN, "%d");
955iscsi_conn_int_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN, "%d"); 1011iscsi_conn_int_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN, "%d");
956iscsi_conn_int_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN, "%d"); 1012iscsi_conn_int_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN, "%d");
957 1013
1014#define iscsi_cdev_to_session(_cdev) \
1015 iscsi_dev_to_session(_cdev->dev)
1016
958/* 1017/*
959 * iSCSI session attrs 1018 * iSCSI session attrs
960 */ 1019 */
@@ -963,20 +1022,11 @@ static ssize_t \
963show_session_int_param_##param(struct class_device *cdev, char *buf) \ 1022show_session_int_param_##param(struct class_device *cdev, char *buf) \
964{ \ 1023{ \
965 uint32_t value = 0; \ 1024 uint32_t value = 0; \
966 struct iscsi_if_session *session = iscsi_cdev_to_if_session(cdev); \ 1025 struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
967 struct Scsi_Host *shost = iscsi_if_session_to_shost(session); \ 1026 struct Scsi_Host *shost = iscsi_session_to_shost(session); \
968 struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \ 1027 struct iscsi_transport *t = session->transport; \
969 struct iscsi_if_conn *conn = NULL; \
970 unsigned long flags; \
971 \
972 spin_lock_irqsave(&connlock, flags); \
973 if (!list_empty(&session->connections)) \
974 conn = list_entry(session->connections.next, \
975 struct iscsi_if_conn, session_list); \
976 spin_unlock_irqrestore(&connlock, flags); \
977 \ 1028 \
978 if (conn && (priv->param_mask & (1 << param))) \ 1029 t->get_session_param(shost, param, &value); \
979 priv->iscsi_transport->get_param(conn->connh, param, &value);\
980 return snprintf(buf, 20, format"\n", value); \ 1030 return snprintf(buf, 20, format"\n", value); \
981} 1031}
982 1032
@@ -1005,23 +1055,18 @@ iscsi_session_int_attr(erl, ISCSI_PARAM_ERL, "%d");
1005 count++; \ 1055 count++; \
1006 } 1056 }
1007 1057
1008static int iscsi_is_session_dev(const struct device *dev)
1009{
1010 return dev->release == iscsi_if_session_dev_release;
1011}
1012
1013static int iscsi_session_match(struct attribute_container *cont, 1058static int iscsi_session_match(struct attribute_container *cont,
1014 struct device *dev) 1059 struct device *dev)
1015{ 1060{
1016 struct iscsi_if_session *session; 1061 struct iscsi_cls_session *session;
1017 struct Scsi_Host *shost; 1062 struct Scsi_Host *shost;
1018 struct iscsi_internal *priv; 1063 struct iscsi_internal *priv;
1019 1064
1020 if (!iscsi_is_session_dev(dev)) 1065 if (!iscsi_is_session_dev(dev))
1021 return 0; 1066 return 0;
1022 1067
1023 session = iscsi_dev_to_if_session(dev); 1068 session = iscsi_dev_to_session(dev);
1024 shost = iscsi_if_session_to_shost(session); 1069 shost = iscsi_session_to_shost(session);
1025 if (!shost->transportt) 1070 if (!shost->transportt)
1026 return 0; 1071 return 0;
1027 1072
@@ -1032,23 +1077,21 @@ static int iscsi_session_match(struct attribute_container *cont,
1032 return &priv->session_cont.ac == cont; 1077 return &priv->session_cont.ac == cont;
1033} 1078}
1034 1079
1035static int iscsi_is_conn_dev(const struct device *dev)
1036{
1037 return dev->release == iscsi_if_conn_dev_release;
1038}
1039
1040static int iscsi_conn_match(struct attribute_container *cont, 1080static int iscsi_conn_match(struct attribute_container *cont,
1041 struct device *dev) 1081 struct device *dev)
1042{ 1082{
1043 struct iscsi_if_conn *conn; 1083 struct iscsi_cls_session *session;
1084 struct iscsi_cls_conn *conn;
1044 struct Scsi_Host *shost; 1085 struct Scsi_Host *shost;
1045 struct iscsi_internal *priv; 1086 struct iscsi_internal *priv;
1046 1087
1047 if (!iscsi_is_conn_dev(dev)) 1088 if (!iscsi_is_conn_dev(dev))
1048 return 0; 1089 return 0;
1049 1090
1050 conn = iscsi_dev_to_if_conn(dev); 1091 conn = iscsi_dev_to_conn(dev);
1051 shost = conn->host; 1092 session = iscsi_dev_to_session(conn->dev.parent);
1093 shost = iscsi_session_to_shost(session);
1094
1052 if (!shost->transportt) 1095 if (!shost->transportt)
1053 return 0; 1096 return 0;
1054 1097
@@ -1059,7 +1102,8 @@ static int iscsi_conn_match(struct attribute_container *cont,
1059 return &priv->conn_cont.ac == cont; 1102 return &priv->conn_cont.ac == cont;
1060} 1103}
1061 1104
1062int iscsi_register_transport(struct iscsi_transport *tt) 1105struct scsi_transport_template *
1106iscsi_register_transport(struct iscsi_transport *tt)
1063{ 1107{
1064 struct iscsi_internal *priv; 1108 struct iscsi_internal *priv;
1065 unsigned long flags; 1109 unsigned long flags;
@@ -1069,15 +1113,14 @@ int iscsi_register_transport(struct iscsi_transport *tt)
1069 1113
1070 priv = iscsi_if_transport_lookup(tt); 1114 priv = iscsi_if_transport_lookup(tt);
1071 if (priv) 1115 if (priv)
1072 return -EEXIST; 1116 return NULL;
1073 1117
1074 priv = kmalloc(sizeof(*priv), GFP_KERNEL); 1118 priv = kmalloc(sizeof(*priv), GFP_KERNEL);
1075 if (!priv) 1119 if (!priv)
1076 return -ENOMEM; 1120 return NULL;
1077 memset(priv, 0, sizeof(*priv)); 1121 memset(priv, 0, sizeof(*priv));
1078 INIT_LIST_HEAD(&priv->list); 1122 INIT_LIST_HEAD(&priv->list);
1079 INIT_LIST_HEAD(&priv->sessions); 1123 INIT_LIST_HEAD(&priv->sessions);
1080 spin_lock_init(&priv->session_lock);
1081 priv->iscsi_transport = tt; 1124 priv->iscsi_transport = tt;
1082 1125
1083 priv->cdev.class = &iscsi_transport_class; 1126 priv->cdev.class = &iscsi_transport_class;
@@ -1143,13 +1186,13 @@ int iscsi_register_transport(struct iscsi_transport *tt)
1143 spin_unlock_irqrestore(&iscsi_transport_lock, flags); 1186 spin_unlock_irqrestore(&iscsi_transport_lock, flags);
1144 1187
1145 printk(KERN_NOTICE "iscsi: registered transport (%s)\n", tt->name); 1188 printk(KERN_NOTICE "iscsi: registered transport (%s)\n", tt->name);
1146 return 0; 1189 return &priv->t;
1147 1190
1148unregister_cdev: 1191unregister_cdev:
1149 class_device_unregister(&priv->cdev); 1192 class_device_unregister(&priv->cdev);
1150free_priv: 1193free_priv:
1151 kfree(priv); 1194 kfree(priv);
1152 return err; 1195 return NULL;
1153} 1196}
1154EXPORT_SYMBOL_GPL(iscsi_register_transport); 1197EXPORT_SYMBOL_GPL(iscsi_register_transport);
1155 1198
@@ -1165,14 +1208,6 @@ int iscsi_unregister_transport(struct iscsi_transport *tt)
1165 priv = iscsi_if_transport_lookup(tt); 1208 priv = iscsi_if_transport_lookup(tt);
1166 BUG_ON (!priv); 1209 BUG_ON (!priv);
1167 1210
1168 spin_lock_irqsave(&priv->session_lock, flags);
1169 if (!list_empty(&priv->sessions)) {
1170 spin_unlock_irqrestore(&priv->session_lock, flags);
1171 mutex_unlock(&rx_queue_mutex);
1172 return -EPERM;
1173 }
1174 spin_unlock_irqrestore(&priv->session_lock, flags);
1175
1176 spin_lock_irqsave(&iscsi_transport_lock, flags); 1211 spin_lock_irqsave(&iscsi_transport_lock, flags);
1177 list_del(&priv->list); 1212 list_del(&priv->list);
1178 spin_unlock_irqrestore(&iscsi_transport_lock, flags); 1213 spin_unlock_irqrestore(&iscsi_transport_lock, flags);
@@ -1195,14 +1230,14 @@ iscsi_rcv_nl_event(struct notifier_block *this, unsigned long event, void *ptr)
1195 1230
1196 if (event == NETLINK_URELEASE && 1231 if (event == NETLINK_URELEASE &&
1197 n->protocol == NETLINK_ISCSI && n->pid) { 1232 n->protocol == NETLINK_ISCSI && n->pid) {
1198 struct iscsi_if_conn *conn; 1233 struct iscsi_cls_conn *conn;
1199 unsigned long flags; 1234 unsigned long flags;
1200 1235
1201 mempool_zone_complete(&z_reply); 1236 mempool_zone_complete(z_reply);
1202 spin_lock_irqsave(&connlock, flags); 1237 spin_lock_irqsave(&connlock, flags);
1203 list_for_each_entry(conn, &connlist, conn_list) { 1238 list_for_each_entry(conn, &connlist, conn_list) {
1204 mempool_zone_complete(&conn->z_error); 1239 mempool_zone_complete(conn->z_error);
1205 mempool_zone_complete(&conn->z_pdu); 1240 mempool_zone_complete(conn->z_pdu);
1206 } 1241 }
1207 spin_unlock_irqrestore(&connlock, flags); 1242 spin_unlock_irqrestore(&connlock, flags);
1208 } 1243 }
@@ -1235,15 +1270,15 @@ static __init int iscsi_transport_init(void)
1235 goto unregister_session_class; 1270 goto unregister_session_class;
1236 1271
1237 nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx, 1272 nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx,
1238 THIS_MODULE); 1273 THIS_MODULE);
1239 if (!nls) { 1274 if (!nls) {
1240 err = -ENOBUFS; 1275 err = -ENOBUFS;
1241 goto unregister_notifier; 1276 goto unregister_notifier;
1242 } 1277 }
1243 1278
1244 err = mempool_zone_init(&z_reply, Z_MAX_REPLY, 1279 z_reply = mempool_zone_init(Z_MAX_REPLY,
1245 NLMSG_SPACE(sizeof(struct iscsi_uevent)), Z_HIWAT_REPLY); 1280 NLMSG_SPACE(sizeof(struct iscsi_uevent)), Z_HIWAT_REPLY);
1246 if (!err) 1281 if (z_reply)
1247 return 0; 1282 return 0;
1248 1283
1249 sock_release(nls->sk_socket); 1284 sock_release(nls->sk_socket);
@@ -1260,7 +1295,7 @@ unregister_transport_class:
1260 1295
1261static void __exit iscsi_transport_exit(void) 1296static void __exit iscsi_transport_exit(void)
1262{ 1297{
1263 mempool_destroy(z_reply.pool); 1298 mempool_zone_destroy(z_reply);
1264 sock_release(nls->sk_socket); 1299 sock_release(nls->sk_socket);
1265 netlink_unregister_notifier(&iscsi_nl_notifier); 1300 netlink_unregister_notifier(&iscsi_nl_notifier);
1266 transport_class_unregister(&iscsi_connection_class); 1301 transport_class_unregister(&iscsi_connection_class);