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