⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iscsi_main.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 5 页
字号:
         * but check pointers to make sure we don't crash the kernel          * if the function is called for a task not in the session.         */        if (task->order_next && task->order_prev) {            task->order_next->order_prev = task->order_prev;            task->order_prev->order_next = task->order_next;        }        else {            DEBUG_ERR4("iSCSI: failed to remove itt %u, task %p from session %p to %s\n",                        task->itt, task, session, session->log_name);            return 0;        }    }    task->order_prev = NULL;    task->order_next = NULL;    atomic_dec(&session->num_active_tasks);    return 1;}/*  * move all tasks in the session for the specified LUN into the collection. */static void move_session_tasks_for_lun(iscsi_task_collection_t *collection, iscsi_session_t *session, int lun){    iscsi_task_t *search = session->arrival_order.head;    while (search) {        iscsi_task_t *next = search->order_next;        if (search->scsi_cmnd && search->scsi_cmnd->lun == lun) {            remove_session_task(session, search);            add_task(collection, search);        }        search = next;    }}/*  * remove cmnds for the specified LUN that are in the session's cmnd queue,  * or the forced abort queue, and return a list of them. */static Scsi_Cmnd *remove_session_cmnds_for_lun(iscsi_session_t *session, int lun){    Scsi_Cmnd *cmnd = NULL;    Scsi_Cmnd *prior = NULL;    Scsi_Cmnd *head = NULL, *tail = NULL;    /* handle any commands we hid from the tx thread */    while (session->ignored_cmnd_head && (session->ignored_cmnd_head->lun == lun)) {        /* move the head */        cmnd = session->ignored_cmnd_head;        session->ignored_cmnd_head = (Scsi_Cmnd *)cmnd->host_scribble;        if (session->ignored_cmnd_head == NULL)            session->ignored_cmnd_tail = NULL;        atomic_dec(&session->num_ignored_cmnds);        if (head) {            tail->host_scribble = (unsigned char *)cmnd;            tail = cmnd;        }        else {            cmnd->host_scribble = NULL;            head = tail = cmnd;        }    }        /* we're either out of cmnds, or the head is for a different LUN */    prior = session->ignored_cmnd_head;    while (prior && (cmnd = (Scsi_Cmnd *)prior->host_scribble)) {        if (cmnd->lun == lun) {            /* splice out cmnd and move it */            prior->host_scribble = cmnd->host_scribble;            if (session->ignored_cmnd_tail == cmnd)                session->ignored_cmnd_tail = prior;            atomic_dec(&session->num_ignored_cmnds);            if (head) {                tail->host_scribble = (unsigned char *)cmnd;                tail = cmnd;            }            else {                cmnd->host_scribble = NULL;                head = tail = cmnd;            }        }        else {            prior = cmnd;        }    }    /* handle cmnds queued for the tx thread to send */    while (session->scsi_cmnd_head && (session->scsi_cmnd_head->lun == lun)) {        /* move the head */        cmnd = session->scsi_cmnd_head;        session->scsi_cmnd_head = (Scsi_Cmnd *)cmnd->host_scribble;        if (session->scsi_cmnd_head == NULL)            session->scsi_cmnd_tail = NULL;        atomic_dec(&session->num_cmnds);        if (head) {            tail->host_scribble = (unsigned char *)cmnd;            tail = cmnd;        }        else {            cmnd->host_scribble = NULL;            head = tail = cmnd;        }    }        /* we're either out of cmnds, or the head is for a different LUN */    prior = session->scsi_cmnd_head;    while (prior && (cmnd = (Scsi_Cmnd *)prior->host_scribble)) {        if (cmnd->lun == lun) {            /* splice out cmnd and move it */            prior->host_scribble = cmnd->host_scribble;            if (session->scsi_cmnd_tail == cmnd)                session->scsi_cmnd_tail = prior;            atomic_dec(&session->num_cmnds);            if (head) {                tail->host_scribble = (unsigned char *)cmnd;                tail = cmnd;            }            else {                cmnd->host_scribble = NULL;                head = tail = cmnd;            }        }        else {            prior = cmnd;        }    }    return head;}/* decode common network errno values into more useful strings. * strerror would be nice right about now. */static char *iscsi_strerror(int errno){    switch (errno) {        case EIO:            return "I/O error";        case EINTR:            return "Interrupted system call";        case ENXIO:            return "No such device or address";        case EFAULT:            return "Bad address";        case EBUSY:            return "Device or resource busy";        case EINVAL:            return "Invalid argument";        case EPIPE:            return "Broken pipe";        case ENONET:            return "Machine is not on the network";        case ECOMM:            return "Communication error on send";        case EPROTO:            return "Protocol error";        case ENOTUNIQ:            return "Name not unique on network";        case ENOTSOCK:            return "Socket operation on non-socket";        case ENETDOWN:            return "Network is down";        case ENETUNREACH:            return "Network is unreachable";        case ENETRESET:            return "Network dropped connection because of reset";        case ECONNABORTED:            return "Software caused connection abort";        case ECONNRESET:            return "Connection reset by peer";        case ESHUTDOWN:            return "Cannot send after shutdown";        case ETIMEDOUT:            return "Connection timed out";        case ECONNREFUSED:            return "Connection refused";        case EHOSTDOWN:            return "Host is down";        case EHOSTUNREACH:            return "No route to host";        default:            return "";    }}static int iscsi_recvmsg( iscsi_session_t *session, struct msghdr *msg, int len ){    int rc = 0;    mm_segment_t oldfs;    if (session->socket) {        oldfs = get_fs();        set_fs( get_ds() );        /* Try to avoid memory allocation deadlocks by using GFP_ATOMIC. */        session->socket->sk->allocation = GFP_ATOMIC;                    rc = sock_recvmsg( session->socket, msg, len, MSG_WAITALL);        if (rc > 0) {            session->last_rx = jiffies;            mb();        }    }        set_fs( oldfs );    return rc;}static int iscsi_sendmsg( iscsi_session_t *session, struct msghdr *msg, int len ){    int rc = 0;    mm_segment_t oldfs;    if (session->socket) {        oldfs = get_fs();        set_fs( get_ds() );                /* Try to avoid resource acquisition deadlocks by using GFP_ATOMIC. */        session->socket->sk->allocation = GFP_ATOMIC;        /* FIXME: ought to loop handling short writes, unless a signal occurs */        rc = sock_sendmsg(session->socket, msg, len);                set_fs( oldfs );    }            return rc;}/* create and connect a new socket for this session */static int iscsi_connect(iscsi_session_t *session) {    mm_segment_t oldfs;    struct socket           *socket;    struct sockaddr_in      addr;    int window_size;    int arg = 1, arglen = 0;    int rc = 0, ret = 0;    if (session->socket) {        printk("iSCSI: session %p already has socket %p\n", session, session->socket);        return 1;    }    oldfs = get_fs();    set_fs( get_ds() );    if (sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &socket) < 0) {        printk("iSCSI: failed to create socket\n");        set_fs(oldfs);        return 0;    }    /* no delay in sending */    if (socket->ops->setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *)&arg, sizeof(arg)) < 0) {        printk("iSCSI: failed to setsockopt TCP_NODELAY\n");        goto done;    }    /* try to ensure a reasonably sized TCP window */    arglen = sizeof(window_size);    if (sock_getsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&window_size, &arglen) >= 0) {        DEBUG_FLOW1("iSCSI: TCP recv window size %u\n", window_size);                if (session->tcp_window_size && (window_size < session->tcp_window_size)) {            window_size = session->tcp_window_size;            if (sock_setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&window_size, sizeof(window_size)) < 0) {                printk("iSCSI: failed to set TCP recv window size to %u\n", window_size);            }            else if (sock_getsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&window_size, &arglen) >= 0) {                DEBUG_FLOW2("iSCSI: set TCP recv window size to %u, actually got %u\n", session->tcp_window_size, window_size);            }        }    }    else {        printk("iSCSI: getsockopt RCVBUF %p failed\n", socket);    }    if (sock_getsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&window_size, &arglen) >= 0) {        DEBUG_FLOW1("iSCSI: TCP send window size %u\n", window_size);                if (session->tcp_window_size && (window_size < session->tcp_window_size)) {            window_size = session->tcp_window_size;            if (sock_setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&window_size, sizeof(window_size)) < 0) {                printk("iSCSI: failed to set TCP send window size to %u\n", window_size);            }            else if (sock_getsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&window_size, &arglen) >= 0) {                DEBUG_FLOW2("iSCSI: set TCP send window size to %u, actually got %u\n", session->tcp_window_size, window_size);            }        }    }    else {        printk("iSCSI: getsockopt SNDBUF %p failed\n", socket);    }    /* connect to the target */    addr.sin_family = AF_INET;    addr.sin_port = htons(session->port);    if (session->address_length == 4) {        memcpy(&addr.sin_addr.s_addr, session->ip_address, MIN(sizeof(addr.sin_addr.s_addr), session->address_length));    }    else {        /* FIXME: IPv6 */        printk("iSCSI: unable to handle IPv6 address\n");        goto done;    }    rc = socket->ops->connect(socket, (struct sockaddr *)&addr, sizeof(addr), 0);    if (signal_pending(current))        goto done;    if (rc < 0) {        char *error = iscsi_strerror(-rc);        if (error && error[0] != '\0') {            printk("iSCSI: session %p to %s failed to connect, rc %d, %s\n", session, session->log_name, rc, error);        }        else {            printk("iSCSI: session %p to %s failed to connect, rc %d\n", session, session->log_name, rc);        }    }    else {        if (LOG_ENABLED(ISCSI_LOG_LOGIN))            printk("iSCSI: session %p to %s connected at %lu\n", session, session->log_name, jiffies);        ret = 1;    } done:    if (ret) {        /* save the socket pointer for later */        session->socket = socket;        mb();    }    else {        /* close the socket */        sock_release(socket);    }    set_fs(oldfs);    return ret;}static void iscsi_disconnect(iscsi_session_t *session) {    if (session->socket) {        sock_release(session->socket);        session->socket = NULL;        mb();    }}int iscsi_send_login_pdu(iscsi_session_t *session, struct IscsiLoginHdr *pdu, int max_pdu_length){    struct msghdr msg;    struct iovec iov;    int rc;    int pdu_length = sizeof(*pdu) + ntoh24(pdu->dlength);    /* add any padding needed */    if (pdu_length % PAD_WORD_LEN) {        int pad = 0;        char *data = ((char *)pdu) + pdu_length;        pad = PAD_WORD_LEN - (pdu_length % PAD_WORD_LEN);        if (pdu_length + pad > max_pdu_length) {            printk("iSCSI: session %p failing to send login pdu %p, no room for padding\n", pdu, session);            return 0;        }        DEBUG_FLOW3("iSCSI: session %p adding %d pad bytes on login pdu %p\n", session, pad, pdu);        for (; pad; pad--) {            *data++ = 0;            pdu_length++;        }    }    memset(&iov, 0, sizeof(iov));    iov.iov_base = pdu;    iov.iov_len = pdu_length;    memset(&msg, 0, sizeof(msg));    msg.msg_iov = &iov;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -