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

📄 iscsi.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 5 页
字号:
     * symbols like child_reaper aren't exported to modules     */         /* increase priority like the md driver does for it's kernel threads */    this_task->policy = SCHED_NORMAL;    this_task->nice = -20;    wmb();    # else    /* 2.2.18 and later has daemonize(), but it's not always correct, so we do it ourselves. */    struct fs_struct *fs;    lock_kernel();        /*     * If we were started as result of loading a module, close all of the     * user space pages.  We don't need them, and if we didn't close them     * they would be locked into memory.     */    exit_mm(this_task);        this_task->session = 1;    this_task->pgrp = 1;    this_task->tty = NULL;        /* Become as one with the init task */    exit_files(this_task);    this_task->files = init_task.files;    atomic_inc(&this_task->files->count);        exit_fs(this_task);       /* this_task->fs->count--; */    fs = init_task.fs;    this_task->fs = fs;    atomic_inc(&fs->count);                                                     /* We'd like to reparent to init, but don't have a function to do it, and     * symbols like child_reaper aren't exported to modules.     */     /* increase priority like the md driver does for it's kernel threads */    this_task->policy = SCHED_NORMAL;    this_task->priority = 40;    wmb();        unlock_kernel();# endif}/* wake up the tx_thread without ever losing the wakeup event */static void wake_tx_thread(int control_bit, iscsi_session_t *session){    /* tell the tx thread what to do when it wakes up. */    set_bit(control_bit, &session->control_bits);        /* We make a condition variable out of a wait queue and atomic test&clear.     * May get spurious wake-ups, but no wakeups will be lost.     * this is cv_signal().  wait_event_interruptible is cv_wait().     */    set_bit(TX_WAKE, &session->control_bits);    wake_up(&session->tx_wait_q);}/* drop an iscsi session */static void iscsi_drop_session(iscsi_session_t *session){    pid_t pid;                  DEBUG_INIT4("iSCSI: iscsi_drop_session %p, rx %d, tx %d at %lu\n",                 session, session->rx_pid, session->tx_pid, jiffies);    clear_bit(SESSION_ESTABLISHED, &session->control_bits);    set_bit(SESSION_DROPPED, &session->control_bits);  /* so we know whether to abort the connection */    if ((pid = session->tx_pid))        kill_proc(pid, SIGHUP, 1);    if ((pid = session->rx_pid))        kill_proc(pid, SIGHUP, 1);}/* caller must hold session->task_lock */static void iscsi_request_logout(iscsi_session_t *session, int logout, int logout_response){    if (atomic_read(&session->num_active_tasks) == 0) {        DEBUG_INIT2("iSCSI: session %p currently has no active tasks, queueing logout at %lu\n",                     session, jiffies);        session->logout_response_deadline = jiffies + (logout_response * HZ);        if (session->logout_response_deadline == 0)            session->logout_response_deadline = 1;        wmb();        set_bit(SESSION_LOGOUT_REQUESTED, &session->control_bits);        wake_tx_thread(TX_LOGOUT, session);    }    else {        session->logout_deadline = jiffies + (logout * HZ);        if (session->logout_deadline == 0)            session->logout_deadline = 1;        session->logout_response_deadline = session->logout_deadline + (logout_response * HZ);        if (session->logout_response_deadline == 0)            session->logout_response_deadline = 1;        wmb();        set_bit(SESSION_LOGOUT_REQUESTED, &session->control_bits);    }}static void iscsi_terminate_session(iscsi_session_t *session){    pid_t pid;                  if ((test_and_set_bit(SESSION_TERMINATING, &session->control_bits) == 0) &&         test_bit(SESSION_ESTABLISHED, &session->control_bits))    {        DEBUG_INIT2("iSCSI: iscsi_terminate_session %p, requesting logout at %lu\n",                    session, jiffies);        /* on the first terminate request while the session is up, request a logout in the next 3 seconds */        spin_lock(&session->task_lock);        iscsi_request_logout(session, 3, session->active_timeout);        spin_unlock(&session->task_lock);    }    else {        /* either we've already tried to terminate once, or the the session is down.  just kill everything. */        clear_bit(SESSION_ESTABLISHED, &session->control_bits);        DEBUG_INIT4("iSCSI: iscsi_terminate_session %p, killing rx %d, tx %d at %lu\n",                     session, session->rx_pid, session->tx_pid, jiffies);                /* kill the session's threads */        if ((pid = session->tx_pid))            kill_proc(pid, SIGKILL, 1);        if ((pid = session->rx_pid))            kill_proc(pid, SIGKILL, 1);    }}/* if a signal is pending, deal with it, and return 1. * Otherwise, return 0. */static int iscsi_handle_signals(iscsi_session_t *session){    pid_t pid;    int ret = 0;        /* if we got SIGHUP, try to establish a replacement session.     * if we got SIGKILL, terminate this session.     */    if (signal_pending(current)) {        spin_lock_irq(&current->sighand->siglock);        /* iscsi_drop_session and iscsi_terminate_session signal both         * threads, but someone logged in as root may not.  So, we         * make sure whichever process gets signalled first propagates         * the signal when it looks like only one thread got         * signalled.         */        /* on SIGKILL, terminate the session */        if (SIGNAL_IS_PENDING(SIGKILL)) {            if (!test_and_set_bit(SESSION_TERMINATING, &session->control_bits)) {                if ((pid = session->tx_pid) && (pid != current->pid)) {                    printk("iSCSI: rx thread %d received SIGKILL, killing tx thread %d\n", current->pid, pid);                    kill_proc(pid, SIGKILL, 1);                }                if ((pid = session->rx_pid) && (pid != current->pid)) {                    printk("iSCSI: tx thread %d received SIGKILL, killing rx thread %d\n", current->pid, pid);                    kill_proc(pid, SIGKILL, 1);                }            }            ret = 1;        }        /* on SIGHUP, drop the session, and try to establish a replacement session */        if (SIGNAL_IS_PENDING(SIGHUP)) {            if (test_and_clear_bit(SESSION_ESTABLISHED, &session->control_bits)) {                if ((pid = session->tx_pid) && (pid != current->pid)) {                    printk("iSCSI: rx thread %d received SIGHUP, signaling tx thread %d\n", current->pid, pid);                    kill_proc(pid, SIGHUP, 1);                }                if ((pid = session->rx_pid) && (pid != current->pid)) {                    printk("iSCSI: tx thread %d received SIGHUP, signaling rx thread %d\n", current->pid, pid);                    kill_proc(pid, SIGHUP, 1);                }            }            ret = 1;        }        /* we don't care about any other signals */        flush_signals(current);        spin_unlock_irq(&current->sighand->siglock);    }    return ret;}unsigned int iscsi_expected_data_length(Scsi_Cmnd *sc){    unsigned int length = 0;    switch (sc->cmnd[0]) {        case INQUIRY:        case REQUEST_SENSE:            length = sc->cmnd[4];            return length;        case REPORT_LUNS:            length |= sc->cmnd[6] << 24;            length |= sc->cmnd[7] << 16;            length |= sc->cmnd[8] << 8;            length |= sc->cmnd[9];            return length;        default:            return sc->request_bufflen;    }}/* compare against 2^31 */#define SNA32_CHECK 2147483648UL/* Serial Number Arithmetic, 32 bits, less than, RFC1982 */static int sna_lt(uint32_t n1, uint32_t n2){    return ((n1 != n2) &&             (((n1 < n2) && ((n2 - n1) < SNA32_CHECK)) || ((n1 > n2) && ((n2 - n1) < SNA32_CHECK))));}/* Serial Number Arithmetic, 32 bits, less than, RFC1982 */static int sna_lte(uint32_t n1, uint32_t n2){    return ((n1 == n2) ||            (((n1 < n2) && ((n2 - n1) < SNA32_CHECK)) || ((n1 > n2) && ((n2 - n1) < SNA32_CHECK))));}/* difference isn't really a defined operation in SNA, but we'd like it so that * we can determine how many commands can be queued to a session. */static int cmdsn_window_size(uint32_t expected, uint32_t max){    if ((expected <= max) && ((max - expected) < SNA32_CHECK)) {        return (max - expected + 1);    }    else if ((expected > max) && ((expected - max) < SNA32_CHECK)) {        /* window wraps around */        return ((UINT32_MAX - expected) + 1 + max + 1);    }    else {        /* window closed, or numbers bogus */        return 0;    }}/* remember old peak cmdsn window size, and report the largest */static int max_tasks_for_session(iscsi_session_t *session){    if (session->ExpCmdSn == session->MaxCmdSn + 1)        /* if the window is closed, report nothing, regardless of what it was in the past */        return 0;    else if (session->last_peak_window_size < session->current_peak_window_size)        /* window increasing, so report the current peak size */        return MIN(session->current_peak_window_size, ISCSI_CMDS_PER_LUN * session->num_luns);    else        /* window decreasing.  report the previous peak size, in case it's         * a temporary decrease caused by the commands we're sending.         * we want to keep the right number of commands queued in the driver,         * ready to go as soon as they can.         */        return MIN(session->last_peak_window_size, ISCSI_CMDS_PER_LUN * session->num_luns);}/* possibly update the ExpCmdSN and MaxCmdSN, and peak window sizes */static void updateSN(iscsi_session_t *session, UINT32 expcmdsn, UINT32 maxcmdsn) {    int window_size;    /* standard specifies this check for when to update expected and max sequence numbers */    if (!sna_lt(maxcmdsn, expcmdsn - 1)) {        if ((expcmdsn != session->ExpCmdSn) && !sna_lt(expcmdsn, session->ExpCmdSn)) {            session->ExpCmdSn = expcmdsn;        }        if ((maxcmdsn != session->MaxCmdSn) && !sna_lt(maxcmdsn, session->MaxCmdSn)) {                        session->MaxCmdSn = maxcmdsn;            /* look for the peak window size */            window_size = cmdsn_window_size(expcmdsn, maxcmdsn);            if (window_size > session->current_peak_window_size)                session->current_peak_window_size = window_size;            /* age peak window size info */            if (time_before(session->window_peak_check + (15 * HZ), jiffies)) {                session->last_peak_window_size = session->current_peak_window_size;                session->current_peak_window_size = window_size;                session->window_peak_check = jiffies;            }            /* memory barrier for all of that */            mb();            /* wake the tx thread to try sending more commands */            wake_tx_thread(TX_SCSI_COMMAND, session);        }        /* record whether or not the command window for this session has closed,         * so that we can ping the target periodically to ensure we eventually         * find out that the window has re-opened.           */        if (maxcmdsn == expcmdsn - 1) {            session->current_peak_window_size = 0;            set_bit(SESSION_WINDOW_CLOSED, &session->control_bits);        }        else            clear_bit(SESSION_WINDOW_CLOSED, &session->control_bits);        DEBUG_FLOW3("iSCSI: session %p - ExpCmdSN %u, MaxCmdSN %u\n",                     session, session->ExpCmdSn, session->MaxCmdSn);    }}/* add a session from an HBA's collection of sessions. * caller must hold the HBA's session lock. */static int add_session(iscsi_hba_t *hba, iscsi_session_t *session){    iscsi_session_t *prior, *next;    if (!hba)        return 0;    if (test_bit(ISCSI_HBA_SHUTTING_DOWN, &hba->flags)) {        printk("iSCSI: HBA %p is shutting down, can't add session %p\n", hba, session);        return 0;    }        prior = NULL;    next = hba->session_list_head;    while (next && (next->channel < session->channel)) {        prior = next;        next = prior->next;    }    while (next && (next->channel == session->channel) && (next->target_id < session->target_id)) {        prior = next;        next = prior->next;    }        /* same Linux SCSI address? */    if (next && (next->channel == session->channel) && (next->target_id == session->target_id)) {        if (strcmp(next->TargetName, session->TargetName) == 0) {            /* already have a session running to this target */            printk("iSCSI: session to %s already exists\n", session->TargetName);        }        else {            printk("iSCSI: error - TargetName %s cannot claim bus %d id %d, already in use by %s\n",                    session->TargetName, session->iscsi_bus, next->target_id, next->TargetName);        }        return 0;    }    else {        /* insert the session into the list */        if ((session->next = next))            next->prev = session;        else            hba->session_list_tail = session;        if ((session->prev = prior))            prior->next = session;        else            hba->session_list_head = session;        session->hba = hba;        wmb();        DEBUG_INIT2("iSCSI: added session %p to hba %p\n", session, hba);                return 1;    }}/* remove a session from an HBA's collection of sessions. * caller must hold the HBA's session lock. */static int remove_session(iscsi_hba_t *hba, iscsi_session_t *session){    if (session->hba && (hba != session->hba)) {        printk("iSCSI: tried to remove session %p from hba %p, but session->hba is %p\n",               session, hba, session->hba);        return 0;    }    /* remove the session from the HBA */    if (session == hba->session_list_head) {        if ((hba->session_list_head = session->next))            hba->session_list_head->prev = NULL;        else

⌨️ 快捷键说明

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