linux/drivers/scsi/scsi_transport_iscsi.c
<<
>>
Prefs
   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 15
  34#define ISCSI_CONN_ATTRS 11
  35#define ISCSI_HOST_ATTRS 4
  36#define ISCSI_TRANSPORT_VERSION "2.0-724"
  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 atomic_t 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(struct work_struct *work)
 238{
 239        struct iscsi_cls_session *session =
 240                container_of(work, struct iscsi_cls_session,
 241                             recovery_work.work);
 242
 243        dev_printk(KERN_INFO, &session->dev, "iscsi: session recovery timed "
 244                  "out after %d secs\n", session->recovery_tmo);
 245
 246        if (session->transport->session_recovery_timedout)
 247                session->transport->session_recovery_timedout(session);
 248
 249        scsi_target_unblock(&session->dev);
 250}
 251
 252void iscsi_unblock_session(struct iscsi_cls_session *session)
 253{
 254        if (!cancel_delayed_work(&session->recovery_work))
 255                flush_scheduled_work();
 256        scsi_target_unblock(&session->dev);
 257}
 258EXPORT_SYMBOL_GPL(iscsi_unblock_session);
 259
 260void iscsi_block_session(struct iscsi_cls_session *session)
 261{
 262        scsi_target_block(&session->dev);
 263        schedule_delayed_work(&session->recovery_work,
 264                             session->recovery_tmo * HZ);
 265}
 266EXPORT_SYMBOL_GPL(iscsi_block_session);
 267
 268struct iscsi_cls_session *
 269iscsi_alloc_session(struct Scsi_Host *shost,
 270                    struct iscsi_transport *transport)
 271{
 272        struct iscsi_cls_session *session;
 273
 274        session = kzalloc(sizeof(*session) + transport->sessiondata_size,
 275                          GFP_KERNEL);
 276        if (!session)
 277                return NULL;
 278
 279        session->transport = transport;
 280        session->recovery_tmo = 120;
 281        INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout);
 282        INIT_LIST_HEAD(&session->host_list);
 283        INIT_LIST_HEAD(&session->sess_list);
 284
 285        /* this is released in the dev's release function */
 286        scsi_host_get(shost);
 287        session->dev.parent = &shost->shost_gendev;
 288        session->dev.release = iscsi_session_release;
 289        device_initialize(&session->dev);
 290        if (transport->sessiondata_size)
 291                session->dd_data = &session[1];
 292        return session;
 293}
 294EXPORT_SYMBOL_GPL(iscsi_alloc_session);
 295
 296int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
 297{
 298        struct Scsi_Host *shost = iscsi_session_to_shost(session);
 299        struct iscsi_host *ihost;
 300        int err;
 301
 302        ihost = shost->shost_data;
 303        session->sid = atomic_add_return(1, &iscsi_session_nr);
 304        session->target_id = target_id;
 305
 306        snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u",
 307                 session->sid);
 308        err = device_add(&session->dev);
 309        if (err) {
 310                dev_printk(KERN_ERR, &session->dev, "iscsi: could not "
 311                           "register session's dev\n");
 312                goto release_host;
 313        }
 314        transport_register_device(&session->dev);
 315
 316        mutex_lock(&ihost->mutex);
 317        list_add(&session->host_list, &ihost->sessions);
 318        mutex_unlock(&ihost->mutex);
 319        return 0;
 320
 321release_host:
 322        scsi_host_put(shost);
 323        return err;
 324}
 325EXPORT_SYMBOL_GPL(iscsi_add_session);
 326
 327/**
 328 * iscsi_create_session - create iscsi class session
 329 * @shost: scsi host
 330 * @transport: iscsi transport
 331 *
 332 * This can be called from a LLD or iscsi_transport.
 333 **/
 334struct iscsi_cls_session *
 335iscsi_create_session(struct Scsi_Host *shost,
 336                     struct iscsi_transport *transport,
 337                     unsigned int target_id)
 338{
 339        struct iscsi_cls_session *session;
 340
 341        session = iscsi_alloc_session(shost, transport);
 342        if (!session)
 343                return NULL;
 344
 345        if (iscsi_add_session(session, target_id)) {
 346                iscsi_free_session(session);
 347                return NULL;
 348        }
 349        return session;
 350}
 351EXPORT_SYMBOL_GPL(iscsi_create_session);
 352
 353void iscsi_remove_session(struct iscsi_cls_session *session)
 354{
 355        struct Scsi_Host *shost = iscsi_session_to_shost(session);
 356        struct iscsi_host *ihost = shost->shost_data;
 357
 358        if (!cancel_delayed_work(&session->recovery_work))
 359                flush_scheduled_work();
 360
 361        mutex_lock(&ihost->mutex);
 362        list_del(&session->host_list);
 363        mutex_unlock(&ihost->mutex);
 364
 365        scsi_remove_target(&session->dev);
 366
 367        transport_unregister_device(&session->dev);
 368        device_del(&session->dev);
 369}
 370EXPORT_SYMBOL_GPL(iscsi_remove_session);
 371
 372void iscsi_free_session(struct iscsi_cls_session *session)
 373{
 374        put_device(&session->dev);
 375}
 376
 377EXPORT_SYMBOL_GPL(iscsi_free_session);
 378
 379/**
 380 * iscsi_destroy_session - destroy iscsi session
 381 * @session: iscsi_session
 382 *
 383 * Can be called by a LLD or iscsi_transport. There must not be
 384 * any running connections.
 385 **/
 386int iscsi_destroy_session(struct iscsi_cls_session *session)
 387{
 388        iscsi_remove_session(session);
 389        iscsi_free_session(session);
 390        return 0;
 391}
 392EXPORT_SYMBOL_GPL(iscsi_destroy_session);
 393
 394static void iscsi_conn_release(struct device *dev)
 395{
 396        struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev);
 397        struct device *parent = conn->dev.parent;
 398
 399        kfree(conn);
 400        put_device(parent);
 401}
 402
 403static int iscsi_is_conn_dev(const struct device *dev)
 404{
 405        return dev->release == iscsi_conn_release;
 406}
 407
 408/**
 409 * iscsi_create_conn - create iscsi class connection
 410 * @session: iscsi cls session
 411 * @cid: connection id
 412 *
 413 * This can be called from a LLD or iscsi_transport. The connection
 414 * is child of the session so cid must be unique for all connections
 415 * on the session.
 416 *
 417 * Since we do not support MCS, cid will normally be zero. In some cases
 418 * for software iscsi we could be trying to preallocate a connection struct
 419 * in which case there could be two connection structs and cid would be
 420 * non-zero.
 421 **/
 422struct iscsi_cls_conn *
 423iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid)
 424{
 425        struct iscsi_transport *transport = session->transport;
 426        struct iscsi_cls_conn *conn;
 427        int err;
 428
 429        conn = kzalloc(sizeof(*conn) + transport->conndata_size, GFP_KERNEL);
 430        if (!conn)
 431                return NULL;
 432
 433        if (transport->conndata_size)
 434                conn->dd_data = &conn[1];
 435
 436        INIT_LIST_HEAD(&conn->conn_list);
 437        conn->transport = transport;
 438        conn->cid = cid;
 439
 440        /* this is released in the dev's release function */
 441        if (!get_device(&session->dev))
 442                goto free_conn;
 443
 444        snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
 445                 session->sid, cid);
 446        conn->dev.parent = &session->dev;
 447        conn->dev.release = iscsi_conn_release;
 448        err = device_register(&conn->dev);
 449        if (err) {
 450                dev_printk(KERN_ERR, &conn->dev, "iscsi: could not register "
 451                           "connection's dev\n");
 452                goto release_parent_ref;
 453        }
 454        transport_register_device(&conn->dev);
 455        return conn;
 456
 457release_parent_ref:
 458        put_device(&session->dev);
 459free_conn:
 460        kfree(conn);
 461        return NULL;
 462}
 463
 464EXPORT_SYMBOL_GPL(iscsi_create_conn);
 465
 466/**
 467 * iscsi_destroy_conn - destroy iscsi class connection
 468 * @session: iscsi cls session
 469 *
 470 * This can be called from a LLD or iscsi_transport.
 471 **/
 472int iscsi_destroy_conn(struct iscsi_cls_conn *conn)
 473{
 474        transport_unregister_device(&conn->dev);
 475        device_unregister(&conn->dev);
 476        return 0;
 477}
 478
 479EXPORT_SYMBOL_GPL(iscsi_destroy_conn);
 480
 481/*
 482 * iscsi interface functions
 483 */
 484static struct iscsi_internal *
 485iscsi_if_transport_lookup(struct iscsi_transport *tt)
 486{
 487        struct iscsi_internal *priv;
 488        unsigned long flags;
 489
 490        spin_lock_irqsave(&iscsi_transport_lock, flags);
 491        list_for_each_entry(priv, &iscsi_transports, list) {
 492                if (tt == priv->iscsi_transport) {
 493                        spin_unlock_irqrestore(&iscsi_transport_lock, flags);
 494                        return priv;
 495                }
 496        }
 497        spin_unlock_irqrestore(&iscsi_transport_lock, flags);
 498        return NULL;
 499}
 500
 501static int
 502iscsi_broadcast_skb(struct sk_buff *skb, gfp_t gfp)
 503{
 504        int rc;
 505
 506        rc = netlink_broadcast(nls, skb, 0, 1, gfp);
 507        if (rc < 0) {
 508                printk(KERN_ERR "iscsi: can not broadcast skb (%d)\n", rc);
 509                return rc;
 510        }
 511
 512        return 0;
 513}
 514
 515static int
 516iscsi_unicast_skb(struct sk_buff *skb, int pid)
 517{
 518        int rc;
 519
 520        rc = netlink_unicast(nls, skb, pid, MSG_DONTWAIT);
 521        if (rc < 0) {
 522                printk(KERN_ERR "iscsi: can not unicast skb (%d)\n", rc);
 523                return rc;
 524        }
 525
 526        return 0;
 527}
 528
 529int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
 530                   char *data, uint32_t data_size)
 531{
 532        struct nlmsghdr *nlh;
 533        struct sk_buff *skb;
 534        struct iscsi_uevent *ev;
 535        char *pdu;
 536        struct iscsi_internal *priv;
 537        int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) +
 538                              data_size);
 539
 540        priv = iscsi_if_transport_lookup(conn->transport);
 541        if (!priv)
 542                return -EINVAL;
 543
 544        skb = alloc_skb(len, GFP_ATOMIC);
 545        if (!skb) {
 546                iscsi_conn_error(conn, ISCSI_ERR_CONN_FAILED);
 547                dev_printk(KERN_ERR, &conn->dev, "iscsi: can not deliver "
 548                           "control PDU: OOM\n");
 549                return -ENOMEM;
 550        }
 551
 552        nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
 553        ev = NLMSG_DATA(nlh);
 554        memset(ev, 0, sizeof(*ev));
 555        ev->transport_handle = iscsi_handle(conn->transport);
 556        ev->type = ISCSI_KEVENT_RECV_PDU;
 557        ev->r.recv_req.cid = conn->cid;
 558        ev->r.recv_req.sid = iscsi_conn_get_sid(conn);
 559        pdu = (char*)ev + sizeof(*ev);
 560        memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
 561        memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
 562
 563        return iscsi_unicast_skb(skb, priv->daemon_pid);
 564}
 565EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
 566
 567void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
 568{
 569        struct nlmsghdr *nlh;
 570        struct sk_buff  *skb;
 571        struct iscsi_uevent *ev;
 572        struct iscsi_internal *priv;
 573        int len = NLMSG_SPACE(sizeof(*ev));
 574
 575        priv = iscsi_if_transport_lookup(conn->transport);
 576        if (!priv)
 577                return;
 578
 579        skb = alloc_skb(len, GFP_ATOMIC);
 580        if (!skb) {
 581                dev_printk(KERN_ERR, &conn->dev, "iscsi: gracefully ignored "
 582                          "conn error (%d)\n", error);
 583                return;
 584        }
 585
 586        nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
 587        ev = NLMSG_DATA(nlh);
 588        ev->transport_handle = iscsi_handle(conn->transport);
 589        ev->type = ISCSI_KEVENT_CONN_ERROR;
 590        ev->r.connerror.error = error;
 591        ev->r.connerror.cid = conn->cid;
 592        ev->r.connerror.sid = iscsi_conn_get_sid(conn);
 593
 594        iscsi_broadcast_skb(skb, GFP_ATOMIC);
 595
 596        dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n",
 597                   error);
 598}
 599EXPORT_SYMBOL_GPL(iscsi_conn_error);
 600
 601static int
 602iscsi_if_send_reply(int pid, int seq, int type, int done, int multi,
 603                      void *payload, int size)
 604{
 605        struct sk_buff  *skb;
 606        struct nlmsghdr *nlh;
 607        int len = NLMSG_SPACE(size);
 608        int flags = multi ? NLM_F_MULTI : 0;
 609        int t = done ? NLMSG_DONE : type;
 610
 611        skb = alloc_skb(len, GFP_ATOMIC);
 612        if (!skb) {
 613                printk(KERN_ERR "Could not allocate skb to send reply.\n");
 614                return -ENOMEM;
 615        }
 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.cmds_max,
 818                                            ev->u.c_session.queue_depth,
 819                                            ev->u.c_session.initial_cmdsn,
 820                                            &hostno);
 821        if (!session)
 822                return -ENOMEM;
 823
 824        spin_lock_irqsave(&sesslock, flags);
 825        list_add(&session->sess_list, &sesslist);
 826        spin_unlock_irqrestore(&sesslock, flags);
 827
 828        ev->r.c_session_ret.host_no = hostno;
 829        ev->r.c_session_ret.sid = session->sid;
 830        return 0;
 831}
 832
 833static int
 834iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
 835{
 836        struct iscsi_cls_conn *conn;
 837        struct iscsi_cls_session *session;
 838        unsigned long flags;
 839
 840        session = iscsi_session_lookup(ev->u.c_conn.sid);
 841        if (!session) {
 842                printk(KERN_ERR "iscsi: invalid session %d\n",
 843                       ev->u.c_conn.sid);
 844                return -EINVAL;
 845        }
 846
 847        conn = transport->create_conn(session, ev->u.c_conn.cid);
 848        if (!conn) {
 849                printk(KERN_ERR "iscsi: couldn't create a new "
 850                           "connection for session %d\n",
 851                           session->sid);
 852                return -ENOMEM;
 853        }
 854
 855        ev->r.c_conn_ret.sid = session->sid;
 856        ev->r.c_conn_ret.cid = conn->cid;
 857
 858        spin_lock_irqsave(&connlock, flags);
 859        list_add(&conn->conn_list, &connlist);
 860        conn->active = 1;
 861        spin_unlock_irqrestore(&connlock, flags);
 862
 863        return 0;
 864}
 865
 866static int
 867iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
 868{
 869        unsigned long flags;
 870        struct iscsi_cls_conn *conn;
 871
 872        conn = iscsi_conn_lookup(ev->u.d_conn.sid, ev->u.d_conn.cid);
 873        if (!conn)
 874                return -EINVAL;
 875        spin_lock_irqsave(&connlock, flags);
 876        conn->active = 0;
 877        list_del(&conn->conn_list);
 878        spin_unlock_irqrestore(&connlock, flags);
 879
 880        if (transport->destroy_conn)
 881                transport->destroy_conn(conn);
 882        return 0;
 883}
 884
 885static int
 886iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
 887{
 888        char *data = (char*)ev + sizeof(*ev);
 889        struct iscsi_cls_conn *conn;
 890        struct iscsi_cls_session *session;
 891        int err = 0, value = 0;
 892
 893        session = iscsi_session_lookup(ev->u.set_param.sid);
 894        conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid);
 895        if (!conn || !session)
 896                return -EINVAL;
 897
 898        switch (ev->u.set_param.param) {
 899        case ISCSI_PARAM_SESS_RECOVERY_TMO:
 900                sscanf(data, "%d", &value);
 901                if (value != 0)
 902                        session->recovery_tmo = value;
 903                break;
 904        default:
 905                err = transport->set_param(conn, ev->u.set_param.param,
 906                                           data, ev->u.set_param.len);
 907        }
 908
 909        return err;
 910}
 911
 912static int
 913iscsi_if_transport_ep(struct iscsi_transport *transport,
 914                      struct iscsi_uevent *ev, int msg_type)
 915{
 916        struct sockaddr *dst_addr;
 917        int rc = 0;
 918
 919        switch (msg_type) {
 920        case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
 921                if (!transport->ep_connect)
 922                        return -EINVAL;
 923
 924                dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
 925                rc = transport->ep_connect(dst_addr,
 926                                           ev->u.ep_connect.non_blocking,
 927                                           &ev->r.ep_connect_ret.handle);
 928                break;
 929        case ISCSI_UEVENT_TRANSPORT_EP_POLL:
 930                if (!transport->ep_poll)
 931                        return -EINVAL;
 932
 933                ev->r.retcode = transport->ep_poll(ev->u.ep_poll.ep_handle,
 934                                                   ev->u.ep_poll.timeout_ms);
 935                break;
 936        case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
 937                if (!transport->ep_disconnect)
 938                        return -EINVAL;
 939
 940                transport->ep_disconnect(ev->u.ep_disconnect.ep_handle);
 941                break;
 942        }
 943        return rc;
 944}
 945
 946static int
 947iscsi_tgt_dscvr(struct iscsi_transport *transport,
 948                struct iscsi_uevent *ev)
 949{
 950        struct Scsi_Host *shost;
 951        struct sockaddr *dst_addr;
 952        int err;
 953
 954        if (!transport->tgt_dscvr)
 955                return -EINVAL;
 956
 957        shost = scsi_host_lookup(ev->u.tgt_dscvr.host_no);
 958        if (IS_ERR(shost)) {
 959                printk(KERN_ERR "target discovery could not find host no %u\n",
 960                       ev->u.tgt_dscvr.host_no);
 961                return -ENODEV;
 962        }
 963
 964
 965        dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
 966        err = transport->tgt_dscvr(shost, ev->u.tgt_dscvr.type,
 967                                   ev->u.tgt_dscvr.enable, dst_addr);
 968        scsi_host_put(shost);
 969        return err;
 970}
 971
 972static int
 973iscsi_set_host_param(struct iscsi_transport *transport,
 974                     struct iscsi_uevent *ev)
 975{
 976        char *data = (char*)ev + sizeof(*ev);
 977        struct Scsi_Host *shost;
 978        int err;
 979
 980        if (!transport->set_host_param)
 981                return -ENOSYS;
 982
 983        shost = scsi_host_lookup(ev->u.set_host_param.host_no);
 984        if (IS_ERR(shost)) {
 985                printk(KERN_ERR "set_host_param could not find host no %u\n",
 986                       ev->u.set_host_param.host_no);
 987                return -ENODEV;
 988        }
 989
 990        err = transport->set_host_param(shost, ev->u.set_host_param.param,
 991                                        data, ev->u.set_host_param.len);
 992        scsi_host_put(shost);
 993        return err;
 994}
 995
 996static int
 997iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 998{
 999        int err = 0;
1000        struct iscsi_uevent *ev = NLMSG_DATA(nlh);
1001        struct iscsi_transport *transport = NULL;
1002        struct iscsi_internal *priv;
1003        struct iscsi_cls_session *session;
1004        struct iscsi_cls_conn *conn;
1005        unsigned long flags;
1006
1007        priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle));
1008        if (!priv)
1009                return -EINVAL;
1010        transport = priv->iscsi_transport;
1011
1012        if (!try_module_get(transport->owner))
1013                return -EINVAL;
1014
1015        priv->daemon_pid = NETLINK_CREDS(skb)->pid;
1016
1017        switch (nlh->nlmsg_type) {
1018        case ISCSI_UEVENT_CREATE_SESSION:
1019                err = iscsi_if_create_session(priv, ev);
1020                break;
1021        case ISCSI_UEVENT_DESTROY_SESSION:
1022                session = iscsi_session_lookup(ev->u.d_session.sid);
1023                if (session) {
1024                        spin_lock_irqsave(&sesslock, flags);
1025                        list_del(&session->sess_list);
1026                        spin_unlock_irqrestore(&sesslock, flags);
1027
1028                        transport->destroy_session(session);
1029                } else
1030                        err = -EINVAL;
1031                break;
1032        case ISCSI_UEVENT_CREATE_CONN:
1033                err = iscsi_if_create_conn(transport, ev);
1034                break;
1035        case ISCSI_UEVENT_DESTROY_CONN:
1036                err = iscsi_if_destroy_conn(transport, ev);
1037                break;
1038        case ISCSI_UEVENT_BIND_CONN:
1039                session = iscsi_session_lookup(ev->u.b_conn.sid);
1040                conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid);
1041
1042                if (session && conn)
1043                        ev->r.retcode = transport->bind_conn(session, conn,
1044                                        ev->u.b_conn.transport_eph,
1045                                        ev->u.b_conn.is_leading);
1046                else
1047                        err = -EINVAL;
1048                break;
1049        case ISCSI_UEVENT_SET_PARAM:
1050                err = iscsi_set_param(transport, ev);
1051                break;
1052        case ISCSI_UEVENT_START_CONN:
1053                conn = iscsi_conn_lookup(ev->u.start_conn.sid, ev->u.start_conn.cid);
1054                if (conn)
1055                        ev->r.retcode = transport->start_conn(conn);
1056                else
1057                        err = -EINVAL;
1058                break;
1059        case ISCSI_UEVENT_STOP_CONN:
1060                conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ev->u.stop_conn.cid);
1061                if (conn)
1062                        transport->stop_conn(conn, ev->u.stop_conn.flag);
1063                else
1064                        err = -EINVAL;
1065                break;
1066        case ISCSI_UEVENT_SEND_PDU:
1067                conn = iscsi_conn_lookup(ev->u.send_pdu.sid, ev->u.send_pdu.cid);
1068                if (conn)
1069                        ev->r.retcode = transport->send_pdu(conn,
1070                                (struct iscsi_hdr*)((char*)ev + sizeof(*ev)),
1071                                (char*)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size,
1072                                ev->u.send_pdu.data_size);
1073                else
1074                        err = -EINVAL;
1075                break;
1076        case ISCSI_UEVENT_GET_STATS:
1077                err = iscsi_if_get_stats(transport, nlh);
1078                break;
1079        case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
1080        case ISCSI_UEVENT_TRANSPORT_EP_POLL:
1081        case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
1082                err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type);
1083                break;
1084        case ISCSI_UEVENT_TGT_DSCVR:
1085                err = iscsi_tgt_dscvr(transport, ev);
1086                break;
1087        case ISCSI_UEVENT_SET_HOST_PARAM:
1088                err = iscsi_set_host_param(transport, ev);
1089                break;
1090        default:
1091                err = -ENOSYS;
1092                break;
1093        }
1094
1095        module_put(transport->owner);
1096        return err;
1097}
1098
1099/*
1100 * Get message from skb.  Each message is processed by iscsi_if_recv_msg.
1101 * Malformed skbs with wrong lengths or invalid creds are not processed.
1102 */
1103static void
1104iscsi_if_rx(struct sk_buff *skb)
1105{
1106        mutex_lock(&rx_queue_mutex);
1107        while (skb->len >= NLMSG_SPACE(0)) {
1108                int err;
1109                uint32_t rlen;
1110                struct nlmsghdr *nlh;
1111                struct iscsi_uevent *ev;
1112
1113                nlh = nlmsg_hdr(skb);
1114                if (nlh->nlmsg_len < sizeof(*nlh) ||
1115                    skb->len < nlh->nlmsg_len) {
1116                        break;
1117                }
1118
1119                ev = NLMSG_DATA(nlh);
1120                rlen = NLMSG_ALIGN(nlh->nlmsg_len);
1121                if (rlen > skb->len)
1122                        rlen = skb->len;
1123
1124                err = iscsi_if_recv_msg(skb, nlh);
1125                if (err) {
1126                        ev->type = ISCSI_KEVENT_IF_ERROR;
1127                        ev->iferror = err;
1128                }
1129                do {
1130                        /*
1131                         * special case for GET_STATS:
1132                         * on success - sending reply and stats from
1133                         * inside of if_recv_msg(),
1134                         * on error - fall through.
1135                         */
1136                        if (ev->type == ISCSI_UEVENT_GET_STATS && !err)
1137                                break;
1138                        err = iscsi_if_send_reply(
1139                                NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq,
1140                                nlh->nlmsg_type, 0, 0, ev, sizeof(*ev));
1141                } while (err < 0 && err != -ECONNREFUSED);
1142                skb_pull(skb, rlen);
1143        }
1144        mutex_unlock(&rx_queue_mutex);
1145}
1146
1147#define iscsi_cdev_to_conn(_cdev) \
1148        iscsi_dev_to_conn(_cdev->dev)
1149
1150#define ISCSI_CLASS_ATTR(_prefix,_name,_mode,_show,_store)              \
1151struct class_device_attribute class_device_attr_##_prefix##_##_name =   \
1152        __ATTR(_name,_mode,_show,_store)
1153
1154/*
1155 * iSCSI connection attrs
1156 */
1157#define iscsi_conn_attr_show(param)                                     \
1158static ssize_t                                                          \
1159show_conn_param_##param(struct class_device *cdev, char *buf)           \
1160{                                                                       \
1161        struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev);         \
1162        struct iscsi_transport *t = conn->transport;                    \
1163        return t->get_conn_param(conn, param, buf);                     \
1164}
1165
1166#define iscsi_conn_attr(field, param)                                   \
1167        iscsi_conn_attr_show(param)                                     \
1168static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_param_##param,  \
1169                        NULL);
1170
1171iscsi_conn_attr(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH);
1172iscsi_conn_attr(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH);
1173iscsi_conn_attr(header_digest, ISCSI_PARAM_HDRDGST_EN);
1174iscsi_conn_attr(data_digest, ISCSI_PARAM_DATADGST_EN);
1175iscsi_conn_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN);
1176iscsi_conn_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN);
1177iscsi_conn_attr(persistent_port, ISCSI_PARAM_PERSISTENT_PORT);
1178iscsi_conn_attr(port, ISCSI_PARAM_CONN_PORT);
1179iscsi_conn_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN);
1180iscsi_conn_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS);
1181iscsi_conn_attr(address, ISCSI_PARAM_CONN_ADDRESS);
1182
1183#define iscsi_cdev_to_session(_cdev) \
1184        iscsi_dev_to_session(_cdev->dev)
1185
1186/*
1187 * iSCSI session attrs
1188 */
1189#define iscsi_session_attr_show(param, perm)                            \
1190static ssize_t                                                          \
1191show_session_param_##param(struct class_device *cdev, char *buf)        \
1192{                                                                       \
1193        struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
1194        struct iscsi_transport *t = session->transport;                 \
1195                                                                        \
1196        if (perm && !capable(CAP_SYS_ADMIN))                            \
1197                return -EACCES;                                         \
1198        return t->get_session_param(session, param, buf);               \
1199}
1200
1201#define iscsi_session_attr(field, param, perm)                          \
1202        iscsi_session_attr_show(param, perm)                            \
1203static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_param_##param, \
1204                        NULL);
1205
1206iscsi_session_attr(targetname, ISCSI_PARAM_TARGET_NAME, 0);
1207iscsi_session_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN, 0);
1208iscsi_session_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T, 0);
1209iscsi_session_attr(immediate_data, ISCSI_PARAM_IMM_DATA_EN, 0);
1210iscsi_session_attr(first_burst_len, ISCSI_PARAM_FIRST_BURST, 0);
1211iscsi_session_attr(max_burst_len, ISCSI_PARAM_MAX_BURST, 0);
1212iscsi_session_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN, 0);
1213iscsi_session_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN, 0);
1214iscsi_session_attr(erl, ISCSI_PARAM_ERL, 0);
1215iscsi_session_attr(tpgt, ISCSI_PARAM_TPGT, 0);
1216iscsi_session_attr(username, ISCSI_PARAM_USERNAME, 1);
1217iscsi_session_attr(username_in, ISCSI_PARAM_USERNAME_IN, 1);
1218iscsi_session_attr(password, ISCSI_PARAM_PASSWORD, 1);
1219iscsi_session_attr(password_in, ISCSI_PARAM_PASSWORD_IN, 1);
1220
1221#define iscsi_priv_session_attr_show(field, format)                     \
1222static ssize_t                                                          \
1223show_priv_session_##field(struct class_device *cdev, char *buf)         \
1224{                                                                       \
1225        struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev);\
1226        return sprintf(buf, format"\n", session->field);                \
1227}
1228
1229#define iscsi_priv_session_attr(field, format)                          \
1230        iscsi_priv_session_attr_show(field, format)                     \
1231static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO, show_priv_session_##field, \
1232                        NULL)
1233iscsi_priv_session_attr(recovery_tmo, "%d");
1234
1235/*
1236 * iSCSI host attrs
1237 */
1238#define iscsi_host_attr_show(param)                                     \
1239static ssize_t                                                          \
1240show_host_param_##param(struct class_device *cdev, char *buf)           \
1241{                                                                       \
1242        struct Scsi_Host *shost = transport_class_to_shost(cdev);       \
1243        struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \
1244        return priv->iscsi_transport->get_host_param(shost, param, buf); \
1245}
1246
1247#define iscsi_host_attr(field, param)                                   \
1248        iscsi_host_attr_show(param)                                     \
1249static ISCSI_CLASS_ATTR(host, field, S_IRUGO, show_host_param_##param,  \
1250                        NULL);
1251
1252iscsi_host_attr(netdev, ISCSI_HOST_PARAM_NETDEV_NAME);
1253iscsi_host_attr(hwaddress, ISCSI_HOST_PARAM_HWADDRESS);
1254iscsi_host_attr(ipaddress, ISCSI_HOST_PARAM_IPADDRESS);
1255iscsi_host_attr(initiatorname, ISCSI_HOST_PARAM_INITIATOR_NAME);
1256
1257#define SETUP_PRIV_SESSION_RD_ATTR(field)                               \
1258do {                                                                    \
1259        priv->session_attrs[count] = &class_device_attr_priv_sess_##field; \
1260        count++;                                                        \
1261} while (0)
1262
1263
1264#define SETUP_SESSION_RD_ATTR(field, param_flag)                        \
1265do {                                                                    \
1266        if (tt->param_mask & param_flag) {                              \
1267                priv->session_attrs[count] = &class_device_attr_sess_##field; \
1268                count++;                                                \
1269        }                                                               \
1270} while (0)
1271
1272#define SETUP_CONN_RD_ATTR(field, param_flag)                           \
1273do {                                                                    \
1274        if (tt->param_mask & param_flag) {                              \
1275                priv->conn_attrs[count] = &class_device_attr_conn_##field; \
1276                count++;                                                \
1277        }                                                               \
1278} while (0)
1279
1280#define SETUP_HOST_RD_ATTR(field, param_flag)                           \
1281do {                                                                    \
1282        if (tt->host_param_mask & param_flag) {                         \
1283                priv->host_attrs[count] = &class_device_attr_host_##field; \
1284                count++;                                                \
1285        }                                                               \
1286} while (0)
1287
1288static int iscsi_session_match(struct attribute_container *cont,
1289                           struct device *dev)
1290{
1291        struct iscsi_cls_session *session;
1292        struct Scsi_Host *shost;
1293        struct iscsi_internal *priv;
1294
1295        if (!iscsi_is_session_dev(dev))
1296                return 0;
1297
1298        session = iscsi_dev_to_session(dev);
1299        shost = iscsi_session_to_shost(session);
1300        if (!shost->transportt)
1301                return 0;
1302
1303        priv = to_iscsi_internal(shost->transportt);
1304        if (priv->session_cont.ac.class != &iscsi_session_class.class)
1305                return 0;
1306
1307        return &priv->session_cont.ac == cont;
1308}
1309
1310static int iscsi_conn_match(struct attribute_container *cont,
1311                           struct device *dev)
1312{
1313        struct iscsi_cls_session *session;
1314        struct iscsi_cls_conn *conn;
1315        struct Scsi_Host *shost;
1316        struct iscsi_internal *priv;
1317
1318        if (!iscsi_is_conn_dev(dev))
1319                return 0;
1320
1321        conn = iscsi_dev_to_conn(dev);
1322        session = iscsi_dev_to_session(conn->dev.parent);
1323        shost = iscsi_session_to_shost(session);
1324
1325        if (!shost->transportt)
1326                return 0;
1327
1328        priv = to_iscsi_internal(shost->transportt);
1329        if (priv->conn_cont.ac.class != &iscsi_connection_class.class)
1330                return 0;
1331
1332        return &priv->conn_cont.ac == cont;
1333}
1334
1335static int iscsi_host_match(struct attribute_container *cont,
1336                            struct device *dev)
1337{
1338        struct Scsi_Host *shost;
1339        struct iscsi_internal *priv;
1340
1341        if (!scsi_is_host_device(dev))
1342                return 0;
1343
1344        shost = dev_to_shost(dev);
1345        if (!shost->transportt  ||
1346            shost->transportt->host_attrs.ac.class != &iscsi_host_class.class)
1347                return 0;
1348
1349        priv = to_iscsi_internal(shost->transportt);
1350        return &priv->t.host_attrs.ac == cont;
1351}
1352
1353struct scsi_transport_template *
1354iscsi_register_transport(struct iscsi_transport *tt)
1355{
1356        struct iscsi_internal *priv;
1357        unsigned long flags;
1358        int count = 0, err;
1359
1360        BUG_ON(!tt);
1361
1362        priv = iscsi_if_transport_lookup(tt);
1363        if (priv)
1364                return NULL;
1365
1366        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
1367        if (!priv)
1368                return NULL;
1369        INIT_LIST_HEAD(&priv->list);
1370        priv->daemon_pid = -1;
1371        priv->iscsi_transport = tt;
1372        priv->t.user_scan = iscsi_user_scan;
1373
1374        priv->cdev.class = &iscsi_transport_class;
1375        snprintf(priv->cdev.class_id, BUS_ID_SIZE, "%s", tt->name);
1376        err = class_device_register(&priv->cdev);
1377        if (err)
1378                goto free_priv;
1379
1380        err = sysfs_create_group(&priv->cdev.kobj, &iscsi_transport_group);
1381        if (err)
1382                goto unregister_cdev;
1383
1384        /* host parameters */
1385        priv->t.host_attrs.ac.attrs = &priv->host_attrs[0];
1386        priv->t.host_attrs.ac.class = &iscsi_host_class.class;
1387        priv->t.host_attrs.ac.match = iscsi_host_match;
1388        priv->t.host_size = sizeof(struct iscsi_host);
1389        transport_container_register(&priv->t.host_attrs);
1390
1391        SETUP_HOST_RD_ATTR(netdev, ISCSI_HOST_NETDEV_NAME);
1392        SETUP_HOST_RD_ATTR(ipaddress, ISCSI_HOST_IPADDRESS);
1393        SETUP_HOST_RD_ATTR(hwaddress, ISCSI_HOST_HWADDRESS);
1394        SETUP_HOST_RD_ATTR(initiatorname, ISCSI_HOST_INITIATOR_NAME);
1395        BUG_ON(count > ISCSI_HOST_ATTRS);
1396        priv->host_attrs[count] = NULL;
1397        count = 0;
1398
1399        /* connection parameters */
1400        priv->conn_cont.ac.attrs = &priv->conn_attrs[0];
1401        priv->conn_cont.ac.class = &iscsi_connection_class.class;
1402        priv->conn_cont.ac.match = iscsi_conn_match;
1403        transport_container_register(&priv->conn_cont);
1404
1405        SETUP_CONN_RD_ATTR(max_recv_dlength, ISCSI_MAX_RECV_DLENGTH);
1406        SETUP_CONN_RD_ATTR(max_xmit_dlength, ISCSI_MAX_XMIT_DLENGTH);
1407        SETUP_CONN_RD_ATTR(header_digest, ISCSI_HDRDGST_EN);
1408        SETUP_CONN_RD_ATTR(data_digest, ISCSI_DATADGST_EN);
1409        SETUP_CONN_RD_ATTR(ifmarker, ISCSI_IFMARKER_EN);
1410        SETUP_CONN_RD_ATTR(ofmarker, ISCSI_OFMARKER_EN);
1411        SETUP_CONN_RD_ATTR(address, ISCSI_CONN_ADDRESS);
1412        SETUP_CONN_RD_ATTR(port, ISCSI_CONN_PORT);
1413        SETUP_CONN_RD_ATTR(exp_statsn, ISCSI_EXP_STATSN);
1414        SETUP_CONN_RD_ATTR(persistent_address, ISCSI_PERSISTENT_ADDRESS);
1415        SETUP_CONN_RD_ATTR(persistent_port, ISCSI_PERSISTENT_PORT);
1416
1417        BUG_ON(count > ISCSI_CONN_ATTRS);
1418        priv->conn_attrs[count] = NULL;
1419        count = 0;
1420
1421        /* session parameters */
1422        priv->session_cont.ac.attrs = &priv->session_attrs[0];
1423        priv->session_cont.ac.class = &iscsi_session_class.class;
1424        priv->session_cont.ac.match = iscsi_session_match;
1425        transport_container_register(&priv->session_cont);
1426
1427        SETUP_SESSION_RD_ATTR(initial_r2t, ISCSI_INITIAL_R2T_EN);
1428        SETUP_SESSION_RD_ATTR(max_outstanding_r2t, ISCSI_MAX_R2T);
1429        SETUP_SESSION_RD_ATTR(immediate_data, ISCSI_IMM_DATA_EN);
1430        SETUP_SESSION_RD_ATTR(first_burst_len, ISCSI_FIRST_BURST);
1431        SETUP_SESSION_RD_ATTR(max_burst_len, ISCSI_MAX_BURST);
1432        SETUP_SESSION_RD_ATTR(data_pdu_in_order, ISCSI_PDU_INORDER_EN);
1433        SETUP_SESSION_RD_ATTR(data_seq_in_order, ISCSI_DATASEQ_INORDER_EN);
1434        SETUP_SESSION_RD_ATTR(erl, ISCSI_ERL);
1435        SETUP_SESSION_RD_ATTR(targetname, ISCSI_TARGET_NAME);
1436        SETUP_SESSION_RD_ATTR(tpgt, ISCSI_TPGT);
1437        SETUP_SESSION_RD_ATTR(password, ISCSI_USERNAME);
1438        SETUP_SESSION_RD_ATTR(password_in, ISCSI_USERNAME_IN);
1439        SETUP_SESSION_RD_ATTR(username, ISCSI_PASSWORD);
1440        SETUP_SESSION_RD_ATTR(username_in, ISCSI_PASSWORD_IN);
1441        SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo);
1442
1443        BUG_ON(count > ISCSI_SESSION_ATTRS);
1444        priv->session_attrs[count] = NULL;
1445
1446        spin_lock_irqsave(&iscsi_transport_lock, flags);
1447        list_add(&priv->list, &iscsi_transports);
1448        spin_unlock_irqrestore(&iscsi_transport_lock, flags);
1449
1450        printk(KERN_NOTICE "iscsi: registered transport (%s)\n", tt->name);
1451        return &priv->t;
1452
1453unregister_cdev:
1454        class_device_unregister(&priv->cdev);
1455free_priv:
1456        kfree(priv);
1457        return NULL;
1458}
1459EXPORT_SYMBOL_GPL(iscsi_register_transport);
1460
1461int iscsi_unregister_transport(struct iscsi_transport *tt)
1462{
1463        struct iscsi_internal *priv;
1464        unsigned long flags;
1465
1466        BUG_ON(!tt);
1467
1468        mutex_lock(&rx_queue_mutex);
1469
1470        priv = iscsi_if_transport_lookup(tt);
1471        BUG_ON (!priv);
1472
1473        spin_lock_irqsave(&iscsi_transport_lock, flags);
1474        list_del(&priv->list);
1475        spin_unlock_irqrestore(&iscsi_transport_lock, flags);
1476
1477        transport_container_unregister(&priv->conn_cont);
1478        transport_container_unregister(&priv->session_cont);
1479        transport_container_unregister(&priv->t.host_attrs);
1480
1481        sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group);
1482        class_device_unregister(&priv->cdev);
1483        mutex_unlock(&rx_queue_mutex);
1484
1485        return 0;
1486}
1487EXPORT_SYMBOL_GPL(iscsi_unregister_transport);
1488
1489static __init int iscsi_transport_init(void)
1490{
1491        int err;
1492
1493        printk(KERN_INFO "Loading iSCSI transport class v%s.\n",
1494                ISCSI_TRANSPORT_VERSION);
1495
1496        atomic_set(&iscsi_session_nr, 0);
1497
1498        err = class_register(&iscsi_transport_class);
1499        if (err)
1500                return err;
1501
1502        err = transport_class_register(&iscsi_host_class);
1503        if (err)
1504                goto unregister_transport_class;
1505
1506        err = transport_class_register(&iscsi_connection_class);
1507        if (err)
1508                goto unregister_host_class;
1509
1510        err = transport_class_register(&iscsi_session_class);
1511        if (err)
1512                goto unregister_conn_class;
1513
1514        nls = netlink_kernel_create(&init_net, NETLINK_ISCSI, 1, iscsi_if_rx, NULL,
1515                        THIS_MODULE);
1516        if (!nls) {
1517                err = -ENOBUFS;
1518                goto unregister_session_class;
1519        }
1520
1521        return 0;
1522
1523unregister_session_class:
1524        transport_class_unregister(&iscsi_session_class);
1525unregister_conn_class:
1526        transport_class_unregister(&iscsi_connection_class);
1527unregister_host_class:
1528        transport_class_unregister(&iscsi_host_class);
1529unregister_transport_class:
1530        class_unregister(&iscsi_transport_class);
1531        return err;
1532}
1533
1534static void __exit iscsi_transport_exit(void)
1535{
1536        sock_release(nls->sk_socket);
1537        transport_class_unregister(&iscsi_connection_class);
1538        transport_class_unregister(&iscsi_session_class);
1539        transport_class_unregister(&iscsi_host_class);
1540        class_unregister(&iscsi_transport_class);
1541}
1542
1543module_init(iscsi_transport_init);
1544module_exit(iscsi_transport_exit);
1545
1546MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>, "
1547              "Dmitry Yusupov <dmitry_yus@yahoo.com>, "
1548              "Alex Aizman <itn780@yahoo.com>");
1549MODULE_DESCRIPTION("iSCSI Transport Interface");
1550MODULE_LICENSE("GPL");
1551MODULE_VERSION(ISCSI_TRANSPORT_VERSION);
1552