aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_transport_iscsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_transport_iscsi.c')
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c859
1 files changed, 448 insertions, 411 deletions
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index e08462d50c97..59a1c9d9d3bd 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -21,11 +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>
25#include <linux/mutex.h>
27#include <net/tcp.h> 26#include <net/tcp.h>
28
29#include <scsi/scsi.h> 27#include <scsi/scsi.h>
30#include <scsi/scsi_host.h> 28#include <scsi/scsi_host.h>
31#include <scsi/scsi_device.h> 29#include <scsi/scsi_device.h>
@@ -45,11 +43,6 @@ struct iscsi_internal {
45 */ 43 */
46 struct list_head sessions; 44 struct list_head sessions;
47 /* 45 /*
48 * lock to serialize access to the sessions list which must
49 * be taken after the rx_queue_sema
50 */
51 spinlock_t session_lock;
52 /*
53 * based on transport capabilities, at register time we set these 46 * based on transport capabilities, at register time we set these
54 * bits to tell the transport class it wants attributes displayed 47 * bits to tell the transport class it wants attributes displayed
55 * in sysfs or that it can support different iSCSI Data-Path 48 * in sysfs or that it can support different iSCSI Data-Path
@@ -70,7 +63,7 @@ struct iscsi_internal {
70/* 63/*
71 * list of registered transports and lock that must 64 * list of registered transports and lock that must
72 * be held while accessing list. The iscsi_transport_lock must 65 * be held while accessing list. The iscsi_transport_lock must
73 * be acquired after the rx_queue_sema. 66 * be acquired after the rx_queue_mutex.
74 */ 67 */
75static LIST_HEAD(iscsi_transports); 68static LIST_HEAD(iscsi_transports);
76static DEFINE_SPINLOCK(iscsi_transport_lock); 69static DEFINE_SPINLOCK(iscsi_transport_lock);
@@ -145,7 +138,7 @@ static DECLARE_TRANSPORT_CLASS(iscsi_connection_class,
145 138
146static struct sock *nls; 139static struct sock *nls;
147static int daemon_pid; 140static int daemon_pid;
148static DECLARE_MUTEX(rx_queue_sema); 141static DEFINE_MUTEX(rx_queue_mutex);
149 142
150struct mempool_zone { 143struct mempool_zone {
151 mempool_t *pool; 144 mempool_t *pool;
@@ -156,7 +149,7 @@ struct mempool_zone {
156 spinlock_t freelock; 149 spinlock_t freelock;
157}; 150};
158 151
159static struct mempool_zone z_reply; 152static struct mempool_zone *z_reply;
160 153
161/* 154/*
162 * 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
@@ -171,50 +164,271 @@ static struct mempool_zone z_reply;
171#define Z_MAX_ERROR 16 164#define Z_MAX_ERROR 16
172#define Z_HIWAT_ERROR 12 165#define Z_HIWAT_ERROR 12
173 166
174struct iscsi_if_conn { 167static LIST_HEAD(connlist);
175 struct list_head conn_list; /* item in connlist */ 168static DEFINE_SPINLOCK(connlock);
176 struct list_head session_list; /* item in session->connections */
177 iscsi_connh_t connh;
178 int active; /* must be accessed with the connlock */
179 struct Scsi_Host *host; /* originated shost */
180 struct device dev; /* sysfs transport/container device */
181 struct iscsi_transport *transport;
182 struct mempool_zone z_error;
183 struct mempool_zone z_pdu;
184 struct list_head freequeue;
185};
186 169
187#define iscsi_dev_to_if_conn(_dev) \ 170/*
188 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;
189 179
190#define iscsi_cdev_to_if_conn(_cdev) \ 180 shost = iscsi_session_to_shost(session);
191 iscsi_dev_to_if_conn(_cdev->dev) 181 scsi_host_put(shost);
182 kfree(session);
183 module_put(transport->owner);
184}
192 185
193static LIST_HEAD(connlist); 186static int iscsi_is_session_dev(const struct device *dev)
194static DEFINE_SPINLOCK(connlock); 187{
188 return dev->release == iscsi_session_release;
189}
195 190
196struct iscsi_if_session { 191/**
197 struct list_head list; /* item in session_list */ 192 * iscsi_create_session - create iscsi class session
198 struct list_head connections; 193 * @shost: scsi host
199 iscsi_sessionh_t sessionh; 194 * @transport: iscsi transport
200 struct iscsi_transport *transport; 195 *
201 struct device dev; /* sysfs transport/container device */ 196 * This can be called from a LLD or iscsi_transport
202}; 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 shost->transportt->create_work_queue = 1;
383
384 if (scsi_add_host(shost, NULL))
385 goto free_host;
386
387 session = iscsi_create_session(shost, transport);
388 if (!session)
389 goto remove_host;
203 390
204#define iscsi_dev_to_if_session(_dev) \ 391 *(unsigned long*)shost->hostdata = (unsigned long)session;
205 container_of(_dev, struct iscsi_if_session, dev) 392 return shost;
393
394remove_host:
395 scsi_remove_host(shost);
396free_host:
397 scsi_host_put(shost);
398 return NULL;
399}
206 400
207#define iscsi_cdev_to_if_session(_cdev) \ 401EXPORT_SYMBOL_GPL(iscsi_transport_create_session);
208 iscsi_dev_to_if_session(_cdev->dev)
209 402
210#define iscsi_if_session_to_shost(_session) \ 403/**
211 dev_to_shost(_session->dev.parent) 404 * iscsi_transport_destroy_session - destroy session and scsi host
405 * shost: scsi host
406 *
407 * This can be used by software iscsi_transports that allocate
408 * a session per scsi host.
409 **/
410int iscsi_transport_destroy_session(struct Scsi_Host *shost)
411{
412 struct iscsi_cls_session *session;
212 413
213static struct iscsi_if_conn* 414 scsi_remove_host(shost);
415 session = hostdata_session(shost->hostdata);
416 iscsi_destroy_session(session);
417 /* ref from host alloc */
418 scsi_host_put(shost);
419 return 0;
420}
421
422EXPORT_SYMBOL_GPL(iscsi_transport_destroy_session);
423
424/*
425 * iscsi interface functions
426 */
427static struct iscsi_cls_conn*
214iscsi_if_find_conn(uint64_t key) 428iscsi_if_find_conn(uint64_t key)
215{ 429{
216 unsigned long flags; 430 unsigned long flags;
217 struct iscsi_if_conn *conn; 431 struct iscsi_cls_conn *conn;
218 432
219 spin_lock_irqsave(&connlock, flags); 433 spin_lock_irqsave(&connlock, flags);
220 list_for_each_entry(conn, &connlist, conn_list) 434 list_for_each_entry(conn, &connlist, conn_list)
@@ -249,7 +463,7 @@ static inline struct list_head *skb_to_lh(struct sk_buff *skb)
249} 463}
250 464
251static void* 465static void*
252mempool_zone_alloc_skb(gfp_t gfp_mask, void *pool_data) 466mempool_zone_alloc_skb(unsigned int gfp_mask, void *pool_data)
253{ 467{
254 struct mempool_zone *zone = pool_data; 468 struct mempool_zone *zone = pool_data;
255 469
@@ -281,14 +495,21 @@ mempool_zone_complete(struct mempool_zone *zone)
281 spin_unlock_irqrestore(&zone->freelock, flags); 495 spin_unlock_irqrestore(&zone->freelock, flags);
282} 496}
283 497
284static int 498static struct mempool_zone *
285mempool_zone_init(struct mempool_zone *zp, unsigned max, unsigned size, 499mempool_zone_init(unsigned max, unsigned size, unsigned hiwat)
286 unsigned hiwat)
287{ 500{
501 struct mempool_zone *zp;
502
503 zp = kzalloc(sizeof(*zp), GFP_KERNEL);
504 if (!zp)
505 return NULL;
506
288 zp->pool = mempool_create(max, mempool_zone_alloc_skb, 507 zp->pool = mempool_create(max, mempool_zone_alloc_skb,
289 mempool_zone_free_skb, zp); 508 mempool_zone_free_skb, zp);
290 if (!zp->pool) 509 if (!zp->pool) {
291 return -ENOMEM; 510 kfree(zp);
511 return NULL;
512 }
292 513
293 zp->size = size; 514 zp->size = size;
294 zp->hiwat = hiwat; 515 zp->hiwat = hiwat;
@@ -297,9 +518,14 @@ mempool_zone_init(struct mempool_zone *zp, unsigned max, unsigned size,
297 spin_lock_init(&zp->freelock); 518 spin_lock_init(&zp->freelock);
298 atomic_set(&zp->allocated, 0); 519 atomic_set(&zp->allocated, 0);
299 520
300 return 0; 521 return zp;
301} 522}
302 523
524static void mempool_zone_destroy(struct mempool_zone *zp)
525{
526 mempool_destroy(zp->pool);
527 kfree(zp);
528}
303 529
304static struct sk_buff* 530static struct sk_buff*
305mempool_zone_get_skb(struct mempool_zone *zone) 531mempool_zone_get_skb(struct mempool_zone *zone)
@@ -339,7 +565,7 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
339 struct nlmsghdr *nlh; 565 struct nlmsghdr *nlh;
340 struct sk_buff *skb; 566 struct sk_buff *skb;
341 struct iscsi_uevent *ev; 567 struct iscsi_uevent *ev;
342 struct iscsi_if_conn *conn; 568 struct iscsi_cls_conn *conn;
343 char *pdu; 569 char *pdu;
344 int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) + 570 int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) +
345 data_size); 571 data_size);
@@ -347,13 +573,13 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
347 conn = iscsi_if_find_conn(connh); 573 conn = iscsi_if_find_conn(connh);
348 BUG_ON(!conn); 574 BUG_ON(!conn);
349 575
350 mempool_zone_complete(&conn->z_pdu); 576 mempool_zone_complete(conn->z_pdu);
351 577
352 skb = mempool_zone_get_skb(&conn->z_pdu); 578 skb = mempool_zone_get_skb(conn->z_pdu);
353 if (!skb) { 579 if (!skb) {
354 iscsi_conn_error(connh, ISCSI_ERR_CONN_FAILED); 580 iscsi_conn_error(connh, ISCSI_ERR_CONN_FAILED);
355 printk(KERN_ERR "iscsi%d: can not deliver control PDU: OOM\n", 581 dev_printk(KERN_ERR, &conn->dev, "iscsi: can not deliver "
356 conn->host->host_no); 582 "control PDU: OOM\n");
357 return -ENOMEM; 583 return -ENOMEM;
358 } 584 }
359 585
@@ -362,14 +588,14 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
362 memset(ev, 0, sizeof(*ev)); 588 memset(ev, 0, sizeof(*ev));
363 ev->transport_handle = iscsi_handle(conn->transport); 589 ev->transport_handle = iscsi_handle(conn->transport);
364 ev->type = ISCSI_KEVENT_RECV_PDU; 590 ev->type = ISCSI_KEVENT_RECV_PDU;
365 if (atomic_read(&conn->z_pdu.allocated) >= conn->z_pdu.hiwat) 591 if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
366 ev->iferror = -ENOMEM; 592 ev->iferror = -ENOMEM;
367 ev->r.recv_req.conn_handle = connh; 593 ev->r.recv_req.conn_handle = connh;
368 pdu = (char*)ev + sizeof(*ev); 594 pdu = (char*)ev + sizeof(*ev);
369 memcpy(pdu, hdr, sizeof(struct iscsi_hdr)); 595 memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
370 memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size); 596 memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
371 597
372 return iscsi_unicast_skb(&conn->z_pdu, skb); 598 return iscsi_unicast_skb(conn->z_pdu, skb);
373} 599}
374EXPORT_SYMBOL_GPL(iscsi_recv_pdu); 600EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
375 601
@@ -378,18 +604,18 @@ void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error)
378 struct nlmsghdr *nlh; 604 struct nlmsghdr *nlh;
379 struct sk_buff *skb; 605 struct sk_buff *skb;
380 struct iscsi_uevent *ev; 606 struct iscsi_uevent *ev;
381 struct iscsi_if_conn *conn; 607 struct iscsi_cls_conn *conn;
382 int len = NLMSG_SPACE(sizeof(*ev)); 608 int len = NLMSG_SPACE(sizeof(*ev));
383 609
384 conn = iscsi_if_find_conn(connh); 610 conn = iscsi_if_find_conn(connh);
385 BUG_ON(!conn); 611 BUG_ON(!conn);
386 612
387 mempool_zone_complete(&conn->z_error); 613 mempool_zone_complete(conn->z_error);
388 614
389 skb = mempool_zone_get_skb(&conn->z_error); 615 skb = mempool_zone_get_skb(conn->z_error);
390 if (!skb) { 616 if (!skb) {
391 printk(KERN_ERR "iscsi%d: gracefully ignored conn error (%d)\n", 617 dev_printk(KERN_ERR, &conn->dev, "iscsi: gracefully ignored "
392 conn->host->host_no, error); 618 "conn error (%d)\n", error);
393 return; 619 return;
394 } 620 }
395 621
@@ -397,15 +623,15 @@ void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error)
397 ev = NLMSG_DATA(nlh); 623 ev = NLMSG_DATA(nlh);
398 ev->transport_handle = iscsi_handle(conn->transport); 624 ev->transport_handle = iscsi_handle(conn->transport);
399 ev->type = ISCSI_KEVENT_CONN_ERROR; 625 ev->type = ISCSI_KEVENT_CONN_ERROR;
400 if (atomic_read(&conn->z_error.allocated) >= conn->z_error.hiwat) 626 if (atomic_read(&conn->z_error->allocated) >= conn->z_error->hiwat)
401 ev->iferror = -ENOMEM; 627 ev->iferror = -ENOMEM;
402 ev->r.connerror.error = error; 628 ev->r.connerror.error = error;
403 ev->r.connerror.conn_handle = connh; 629 ev->r.connerror.conn_handle = connh;
404 630
405 iscsi_unicast_skb(&conn->z_error, skb); 631 iscsi_unicast_skb(conn->z_error, skb);
406 632
407 printk(KERN_INFO "iscsi%d: detected conn error (%d)\n", 633 dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n",
408 conn->host->host_no, error); 634 error);
409} 635}
410EXPORT_SYMBOL_GPL(iscsi_conn_error); 636EXPORT_SYMBOL_GPL(iscsi_conn_error);
411 637
@@ -419,9 +645,9 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi,
419 int flags = multi ? NLM_F_MULTI : 0; 645 int flags = multi ? NLM_F_MULTI : 0;
420 int t = done ? NLMSG_DONE : type; 646 int t = done ? NLMSG_DONE : type;
421 647
422 mempool_zone_complete(&z_reply); 648 mempool_zone_complete(z_reply);
423 649
424 skb = mempool_zone_get_skb(&z_reply); 650 skb = mempool_zone_get_skb(z_reply);
425 /* 651 /*
426 * FIXME: 652 * FIXME:
427 * user is supposed to react on iferror == -ENOMEM; 653 * user is supposed to react on iferror == -ENOMEM;
@@ -432,366 +658,197 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi,
432 nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0); 658 nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0);
433 nlh->nlmsg_flags = flags; 659 nlh->nlmsg_flags = flags;
434 memcpy(NLMSG_DATA(nlh), payload, size); 660 memcpy(NLMSG_DATA(nlh), payload, size);
435 return iscsi_unicast_skb(&z_reply, skb); 661 return iscsi_unicast_skb(z_reply, skb);
436} 662}
437 663
438/* 664static int
439 * iSCSI Session's hostdata organization: 665iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
440 * 666 struct nlmsghdr *nlh)
441 * *------------------* <== host->hostdata 667{
442 * | transport | 668 struct iscsi_uevent *ev = NLMSG_DATA(nlh);
443 * |------------------| <== iscsi_hostdata(host->hostdata) 669 struct iscsi_stats *stats;
444 * | transport's data | 670 struct sk_buff *skbstat;
445 * |------------------| <== hostdata_session(host->hostdata) 671 struct iscsi_cls_conn *conn;
446 * | interface's data | 672 struct nlmsghdr *nlhstat;
447 * *------------------* 673 struct iscsi_uevent *evstat;
448 */ 674 int len = NLMSG_SPACE(sizeof(*ev) +
675 sizeof(struct iscsi_stats) +
676 sizeof(struct iscsi_stats_custom) *
677 ISCSI_STATS_CUSTOM_MAX);
678 int err = 0;
449 679
450#define hostdata_privsize(_t) (sizeof(unsigned long) + _t->hostdata_size + \ 680 conn = iscsi_if_find_conn(ev->u.get_stats.conn_handle);
451 _t->hostdata_size % sizeof(unsigned long) + \ 681 if (!conn)
452 sizeof(struct iscsi_if_session)) 682 return -EEXIST;
453 683
454#define hostdata_session(_hostdata) ((void*)_hostdata + sizeof(unsigned long) + \ 684 do {
455 ((struct iscsi_transport *) \ 685 int actual_size;
456 iscsi_ptr(*(uint64_t *)_hostdata))->hostdata_size)
457 686
458static void iscsi_if_session_dev_release(struct device *dev) 687 mempool_zone_complete(conn->z_pdu);
459{
460 struct iscsi_if_session *session = iscsi_dev_to_if_session(dev);
461 struct iscsi_transport *transport = session->transport;
462 struct Scsi_Host *shost = iscsi_if_session_to_shost(session);
463 struct iscsi_if_conn *conn, *tmp;
464 unsigned long flags;
465 688
466 /* now free connections */ 689 skbstat = mempool_zone_get_skb(conn->z_pdu);
467 spin_lock_irqsave(&connlock, flags); 690 if (!skbstat) {
468 list_for_each_entry_safe(conn, tmp, &session->connections, 691 dev_printk(KERN_ERR, &conn->dev, "iscsi: can not "
469 session_list) { 692 "deliver stats: OOM\n");
470 list_del(&conn->session_list); 693 return -ENOMEM;
471 mempool_destroy(conn->z_pdu.pool); 694 }
472 mempool_destroy(conn->z_error.pool); 695
473 kfree(conn); 696 nlhstat = __nlmsg_put(skbstat, daemon_pid, 0, 0,
474 } 697 (len - sizeof(*nlhstat)), 0);
475 spin_unlock_irqrestore(&connlock, flags); 698 evstat = NLMSG_DATA(nlhstat);
476 scsi_host_put(shost); 699 memset(evstat, 0, sizeof(*evstat));
477 module_put(transport->owner); 700 evstat->transport_handle = iscsi_handle(conn->transport);
701 evstat->type = nlh->nlmsg_type;
702 if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
703 evstat->iferror = -ENOMEM;
704 evstat->u.get_stats.conn_handle =
705 ev->u.get_stats.conn_handle;
706 stats = (struct iscsi_stats *)
707 ((char*)evstat + sizeof(*evstat));
708 memset(stats, 0, sizeof(*stats));
709
710 transport->get_stats(ev->u.get_stats.conn_handle, stats);
711 actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) +
712 sizeof(struct iscsi_stats) +
713 sizeof(struct iscsi_stats_custom) *
714 stats->custom_length);
715 actual_size -= sizeof(*nlhstat);
716 actual_size = NLMSG_LENGTH(actual_size);
717 skb_trim(skb, NLMSG_ALIGN(actual_size));
718 nlhstat->nlmsg_len = actual_size;
719
720 err = iscsi_unicast_skb(conn->z_pdu, skbstat);
721 } while (err < 0 && err != -ECONNREFUSED);
722
723 return err;
478} 724}
479 725
480static int 726static int
481iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev) 727iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
482{ 728{
483 struct iscsi_transport *transport = priv->iscsi_transport; 729 struct iscsi_transport *transport = priv->iscsi_transport;
484 struct iscsi_if_session *session;
485 struct Scsi_Host *shost; 730 struct Scsi_Host *shost;
486 unsigned long flags;
487 int error;
488
489 if (!try_module_get(transport->owner))
490 return -EPERM;
491 731
492 shost = scsi_host_alloc(transport->host_template, 732 if (!transport->create_session)
493 hostdata_privsize(transport)); 733 return -EINVAL;
494 if (!shost) {
495 ev->r.c_session_ret.session_handle = iscsi_handle(NULL);
496 printk(KERN_ERR "iscsi: can not allocate SCSI host for "
497 "session\n");
498 error = -ENOMEM;
499 goto out_module_put;
500 }
501 shost->max_id = 1;
502 shost->max_channel = 0;
503 shost->max_lun = transport->max_lun;
504 shost->max_cmd_len = transport->max_cmd_len;
505 shost->transportt = &priv->t;
506
507 /* store struct iscsi_transport in hostdata */
508 *(uint64_t*)shost->hostdata = ev->transport_handle;
509 734
510 ev->r.c_session_ret.session_handle = transport->create_session( 735 shost = transport->create_session(&priv->t,
511 ev->u.c_session.initial_cmdsn, shost); 736 ev->u.c_session.initial_cmdsn);
512 if (ev->r.c_session_ret.session_handle == iscsi_handle(NULL)) { 737 if (!shost)
513 error = 0; 738 return -ENOMEM;
514 goto out_host_put;
515 }
516 739
517 /* host_no becomes assigned SID */ 740 ev->r.c_session_ret.session_handle = iscsi_handle(iscsi_hostdata(shost->hostdata));
518 ev->r.c_session_ret.sid = shost->host_no; 741 ev->r.c_session_ret.sid = shost->host_no;
519 /* initialize session */
520 session = hostdata_session(shost->hostdata);
521 INIT_LIST_HEAD(&session->connections);
522 INIT_LIST_HEAD(&session->list);
523 session->sessionh = ev->r.c_session_ret.session_handle;
524 session->transport = transport;
525
526 error = scsi_add_host(shost, NULL);
527 if (error)
528 goto out_destroy_session;
529
530 /*
531 * this is released in the dev's release function)
532 */
533 scsi_host_get(shost);
534 snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", shost->host_no);
535 session->dev.parent = &shost->shost_gendev;
536 session->dev.release = iscsi_if_session_dev_release;
537 error = device_register(&session->dev);
538 if (error) {
539 printk(KERN_ERR "iscsi: could not register session%d's dev\n",
540 shost->host_no);
541 goto out_remove_host;
542 }
543 transport_register_device(&session->dev);
544
545 /* add this session to the list of active sessions */
546 spin_lock_irqsave(&priv->session_lock, flags);
547 list_add(&session->list, &priv->sessions);
548 spin_unlock_irqrestore(&priv->session_lock, flags);
549
550 return 0; 742 return 0;
551
552out_remove_host:
553 scsi_remove_host(shost);
554out_destroy_session:
555 transport->destroy_session(ev->r.c_session_ret.session_handle);
556 ev->r.c_session_ret.session_handle = iscsi_handle(NULL);
557out_host_put:
558 scsi_host_put(shost);
559out_module_put:
560 module_put(transport->owner);
561 return error;
562} 743}
563 744
564static int 745static int
565iscsi_if_destroy_session(struct iscsi_internal *priv, struct iscsi_uevent *ev) 746iscsi_if_destroy_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
566{ 747{
567 struct iscsi_transport *transport = priv->iscsi_transport; 748 struct iscsi_transport *transport = priv->iscsi_transport;
749
568 struct Scsi_Host *shost; 750 struct Scsi_Host *shost;
569 struct iscsi_if_session *session; 751
570 unsigned long flags; 752 if (!transport->destroy_session)
571 struct iscsi_if_conn *conn; 753 return -EINVAL;
572 int error = 0;
573 754
574 shost = scsi_host_lookup(ev->u.d_session.sid); 755 shost = scsi_host_lookup(ev->u.d_session.sid);
575 if (shost == ERR_PTR(-ENXIO)) 756 if (shost == ERR_PTR(-ENXIO))
576 return -EEXIST; 757 return -EEXIST;
577 session = hostdata_session(shost->hostdata);
578 758
579 /* check if we have active connections */ 759 if (transport->destroy_session)
580 spin_lock_irqsave(&connlock, flags); 760 transport->destroy_session(shost);
581 list_for_each_entry(conn, &session->connections, session_list) { 761 /* ref from host lookup */
582 if (conn->active) { 762 scsi_host_put(shost);
583 printk(KERN_ERR "iscsi%d: can not destroy session: " 763 return 0;
584 "has active connection (%p)\n",
585 shost->host_no, iscsi_ptr(conn->connh));
586 spin_unlock_irqrestore(&connlock, flags);
587 error = EIO;
588 goto out_release_ref;
589 }
590 }
591 spin_unlock_irqrestore(&connlock, flags);
592
593 scsi_remove_host(shost);
594 transport->destroy_session(ev->u.d_session.session_handle);
595 transport_unregister_device(&session->dev);
596 device_unregister(&session->dev);
597
598 /* remove this session from the list of active sessions */
599 spin_lock_irqsave(&priv->session_lock, flags);
600 list_del(&session->list);
601 spin_unlock_irqrestore(&priv->session_lock, flags);
602
603 /* ref from host alloc */
604 scsi_host_put(shost);
605out_release_ref:
606 /* ref from host lookup */
607 scsi_host_put(shost);
608 return error;
609}
610
611static void iscsi_if_conn_dev_release(struct device *dev)
612{
613 struct iscsi_if_conn *conn = iscsi_dev_to_if_conn(dev);
614 struct Scsi_Host *shost = conn->host;
615
616 scsi_host_put(shost);
617} 764}
618 765
619static int 766static int
620iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev) 767iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev){
621{
622 struct iscsi_if_session *session;
623 struct Scsi_Host *shost; 768 struct Scsi_Host *shost;
624 struct iscsi_if_conn *conn; 769 struct iscsi_cls_conn *conn;
625 unsigned long flags; 770 unsigned long flags;
626 int error; 771
772 if (!transport->create_conn)
773 return -EINVAL;
627 774
628 shost = scsi_host_lookup(ev->u.c_conn.sid); 775 shost = scsi_host_lookup(ev->u.c_conn.sid);
629 if (shost == ERR_PTR(-ENXIO)) 776 if (shost == ERR_PTR(-ENXIO))
630 return -EEXIST; 777 return -EEXIST;
631 session = hostdata_session(shost->hostdata);
632 778
633 conn = kmalloc(sizeof(struct iscsi_if_conn), GFP_KERNEL); 779 conn = transport->create_conn(shost, ev->u.c_conn.cid);
634 if (!conn) { 780 if (!conn)
635 error = -ENOMEM; 781 goto release_ref;
636 goto out_release_ref;
637 }
638 memset(conn, 0, sizeof(struct iscsi_if_conn));
639 INIT_LIST_HEAD(&conn->session_list);
640 INIT_LIST_HEAD(&conn->conn_list);
641 conn->host = shost;
642 conn->transport = transport;
643 782
644 error = mempool_zone_init(&conn->z_pdu, Z_MAX_PDU, 783 conn->z_pdu = mempool_zone_init(Z_MAX_PDU,
645 NLMSG_SPACE(sizeof(struct iscsi_uevent) + 784 NLMSG_SPACE(sizeof(struct iscsi_uevent) +
646 sizeof(struct iscsi_hdr) + 785 sizeof(struct iscsi_hdr) +
647 DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH), 786 DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH),
648 Z_HIWAT_PDU); 787 Z_HIWAT_PDU);
649 if (error) { 788 if (!conn->z_pdu) {
650 printk(KERN_ERR "iscsi%d: can not allocate pdu zone for new " 789 dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
651 "conn\n", shost->host_no); 790 "pdu zone for new conn\n");
652 goto out_free_conn; 791 goto destroy_conn;
653 } 792 }
654 error = mempool_zone_init(&conn->z_error, Z_MAX_ERROR, 793
794 conn->z_error = mempool_zone_init(Z_MAX_ERROR,
655 NLMSG_SPACE(sizeof(struct iscsi_uevent)), 795 NLMSG_SPACE(sizeof(struct iscsi_uevent)),
656 Z_HIWAT_ERROR); 796 Z_HIWAT_ERROR);
657 if (error) { 797 if (!conn->z_error) {
658 printk(KERN_ERR "iscsi%d: can not allocate error zone for " 798 dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
659 "new conn\n", shost->host_no); 799 "error zone for new conn\n");
660 goto out_free_pdu_pool; 800 goto free_pdu_pool;
661 }
662
663 ev->r.handle = transport->create_conn(ev->u.c_conn.session_handle,
664 ev->u.c_conn.cid);
665 if (!ev->r.handle) {
666 error = -ENODEV;
667 goto out_free_error_pool;
668 } 801 }
669 802
670 conn->connh = ev->r.handle; 803 ev->r.handle = conn->connh = iscsi_handle(conn->dd_data);
671
672 /*
673 * this is released in the dev's release function
674 */
675 if (!scsi_host_get(shost))
676 goto out_destroy_conn;
677 snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
678 shost->host_no, ev->u.c_conn.cid);
679 conn->dev.parent = &session->dev;
680 conn->dev.release = iscsi_if_conn_dev_release;
681 error = device_register(&conn->dev);
682 if (error) {
683 printk(KERN_ERR "iscsi%d: could not register connections%u "
684 "dev\n", shost->host_no, ev->u.c_conn.cid);
685 goto out_release_parent_ref;
686 }
687 transport_register_device(&conn->dev);
688 804
689 spin_lock_irqsave(&connlock, flags); 805 spin_lock_irqsave(&connlock, flags);
690 list_add(&conn->conn_list, &connlist); 806 list_add(&conn->conn_list, &connlist);
691 list_add(&conn->session_list, &session->connections);
692 conn->active = 1; 807 conn->active = 1;
693 spin_unlock_irqrestore(&connlock, flags); 808 spin_unlock_irqrestore(&connlock, flags);
694 809
695 scsi_host_put(shost); 810 scsi_host_put(shost);
696 return 0; 811 return 0;
697 812
698out_release_parent_ref: 813free_pdu_pool:
814 mempool_zone_destroy(conn->z_pdu);
815destroy_conn:
816 if (transport->destroy_conn)
817 transport->destroy_conn(conn->dd_data);
818release_ref:
699 scsi_host_put(shost); 819 scsi_host_put(shost);
700out_destroy_conn: 820 return -ENOMEM;
701 transport->destroy_conn(ev->r.handle);
702out_free_error_pool:
703 mempool_destroy(conn->z_error.pool);
704out_free_pdu_pool:
705 mempool_destroy(conn->z_pdu.pool);
706out_free_conn:
707 kfree(conn);
708out_release_ref:
709 scsi_host_put(shost);
710 return error;
711} 821}
712 822
713static int 823static int
714iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev) 824iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
715{ 825{
716 unsigned long flags; 826 unsigned long flags;
717 struct iscsi_if_conn *conn; 827 struct iscsi_cls_conn *conn;
828 struct mempool_zone *z_error, *z_pdu;
718 829
719 conn = iscsi_if_find_conn(ev->u.d_conn.conn_handle); 830 conn = iscsi_if_find_conn(ev->u.d_conn.conn_handle);
720 if (!conn) 831 if (!conn)
721 return -EEXIST; 832 return -EEXIST;
722 833
723 transport->destroy_conn(ev->u.d_conn.conn_handle); 834 if (!transport->destroy_conn)
835 return -EINVAL;
724 836
725 spin_lock_irqsave(&connlock, flags); 837 spin_lock_irqsave(&connlock, flags);
726 conn->active = 0; 838 conn->active = 0;
727 list_del(&conn->conn_list); 839 list_del(&conn->conn_list);
728 spin_unlock_irqrestore(&connlock, flags); 840 spin_unlock_irqrestore(&connlock, flags);
729 841
730 transport_unregister_device(&conn->dev); 842 z_pdu = conn->z_pdu;
731 device_unregister(&conn->dev); 843 z_error = conn->z_error;
732 return 0;
733}
734
735static int
736iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
737 struct nlmsghdr *nlh)
738{
739 struct iscsi_uevent *ev = NLMSG_DATA(nlh);
740 struct iscsi_stats *stats;
741 struct sk_buff *skbstat;
742 struct iscsi_if_conn *conn;
743 struct nlmsghdr *nlhstat;
744 struct iscsi_uevent *evstat;
745 int len = NLMSG_SPACE(sizeof(*ev) +
746 sizeof(struct iscsi_stats) +
747 sizeof(struct iscsi_stats_custom) *
748 ISCSI_STATS_CUSTOM_MAX);
749 int err = 0;
750
751 conn = iscsi_if_find_conn(ev->u.get_stats.conn_handle);
752 if (!conn)
753 return -EEXIST;
754
755 do {
756 int actual_size;
757
758 mempool_zone_complete(&conn->z_pdu);
759
760 skbstat = mempool_zone_get_skb(&conn->z_pdu);
761 if (!skbstat) {
762 printk(KERN_ERR "iscsi%d: can not deliver stats: OOM\n",
763 conn->host->host_no);
764 return -ENOMEM;
765 }
766
767 nlhstat = __nlmsg_put(skbstat, daemon_pid, 0, 0,
768 (len - sizeof(*nlhstat)), 0);
769 evstat = NLMSG_DATA(nlhstat);
770 memset(evstat, 0, sizeof(*evstat));
771 evstat->transport_handle = iscsi_handle(conn->transport);
772 evstat->type = nlh->nlmsg_type;
773 if (atomic_read(&conn->z_pdu.allocated) >= conn->z_pdu.hiwat)
774 evstat->iferror = -ENOMEM;
775 evstat->u.get_stats.conn_handle =
776 ev->u.get_stats.conn_handle;
777 stats = (struct iscsi_stats *)
778 ((char*)evstat + sizeof(*evstat));
779 memset(stats, 0, sizeof(*stats));
780 844
781 transport->get_stats(ev->u.get_stats.conn_handle, stats); 845 if (transport->destroy_conn)
782 actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) + 846 transport->destroy_conn(conn);
783 sizeof(struct iscsi_stats) +
784 sizeof(struct iscsi_stats_custom) *
785 stats->custom_length);
786 actual_size -= sizeof(*nlhstat);
787 actual_size = NLMSG_LENGTH(actual_size);
788 skb_trim(skb, NLMSG_ALIGN(actual_size));
789 nlhstat->nlmsg_len = actual_size;
790 847
791 err = iscsi_unicast_skb(&conn->z_pdu, skbstat); 848 mempool_zone_destroy(z_pdu);
792 } while (err < 0 && err != -ECONNREFUSED); 849 mempool_zone_destroy(z_error);
793 850
794 return err; 851 return 0;
795} 852}
796 853
797static int 854static int
@@ -881,7 +938,7 @@ iscsi_if_rx(struct sock *sk, int len)
881{ 938{
882 struct sk_buff *skb; 939 struct sk_buff *skb;
883 940
884 down(&rx_queue_sema); 941 mutex_lock(&rx_queue_mutex);
885 while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { 942 while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
886 while (skb->len >= NLMSG_SPACE(0)) { 943 while (skb->len >= NLMSG_SPACE(0)) {
887 int err; 944 int err;
@@ -915,17 +972,20 @@ iscsi_if_rx(struct sock *sk, int len)
915 err = iscsi_if_send_reply( 972 err = iscsi_if_send_reply(
916 NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq, 973 NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq,
917 nlh->nlmsg_type, 0, 0, ev, sizeof(*ev)); 974 nlh->nlmsg_type, 0, 0, ev, sizeof(*ev));
918 if (atomic_read(&z_reply.allocated) >= 975 if (atomic_read(&z_reply->allocated) >=
919 z_reply.hiwat) 976 z_reply->hiwat)
920 ev->iferror = -ENOMEM; 977 ev->iferror = -ENOMEM;
921 } while (err < 0 && err != -ECONNREFUSED); 978 } while (err < 0 && err != -ECONNREFUSED);
922 skb_pull(skb, rlen); 979 skb_pull(skb, rlen);
923 } 980 }
924 kfree_skb(skb); 981 kfree_skb(skb);
925 } 982 }
926 up(&rx_queue_sema); 983 mutex_unlock(&rx_queue_mutex);
927} 984}
928 985
986#define iscsi_cdev_to_conn(_cdev) \
987 iscsi_dev_to_conn(_cdev->dev)
988
929/* 989/*
930 * iSCSI connection attrs 990 * iSCSI connection attrs
931 */ 991 */
@@ -934,12 +994,10 @@ static ssize_t \
934show_conn_int_param_##param(struct class_device *cdev, char *buf) \ 994show_conn_int_param_##param(struct class_device *cdev, char *buf) \
935{ \ 995{ \
936 uint32_t value = 0; \ 996 uint32_t value = 0; \
937 struct iscsi_if_conn *conn = iscsi_cdev_to_if_conn(cdev); \ 997 struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \
938 struct iscsi_internal *priv; \ 998 struct iscsi_transport *t = conn->transport; \
939 \ 999 \
940 priv = to_iscsi_internal(conn->host->transportt); \ 1000 t->get_conn_param(conn->dd_data, param, &value); \
941 if (priv->param_mask & (1 << param)) \
942 priv->iscsi_transport->get_param(conn->connh, param, &value); \
943 return snprintf(buf, 20, format"\n", value); \ 1001 return snprintf(buf, 20, format"\n", value); \
944} 1002}
945 1003
@@ -954,6 +1012,9 @@ iscsi_conn_int_attr(data_digest, ISCSI_PARAM_DATADGST_EN, "%d");
954iscsi_conn_int_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN, "%d"); 1012iscsi_conn_int_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN, "%d");
955iscsi_conn_int_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN, "%d"); 1013iscsi_conn_int_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN, "%d");
956 1014
1015#define iscsi_cdev_to_session(_cdev) \
1016 iscsi_dev_to_session(_cdev->dev)
1017
957/* 1018/*
958 * iSCSI session attrs 1019 * iSCSI session attrs
959 */ 1020 */
@@ -962,20 +1023,11 @@ static ssize_t \
962show_session_int_param_##param(struct class_device *cdev, char *buf) \ 1023show_session_int_param_##param(struct class_device *cdev, char *buf) \
963{ \ 1024{ \
964 uint32_t value = 0; \ 1025 uint32_t value = 0; \
965 struct iscsi_if_session *session = iscsi_cdev_to_if_session(cdev); \ 1026 struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
966 struct Scsi_Host *shost = iscsi_if_session_to_shost(session); \ 1027 struct Scsi_Host *shost = iscsi_session_to_shost(session); \
967 struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \ 1028 struct iscsi_transport *t = session->transport; \
968 struct iscsi_if_conn *conn = NULL; \
969 unsigned long flags; \
970 \
971 spin_lock_irqsave(&connlock, flags); \
972 if (!list_empty(&session->connections)) \
973 conn = list_entry(session->connections.next, \
974 struct iscsi_if_conn, session_list); \
975 spin_unlock_irqrestore(&connlock, flags); \
976 \ 1029 \
977 if (conn && (priv->param_mask & (1 << param))) \ 1030 t->get_session_param(shost, param, &value); \
978 priv->iscsi_transport->get_param(conn->connh, param, &value);\
979 return snprintf(buf, 20, format"\n", value); \ 1031 return snprintf(buf, 20, format"\n", value); \
980} 1032}
981 1033
@@ -1004,23 +1056,18 @@ iscsi_session_int_attr(erl, ISCSI_PARAM_ERL, "%d");
1004 count++; \ 1056 count++; \
1005 } 1057 }
1006 1058
1007static int iscsi_is_session_dev(const struct device *dev)
1008{
1009 return dev->release == iscsi_if_session_dev_release;
1010}
1011
1012static int iscsi_session_match(struct attribute_container *cont, 1059static int iscsi_session_match(struct attribute_container *cont,
1013 struct device *dev) 1060 struct device *dev)
1014{ 1061{
1015 struct iscsi_if_session *session; 1062 struct iscsi_cls_session *session;
1016 struct Scsi_Host *shost; 1063 struct Scsi_Host *shost;
1017 struct iscsi_internal *priv; 1064 struct iscsi_internal *priv;
1018 1065
1019 if (!iscsi_is_session_dev(dev)) 1066 if (!iscsi_is_session_dev(dev))
1020 return 0; 1067 return 0;
1021 1068
1022 session = iscsi_dev_to_if_session(dev); 1069 session = iscsi_dev_to_session(dev);
1023 shost = iscsi_if_session_to_shost(session); 1070 shost = iscsi_session_to_shost(session);
1024 if (!shost->transportt) 1071 if (!shost->transportt)
1025 return 0; 1072 return 0;
1026 1073
@@ -1031,23 +1078,21 @@ static int iscsi_session_match(struct attribute_container *cont,
1031 return &priv->session_cont.ac == cont; 1078 return &priv->session_cont.ac == cont;
1032} 1079}
1033 1080
1034static int iscsi_is_conn_dev(const struct device *dev)
1035{
1036 return dev->release == iscsi_if_conn_dev_release;
1037}
1038
1039static int iscsi_conn_match(struct attribute_container *cont, 1081static int iscsi_conn_match(struct attribute_container *cont,
1040 struct device *dev) 1082 struct device *dev)
1041{ 1083{
1042 struct iscsi_if_conn *conn; 1084 struct iscsi_cls_session *session;
1085 struct iscsi_cls_conn *conn;
1043 struct Scsi_Host *shost; 1086 struct Scsi_Host *shost;
1044 struct iscsi_internal *priv; 1087 struct iscsi_internal *priv;
1045 1088
1046 if (!iscsi_is_conn_dev(dev)) 1089 if (!iscsi_is_conn_dev(dev))
1047 return 0; 1090 return 0;
1048 1091
1049 conn = iscsi_dev_to_if_conn(dev); 1092 conn = iscsi_dev_to_conn(dev);
1050 shost = conn->host; 1093 session = iscsi_dev_to_session(conn->dev.parent);
1094 shost = iscsi_session_to_shost(session);
1095
1051 if (!shost->transportt) 1096 if (!shost->transportt)
1052 return 0; 1097 return 0;
1053 1098
@@ -1058,7 +1103,8 @@ static int iscsi_conn_match(struct attribute_container *cont,
1058 return &priv->conn_cont.ac == cont; 1103 return &priv->conn_cont.ac == cont;
1059} 1104}
1060 1105
1061int iscsi_register_transport(struct iscsi_transport *tt) 1106struct scsi_transport_template *
1107iscsi_register_transport(struct iscsi_transport *tt)
1062{ 1108{
1063 struct iscsi_internal *priv; 1109 struct iscsi_internal *priv;
1064 unsigned long flags; 1110 unsigned long flags;
@@ -1068,15 +1114,14 @@ int iscsi_register_transport(struct iscsi_transport *tt)
1068 1114
1069 priv = iscsi_if_transport_lookup(tt); 1115 priv = iscsi_if_transport_lookup(tt);
1070 if (priv) 1116 if (priv)
1071 return -EEXIST; 1117 return NULL;
1072 1118
1073 priv = kmalloc(sizeof(*priv), GFP_KERNEL); 1119 priv = kmalloc(sizeof(*priv), GFP_KERNEL);
1074 if (!priv) 1120 if (!priv)
1075 return -ENOMEM; 1121 return NULL;
1076 memset(priv, 0, sizeof(*priv)); 1122 memset(priv, 0, sizeof(*priv));
1077 INIT_LIST_HEAD(&priv->list); 1123 INIT_LIST_HEAD(&priv->list);
1078 INIT_LIST_HEAD(&priv->sessions); 1124 INIT_LIST_HEAD(&priv->sessions);
1079 spin_lock_init(&priv->session_lock);
1080 priv->iscsi_transport = tt; 1125 priv->iscsi_transport = tt;
1081 1126
1082 priv->cdev.class = &iscsi_transport_class; 1127 priv->cdev.class = &iscsi_transport_class;
@@ -1142,13 +1187,13 @@ int iscsi_register_transport(struct iscsi_transport *tt)
1142 spin_unlock_irqrestore(&iscsi_transport_lock, flags); 1187 spin_unlock_irqrestore(&iscsi_transport_lock, flags);
1143 1188
1144 printk(KERN_NOTICE "iscsi: registered transport (%s)\n", tt->name); 1189 printk(KERN_NOTICE "iscsi: registered transport (%s)\n", tt->name);
1145 return 0; 1190 return &priv->t;
1146 1191
1147unregister_cdev: 1192unregister_cdev:
1148 class_device_unregister(&priv->cdev); 1193 class_device_unregister(&priv->cdev);
1149free_priv: 1194free_priv:
1150 kfree(priv); 1195 kfree(priv);
1151 return err; 1196 return NULL;
1152} 1197}
1153EXPORT_SYMBOL_GPL(iscsi_register_transport); 1198EXPORT_SYMBOL_GPL(iscsi_register_transport);
1154 1199
@@ -1159,19 +1204,11 @@ int iscsi_unregister_transport(struct iscsi_transport *tt)
1159 1204
1160 BUG_ON(!tt); 1205 BUG_ON(!tt);
1161 1206
1162 down(&rx_queue_sema); 1207 mutex_lock(&rx_queue_mutex);
1163 1208
1164 priv = iscsi_if_transport_lookup(tt); 1209 priv = iscsi_if_transport_lookup(tt);
1165 BUG_ON (!priv); 1210 BUG_ON (!priv);
1166 1211
1167 spin_lock_irqsave(&priv->session_lock, flags);
1168 if (!list_empty(&priv->sessions)) {
1169 spin_unlock_irqrestore(&priv->session_lock, flags);
1170 up(&rx_queue_sema);
1171 return -EPERM;
1172 }
1173 spin_unlock_irqrestore(&priv->session_lock, flags);
1174
1175 spin_lock_irqsave(&iscsi_transport_lock, flags); 1212 spin_lock_irqsave(&iscsi_transport_lock, flags);
1176 list_del(&priv->list); 1213 list_del(&priv->list);
1177 spin_unlock_irqrestore(&iscsi_transport_lock, flags); 1214 spin_unlock_irqrestore(&iscsi_transport_lock, flags);
@@ -1181,7 +1218,7 @@ int iscsi_unregister_transport(struct iscsi_transport *tt)
1181 1218
1182 sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group); 1219 sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group);
1183 class_device_unregister(&priv->cdev); 1220 class_device_unregister(&priv->cdev);
1184 up(&rx_queue_sema); 1221 mutex_unlock(&rx_queue_mutex);
1185 1222
1186 return 0; 1223 return 0;
1187} 1224}
@@ -1194,14 +1231,14 @@ iscsi_rcv_nl_event(struct notifier_block *this, unsigned long event, void *ptr)
1194 1231
1195 if (event == NETLINK_URELEASE && 1232 if (event == NETLINK_URELEASE &&
1196 n->protocol == NETLINK_ISCSI && n->pid) { 1233 n->protocol == NETLINK_ISCSI && n->pid) {
1197 struct iscsi_if_conn *conn; 1234 struct iscsi_cls_conn *conn;
1198 unsigned long flags; 1235 unsigned long flags;
1199 1236
1200 mempool_zone_complete(&z_reply); 1237 mempool_zone_complete(z_reply);
1201 spin_lock_irqsave(&connlock, flags); 1238 spin_lock_irqsave(&connlock, flags);
1202 list_for_each_entry(conn, &connlist, conn_list) { 1239 list_for_each_entry(conn, &connlist, conn_list) {
1203 mempool_zone_complete(&conn->z_error); 1240 mempool_zone_complete(conn->z_error);
1204 mempool_zone_complete(&conn->z_pdu); 1241 mempool_zone_complete(conn->z_pdu);
1205 } 1242 }
1206 spin_unlock_irqrestore(&connlock, flags); 1243 spin_unlock_irqrestore(&connlock, flags);
1207 } 1244 }
@@ -1234,15 +1271,15 @@ static __init int iscsi_transport_init(void)
1234 goto unregister_session_class; 1271 goto unregister_session_class;
1235 1272
1236 nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx, 1273 nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx,
1237 THIS_MODULE); 1274 THIS_MODULE);
1238 if (!nls) { 1275 if (!nls) {
1239 err = -ENOBUFS; 1276 err = -ENOBUFS;
1240 goto unregister_notifier; 1277 goto unregister_notifier;
1241 } 1278 }
1242 1279
1243 err = mempool_zone_init(&z_reply, Z_MAX_REPLY, 1280 z_reply = mempool_zone_init(Z_MAX_REPLY,
1244 NLMSG_SPACE(sizeof(struct iscsi_uevent)), Z_HIWAT_REPLY); 1281 NLMSG_SPACE(sizeof(struct iscsi_uevent)), Z_HIWAT_REPLY);
1245 if (!err) 1282 if (z_reply)
1246 return 0; 1283 return 0;
1247 1284
1248 sock_release(nls->sk_socket); 1285 sock_release(nls->sk_socket);
@@ -1259,7 +1296,7 @@ unregister_transport_class:
1259 1296
1260static void __exit iscsi_transport_exit(void) 1297static void __exit iscsi_transport_exit(void)
1261{ 1298{
1262 mempool_destroy(z_reply.pool); 1299 mempool_zone_destroy(z_reply);
1263 sock_release(nls->sk_socket); 1300 sock_release(nls->sk_socket);
1264 netlink_unregister_notifier(&iscsi_nl_notifier); 1301 netlink_unregister_notifier(&iscsi_nl_notifier);
1265 transport_class_unregister(&iscsi_connection_class); 1302 transport_class_unregister(&iscsi_connection_class);