Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.19-rc6 1473 lines 40 kB view raw
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/mutex.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 11 34#define ISCSI_CONN_ATTRS 11 35#define ISCSI_HOST_ATTRS 0 36#define ISCSI_TRANSPORT_VERSION "2.0-685" 37 38struct iscsi_internal { 39 int daemon_pid; 40 struct scsi_transport_template t; 41 struct iscsi_transport *iscsi_transport; 42 struct list_head list; 43 struct class_device cdev; 44 45 struct class_device_attribute *host_attrs[ISCSI_HOST_ATTRS + 1]; 46 struct transport_container conn_cont; 47 struct class_device_attribute *conn_attrs[ISCSI_CONN_ATTRS + 1]; 48 struct transport_container session_cont; 49 struct class_device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1]; 50}; 51 52static int iscsi_session_nr; /* sysfs session id for next new session */ 53 54/* 55 * list of registered transports and lock that must 56 * be held while accessing list. The iscsi_transport_lock must 57 * be acquired after the rx_queue_mutex. 58 */ 59static LIST_HEAD(iscsi_transports); 60static DEFINE_SPINLOCK(iscsi_transport_lock); 61 62#define to_iscsi_internal(tmpl) \ 63 container_of(tmpl, struct iscsi_internal, t) 64 65#define cdev_to_iscsi_internal(_cdev) \ 66 container_of(_cdev, struct iscsi_internal, cdev) 67 68static void iscsi_transport_release(struct class_device *cdev) 69{ 70 struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev); 71 kfree(priv); 72} 73 74/* 75 * iscsi_transport_class represents the iscsi_transports that are 76 * registered. 77 */ 78static struct class iscsi_transport_class = { 79 .name = "iscsi_transport", 80 .release = iscsi_transport_release, 81}; 82 83static ssize_t 84show_transport_handle(struct class_device *cdev, char *buf) 85{ 86 struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev); 87 return sprintf(buf, "%llu\n", (unsigned long long)iscsi_handle(priv->iscsi_transport)); 88} 89static CLASS_DEVICE_ATTR(handle, S_IRUGO, show_transport_handle, NULL); 90 91#define show_transport_attr(name, format) \ 92static ssize_t \ 93show_transport_##name(struct class_device *cdev, char *buf) \ 94{ \ 95 struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev); \ 96 return sprintf(buf, format"\n", priv->iscsi_transport->name); \ 97} \ 98static CLASS_DEVICE_ATTR(name, S_IRUGO, show_transport_##name, NULL); 99 100show_transport_attr(caps, "0x%x"); 101show_transport_attr(max_lun, "%d"); 102show_transport_attr(max_conn, "%d"); 103show_transport_attr(max_cmd_len, "%d"); 104 105static struct attribute *iscsi_transport_attrs[] = { 106 &class_device_attr_handle.attr, 107 &class_device_attr_caps.attr, 108 &class_device_attr_max_lun.attr, 109 &class_device_attr_max_conn.attr, 110 &class_device_attr_max_cmd_len.attr, 111 NULL, 112}; 113 114static struct attribute_group iscsi_transport_group = { 115 .attrs = iscsi_transport_attrs, 116}; 117 118static int iscsi_setup_host(struct transport_container *tc, struct device *dev, 119 struct class_device *cdev) 120{ 121 struct Scsi_Host *shost = dev_to_shost(dev); 122 struct iscsi_host *ihost = shost->shost_data; 123 124 memset(ihost, 0, sizeof(*ihost)); 125 INIT_LIST_HEAD(&ihost->sessions); 126 mutex_init(&ihost->mutex); 127 return 0; 128} 129 130static DECLARE_TRANSPORT_CLASS(iscsi_host_class, 131 "iscsi_host", 132 iscsi_setup_host, 133 NULL, 134 NULL); 135 136static DECLARE_TRANSPORT_CLASS(iscsi_session_class, 137 "iscsi_session", 138 NULL, 139 NULL, 140 NULL); 141 142static DECLARE_TRANSPORT_CLASS(iscsi_connection_class, 143 "iscsi_connection", 144 NULL, 145 NULL, 146 NULL); 147 148static struct sock *nls; 149static DEFINE_MUTEX(rx_queue_mutex); 150 151static LIST_HEAD(sesslist); 152static DEFINE_SPINLOCK(sesslock); 153static LIST_HEAD(connlist); 154static DEFINE_SPINLOCK(connlock); 155 156static uint32_t iscsi_conn_get_sid(struct iscsi_cls_conn *conn) 157{ 158 struct iscsi_cls_session *sess = iscsi_dev_to_session(conn->dev.parent); 159 return sess->sid; 160} 161 162/* 163 * Returns the matching session to a given sid 164 */ 165static struct iscsi_cls_session *iscsi_session_lookup(uint32_t sid) 166{ 167 unsigned long flags; 168 struct iscsi_cls_session *sess; 169 170 spin_lock_irqsave(&sesslock, flags); 171 list_for_each_entry(sess, &sesslist, sess_list) { 172 if (sess->sid == sid) { 173 spin_unlock_irqrestore(&sesslock, flags); 174 return sess; 175 } 176 } 177 spin_unlock_irqrestore(&sesslock, flags); 178 return NULL; 179} 180 181/* 182 * Returns the matching connection to a given sid / cid tuple 183 */ 184static struct iscsi_cls_conn *iscsi_conn_lookup(uint32_t sid, uint32_t cid) 185{ 186 unsigned long flags; 187 struct iscsi_cls_conn *conn; 188 189 spin_lock_irqsave(&connlock, flags); 190 list_for_each_entry(conn, &connlist, conn_list) { 191 if ((conn->cid == cid) && (iscsi_conn_get_sid(conn) == sid)) { 192 spin_unlock_irqrestore(&connlock, flags); 193 return conn; 194 } 195 } 196 spin_unlock_irqrestore(&connlock, flags); 197 return NULL; 198} 199 200/* 201 * The following functions can be used by LLDs that allocate 202 * their own scsi_hosts or by software iscsi LLDs 203 */ 204static void iscsi_session_release(struct device *dev) 205{ 206 struct iscsi_cls_session *session = iscsi_dev_to_session(dev); 207 struct Scsi_Host *shost; 208 209 shost = iscsi_session_to_shost(session); 210 scsi_host_put(shost); 211 kfree(session); 212} 213 214static int iscsi_is_session_dev(const struct device *dev) 215{ 216 return dev->release == iscsi_session_release; 217} 218 219static int iscsi_user_scan(struct Scsi_Host *shost, uint channel, 220 uint id, uint lun) 221{ 222 struct iscsi_host *ihost = shost->shost_data; 223 struct iscsi_cls_session *session; 224 225 mutex_lock(&ihost->mutex); 226 list_for_each_entry(session, &ihost->sessions, host_list) { 227 if ((channel == SCAN_WILD_CARD || channel == 0) && 228 (id == SCAN_WILD_CARD || id == session->target_id)) 229 scsi_scan_target(&session->dev, 0, 230 session->target_id, lun, 1); 231 } 232 mutex_unlock(&ihost->mutex); 233 234 return 0; 235} 236 237static void session_recovery_timedout(void *data) 238{ 239 struct iscsi_cls_session *session = data; 240 241 dev_printk(KERN_INFO, &session->dev, "iscsi: session recovery timed " 242 "out after %d secs\n", session->recovery_tmo); 243 244 if (session->transport->session_recovery_timedout) 245 session->transport->session_recovery_timedout(session); 246 247 scsi_target_unblock(&session->dev); 248} 249 250void iscsi_unblock_session(struct iscsi_cls_session *session) 251{ 252 if (!cancel_delayed_work(&session->recovery_work)) 253 flush_scheduled_work(); 254 scsi_target_unblock(&session->dev); 255} 256EXPORT_SYMBOL_GPL(iscsi_unblock_session); 257 258void iscsi_block_session(struct iscsi_cls_session *session) 259{ 260 scsi_target_block(&session->dev); 261 schedule_delayed_work(&session->recovery_work, 262 session->recovery_tmo * HZ); 263} 264EXPORT_SYMBOL_GPL(iscsi_block_session); 265 266struct iscsi_cls_session * 267iscsi_alloc_session(struct Scsi_Host *shost, 268 struct iscsi_transport *transport) 269{ 270 struct iscsi_cls_session *session; 271 272 session = kzalloc(sizeof(*session) + transport->sessiondata_size, 273 GFP_KERNEL); 274 if (!session) 275 return NULL; 276 277 session->transport = transport; 278 session->recovery_tmo = 120; 279 INIT_WORK(&session->recovery_work, session_recovery_timedout, session); 280 INIT_LIST_HEAD(&session->host_list); 281 INIT_LIST_HEAD(&session->sess_list); 282 283 /* this is released in the dev's release function */ 284 scsi_host_get(shost); 285 session->dev.parent = &shost->shost_gendev; 286 session->dev.release = iscsi_session_release; 287 device_initialize(&session->dev); 288 if (transport->sessiondata_size) 289 session->dd_data = &session[1]; 290 return session; 291} 292EXPORT_SYMBOL_GPL(iscsi_alloc_session); 293 294int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id) 295{ 296 struct Scsi_Host *shost = iscsi_session_to_shost(session); 297 struct iscsi_host *ihost; 298 int err; 299 300 ihost = shost->shost_data; 301 session->sid = iscsi_session_nr++; 302 session->target_id = target_id; 303 304 snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", 305 session->sid); 306 err = device_add(&session->dev); 307 if (err) { 308 dev_printk(KERN_ERR, &session->dev, "iscsi: could not " 309 "register session's dev\n"); 310 goto release_host; 311 } 312 transport_register_device(&session->dev); 313 314 mutex_lock(&ihost->mutex); 315 list_add(&session->host_list, &ihost->sessions); 316 mutex_unlock(&ihost->mutex); 317 return 0; 318 319release_host: 320 scsi_host_put(shost); 321 return err; 322} 323EXPORT_SYMBOL_GPL(iscsi_add_session); 324 325/** 326 * iscsi_create_session - create iscsi class session 327 * @shost: scsi host 328 * @transport: iscsi transport 329 * 330 * This can be called from a LLD or iscsi_transport. 331 **/ 332struct iscsi_cls_session * 333iscsi_create_session(struct Scsi_Host *shost, 334 struct iscsi_transport *transport, 335 unsigned int target_id) 336{ 337 struct iscsi_cls_session *session; 338 339 session = iscsi_alloc_session(shost, transport); 340 if (!session) 341 return NULL; 342 343 if (iscsi_add_session(session, target_id)) { 344 iscsi_free_session(session); 345 return NULL; 346 } 347 return session; 348} 349EXPORT_SYMBOL_GPL(iscsi_create_session); 350 351void iscsi_remove_session(struct iscsi_cls_session *session) 352{ 353 struct Scsi_Host *shost = iscsi_session_to_shost(session); 354 struct iscsi_host *ihost = shost->shost_data; 355 356 if (!cancel_delayed_work(&session->recovery_work)) 357 flush_scheduled_work(); 358 359 mutex_lock(&ihost->mutex); 360 list_del(&session->host_list); 361 mutex_unlock(&ihost->mutex); 362 363 scsi_remove_target(&session->dev); 364 365 transport_unregister_device(&session->dev); 366 device_del(&session->dev); 367} 368EXPORT_SYMBOL_GPL(iscsi_remove_session); 369 370void iscsi_free_session(struct iscsi_cls_session *session) 371{ 372 put_device(&session->dev); 373} 374 375EXPORT_SYMBOL_GPL(iscsi_free_session); 376 377/** 378 * iscsi_destroy_session - destroy iscsi session 379 * @session: iscsi_session 380 * 381 * Can be called by a LLD or iscsi_transport. There must not be 382 * any running connections. 383 **/ 384int iscsi_destroy_session(struct iscsi_cls_session *session) 385{ 386 iscsi_remove_session(session); 387 iscsi_free_session(session); 388 return 0; 389} 390EXPORT_SYMBOL_GPL(iscsi_destroy_session); 391 392static void iscsi_conn_release(struct device *dev) 393{ 394 struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev); 395 struct device *parent = conn->dev.parent; 396 397 kfree(conn); 398 put_device(parent); 399} 400 401static int iscsi_is_conn_dev(const struct device *dev) 402{ 403 return dev->release == iscsi_conn_release; 404} 405 406/** 407 * iscsi_create_conn - create iscsi class connection 408 * @session: iscsi cls session 409 * @cid: connection id 410 * 411 * This can be called from a LLD or iscsi_transport. The connection 412 * is child of the session so cid must be unique for all connections 413 * on the session. 414 * 415 * Since we do not support MCS, cid will normally be zero. In some cases 416 * for software iscsi we could be trying to preallocate a connection struct 417 * in which case there could be two connection structs and cid would be 418 * non-zero. 419 **/ 420struct iscsi_cls_conn * 421iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid) 422{ 423 struct iscsi_transport *transport = session->transport; 424 struct iscsi_cls_conn *conn; 425 int err; 426 427 conn = kzalloc(sizeof(*conn) + transport->conndata_size, GFP_KERNEL); 428 if (!conn) 429 return NULL; 430 431 if (transport->conndata_size) 432 conn->dd_data = &conn[1]; 433 434 INIT_LIST_HEAD(&conn->conn_list); 435 conn->transport = transport; 436 conn->cid = cid; 437 438 /* this is released in the dev's release function */ 439 if (!get_device(&session->dev)) 440 goto free_conn; 441 442 snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u", 443 session->sid, cid); 444 conn->dev.parent = &session->dev; 445 conn->dev.release = iscsi_conn_release; 446 err = device_register(&conn->dev); 447 if (err) { 448 dev_printk(KERN_ERR, &conn->dev, "iscsi: could not register " 449 "connection's dev\n"); 450 goto release_parent_ref; 451 } 452 transport_register_device(&conn->dev); 453 return conn; 454 455release_parent_ref: 456 put_device(&session->dev); 457free_conn: 458 kfree(conn); 459 return NULL; 460} 461 462EXPORT_SYMBOL_GPL(iscsi_create_conn); 463 464/** 465 * iscsi_destroy_conn - destroy iscsi class connection 466 * @session: iscsi cls session 467 * 468 * This can be called from a LLD or iscsi_transport. 469 **/ 470int iscsi_destroy_conn(struct iscsi_cls_conn *conn) 471{ 472 transport_unregister_device(&conn->dev); 473 device_unregister(&conn->dev); 474 return 0; 475} 476 477EXPORT_SYMBOL_GPL(iscsi_destroy_conn); 478 479/* 480 * iscsi interface functions 481 */ 482static struct iscsi_internal * 483iscsi_if_transport_lookup(struct iscsi_transport *tt) 484{ 485 struct iscsi_internal *priv; 486 unsigned long flags; 487 488 spin_lock_irqsave(&iscsi_transport_lock, flags); 489 list_for_each_entry(priv, &iscsi_transports, list) { 490 if (tt == priv->iscsi_transport) { 491 spin_unlock_irqrestore(&iscsi_transport_lock, flags); 492 return priv; 493 } 494 } 495 spin_unlock_irqrestore(&iscsi_transport_lock, flags); 496 return NULL; 497} 498 499static int 500iscsi_broadcast_skb(struct sk_buff *skb, gfp_t gfp) 501{ 502 int rc; 503 504 rc = netlink_broadcast(nls, skb, 0, 1, gfp); 505 if (rc < 0) { 506 printk(KERN_ERR "iscsi: can not broadcast skb (%d)\n", rc); 507 return rc; 508 } 509 510 return 0; 511} 512 513static int 514iscsi_unicast_skb(struct sk_buff *skb, int pid) 515{ 516 int rc; 517 518 rc = netlink_unicast(nls, skb, pid, MSG_DONTWAIT); 519 if (rc < 0) { 520 printk(KERN_ERR "iscsi: can not unicast skb (%d)\n", rc); 521 return rc; 522 } 523 524 return 0; 525} 526 527int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, 528 char *data, uint32_t data_size) 529{ 530 struct nlmsghdr *nlh; 531 struct sk_buff *skb; 532 struct iscsi_uevent *ev; 533 char *pdu; 534 struct iscsi_internal *priv; 535 int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) + 536 data_size); 537 538 priv = iscsi_if_transport_lookup(conn->transport); 539 if (!priv) 540 return -EINVAL; 541 542 skb = alloc_skb(len, GFP_ATOMIC); 543 if (!skb) { 544 iscsi_conn_error(conn, ISCSI_ERR_CONN_FAILED); 545 dev_printk(KERN_ERR, &conn->dev, "iscsi: can not deliver " 546 "control PDU: OOM\n"); 547 return -ENOMEM; 548 } 549 550 nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0); 551 ev = NLMSG_DATA(nlh); 552 memset(ev, 0, sizeof(*ev)); 553 ev->transport_handle = iscsi_handle(conn->transport); 554 ev->type = ISCSI_KEVENT_RECV_PDU; 555 ev->r.recv_req.cid = conn->cid; 556 ev->r.recv_req.sid = iscsi_conn_get_sid(conn); 557 pdu = (char*)ev + sizeof(*ev); 558 memcpy(pdu, hdr, sizeof(struct iscsi_hdr)); 559 memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size); 560 561 return iscsi_unicast_skb(skb, priv->daemon_pid); 562} 563EXPORT_SYMBOL_GPL(iscsi_recv_pdu); 564 565void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error) 566{ 567 struct nlmsghdr *nlh; 568 struct sk_buff *skb; 569 struct iscsi_uevent *ev; 570 struct iscsi_internal *priv; 571 int len = NLMSG_SPACE(sizeof(*ev)); 572 573 priv = iscsi_if_transport_lookup(conn->transport); 574 if (!priv) 575 return; 576 577 skb = alloc_skb(len, GFP_ATOMIC); 578 if (!skb) { 579 dev_printk(KERN_ERR, &conn->dev, "iscsi: gracefully ignored " 580 "conn error (%d)\n", error); 581 return; 582 } 583 584 nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0); 585 ev = NLMSG_DATA(nlh); 586 ev->transport_handle = iscsi_handle(conn->transport); 587 ev->type = ISCSI_KEVENT_CONN_ERROR; 588 ev->r.connerror.error = error; 589 ev->r.connerror.cid = conn->cid; 590 ev->r.connerror.sid = iscsi_conn_get_sid(conn); 591 592 iscsi_broadcast_skb(skb, GFP_ATOMIC); 593 594 dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n", 595 error); 596} 597EXPORT_SYMBOL_GPL(iscsi_conn_error); 598 599static int 600iscsi_if_send_reply(int pid, int seq, int type, int done, int multi, 601 void *payload, int size) 602{ 603 struct sk_buff *skb; 604 struct nlmsghdr *nlh; 605 int len = NLMSG_SPACE(size); 606 int flags = multi ? NLM_F_MULTI : 0; 607 int t = done ? NLMSG_DONE : type; 608 609 skb = alloc_skb(len, GFP_ATOMIC); 610 /* 611 * FIXME: 612 * user is supposed to react on iferror == -ENOMEM; 613 * see iscsi_if_rx(). 614 */ 615 BUG_ON(!skb); 616 617 nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0); 618 nlh->nlmsg_flags = flags; 619 memcpy(NLMSG_DATA(nlh), payload, size); 620 return iscsi_unicast_skb(skb, pid); 621} 622 623static int 624iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh) 625{ 626 struct iscsi_uevent *ev = NLMSG_DATA(nlh); 627 struct iscsi_stats *stats; 628 struct sk_buff *skbstat; 629 struct iscsi_cls_conn *conn; 630 struct nlmsghdr *nlhstat; 631 struct iscsi_uevent *evstat; 632 struct iscsi_internal *priv; 633 int len = NLMSG_SPACE(sizeof(*ev) + 634 sizeof(struct iscsi_stats) + 635 sizeof(struct iscsi_stats_custom) * 636 ISCSI_STATS_CUSTOM_MAX); 637 int err = 0; 638 639 priv = iscsi_if_transport_lookup(transport); 640 if (!priv) 641 return -EINVAL; 642 643 conn = iscsi_conn_lookup(ev->u.get_stats.sid, ev->u.get_stats.cid); 644 if (!conn) 645 return -EEXIST; 646 647 do { 648 int actual_size; 649 650 skbstat = alloc_skb(len, GFP_ATOMIC); 651 if (!skbstat) { 652 dev_printk(KERN_ERR, &conn->dev, "iscsi: can not " 653 "deliver stats: OOM\n"); 654 return -ENOMEM; 655 } 656 657 nlhstat = __nlmsg_put(skbstat, priv->daemon_pid, 0, 0, 658 (len - sizeof(*nlhstat)), 0); 659 evstat = NLMSG_DATA(nlhstat); 660 memset(evstat, 0, sizeof(*evstat)); 661 evstat->transport_handle = iscsi_handle(conn->transport); 662 evstat->type = nlh->nlmsg_type; 663 evstat->u.get_stats.cid = 664 ev->u.get_stats.cid; 665 evstat->u.get_stats.sid = 666 ev->u.get_stats.sid; 667 stats = (struct iscsi_stats *) 668 ((char*)evstat + sizeof(*evstat)); 669 memset(stats, 0, sizeof(*stats)); 670 671 transport->get_stats(conn, stats); 672 actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) + 673 sizeof(struct iscsi_stats) + 674 sizeof(struct iscsi_stats_custom) * 675 stats->custom_length); 676 actual_size -= sizeof(*nlhstat); 677 actual_size = NLMSG_LENGTH(actual_size); 678 skb_trim(skbstat, NLMSG_ALIGN(actual_size)); 679 nlhstat->nlmsg_len = actual_size; 680 681 err = iscsi_unicast_skb(skbstat, priv->daemon_pid); 682 } while (err < 0 && err != -ECONNREFUSED); 683 684 return err; 685} 686 687/** 688 * iscsi_if_destroy_session_done - send session destr. completion event 689 * @conn: last connection for session 690 * 691 * This is called by HW iscsi LLDs to notify userpsace that its HW has 692 * removed a session. 693 **/ 694int iscsi_if_destroy_session_done(struct iscsi_cls_conn *conn) 695{ 696 struct iscsi_internal *priv; 697 struct iscsi_cls_session *session; 698 struct Scsi_Host *shost; 699 struct iscsi_uevent *ev; 700 struct sk_buff *skb; 701 struct nlmsghdr *nlh; 702 unsigned long flags; 703 int rc, len = NLMSG_SPACE(sizeof(*ev)); 704 705 priv = iscsi_if_transport_lookup(conn->transport); 706 if (!priv) 707 return -EINVAL; 708 709 session = iscsi_dev_to_session(conn->dev.parent); 710 shost = iscsi_session_to_shost(session); 711 712 skb = alloc_skb(len, GFP_KERNEL); 713 if (!skb) { 714 dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of " 715 "session creation event\n"); 716 return -ENOMEM; 717 } 718 719 nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0); 720 ev = NLMSG_DATA(nlh); 721 ev->transport_handle = iscsi_handle(conn->transport); 722 ev->type = ISCSI_KEVENT_DESTROY_SESSION; 723 ev->r.d_session.host_no = shost->host_no; 724 ev->r.d_session.sid = session->sid; 725 726 /* 727 * this will occur if the daemon is not up, so we just warn 728 * the user and when the daemon is restarted it will handle it 729 */ 730 rc = iscsi_broadcast_skb(skb, GFP_KERNEL); 731 if (rc < 0) 732 dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of " 733 "session destruction event. Check iscsi daemon\n"); 734 735 spin_lock_irqsave(&sesslock, flags); 736 list_del(&session->sess_list); 737 spin_unlock_irqrestore(&sesslock, flags); 738 739 spin_lock_irqsave(&connlock, flags); 740 conn->active = 0; 741 list_del(&conn->conn_list); 742 spin_unlock_irqrestore(&connlock, flags); 743 744 return rc; 745} 746EXPORT_SYMBOL_GPL(iscsi_if_destroy_session_done); 747 748/** 749 * iscsi_if_create_session_done - send session creation completion event 750 * @conn: leading connection for session 751 * 752 * This is called by HW iscsi LLDs to notify userpsace that its HW has 753 * created a session or a existing session is back in the logged in state. 754 **/ 755int iscsi_if_create_session_done(struct iscsi_cls_conn *conn) 756{ 757 struct iscsi_internal *priv; 758 struct iscsi_cls_session *session; 759 struct Scsi_Host *shost; 760 struct iscsi_uevent *ev; 761 struct sk_buff *skb; 762 struct nlmsghdr *nlh; 763 unsigned long flags; 764 int rc, len = NLMSG_SPACE(sizeof(*ev)); 765 766 priv = iscsi_if_transport_lookup(conn->transport); 767 if (!priv) 768 return -EINVAL; 769 770 session = iscsi_dev_to_session(conn->dev.parent); 771 shost = iscsi_session_to_shost(session); 772 773 skb = alloc_skb(len, GFP_KERNEL); 774 if (!skb) { 775 dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of " 776 "session creation event\n"); 777 return -ENOMEM; 778 } 779 780 nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0); 781 ev = NLMSG_DATA(nlh); 782 ev->transport_handle = iscsi_handle(conn->transport); 783 ev->type = ISCSI_UEVENT_CREATE_SESSION; 784 ev->r.c_session_ret.host_no = shost->host_no; 785 ev->r.c_session_ret.sid = session->sid; 786 787 /* 788 * this will occur if the daemon is not up, so we just warn 789 * the user and when the daemon is restarted it will handle it 790 */ 791 rc = iscsi_broadcast_skb(skb, GFP_KERNEL); 792 if (rc < 0) 793 dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of " 794 "session creation event. Check iscsi daemon\n"); 795 796 spin_lock_irqsave(&sesslock, flags); 797 list_add(&session->sess_list, &sesslist); 798 spin_unlock_irqrestore(&sesslock, flags); 799 800 spin_lock_irqsave(&connlock, flags); 801 list_add(&conn->conn_list, &connlist); 802 conn->active = 1; 803 spin_unlock_irqrestore(&connlock, flags); 804 return rc; 805} 806EXPORT_SYMBOL_GPL(iscsi_if_create_session_done); 807 808static int 809iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev) 810{ 811 struct iscsi_transport *transport = priv->iscsi_transport; 812 struct iscsi_cls_session *session; 813 unsigned long flags; 814 uint32_t hostno; 815 816 session = transport->create_session(transport, &priv->t, 817 ev->u.c_session.initial_cmdsn, 818 &hostno); 819 if (!session) 820 return -ENOMEM; 821 822 spin_lock_irqsave(&sesslock, flags); 823 list_add(&session->sess_list, &sesslist); 824 spin_unlock_irqrestore(&sesslock, flags); 825 826 ev->r.c_session_ret.host_no = hostno; 827 ev->r.c_session_ret.sid = session->sid; 828 return 0; 829} 830 831static int 832iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev) 833{ 834 struct iscsi_cls_conn *conn; 835 struct iscsi_cls_session *session; 836 unsigned long flags; 837 838 session = iscsi_session_lookup(ev->u.c_conn.sid); 839 if (!session) { 840 printk(KERN_ERR "iscsi: invalid session %d\n", 841 ev->u.c_conn.sid); 842 return -EINVAL; 843 } 844 845 conn = transport->create_conn(session, ev->u.c_conn.cid); 846 if (!conn) { 847 printk(KERN_ERR "iscsi: couldn't create a new " 848 "connection for session %d\n", 849 session->sid); 850 return -ENOMEM; 851 } 852 853 ev->r.c_conn_ret.sid = session->sid; 854 ev->r.c_conn_ret.cid = conn->cid; 855 856 spin_lock_irqsave(&connlock, flags); 857 list_add(&conn->conn_list, &connlist); 858 conn->active = 1; 859 spin_unlock_irqrestore(&connlock, flags); 860 861 return 0; 862} 863 864static int 865iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev) 866{ 867 unsigned long flags; 868 struct iscsi_cls_conn *conn; 869 870 conn = iscsi_conn_lookup(ev->u.d_conn.sid, ev->u.d_conn.cid); 871 if (!conn) 872 return -EINVAL; 873 spin_lock_irqsave(&connlock, flags); 874 conn->active = 0; 875 list_del(&conn->conn_list); 876 spin_unlock_irqrestore(&connlock, flags); 877 878 if (transport->destroy_conn) 879 transport->destroy_conn(conn); 880 return 0; 881} 882 883static int 884iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev) 885{ 886 char *data = (char*)ev + sizeof(*ev); 887 struct iscsi_cls_conn *conn; 888 struct iscsi_cls_session *session; 889 int err = 0, value = 0; 890 891 session = iscsi_session_lookup(ev->u.set_param.sid); 892 conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid); 893 if (!conn || !session) 894 return -EINVAL; 895 896 switch (ev->u.set_param.param) { 897 case ISCSI_PARAM_SESS_RECOVERY_TMO: 898 sscanf(data, "%d", &value); 899 if (value != 0) 900 session->recovery_tmo = value; 901 break; 902 default: 903 err = transport->set_param(conn, ev->u.set_param.param, 904 data, ev->u.set_param.len); 905 } 906 907 return err; 908} 909 910static int 911iscsi_if_transport_ep(struct iscsi_transport *transport, 912 struct iscsi_uevent *ev, int msg_type) 913{ 914 struct sockaddr *dst_addr; 915 int rc = 0; 916 917 switch (msg_type) { 918 case ISCSI_UEVENT_TRANSPORT_EP_CONNECT: 919 if (!transport->ep_connect) 920 return -EINVAL; 921 922 dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev)); 923 rc = transport->ep_connect(dst_addr, 924 ev->u.ep_connect.non_blocking, 925 &ev->r.ep_connect_ret.handle); 926 break; 927 case ISCSI_UEVENT_TRANSPORT_EP_POLL: 928 if (!transport->ep_poll) 929 return -EINVAL; 930 931 ev->r.retcode = transport->ep_poll(ev->u.ep_poll.ep_handle, 932 ev->u.ep_poll.timeout_ms); 933 break; 934 case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT: 935 if (!transport->ep_disconnect) 936 return -EINVAL; 937 938 transport->ep_disconnect(ev->u.ep_disconnect.ep_handle); 939 break; 940 } 941 return rc; 942} 943 944static int 945iscsi_tgt_dscvr(struct iscsi_transport *transport, 946 struct iscsi_uevent *ev) 947{ 948 struct sockaddr *dst_addr; 949 950 if (!transport->tgt_dscvr) 951 return -EINVAL; 952 953 dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev)); 954 return transport->tgt_dscvr(ev->u.tgt_dscvr.type, 955 ev->u.tgt_dscvr.host_no, 956 ev->u.tgt_dscvr.enable, dst_addr); 957} 958 959static int 960iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) 961{ 962 int err = 0; 963 struct iscsi_uevent *ev = NLMSG_DATA(nlh); 964 struct iscsi_transport *transport = NULL; 965 struct iscsi_internal *priv; 966 struct iscsi_cls_session *session; 967 struct iscsi_cls_conn *conn; 968 unsigned long flags; 969 970 priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle)); 971 if (!priv) 972 return -EINVAL; 973 transport = priv->iscsi_transport; 974 975 if (!try_module_get(transport->owner)) 976 return -EINVAL; 977 978 priv->daemon_pid = NETLINK_CREDS(skb)->pid; 979 980 switch (nlh->nlmsg_type) { 981 case ISCSI_UEVENT_CREATE_SESSION: 982 err = iscsi_if_create_session(priv, ev); 983 break; 984 case ISCSI_UEVENT_DESTROY_SESSION: 985 session = iscsi_session_lookup(ev->u.d_session.sid); 986 if (session) { 987 spin_lock_irqsave(&sesslock, flags); 988 list_del(&session->sess_list); 989 spin_unlock_irqrestore(&sesslock, flags); 990 991 transport->destroy_session(session); 992 } else 993 err = -EINVAL; 994 break; 995 case ISCSI_UEVENT_CREATE_CONN: 996 err = iscsi_if_create_conn(transport, ev); 997 break; 998 case ISCSI_UEVENT_DESTROY_CONN: 999 err = iscsi_if_destroy_conn(transport, ev); 1000 break; 1001 case ISCSI_UEVENT_BIND_CONN: 1002 session = iscsi_session_lookup(ev->u.b_conn.sid); 1003 conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid); 1004 1005 if (session && conn) 1006 ev->r.retcode = transport->bind_conn(session, conn, 1007 ev->u.b_conn.transport_eph, 1008 ev->u.b_conn.is_leading); 1009 else 1010 err = -EINVAL; 1011 break; 1012 case ISCSI_UEVENT_SET_PARAM: 1013 err = iscsi_set_param(transport, ev); 1014 break; 1015 case ISCSI_UEVENT_START_CONN: 1016 conn = iscsi_conn_lookup(ev->u.start_conn.sid, ev->u.start_conn.cid); 1017 if (conn) 1018 ev->r.retcode = transport->start_conn(conn); 1019 else 1020 err = -EINVAL; 1021 break; 1022 case ISCSI_UEVENT_STOP_CONN: 1023 conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ev->u.stop_conn.cid); 1024 if (conn) 1025 transport->stop_conn(conn, ev->u.stop_conn.flag); 1026 else 1027 err = -EINVAL; 1028 break; 1029 case ISCSI_UEVENT_SEND_PDU: 1030 conn = iscsi_conn_lookup(ev->u.send_pdu.sid, ev->u.send_pdu.cid); 1031 if (conn) 1032 ev->r.retcode = transport->send_pdu(conn, 1033 (struct iscsi_hdr*)((char*)ev + sizeof(*ev)), 1034 (char*)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size, 1035 ev->u.send_pdu.data_size); 1036 else 1037 err = -EINVAL; 1038 break; 1039 case ISCSI_UEVENT_GET_STATS: 1040 err = iscsi_if_get_stats(transport, nlh); 1041 break; 1042 case ISCSI_UEVENT_TRANSPORT_EP_CONNECT: 1043 case ISCSI_UEVENT_TRANSPORT_EP_POLL: 1044 case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT: 1045 err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type); 1046 break; 1047 case ISCSI_UEVENT_TGT_DSCVR: 1048 err = iscsi_tgt_dscvr(transport, ev); 1049 break; 1050 default: 1051 err = -EINVAL; 1052 break; 1053 } 1054 1055 module_put(transport->owner); 1056 return err; 1057} 1058 1059/* 1060 * Get message from skb (based on rtnetlink_rcv_skb). Each message is 1061 * processed by iscsi_if_recv_msg. Malformed skbs with wrong lengths or 1062 * invalid creds are discarded silently. 1063 */ 1064static void 1065iscsi_if_rx(struct sock *sk, int len) 1066{ 1067 struct sk_buff *skb; 1068 1069 mutex_lock(&rx_queue_mutex); 1070 while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { 1071 if (NETLINK_CREDS(skb)->uid) { 1072 skb_pull(skb, skb->len); 1073 goto free_skb; 1074 } 1075 1076 while (skb->len >= NLMSG_SPACE(0)) { 1077 int err; 1078 uint32_t rlen; 1079 struct nlmsghdr *nlh; 1080 struct iscsi_uevent *ev; 1081 1082 nlh = (struct nlmsghdr *)skb->data; 1083 if (nlh->nlmsg_len < sizeof(*nlh) || 1084 skb->len < nlh->nlmsg_len) { 1085 break; 1086 } 1087 1088 ev = NLMSG_DATA(nlh); 1089 rlen = NLMSG_ALIGN(nlh->nlmsg_len); 1090 if (rlen > skb->len) 1091 rlen = skb->len; 1092 1093 err = iscsi_if_recv_msg(skb, nlh); 1094 if (err) { 1095 ev->type = ISCSI_KEVENT_IF_ERROR; 1096 ev->iferror = err; 1097 } 1098 do { 1099 /* 1100 * special case for GET_STATS: 1101 * on success - sending reply and stats from 1102 * inside of if_recv_msg(), 1103 * on error - fall through. 1104 */ 1105 if (ev->type == ISCSI_UEVENT_GET_STATS && !err) 1106 break; 1107 err = iscsi_if_send_reply( 1108 NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq, 1109 nlh->nlmsg_type, 0, 0, ev, sizeof(*ev)); 1110 } while (err < 0 && err != -ECONNREFUSED); 1111 skb_pull(skb, rlen); 1112 } 1113free_skb: 1114 kfree_skb(skb); 1115 } 1116 mutex_unlock(&rx_queue_mutex); 1117} 1118 1119#define iscsi_cdev_to_conn(_cdev) \ 1120 iscsi_dev_to_conn(_cdev->dev) 1121 1122#define ISCSI_CLASS_ATTR(_prefix,_name,_mode,_show,_store) \ 1123struct class_device_attribute class_device_attr_##_prefix##_##_name = \ 1124 __ATTR(_name,_mode,_show,_store) 1125 1126/* 1127 * iSCSI connection attrs 1128 */ 1129#define iscsi_conn_attr_show(param) \ 1130static ssize_t \ 1131show_conn_param_##param(struct class_device *cdev, char *buf) \ 1132{ \ 1133 struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \ 1134 struct iscsi_transport *t = conn->transport; \ 1135 return t->get_conn_param(conn, param, buf); \ 1136} 1137 1138#define iscsi_conn_attr(field, param) \ 1139 iscsi_conn_attr_show(param) \ 1140static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_param_##param, \ 1141 NULL); 1142 1143iscsi_conn_attr(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH); 1144iscsi_conn_attr(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH); 1145iscsi_conn_attr(header_digest, ISCSI_PARAM_HDRDGST_EN); 1146iscsi_conn_attr(data_digest, ISCSI_PARAM_DATADGST_EN); 1147iscsi_conn_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN); 1148iscsi_conn_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN); 1149iscsi_conn_attr(persistent_port, ISCSI_PARAM_PERSISTENT_PORT); 1150iscsi_conn_attr(port, ISCSI_PARAM_CONN_PORT); 1151iscsi_conn_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN); 1152iscsi_conn_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS); 1153iscsi_conn_attr(address, ISCSI_PARAM_CONN_ADDRESS); 1154 1155#define iscsi_cdev_to_session(_cdev) \ 1156 iscsi_dev_to_session(_cdev->dev) 1157 1158/* 1159 * iSCSI session attrs 1160 */ 1161#define iscsi_session_attr_show(param) \ 1162static ssize_t \ 1163show_session_param_##param(struct class_device *cdev, char *buf) \ 1164{ \ 1165 struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \ 1166 struct iscsi_transport *t = session->transport; \ 1167 return t->get_session_param(session, param, buf); \ 1168} 1169 1170#define iscsi_session_attr(field, param) \ 1171 iscsi_session_attr_show(param) \ 1172static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_param_##param, \ 1173 NULL); 1174 1175iscsi_session_attr(targetname, ISCSI_PARAM_TARGET_NAME); 1176iscsi_session_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN); 1177iscsi_session_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T); 1178iscsi_session_attr(immediate_data, ISCSI_PARAM_IMM_DATA_EN); 1179iscsi_session_attr(first_burst_len, ISCSI_PARAM_FIRST_BURST); 1180iscsi_session_attr(max_burst_len, ISCSI_PARAM_MAX_BURST); 1181iscsi_session_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN); 1182iscsi_session_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN); 1183iscsi_session_attr(erl, ISCSI_PARAM_ERL); 1184iscsi_session_attr(tpgt, ISCSI_PARAM_TPGT); 1185 1186#define iscsi_priv_session_attr_show(field, format) \ 1187static ssize_t \ 1188show_priv_session_##field(struct class_device *cdev, char *buf) \ 1189{ \ 1190 struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev);\ 1191 return sprintf(buf, format"\n", session->field); \ 1192} 1193 1194#define iscsi_priv_session_attr(field, format) \ 1195 iscsi_priv_session_attr_show(field, format) \ 1196static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO, show_priv_session_##field, \ 1197 NULL) 1198iscsi_priv_session_attr(recovery_tmo, "%d"); 1199 1200#define SETUP_PRIV_SESSION_RD_ATTR(field) \ 1201do { \ 1202 priv->session_attrs[count] = &class_device_attr_priv_sess_##field; \ 1203 count++; \ 1204} while (0) 1205 1206 1207#define SETUP_SESSION_RD_ATTR(field, param_flag) \ 1208do { \ 1209 if (tt->param_mask & param_flag) { \ 1210 priv->session_attrs[count] = &class_device_attr_sess_##field; \ 1211 count++; \ 1212 } \ 1213} while (0) 1214 1215#define SETUP_CONN_RD_ATTR(field, param_flag) \ 1216do { \ 1217 if (tt->param_mask & param_flag) { \ 1218 priv->conn_attrs[count] = &class_device_attr_conn_##field; \ 1219 count++; \ 1220 } \ 1221} while (0) 1222 1223static int iscsi_session_match(struct attribute_container *cont, 1224 struct device *dev) 1225{ 1226 struct iscsi_cls_session *session; 1227 struct Scsi_Host *shost; 1228 struct iscsi_internal *priv; 1229 1230 if (!iscsi_is_session_dev(dev)) 1231 return 0; 1232 1233 session = iscsi_dev_to_session(dev); 1234 shost = iscsi_session_to_shost(session); 1235 if (!shost->transportt) 1236 return 0; 1237 1238 priv = to_iscsi_internal(shost->transportt); 1239 if (priv->session_cont.ac.class != &iscsi_session_class.class) 1240 return 0; 1241 1242 return &priv->session_cont.ac == cont; 1243} 1244 1245static int iscsi_conn_match(struct attribute_container *cont, 1246 struct device *dev) 1247{ 1248 struct iscsi_cls_session *session; 1249 struct iscsi_cls_conn *conn; 1250 struct Scsi_Host *shost; 1251 struct iscsi_internal *priv; 1252 1253 if (!iscsi_is_conn_dev(dev)) 1254 return 0; 1255 1256 conn = iscsi_dev_to_conn(dev); 1257 session = iscsi_dev_to_session(conn->dev.parent); 1258 shost = iscsi_session_to_shost(session); 1259 1260 if (!shost->transportt) 1261 return 0; 1262 1263 priv = to_iscsi_internal(shost->transportt); 1264 if (priv->conn_cont.ac.class != &iscsi_connection_class.class) 1265 return 0; 1266 1267 return &priv->conn_cont.ac == cont; 1268} 1269 1270static int iscsi_host_match(struct attribute_container *cont, 1271 struct device *dev) 1272{ 1273 struct Scsi_Host *shost; 1274 struct iscsi_internal *priv; 1275 1276 if (!scsi_is_host_device(dev)) 1277 return 0; 1278 1279 shost = dev_to_shost(dev); 1280 if (!shost->transportt || 1281 shost->transportt->host_attrs.ac.class != &iscsi_host_class.class) 1282 return 0; 1283 1284 priv = to_iscsi_internal(shost->transportt); 1285 return &priv->t.host_attrs.ac == cont; 1286} 1287 1288struct scsi_transport_template * 1289iscsi_register_transport(struct iscsi_transport *tt) 1290{ 1291 struct iscsi_internal *priv; 1292 unsigned long flags; 1293 int count = 0, err; 1294 1295 BUG_ON(!tt); 1296 1297 priv = iscsi_if_transport_lookup(tt); 1298 if (priv) 1299 return NULL; 1300 1301 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 1302 if (!priv) 1303 return NULL; 1304 INIT_LIST_HEAD(&priv->list); 1305 priv->daemon_pid = -1; 1306 priv->iscsi_transport = tt; 1307 priv->t.user_scan = iscsi_user_scan; 1308 1309 priv->cdev.class = &iscsi_transport_class; 1310 snprintf(priv->cdev.class_id, BUS_ID_SIZE, "%s", tt->name); 1311 err = class_device_register(&priv->cdev); 1312 if (err) 1313 goto free_priv; 1314 1315 err = sysfs_create_group(&priv->cdev.kobj, &iscsi_transport_group); 1316 if (err) 1317 goto unregister_cdev; 1318 1319 /* host parameters */ 1320 priv->t.host_attrs.ac.attrs = &priv->host_attrs[0]; 1321 priv->t.host_attrs.ac.class = &iscsi_host_class.class; 1322 priv->t.host_attrs.ac.match = iscsi_host_match; 1323 priv->t.host_size = sizeof(struct iscsi_host); 1324 priv->host_attrs[0] = NULL; 1325 transport_container_register(&priv->t.host_attrs); 1326 1327 /* connection parameters */ 1328 priv->conn_cont.ac.attrs = &priv->conn_attrs[0]; 1329 priv->conn_cont.ac.class = &iscsi_connection_class.class; 1330 priv->conn_cont.ac.match = iscsi_conn_match; 1331 transport_container_register(&priv->conn_cont); 1332 1333 SETUP_CONN_RD_ATTR(max_recv_dlength, ISCSI_MAX_RECV_DLENGTH); 1334 SETUP_CONN_RD_ATTR(max_xmit_dlength, ISCSI_MAX_XMIT_DLENGTH); 1335 SETUP_CONN_RD_ATTR(header_digest, ISCSI_HDRDGST_EN); 1336 SETUP_CONN_RD_ATTR(data_digest, ISCSI_DATADGST_EN); 1337 SETUP_CONN_RD_ATTR(ifmarker, ISCSI_IFMARKER_EN); 1338 SETUP_CONN_RD_ATTR(ofmarker, ISCSI_OFMARKER_EN); 1339 SETUP_CONN_RD_ATTR(address, ISCSI_CONN_ADDRESS); 1340 SETUP_CONN_RD_ATTR(port, ISCSI_CONN_PORT); 1341 SETUP_CONN_RD_ATTR(exp_statsn, ISCSI_EXP_STATSN); 1342 SETUP_CONN_RD_ATTR(persistent_address, ISCSI_PERSISTENT_ADDRESS); 1343 SETUP_CONN_RD_ATTR(persistent_port, ISCSI_PERSISTENT_PORT); 1344 1345 BUG_ON(count > ISCSI_CONN_ATTRS); 1346 priv->conn_attrs[count] = NULL; 1347 count = 0; 1348 1349 /* session parameters */ 1350 priv->session_cont.ac.attrs = &priv->session_attrs[0]; 1351 priv->session_cont.ac.class = &iscsi_session_class.class; 1352 priv->session_cont.ac.match = iscsi_session_match; 1353 transport_container_register(&priv->session_cont); 1354 1355 SETUP_SESSION_RD_ATTR(initial_r2t, ISCSI_INITIAL_R2T_EN); 1356 SETUP_SESSION_RD_ATTR(max_outstanding_r2t, ISCSI_MAX_R2T); 1357 SETUP_SESSION_RD_ATTR(immediate_data, ISCSI_IMM_DATA_EN); 1358 SETUP_SESSION_RD_ATTR(first_burst_len, ISCSI_FIRST_BURST); 1359 SETUP_SESSION_RD_ATTR(max_burst_len, ISCSI_MAX_BURST); 1360 SETUP_SESSION_RD_ATTR(data_pdu_in_order, ISCSI_PDU_INORDER_EN); 1361 SETUP_SESSION_RD_ATTR(data_seq_in_order, ISCSI_DATASEQ_INORDER_EN); 1362 SETUP_SESSION_RD_ATTR(erl, ISCSI_ERL); 1363 SETUP_SESSION_RD_ATTR(targetname, ISCSI_TARGET_NAME); 1364 SETUP_SESSION_RD_ATTR(tpgt, ISCSI_TPGT); 1365 SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo); 1366 1367 BUG_ON(count > ISCSI_SESSION_ATTRS); 1368 priv->session_attrs[count] = NULL; 1369 1370 spin_lock_irqsave(&iscsi_transport_lock, flags); 1371 list_add(&priv->list, &iscsi_transports); 1372 spin_unlock_irqrestore(&iscsi_transport_lock, flags); 1373 1374 printk(KERN_NOTICE "iscsi: registered transport (%s)\n", tt->name); 1375 return &priv->t; 1376 1377unregister_cdev: 1378 class_device_unregister(&priv->cdev); 1379free_priv: 1380 kfree(priv); 1381 return NULL; 1382} 1383EXPORT_SYMBOL_GPL(iscsi_register_transport); 1384 1385int iscsi_unregister_transport(struct iscsi_transport *tt) 1386{ 1387 struct iscsi_internal *priv; 1388 unsigned long flags; 1389 1390 BUG_ON(!tt); 1391 1392 mutex_lock(&rx_queue_mutex); 1393 1394 priv = iscsi_if_transport_lookup(tt); 1395 BUG_ON (!priv); 1396 1397 spin_lock_irqsave(&iscsi_transport_lock, flags); 1398 list_del(&priv->list); 1399 spin_unlock_irqrestore(&iscsi_transport_lock, flags); 1400 1401 transport_container_unregister(&priv->conn_cont); 1402 transport_container_unregister(&priv->session_cont); 1403 transport_container_unregister(&priv->t.host_attrs); 1404 1405 sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group); 1406 class_device_unregister(&priv->cdev); 1407 mutex_unlock(&rx_queue_mutex); 1408 1409 return 0; 1410} 1411EXPORT_SYMBOL_GPL(iscsi_unregister_transport); 1412 1413static __init int iscsi_transport_init(void) 1414{ 1415 int err; 1416 1417 printk(KERN_INFO "Loading iSCSI transport class v%s.", 1418 ISCSI_TRANSPORT_VERSION); 1419 1420 err = class_register(&iscsi_transport_class); 1421 if (err) 1422 return err; 1423 1424 err = transport_class_register(&iscsi_host_class); 1425 if (err) 1426 goto unregister_transport_class; 1427 1428 err = transport_class_register(&iscsi_connection_class); 1429 if (err) 1430 goto unregister_host_class; 1431 1432 err = transport_class_register(&iscsi_session_class); 1433 if (err) 1434 goto unregister_conn_class; 1435 1436 nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx, 1437 THIS_MODULE); 1438 if (!nls) { 1439 err = -ENOBUFS; 1440 goto unregister_session_class; 1441 } 1442 1443 return 0; 1444 1445unregister_session_class: 1446 transport_class_unregister(&iscsi_session_class); 1447unregister_conn_class: 1448 transport_class_unregister(&iscsi_connection_class); 1449unregister_host_class: 1450 transport_class_unregister(&iscsi_host_class); 1451unregister_transport_class: 1452 class_unregister(&iscsi_transport_class); 1453 return err; 1454} 1455 1456static void __exit iscsi_transport_exit(void) 1457{ 1458 sock_release(nls->sk_socket); 1459 transport_class_unregister(&iscsi_connection_class); 1460 transport_class_unregister(&iscsi_session_class); 1461 transport_class_unregister(&iscsi_host_class); 1462 class_unregister(&iscsi_transport_class); 1463} 1464 1465module_init(iscsi_transport_init); 1466module_exit(iscsi_transport_exit); 1467 1468MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>, " 1469 "Dmitry Yusupov <dmitry_yus@yahoo.com>, " 1470 "Alex Aizman <itn780@yahoo.com>"); 1471MODULE_DESCRIPTION("iSCSI Transport Interface"); 1472MODULE_LICENSE("GPL"); 1473MODULE_VERSION(ISCSI_TRANSPORT_VERSION);