]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/scsi/scsi_transport_iscsi.c
Merge HEAD from ../scsi-misc-2.6-old
[linux-2.6-omap-h63xx.git] / drivers / scsi / scsi_transport_iscsi.c
1 /*
2  * iSCSI transport class definitions
3  *
4  * Copyright (C) IBM Corporation, 2004
5  * Copyright (C) Mike Christie, 2004 - 2005
6  * Copyright (C) Dmitry Yusupov, 2004 - 2005
7  * Copyright (C) Alex Aizman, 2004 - 2005
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22  */
23 #include <linux/module.h>
24 #include <linux/mempool.h>
25 #include <net/tcp.h>
26 #include <scsi/scsi.h>
27 #include <scsi/scsi_host.h>
28 #include <scsi/scsi_device.h>
29 #include <scsi/scsi_transport.h>
30 #include <scsi/scsi_transport_iscsi.h>
31 #include <scsi/iscsi_if.h>
32
33 #define ISCSI_SESSION_ATTRS 8
34 #define ISCSI_CONN_ATTRS 6
35
36 struct iscsi_internal {
37         struct scsi_transport_template t;
38         struct iscsi_transport *iscsi_transport;
39         struct list_head list;
40         /*
41          * List of sessions for this transport
42          */
43         struct list_head sessions;
44         /*
45          * lock to serialize access to the sessions list which must
46          * be taken after the rx_queue_sema
47          */
48         spinlock_t session_lock;
49         /*
50          * based on transport capabilities, at register time we set these
51          * bits to tell the transport class it wants attributes displayed
52          * in sysfs or that it can support different iSCSI Data-Path
53          * capabilities
54          */
55         uint32_t param_mask;
56
57         struct class_device cdev;
58         /*
59          * We do not have any private or other attrs.
60          */
61         struct transport_container conn_cont;
62         struct class_device_attribute *conn_attrs[ISCSI_CONN_ATTRS + 1];
63         struct transport_container session_cont;
64         struct class_device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1];
65 };
66
67 /*
68  * list of registered transports and lock that must
69  * be held while accessing list. The iscsi_transport_lock must
70  * be acquired after the rx_queue_sema.
71  */
72 static LIST_HEAD(iscsi_transports);
73 static DEFINE_SPINLOCK(iscsi_transport_lock);
74
75 #define to_iscsi_internal(tmpl) \
76         container_of(tmpl, struct iscsi_internal, t)
77
78 #define cdev_to_iscsi_internal(_cdev) \
79         container_of(_cdev, struct iscsi_internal, cdev)
80
81 static void iscsi_transport_release(struct class_device *cdev)
82 {
83         struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev);
84         kfree(priv);
85 }
86
87 /*
88  * iscsi_transport_class represents the iscsi_transports that are
89  * registered.
90  */
91 static struct class iscsi_transport_class = {
92         .name = "iscsi_transport",
93         .release = iscsi_transport_release,
94 };
95
96 static ssize_t
97 show_transport_handle(struct class_device *cdev, char *buf)
98 {
99         struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev);
100         return sprintf(buf, "%llu\n", (unsigned long long)iscsi_handle(priv->iscsi_transport));
101 }
102 static CLASS_DEVICE_ATTR(handle, S_IRUGO, show_transport_handle, NULL);
103
104 #define show_transport_attr(name, format)                               \
105 static ssize_t                                                          \
106 show_transport_##name(struct class_device *cdev, char *buf)             \
107 {                                                                       \
108         struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev);     \
109         return sprintf(buf, format"\n", priv->iscsi_transport->name);   \
110 }                                                                       \
111 static CLASS_DEVICE_ATTR(name, S_IRUGO, show_transport_##name, NULL);
112
113 show_transport_attr(caps, "0x%x");
114 show_transport_attr(max_lun, "%d");
115 show_transport_attr(max_conn, "%d");
116 show_transport_attr(max_cmd_len, "%d");
117
118 static struct attribute *iscsi_transport_attrs[] = {
119         &class_device_attr_handle.attr,
120         &class_device_attr_caps.attr,
121         &class_device_attr_max_lun.attr,
122         &class_device_attr_max_conn.attr,
123         &class_device_attr_max_cmd_len.attr,
124         NULL,
125 };
126
127 static struct attribute_group iscsi_transport_group = {
128         .attrs = iscsi_transport_attrs,
129 };
130
131 static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
132                                "iscsi_session",
133                                NULL,
134                                NULL,
135                                NULL);
136
137 static DECLARE_TRANSPORT_CLASS(iscsi_connection_class,
138                                "iscsi_connection",
139                                NULL,
140                                NULL,
141                                NULL);
142
143 static struct sock *nls;
144 static int daemon_pid;
145 static DECLARE_MUTEX(rx_queue_sema);
146
147 struct mempool_zone {
148         mempool_t *pool;
149         atomic_t allocated;
150         int size;
151         int hiwat;
152         struct list_head freequeue;
153         spinlock_t freelock;
154 };
155
156 static struct mempool_zone z_reply;
157
158 /*
159  * Z_MAX_* - actual mempool size allocated at the mempool_zone_init() time
160  * Z_HIWAT_* - zone's high watermark when if_error bit will be set to -ENOMEM
161  *             so daemon will notice OOM on NETLINK tranposrt level and will
162  *             be able to predict or change operational behavior
163  */
164 #define Z_MAX_REPLY     8
165 #define Z_HIWAT_REPLY   6
166 #define Z_MAX_PDU       8
167 #define Z_HIWAT_PDU     6
168 #define Z_MAX_ERROR     16
169 #define Z_HIWAT_ERROR   12
170
171 struct iscsi_if_conn {
172         struct list_head conn_list;     /* item in connlist */
173         struct list_head session_list;  /* item in session->connections */
174         iscsi_connh_t connh;
175         int active;                     /* must be accessed with the connlock */
176         struct Scsi_Host *host;         /* originated shost */
177         struct device dev;              /* sysfs transport/container device */
178         struct iscsi_transport *transport;
179         struct mempool_zone z_error;
180         struct mempool_zone z_pdu;
181         struct list_head freequeue;
182 };
183
184 #define iscsi_dev_to_if_conn(_dev) \
185         container_of(_dev, struct iscsi_if_conn, dev)
186
187 #define iscsi_cdev_to_if_conn(_cdev) \
188         iscsi_dev_to_if_conn(_cdev->dev)
189
190 static LIST_HEAD(connlist);
191 static DEFINE_SPINLOCK(connlock);
192
193 struct iscsi_if_session {
194         struct list_head list;  /* item in session_list */
195         struct list_head connections;
196         iscsi_sessionh_t sessionh;
197         struct iscsi_transport *transport;
198         struct device dev;      /* sysfs transport/container device */
199 };
200
201 #define iscsi_dev_to_if_session(_dev) \
202         container_of(_dev, struct iscsi_if_session, dev)
203
204 #define iscsi_cdev_to_if_session(_cdev) \
205         iscsi_dev_to_if_session(_cdev->dev)
206
207 #define iscsi_if_session_to_shost(_session) \
208         dev_to_shost(_session->dev.parent)
209
210 static struct iscsi_if_conn*
211 iscsi_if_find_conn(uint64_t key)
212 {
213         unsigned long flags;
214         struct iscsi_if_conn *conn;
215
216         spin_lock_irqsave(&connlock, flags);
217         list_for_each_entry(conn, &connlist, conn_list)
218                 if (conn->connh == key) {
219                         spin_unlock_irqrestore(&connlock, flags);
220                         return conn;
221                 }
222         spin_unlock_irqrestore(&connlock, flags);
223         return NULL;
224 }
225
226 static struct iscsi_internal *
227 iscsi_if_transport_lookup(struct iscsi_transport *tt)
228 {
229         struct iscsi_internal *priv;
230         unsigned long flags;
231
232         spin_lock_irqsave(&iscsi_transport_lock, flags);
233         list_for_each_entry(priv, &iscsi_transports, list) {
234                 if (tt == priv->iscsi_transport) {
235                         spin_unlock_irqrestore(&iscsi_transport_lock, flags);
236                         return priv;
237                 }
238         }
239         spin_unlock_irqrestore(&iscsi_transport_lock, flags);
240         return NULL;
241 }
242
243 static inline struct list_head *skb_to_lh(struct sk_buff *skb)
244 {
245         return (struct list_head *)&skb->cb;
246 }
247
248 static void*
249 mempool_zone_alloc_skb(unsigned int gfp_mask, void *pool_data)
250 {
251         struct mempool_zone *zone = pool_data;
252
253         return alloc_skb(zone->size, gfp_mask);
254 }
255
256 static void
257 mempool_zone_free_skb(void *element, void *pool_data)
258 {
259         kfree_skb(element);
260 }
261
262 static void
263 mempool_zone_complete(struct mempool_zone *zone)
264 {
265         unsigned long flags;
266         struct list_head *lh, *n;
267
268         spin_lock_irqsave(&zone->freelock, flags);
269         list_for_each_safe(lh, n, &zone->freequeue) {
270                 struct sk_buff *skb = (struct sk_buff *)((char *)lh -
271                                 offsetof(struct sk_buff, cb));
272                 if (!skb_shared(skb)) {
273                         list_del(skb_to_lh(skb));
274                         mempool_free(skb, zone->pool);
275                         atomic_dec(&zone->allocated);
276                 }
277         }
278         spin_unlock_irqrestore(&zone->freelock, flags);
279 }
280
281 static int
282 mempool_zone_init(struct mempool_zone *zp, unsigned max, unsigned size,
283                 unsigned hiwat)
284 {
285         zp->pool = mempool_create(max, mempool_zone_alloc_skb,
286                                   mempool_zone_free_skb, zp);
287         if (!zp->pool)
288                 return -ENOMEM;
289
290         zp->size = size;
291         zp->hiwat = hiwat;
292
293         INIT_LIST_HEAD(&zp->freequeue);
294         spin_lock_init(&zp->freelock);
295         atomic_set(&zp->allocated, 0);
296
297         return 0;
298 }
299
300
301 static struct sk_buff*
302 mempool_zone_get_skb(struct mempool_zone *zone)
303 {
304         struct sk_buff *skb;
305
306         skb = mempool_alloc(zone->pool, GFP_ATOMIC);
307         if (skb)
308                 atomic_inc(&zone->allocated);
309         return skb;
310 }
311
312 static int
313 iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb)
314 {
315         unsigned long flags;
316         int rc;
317
318         skb_get(skb);
319         rc = netlink_unicast(nls, skb, daemon_pid, MSG_DONTWAIT);
320         if (rc < 0) {
321                 mempool_free(skb, zone->pool);
322                 printk(KERN_ERR "iscsi: can not unicast skb (%d)\n", rc);
323                 return rc;
324         }
325
326         spin_lock_irqsave(&zone->freelock, flags);
327         list_add(skb_to_lh(skb), &zone->freequeue);
328         spin_unlock_irqrestore(&zone->freelock, flags);
329
330         return 0;
331 }
332
333 int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
334                    char *data, uint32_t data_size)
335 {
336         struct nlmsghdr *nlh;
337         struct sk_buff *skb;
338         struct iscsi_uevent *ev;
339         struct iscsi_if_conn *conn;
340         char *pdu;
341         int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) +
342                               data_size);
343
344         conn = iscsi_if_find_conn(connh);
345         BUG_ON(!conn);
346
347         mempool_zone_complete(&conn->z_pdu);
348
349         skb = mempool_zone_get_skb(&conn->z_pdu);
350         if (!skb) {
351                 iscsi_conn_error(connh, ISCSI_ERR_CONN_FAILED);
352                 printk(KERN_ERR "iscsi%d: can not deliver control PDU: OOM\n",
353                        conn->host->host_no);
354                 return -ENOMEM;
355         }
356
357         nlh = __nlmsg_put(skb, daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
358         ev = NLMSG_DATA(nlh);
359         memset(ev, 0, sizeof(*ev));
360         ev->transport_handle = iscsi_handle(conn->transport);
361         ev->type = ISCSI_KEVENT_RECV_PDU;
362         if (atomic_read(&conn->z_pdu.allocated) >= conn->z_pdu.hiwat)
363                 ev->iferror = -ENOMEM;
364         ev->r.recv_req.conn_handle = connh;
365         pdu = (char*)ev + sizeof(*ev);
366         memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
367         memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
368
369         return iscsi_unicast_skb(&conn->z_pdu, skb);
370 }
371 EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
372
373 void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error)
374 {
375         struct nlmsghdr *nlh;
376         struct sk_buff  *skb;
377         struct iscsi_uevent *ev;
378         struct iscsi_if_conn *conn;
379         int len = NLMSG_SPACE(sizeof(*ev));
380
381         conn = iscsi_if_find_conn(connh);
382         BUG_ON(!conn);
383
384         mempool_zone_complete(&conn->z_error);
385
386         skb = mempool_zone_get_skb(&conn->z_error);
387         if (!skb) {
388                 printk(KERN_ERR "iscsi%d: gracefully ignored conn error (%d)\n",
389                        conn->host->host_no, error);
390                 return;
391         }
392
393         nlh = __nlmsg_put(skb, daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
394         ev = NLMSG_DATA(nlh);
395         ev->transport_handle = iscsi_handle(conn->transport);
396         ev->type = ISCSI_KEVENT_CONN_ERROR;
397         if (atomic_read(&conn->z_error.allocated) >= conn->z_error.hiwat)
398                 ev->iferror = -ENOMEM;
399         ev->r.connerror.error = error;
400         ev->r.connerror.conn_handle = connh;
401
402         iscsi_unicast_skb(&conn->z_error, skb);
403
404         printk(KERN_INFO "iscsi%d: detected conn error (%d)\n",
405                conn->host->host_no, error);
406 }
407 EXPORT_SYMBOL_GPL(iscsi_conn_error);
408
409 static int
410 iscsi_if_send_reply(int pid, int seq, int type, int done, int multi,
411                       void *payload, int size)
412 {
413         struct sk_buff  *skb;
414         struct nlmsghdr *nlh;
415         int len = NLMSG_SPACE(size);
416         int flags = multi ? NLM_F_MULTI : 0;
417         int t = done ? NLMSG_DONE : type;
418
419         mempool_zone_complete(&z_reply);
420
421         skb = mempool_zone_get_skb(&z_reply);
422         /*
423          * FIXME:
424          * user is supposed to react on iferror == -ENOMEM;
425          * see iscsi_if_rx().
426          */
427         BUG_ON(!skb);
428
429         nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0);
430         nlh->nlmsg_flags = flags;
431         memcpy(NLMSG_DATA(nlh), payload, size);
432         return iscsi_unicast_skb(&z_reply, skb);
433 }
434
435 /*
436  * iSCSI Session's hostdata organization:
437  *
438  *    *------------------* <== host->hostdata
439  *    | transport        |
440  *    |------------------| <== iscsi_hostdata(host->hostdata)
441  *    | transport's data |
442  *    |------------------| <== hostdata_session(host->hostdata)
443  *    | interface's data |
444  *    *------------------*
445  */
446
447 #define hostdata_privsize(_t)   (sizeof(unsigned long) + _t->hostdata_size + \
448                                  _t->hostdata_size % sizeof(unsigned long) + \
449                                  sizeof(struct iscsi_if_session))
450
451 #define hostdata_session(_hostdata) ((void*)_hostdata + sizeof(unsigned long) + \
452                         ((struct iscsi_transport *) \
453                          iscsi_ptr(*(uint64_t *)_hostdata))->hostdata_size)
454
455 static void iscsi_if_session_dev_release(struct device *dev)
456 {
457         struct iscsi_if_session *session = iscsi_dev_to_if_session(dev);
458         struct iscsi_transport *transport = session->transport;
459         struct Scsi_Host *shost = iscsi_if_session_to_shost(session);
460         struct iscsi_if_conn *conn, *tmp;
461         unsigned long flags;
462
463         /* now free connections */
464         spin_lock_irqsave(&connlock, flags);
465         list_for_each_entry_safe(conn, tmp, &session->connections,
466                                  session_list) {
467                 list_del(&conn->session_list);
468                 mempool_destroy(conn->z_pdu.pool);
469                 mempool_destroy(conn->z_error.pool);
470                 kfree(conn);
471         }
472         spin_unlock_irqrestore(&connlock, flags);
473         scsi_host_put(shost);
474         module_put(transport->owner);
475 }
476
477 static int
478 iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
479 {
480         struct iscsi_transport *transport = priv->iscsi_transport;
481         struct iscsi_if_session *session;
482         struct Scsi_Host *shost;
483         unsigned long flags;
484         int error;
485
486         if (!try_module_get(transport->owner))
487                 return -EPERM;
488
489         shost = scsi_host_alloc(transport->host_template,
490                                 hostdata_privsize(transport));
491         if (!shost) {
492                 ev->r.c_session_ret.session_handle = iscsi_handle(NULL);
493                 printk(KERN_ERR "iscsi: can not allocate SCSI host for "
494                        "session\n");
495                 error = -ENOMEM;
496                 goto out_module_put;
497         }
498         shost->max_id = 1;
499         shost->max_channel = 0;
500         shost->max_lun = transport->max_lun;
501         shost->max_cmd_len = transport->max_cmd_len;
502         shost->transportt = &priv->t;
503
504         /* store struct iscsi_transport in hostdata */
505         *(uint64_t*)shost->hostdata = ev->transport_handle;
506
507         ev->r.c_session_ret.session_handle = transport->create_session(
508                                         ev->u.c_session.initial_cmdsn, shost);
509         if (ev->r.c_session_ret.session_handle == iscsi_handle(NULL)) {
510                 error = 0;
511                 goto out_host_put;
512         }
513
514         /* host_no becomes assigned SID */
515         ev->r.c_session_ret.sid = shost->host_no;
516         /* initialize session */
517         session = hostdata_session(shost->hostdata);
518         INIT_LIST_HEAD(&session->connections);
519         INIT_LIST_HEAD(&session->list);
520         session->sessionh = ev->r.c_session_ret.session_handle;
521         session->transport = transport;
522
523         error = scsi_add_host(shost, NULL);
524         if (error)
525                 goto out_destroy_session;
526
527         /*
528          * this is released in the dev's release function)
529          */
530         scsi_host_get(shost);
531         snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", shost->host_no);
532         session->dev.parent = &shost->shost_gendev;
533         session->dev.release = iscsi_if_session_dev_release;
534         error = device_register(&session->dev);
535         if (error) {
536                 printk(KERN_ERR "iscsi: could not register session%d's dev\n",
537                        shost->host_no);
538                 goto out_remove_host;
539         }
540         transport_register_device(&session->dev);
541
542         /* add this session to the list of active sessions */
543         spin_lock_irqsave(&priv->session_lock, flags);
544         list_add(&session->list, &priv->sessions);
545         spin_unlock_irqrestore(&priv->session_lock, flags);
546
547         return 0;
548
549 out_remove_host:
550         scsi_remove_host(shost);
551 out_destroy_session:
552         transport->destroy_session(ev->r.c_session_ret.session_handle);
553         ev->r.c_session_ret.session_handle = iscsi_handle(NULL);
554 out_host_put:
555         scsi_host_put(shost);
556 out_module_put:
557         module_put(transport->owner);
558         return error;
559 }
560
561 static int
562 iscsi_if_destroy_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
563 {
564         struct iscsi_transport *transport = priv->iscsi_transport;
565         struct Scsi_Host *shost;
566         struct iscsi_if_session *session;
567         unsigned long flags;
568         struct iscsi_if_conn *conn;
569         int error = 0;
570
571         shost = scsi_host_lookup(ev->u.d_session.sid);
572         if (shost == ERR_PTR(-ENXIO))
573                 return -EEXIST;
574         session = hostdata_session(shost->hostdata);
575
576         /* check if we have active connections */
577         spin_lock_irqsave(&connlock, flags);
578         list_for_each_entry(conn, &session->connections, session_list) {
579                 if (conn->active) {
580                         printk(KERN_ERR "iscsi%d: can not destroy session: "
581                                "has active connection (%p)\n",
582                                shost->host_no, iscsi_ptr(conn->connh));
583                         spin_unlock_irqrestore(&connlock, flags);
584                         error = EIO;
585                         goto out_release_ref;
586                 }
587         }
588         spin_unlock_irqrestore(&connlock, flags);
589
590         scsi_remove_host(shost);
591         transport->destroy_session(ev->u.d_session.session_handle);
592         transport_unregister_device(&session->dev);
593         device_unregister(&session->dev);
594
595         /* remove this session from the list of active sessions */
596         spin_lock_irqsave(&priv->session_lock, flags);
597         list_del(&session->list);
598         spin_unlock_irqrestore(&priv->session_lock, flags);
599
600         /* ref from host alloc */
601         scsi_host_put(shost);
602 out_release_ref:
603         /* ref from host lookup */
604         scsi_host_put(shost);
605         return error;
606 }
607
608 static void iscsi_if_conn_dev_release(struct device *dev)
609 {
610         struct iscsi_if_conn *conn = iscsi_dev_to_if_conn(dev);
611         struct Scsi_Host *shost = conn->host;
612
613         scsi_host_put(shost);
614 }
615
616 static int
617 iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
618 {
619         struct iscsi_if_session *session;
620         struct Scsi_Host *shost;
621         struct iscsi_if_conn *conn;
622         unsigned long flags;
623         int error;
624
625         shost = scsi_host_lookup(ev->u.c_conn.sid);
626         if (shost == ERR_PTR(-ENXIO))
627                 return -EEXIST;
628         session = hostdata_session(shost->hostdata);
629
630         conn = kmalloc(sizeof(struct iscsi_if_conn), GFP_KERNEL);
631         if (!conn) {
632                 error = -ENOMEM;
633                 goto out_release_ref;
634         }
635         memset(conn, 0, sizeof(struct iscsi_if_conn));
636         INIT_LIST_HEAD(&conn->session_list);
637         INIT_LIST_HEAD(&conn->conn_list);
638         conn->host = shost;
639         conn->transport = transport;
640
641         error = mempool_zone_init(&conn->z_pdu, Z_MAX_PDU,
642                         NLMSG_SPACE(sizeof(struct iscsi_uevent) +
643                                     sizeof(struct iscsi_hdr) +
644                                     DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH),
645                         Z_HIWAT_PDU);
646         if (error) {
647                 printk(KERN_ERR "iscsi%d: can not allocate pdu zone for new "
648                        "conn\n", shost->host_no);
649                 goto out_free_conn;
650         }
651         error = mempool_zone_init(&conn->z_error, Z_MAX_ERROR,
652                         NLMSG_SPACE(sizeof(struct iscsi_uevent)),
653                         Z_HIWAT_ERROR);
654         if (error) {
655                 printk(KERN_ERR "iscsi%d: can not allocate error zone for "
656                        "new conn\n", shost->host_no);
657                 goto out_free_pdu_pool;
658         }
659
660         ev->r.handle = transport->create_conn(ev->u.c_conn.session_handle,
661                                         ev->u.c_conn.cid);
662         if (!ev->r.handle) {
663                 error = -ENODEV;
664                 goto out_free_error_pool;
665         }
666
667         conn->connh = ev->r.handle;
668
669         /*
670          * this is released in the dev's release function
671          */
672         if (!scsi_host_get(shost))
673                 goto out_destroy_conn;
674         snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
675                  shost->host_no, ev->u.c_conn.cid);
676         conn->dev.parent = &session->dev;
677         conn->dev.release = iscsi_if_conn_dev_release;
678         error = device_register(&conn->dev);
679         if (error) {
680                 printk(KERN_ERR "iscsi%d: could not register connections%u "
681                        "dev\n", shost->host_no, ev->u.c_conn.cid);
682                 goto out_release_parent_ref;
683         }
684         transport_register_device(&conn->dev);
685
686         spin_lock_irqsave(&connlock, flags);
687         list_add(&conn->conn_list, &connlist);
688         list_add(&conn->session_list, &session->connections);
689         conn->active = 1;
690         spin_unlock_irqrestore(&connlock, flags);
691
692         scsi_host_put(shost);
693         return 0;
694
695 out_release_parent_ref:
696         scsi_host_put(shost);
697 out_destroy_conn:
698         transport->destroy_conn(ev->r.handle);
699 out_free_error_pool:
700         mempool_destroy(conn->z_error.pool);
701 out_free_pdu_pool:
702         mempool_destroy(conn->z_pdu.pool);
703 out_free_conn:
704         kfree(conn);
705 out_release_ref:
706         scsi_host_put(shost);
707         return error;
708 }
709
710 static int
711 iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
712 {
713         unsigned long flags;
714         struct iscsi_if_conn *conn;
715
716         conn = iscsi_if_find_conn(ev->u.d_conn.conn_handle);
717         if (!conn)
718                 return -EEXIST;
719
720         transport->destroy_conn(ev->u.d_conn.conn_handle);
721
722         spin_lock_irqsave(&connlock, flags);
723         conn->active = 0;
724         list_del(&conn->conn_list);
725         spin_unlock_irqrestore(&connlock, flags);
726
727         transport_unregister_device(&conn->dev);
728         device_unregister(&conn->dev);
729         return 0;
730 }
731
732 static int
733 iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
734                    struct nlmsghdr *nlh)
735 {
736         struct iscsi_uevent *ev = NLMSG_DATA(nlh);
737         struct iscsi_stats *stats;
738         struct sk_buff *skbstat;
739         struct iscsi_if_conn *conn;
740         struct nlmsghdr *nlhstat;
741         struct iscsi_uevent *evstat;
742         int len = NLMSG_SPACE(sizeof(*ev) +
743                               sizeof(struct iscsi_stats) +
744                               sizeof(struct iscsi_stats_custom) *
745                               ISCSI_STATS_CUSTOM_MAX);
746         int err = 0;
747
748         conn = iscsi_if_find_conn(ev->u.get_stats.conn_handle);
749         if (!conn)
750                 return -EEXIST;
751
752         do {
753                 int actual_size;
754
755                 mempool_zone_complete(&conn->z_pdu);
756
757                 skbstat = mempool_zone_get_skb(&conn->z_pdu);
758                 if (!skbstat) {
759                         printk(KERN_ERR "iscsi%d: can not deliver stats: OOM\n",
760                                conn->host->host_no);
761                         return -ENOMEM;
762                 }
763
764                 nlhstat = __nlmsg_put(skbstat, daemon_pid, 0, 0,
765                                       (len - sizeof(*nlhstat)), 0);
766                 evstat = NLMSG_DATA(nlhstat);
767                 memset(evstat, 0, sizeof(*evstat));
768                 evstat->transport_handle = iscsi_handle(conn->transport);
769                 evstat->type = nlh->nlmsg_type;
770                 if (atomic_read(&conn->z_pdu.allocated) >= conn->z_pdu.hiwat)
771                         evstat->iferror = -ENOMEM;
772                 evstat->u.get_stats.conn_handle =
773                         ev->u.get_stats.conn_handle;
774                 stats = (struct iscsi_stats *)
775                         ((char*)evstat + sizeof(*evstat));
776                 memset(stats, 0, sizeof(*stats));
777
778                 transport->get_stats(ev->u.get_stats.conn_handle, stats);
779                 actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) +
780                                           sizeof(struct iscsi_stats) +
781                                           sizeof(struct iscsi_stats_custom) *
782                                           stats->custom_length);
783                 actual_size -= sizeof(*nlhstat);
784                 actual_size = NLMSG_LENGTH(actual_size);
785                 skb_trim(skb, NLMSG_ALIGN(actual_size));
786                 nlhstat->nlmsg_len = actual_size;
787
788                 err = iscsi_unicast_skb(&conn->z_pdu, skbstat);
789         } while (err < 0 && err != -ECONNREFUSED);
790
791         return err;
792 }
793
794 static int
795 iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
796 {
797         int err = 0;
798         struct iscsi_uevent *ev = NLMSG_DATA(nlh);
799         struct iscsi_transport *transport = NULL;
800         struct iscsi_internal *priv;
801
802         if (NETLINK_CREDS(skb)->uid)
803                 return -EPERM;
804
805         priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle));
806         if (!priv)
807                 return -EINVAL;
808         transport = priv->iscsi_transport;
809
810         daemon_pid = NETLINK_CREDS(skb)->pid;
811
812         switch (nlh->nlmsg_type) {
813         case ISCSI_UEVENT_CREATE_SESSION:
814                 err = iscsi_if_create_session(priv, ev);
815                 break;
816         case ISCSI_UEVENT_DESTROY_SESSION:
817                 err = iscsi_if_destroy_session(priv, ev);
818                 break;
819         case ISCSI_UEVENT_CREATE_CONN:
820                 err = iscsi_if_create_conn(transport, ev);
821                 break;
822         case ISCSI_UEVENT_DESTROY_CONN:
823                 err = iscsi_if_destroy_conn(transport, ev);
824                 break;
825         case ISCSI_UEVENT_BIND_CONN:
826                 if (!iscsi_if_find_conn(ev->u.b_conn.conn_handle))
827                         return -EEXIST;
828                 ev->r.retcode = transport->bind_conn(
829                         ev->u.b_conn.session_handle,
830                         ev->u.b_conn.conn_handle,
831                         ev->u.b_conn.transport_fd,
832                         ev->u.b_conn.is_leading);
833                 break;
834         case ISCSI_UEVENT_SET_PARAM:
835                 if (!iscsi_if_find_conn(ev->u.set_param.conn_handle))
836                         return -EEXIST;
837                 ev->r.retcode = transport->set_param(
838                         ev->u.set_param.conn_handle,
839                         ev->u.set_param.param, ev->u.set_param.value);
840                 break;
841         case ISCSI_UEVENT_START_CONN:
842                 if (!iscsi_if_find_conn(ev->u.start_conn.conn_handle))
843                         return -EEXIST;
844                 ev->r.retcode = transport->start_conn(
845                         ev->u.start_conn.conn_handle);
846                 break;
847         case ISCSI_UEVENT_STOP_CONN:
848                 if (!iscsi_if_find_conn(ev->u.stop_conn.conn_handle))
849                         return -EEXIST;
850                 transport->stop_conn(ev->u.stop_conn.conn_handle,
851                         ev->u.stop_conn.flag);
852                 break;
853         case ISCSI_UEVENT_SEND_PDU:
854                 if (!iscsi_if_find_conn(ev->u.send_pdu.conn_handle))
855                         return -EEXIST;
856                 ev->r.retcode = transport->send_pdu(
857                        ev->u.send_pdu.conn_handle,
858                        (struct iscsi_hdr*)((char*)ev + sizeof(*ev)),
859                        (char*)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size,
860                         ev->u.send_pdu.data_size);
861                 break;
862         case ISCSI_UEVENT_GET_STATS:
863                 err = iscsi_if_get_stats(transport, skb, nlh);
864                 break;
865         default:
866                 err = -EINVAL;
867                 break;
868         }
869
870         return err;
871 }
872
873 /* Get message from skb (based on rtnetlink_rcv_skb).  Each message is
874  * processed by iscsi_if_recv_msg.  Malformed skbs with wrong length are
875  * discarded silently.  */
876 static void
877 iscsi_if_rx(struct sock *sk, int len)
878 {
879         struct sk_buff *skb;
880
881         down(&rx_queue_sema);
882         while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
883                 while (skb->len >= NLMSG_SPACE(0)) {
884                         int err;
885                         uint32_t rlen;
886                         struct nlmsghdr *nlh;
887                         struct iscsi_uevent *ev;
888
889                         nlh = (struct nlmsghdr *)skb->data;
890                         if (nlh->nlmsg_len < sizeof(*nlh) ||
891                             skb->len < nlh->nlmsg_len) {
892                                 break;
893                         }
894                         ev = NLMSG_DATA(nlh);
895                         rlen = NLMSG_ALIGN(nlh->nlmsg_len);
896                         if (rlen > skb->len)
897                                 rlen = skb->len;
898                         err = iscsi_if_recv_msg(skb, nlh);
899                         if (err) {
900                                 ev->type = ISCSI_KEVENT_IF_ERROR;
901                                 ev->iferror = err;
902                         }
903                         do {
904                                 /*
905                                  * special case for GET_STATS:
906                                  * on success - sending reply and stats from
907                                  * inside of if_recv_msg(),
908                                  * on error - fall through.
909                                  */
910                                 if (ev->type == ISCSI_UEVENT_GET_STATS && !err)
911                                         break;
912                                 err = iscsi_if_send_reply(
913                                         NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq,
914                                         nlh->nlmsg_type, 0, 0, ev, sizeof(*ev));
915                                 if (atomic_read(&z_reply.allocated) >=
916                                                 z_reply.hiwat)
917                                         ev->iferror = -ENOMEM;
918                         } while (err < 0 && err != -ECONNREFUSED);
919                         skb_pull(skb, rlen);
920                 }
921                 kfree_skb(skb);
922         }
923         up(&rx_queue_sema);
924 }
925
926 /*
927  * iSCSI connection attrs
928  */
929 #define iscsi_conn_int_attr_show(param, format)                         \
930 static ssize_t                                                          \
931 show_conn_int_param_##param(struct class_device *cdev, char *buf)       \
932 {                                                                       \
933         uint32_t value = 0;                                             \
934         struct iscsi_if_conn *conn = iscsi_cdev_to_if_conn(cdev);       \
935         struct iscsi_internal *priv;                                    \
936                                                                         \
937         priv = to_iscsi_internal(conn->host->transportt);               \
938         if (priv->param_mask & (1 << param))                            \
939                 priv->iscsi_transport->get_param(conn->connh, param, &value); \
940         return snprintf(buf, 20, format"\n", value);                    \
941 }
942
943 #define iscsi_conn_int_attr(field, param, format)                       \
944         iscsi_conn_int_attr_show(param, format)                         \
945 static CLASS_DEVICE_ATTR(field, S_IRUGO, show_conn_int_param_##param, NULL);
946
947 iscsi_conn_int_attr(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH, "%u");
948 iscsi_conn_int_attr(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH, "%u");
949 iscsi_conn_int_attr(header_digest, ISCSI_PARAM_HDRDGST_EN, "%d");
950 iscsi_conn_int_attr(data_digest, ISCSI_PARAM_DATADGST_EN, "%d");
951 iscsi_conn_int_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN, "%d");
952 iscsi_conn_int_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN, "%d");
953
954 /*
955  * iSCSI session attrs
956  */
957 #define iscsi_session_int_attr_show(param, format)                      \
958 static ssize_t                                                          \
959 show_session_int_param_##param(struct class_device *cdev, char *buf)    \
960 {                                                                       \
961         uint32_t value = 0;                                             \
962         struct iscsi_if_session *session = iscsi_cdev_to_if_session(cdev); \
963         struct Scsi_Host *shost = iscsi_if_session_to_shost(session);   \
964         struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \
965         struct iscsi_if_conn *conn = NULL;                              \
966         unsigned long  flags;                                           \
967                                                                         \
968         spin_lock_irqsave(&connlock, flags);                            \
969         if (!list_empty(&session->connections))                         \
970                 conn = list_entry(session->connections.next,            \
971                                   struct iscsi_if_conn, session_list);  \
972         spin_unlock_irqrestore(&connlock, flags);                       \
973                                                                         \
974         if (conn && (priv->param_mask & (1 << param)))                  \
975                 priv->iscsi_transport->get_param(conn->connh, param, &value);\
976         return snprintf(buf, 20, format"\n", value);                    \
977 }
978
979 #define iscsi_session_int_attr(field, param, format)                    \
980         iscsi_session_int_attr_show(param, format)                      \
981 static CLASS_DEVICE_ATTR(field, S_IRUGO, show_session_int_param_##param, NULL);
982
983 iscsi_session_int_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN, "%d");
984 iscsi_session_int_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T, "%hu");
985 iscsi_session_int_attr(immediate_data, ISCSI_PARAM_IMM_DATA_EN, "%d");
986 iscsi_session_int_attr(first_burst_len, ISCSI_PARAM_FIRST_BURST, "%u");
987 iscsi_session_int_attr(max_burst_len, ISCSI_PARAM_MAX_BURST, "%u");
988 iscsi_session_int_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN, "%d");
989 iscsi_session_int_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN, "%d");
990 iscsi_session_int_attr(erl, ISCSI_PARAM_ERL, "%d");
991
992 #define SETUP_SESSION_RD_ATTR(field, param)                             \
993         if (priv->param_mask & (1 << param)) {                          \
994                 priv->session_attrs[count] = &class_device_attr_##field;\
995                 count++;                                                \
996         }
997
998 #define SETUP_CONN_RD_ATTR(field, param)                                \
999         if (priv->param_mask & (1 << param)) {                          \
1000                 priv->conn_attrs[count] = &class_device_attr_##field;   \
1001                 count++;                                                \
1002         }
1003
1004 static int iscsi_is_session_dev(const struct device *dev)
1005 {
1006         return dev->release == iscsi_if_session_dev_release;
1007 }
1008
1009 static int iscsi_session_match(struct attribute_container *cont,
1010                            struct device *dev)
1011 {
1012         struct iscsi_if_session *session;
1013         struct Scsi_Host *shost;
1014         struct iscsi_internal *priv;
1015
1016         if (!iscsi_is_session_dev(dev))
1017                 return 0;
1018
1019         session = iscsi_dev_to_if_session(dev);
1020         shost = iscsi_if_session_to_shost(session);
1021         if (!shost->transportt)
1022                 return 0;
1023
1024         priv = to_iscsi_internal(shost->transportt);
1025         if (priv->session_cont.ac.class != &iscsi_session_class.class)
1026                 return 0;
1027
1028         return &priv->session_cont.ac == cont;
1029 }
1030
1031 static int iscsi_is_conn_dev(const struct device *dev)
1032 {
1033         return dev->release == iscsi_if_conn_dev_release;
1034 }
1035
1036 static int iscsi_conn_match(struct attribute_container *cont,
1037                            struct device *dev)
1038 {
1039         struct iscsi_if_conn *conn;
1040         struct Scsi_Host *shost;
1041         struct iscsi_internal *priv;
1042
1043         if (!iscsi_is_conn_dev(dev))
1044                 return 0;
1045
1046         conn = iscsi_dev_to_if_conn(dev);
1047         shost = conn->host;
1048         if (!shost->transportt)
1049                 return 0;
1050
1051         priv = to_iscsi_internal(shost->transportt);
1052         if (priv->conn_cont.ac.class != &iscsi_connection_class.class)
1053                 return 0;
1054
1055         return &priv->conn_cont.ac == cont;
1056 }
1057
1058 int iscsi_register_transport(struct iscsi_transport *tt)
1059 {
1060         struct iscsi_internal *priv;
1061         unsigned long flags;
1062         int count = 0, err;
1063
1064         BUG_ON(!tt);
1065
1066         priv = iscsi_if_transport_lookup(tt);
1067         if (priv)
1068                 return -EEXIST;
1069
1070         priv = kmalloc(sizeof(*priv), GFP_KERNEL);
1071         if (!priv)
1072                 return -ENOMEM;
1073         memset(priv, 0, sizeof(*priv));
1074         INIT_LIST_HEAD(&priv->list);
1075         INIT_LIST_HEAD(&priv->sessions);
1076         spin_lock_init(&priv->session_lock);
1077         priv->iscsi_transport = tt;
1078
1079         priv->cdev.class = &iscsi_transport_class;
1080         snprintf(priv->cdev.class_id, BUS_ID_SIZE, "%s", tt->name);
1081         err = class_device_register(&priv->cdev);
1082         if (err)
1083                 goto free_priv;
1084
1085         err = sysfs_create_group(&priv->cdev.kobj, &iscsi_transport_group);
1086         if (err)
1087                 goto unregister_cdev;
1088
1089         /* setup parameters mask */
1090         priv->param_mask = 0xFFFFFFFF;
1091         if (!(tt->caps & CAP_MULTI_R2T))
1092                 priv->param_mask &= ~(1 << ISCSI_PARAM_MAX_R2T);
1093         if (!(tt->caps & CAP_HDRDGST))
1094                 priv->param_mask &= ~(1 << ISCSI_PARAM_HDRDGST_EN);
1095         if (!(tt->caps & CAP_DATADGST))
1096                 priv->param_mask &= ~(1 << ISCSI_PARAM_DATADGST_EN);
1097         if (!(tt->caps & CAP_MARKERS)) {
1098                 priv->param_mask &= ~(1 << ISCSI_PARAM_IFMARKER_EN);
1099                 priv->param_mask &= ~(1 << ISCSI_PARAM_OFMARKER_EN);
1100         }
1101
1102         /* connection parameters */
1103         priv->conn_cont.ac.attrs = &priv->conn_attrs[0];
1104         priv->conn_cont.ac.class = &iscsi_connection_class.class;
1105         priv->conn_cont.ac.match = iscsi_conn_match;
1106         transport_container_register(&priv->conn_cont);
1107
1108         SETUP_CONN_RD_ATTR(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH);
1109         SETUP_CONN_RD_ATTR(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH);
1110         SETUP_CONN_RD_ATTR(header_digest, ISCSI_PARAM_HDRDGST_EN);
1111         SETUP_CONN_RD_ATTR(data_digest, ISCSI_PARAM_DATADGST_EN);
1112         SETUP_CONN_RD_ATTR(ifmarker, ISCSI_PARAM_IFMARKER_EN);
1113         SETUP_CONN_RD_ATTR(ofmarker, ISCSI_PARAM_OFMARKER_EN);
1114
1115         BUG_ON(count > ISCSI_CONN_ATTRS);
1116         priv->conn_attrs[count] = NULL;
1117         count = 0;
1118
1119         /* session parameters */
1120         priv->session_cont.ac.attrs = &priv->session_attrs[0];
1121         priv->session_cont.ac.class = &iscsi_session_class.class;
1122         priv->session_cont.ac.match = iscsi_session_match;
1123         transport_container_register(&priv->session_cont);
1124
1125         SETUP_SESSION_RD_ATTR(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN);
1126         SETUP_SESSION_RD_ATTR(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T);
1127         SETUP_SESSION_RD_ATTR(immediate_data, ISCSI_PARAM_IMM_DATA_EN);
1128         SETUP_SESSION_RD_ATTR(first_burst_len, ISCSI_PARAM_FIRST_BURST);
1129         SETUP_SESSION_RD_ATTR(max_burst_len, ISCSI_PARAM_MAX_BURST);
1130         SETUP_SESSION_RD_ATTR(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN);
1131         SETUP_SESSION_RD_ATTR(data_seq_in_order,ISCSI_PARAM_DATASEQ_INORDER_EN)
1132         SETUP_SESSION_RD_ATTR(erl, ISCSI_PARAM_ERL);
1133
1134         BUG_ON(count > ISCSI_SESSION_ATTRS);
1135         priv->session_attrs[count] = NULL;
1136
1137         spin_lock_irqsave(&iscsi_transport_lock, flags);
1138         list_add(&priv->list, &iscsi_transports);
1139         spin_unlock_irqrestore(&iscsi_transport_lock, flags);
1140
1141         printk(KERN_NOTICE "iscsi: registered transport (%s)\n", tt->name);
1142         return 0;
1143
1144 unregister_cdev:
1145         class_device_unregister(&priv->cdev);
1146 free_priv:
1147         kfree(priv);
1148         return err;
1149 }
1150 EXPORT_SYMBOL_GPL(iscsi_register_transport);
1151
1152 int iscsi_unregister_transport(struct iscsi_transport *tt)
1153 {
1154         struct iscsi_internal *priv;
1155         unsigned long flags;
1156
1157         BUG_ON(!tt);
1158
1159         down(&rx_queue_sema);
1160
1161         priv = iscsi_if_transport_lookup(tt);
1162         BUG_ON (!priv);
1163
1164         spin_lock_irqsave(&priv->session_lock, flags);
1165         if (!list_empty(&priv->sessions)) {
1166                 spin_unlock_irqrestore(&priv->session_lock, flags);
1167                 up(&rx_queue_sema);
1168                 return -EPERM;
1169         }
1170         spin_unlock_irqrestore(&priv->session_lock, flags);
1171
1172         spin_lock_irqsave(&iscsi_transport_lock, flags);
1173         list_del(&priv->list);
1174         spin_unlock_irqrestore(&iscsi_transport_lock, flags);
1175
1176         transport_container_unregister(&priv->conn_cont);
1177         transport_container_unregister(&priv->session_cont);
1178
1179         sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group);
1180         class_device_unregister(&priv->cdev);
1181         up(&rx_queue_sema);
1182
1183         return 0;
1184 }
1185 EXPORT_SYMBOL_GPL(iscsi_unregister_transport);
1186
1187 static int
1188 iscsi_rcv_nl_event(struct notifier_block *this, unsigned long event, void *ptr)
1189 {
1190         struct netlink_notify *n = ptr;
1191
1192         if (event == NETLINK_URELEASE &&
1193             n->protocol == NETLINK_ISCSI && n->pid) {
1194                 struct iscsi_if_conn *conn;
1195                 unsigned long flags;
1196
1197                 mempool_zone_complete(&z_reply);
1198                 spin_lock_irqsave(&connlock, flags);
1199                 list_for_each_entry(conn, &connlist, conn_list) {
1200                         mempool_zone_complete(&conn->z_error);
1201                         mempool_zone_complete(&conn->z_pdu);
1202                 }
1203                 spin_unlock_irqrestore(&connlock, flags);
1204         }
1205
1206         return NOTIFY_DONE;
1207 }
1208
1209 static struct notifier_block iscsi_nl_notifier = {
1210         .notifier_call  = iscsi_rcv_nl_event,
1211 };
1212
1213 static __init int iscsi_transport_init(void)
1214 {
1215         int err;
1216
1217         err = class_register(&iscsi_transport_class);
1218         if (err)
1219                 return err;
1220
1221         err = transport_class_register(&iscsi_connection_class);
1222         if (err)
1223                 goto unregister_transport_class;
1224
1225         err = transport_class_register(&iscsi_session_class);
1226         if (err)
1227                 goto unregister_conn_class;
1228
1229         err = netlink_register_notifier(&iscsi_nl_notifier);
1230         if (err)
1231                 goto unregister_session_class;
1232
1233         nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx,
1234                                     THIS_MODULE);
1235         if (!nls) {
1236                 err = -ENOBUFS;
1237                 goto unregister_notifier;
1238         }
1239
1240         err = mempool_zone_init(&z_reply, Z_MAX_REPLY,
1241                 NLMSG_SPACE(sizeof(struct iscsi_uevent)), Z_HIWAT_REPLY);
1242         if (!err)
1243                 return 0;
1244
1245         sock_release(nls->sk_socket);
1246 unregister_notifier:
1247         netlink_unregister_notifier(&iscsi_nl_notifier);
1248 unregister_session_class:
1249         transport_class_unregister(&iscsi_session_class);
1250 unregister_conn_class:
1251         transport_class_unregister(&iscsi_connection_class);
1252 unregister_transport_class:
1253         class_unregister(&iscsi_transport_class);
1254         return err;
1255 }
1256
1257 static void __exit iscsi_transport_exit(void)
1258 {
1259         mempool_destroy(z_reply.pool);
1260         sock_release(nls->sk_socket);
1261         netlink_unregister_notifier(&iscsi_nl_notifier);
1262         transport_class_unregister(&iscsi_connection_class);
1263         transport_class_unregister(&iscsi_session_class);
1264         class_unregister(&iscsi_transport_class);
1265 }
1266
1267 module_init(iscsi_transport_init);
1268 module_exit(iscsi_transport_exit);
1269
1270 MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>, "
1271               "Dmitry Yusupov <dmitry_yus@yahoo.com>, "
1272               "Alex Aizman <itn780@yahoo.com>");
1273 MODULE_DESCRIPTION("iSCSI Transport Interface");
1274 MODULE_LICENSE("GPL");