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

📄 iscsi-probe.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 4 页
字号:
                case DID_BUS_BUSY:                case DID_PARITY:                case DID_TIME_OUT:                case DID_RESET:                default:                    if (LOG_ENABLED(ISCSI_LOG_INIT))                        printk("iSCSI: session %p iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x, "                               "host byte 0x%x, SCSI status 0x%x\n",                                session, c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun, c->sc.cmnd[0],                                (sc->result >> 24) & 0xFF, sc->result & 0xFF);                    /* some sort of problem, possibly retry */                    goto retry;            }                        /* check the SCSI status byte.  Note, Linux values are right-shifted once compared to the SCSI spec */            switch (status_byte(sc->result)) {                case GOOD:                case COMMAND_TERMINATED:#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,19)                    /* make sure we got enough of a response */                    if (sc->resid && ((iscsi_expected_data_length(sc) - sc->resid) < sc->underflow)) {                        /* try again */                        if (LOG_ENABLED(ISCSI_LOG_INIT))                            printk("iSCSI: session %p iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x, "                                   "residual %u, retrying to get %u bytes desired\n",                                    session, c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun,                                    c->sc.cmnd[0], sc->resid, sc->underflow);                        goto retry;                    }#endif                    /* all done */                    return 1;                case BUSY: /* device is busy, try again later */                case QUEUE_FULL: /* tagged queuing device has a full queue, wait a bit and try again. */                    attempts_allowed++;                    if (attempts_allowed > 100) {                        printk("iSCSI: session %p iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x, SCSI status 0x%x, out of retries\n",                                session, c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun, c->sc.cmnd[0],                               sc->result & 0xFF);                        return 0;                    }                    set_current_state(TASK_UNINTERRUPTIBLE);                    schedule_timeout(MSECS_TO_JIFFIES(10));                    goto retry;                case CONDITION_GOOD:                case INTERMEDIATE_GOOD:                case INTERMEDIATE_C_GOOD:                    /* we should never get the linked command return codes */                case RESERVATION_CONFLICT:                    /* this is probably never going to happen for INQUIRY or REPORT_LUNS, but retry if it does */                    printk("iSCSI: session %p iscsi_do_cmnd %p SCSI status 0x%x at %lu, retrying\n",                           session, c, sc->result & 0xFF, jiffies);                    goto retry;                case CHECK_CONDITION:                    /* look at the sense.  If it's illegal request, don't bother retrying the command */                    if ((sc->sense_buffer[0] & 0x70) == 0x70) {                        switch (SENSE_KEY(sc->sense_buffer)) {                            case ILLEGAL_REQUEST:                                printk("iSCSI: session %p iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x, illegal request\n",                                        session, c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun, c->sc.cmnd[0]);                                return 0;                            default:                                /* possibly retry */                                if (LOG_ENABLED(ISCSI_LOG_INIT))                                    printk("iSCSI: session %p iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x with sense, retrying\n",                                            session, c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun,                                            c->sc.cmnd[0]);                                goto retry;                        }                    }                    goto retry;                default:                    printk("iSCSI: session %p iscsi_do_cmnd %p unexpected SCSI status 0x%x at %lu\n",                           session, c, sc->result & 0xFF, jiffies);                    return 0;            }        }    }    if (LOG_ENABLED(ISCSI_LOG_INIT))        printk("iSCSI: session %p iscsi_do_cmnd %p SCSI status 0x%x, out of retries at %lu\n",               session, c, sc->result & 0xFF, jiffies);    return 0;}static void make_report_luns(Scsi_Cmnd *sc, uint32_t max_entries){    uint32_t length = 8 + (max_entries * 8); /* 8 byte header plus 8 bytes per LUN */    sc->cmd_len = 10;    sc->request_bufflen = length;    sc->underflow = 8;  /* need at least the length */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,19)    sc->resid = 0;#endif    /* CDB */    memset(sc->cmnd, 0, sizeof(sc->cmnd));    sc->cmnd[0] = REPORT_LUNS;    sc->cmnd[1] = 0;     sc->cmnd[2] = 0; /* either reserved or select report in various versions of SCSI-3 */    sc->cmnd[3] = 0;     sc->cmnd[4] = 0;     sc->cmnd[5] = 0;     sc->cmnd[6] = (length >> 24) & 0xFF;    sc->cmnd[7] = (length >> 16) & 0xFF;    sc->cmnd[8] = (length >> 8) & 0xFF;    sc->cmnd[9] = (length) & 0xFF;}static void make_inquiry(Scsi_Cmnd *sc, int lun0_scsi_level){    sc->cmd_len = 6;    sc->request_bufflen = 255;    if (sc->lun == 0)        sc->underflow = 3; /* we need at least the peripheral code and SCSI version */    else        sc->underflow = 1; /* we need at least the peripheral code */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,19)    sc->resid = 0;#endif    memset(sc->cmnd, 0, sizeof(sc->cmnd));    sc->cmnd[0] = INQUIRY;    if (lun0_scsi_level >= 0x3)        sc->cmnd[1] = 0; /* reserved in SCSI-3 and higher */    else        sc->cmnd[1] = (sc->lun << 5) & 0xe0;    sc->cmnd[2] = 0;     sc->cmnd[3] = 0;    sc->cmnd[4] = 255;  /* length */    sc->cmnd[5] = 0; }/* scan for LUNs */void iscsi_detect_luns(iscsi_session_t *session){    int l;    iscsi_cmnd_t *c = NULL;    Scsi_Cmnd *sc = NULL;    int lun0_scsi_level = 0;    size_t cmd_size = sizeof(iscsi_cmnd_t);    unsigned int bufflen = 0;    uint32_t length = 0;    uint32_t last_luns = 0;    uint32_t luns = 32; /* start small to avoid bugs in REPORT_LUNS handling */    int report_luns_failed = 0;    /* need enough buffer space for replies to INQUIRY and REPORT_LUNS */    if ((8 + (ISCSI_MAX_LUN * 8)) < 255)        bufflen = 255;    else        bufflen = (ISCSI_MAX_LUN * 8) + 8;        cmd_size += bufflen;    c = kmalloc(cmd_size, GFP_KERNEL);    if (!c) {        printk("iSCSI: session %p iscsi_detect_luns couldn't allocate a Scsi_Cmnd\n", session);        return;    }    /* initialize */    memset(c, 0, cmd_size);    sema_init(&c->done_sem, 0);    c->bufflen = bufflen;#if DEBUG_ALLOC    if (LOG_ENABLED(ISCSI_LOG_ALLOC))        printk("iSCSI: session %p hba %p host %p allocated iscsi cmnd %p, size %d, buffer %p, bufflen %u, end %p\n",                session, session->hba, session->hba->host, c, cmd_size, c->buffer, c->bufflen, c->buffer + c->bufflen);#endif    /* fill in the basic required info in the Scsi_Cmnd */    sc = &(c->sc);    sc->host = session->hba->host;    sc->channel = session->channel;    sc->target = session->target_id;    sc->lun = 0;    sc->use_sg = 0;    sc->request_buffer = c->buffer;    sc->request_bufflen = c->bufflen;    sc->scsi_done = iscsi_done;    /* save a pointer to the iscsi_cmnd in the Scsi_Cmnd, so that iscsi_done can use it */    sc->buffer = (void *)c;        do {        if (signal_pending(current)) {            DEBUG_INIT1("iSCSI: session %p detect LUNs aborted by signal\n", session);            goto done;        }        if (test_bit(SESSION_TERMINATING, &session->control_bits))            goto done;        /* send a REPORT_LUNS to LUN 0.  If it works, we know the LUNs. */        last_luns = luns;        make_report_luns(sc, luns);        if (iscsi_do_cmnd(session, c, 6)) {            uint8_t *lun_list = c->buffer + 8;            int luns_listed;            /* get the list length the target has */            length |= c->buffer[0] << 24;            length |= c->buffer[1] << 16;            length |= c->buffer[2] << 8;            length |= c->buffer[3];            if (length < 8) {                /* odd, assume REPORT_LUNS is broken, fall back to doing INQUIRY */                DEBUG_INIT1("iSCSI: session %p REPORT_LUNS length 0, falling back to INQUIRY\n", session);                report_luns_failed = 1;                break;            }                        /* figure out how many luns we were told about this time */            if ((length / 8U) < luns)                luns_listed = length / 8U;            else                luns_listed = luns;                        /* loop until we run out of data, or out of buffer */            for (l = 0; l < luns_listed; l++) {                int address_method = (lun_list[0] & 0xc0) >> 6;                int lun;                                if (LOG_ENABLED(ISCSI_LOG_LOGIN) || LOG_ENABLED(ISCSI_LOG_INIT))                    printk("iSCSI: session %p (%u %u %u *) REPORT_LUNS[%d] = %02x %02x %02x %02x %02x %02x %02x %02x\n",                           session, session->host_no, session->channel, session->target_id, l,                            lun_list[0], lun_list[1], lun_list[2], lun_list[3],                            lun_list[4], lun_list[5], lun_list[6], lun_list[7]);                                switch (address_method) {                    case 0x0: {                        /* single-level LUN if bus id is 0, else peripheral device addressing */                        lun = lun_list[1];                        set_bit(lun, session->luns_detected);                        break;                    }                    case 0x1: {                        /* flat-space addressing */                        lun = lun_list[1];                        set_bit(lun, session->luns_detected);                        break;                    }                    case 0x2: {                        /* logical unit addressing method */                        lun = lun_list[1] & 0x1F;                        set_bit(lun, session->luns_detected);                        break;                    }                    case 0x3: {                        /* extended logical unit addressing method is too complicated for us to want to deal with */                        printk("iSCSI: session %p (%u %u %u *) REPORT_LUNS[%d] with extended LU address method 0x%x ignored\n",                                session, session->host_no, session->channel, session->target_id, l, address_method);                        break;                    }                    default:                        printk("iSCSI: session %p (%u %u %u *) REPORT_LUNS[%d] with unknown address method 0x%x ignored\n",                                session, session->host_no, session->channel, session->target_id, l, address_method);                        break;                }                                /* next LUN in the list */                lun_list += 8;                }            /* decide how many luns to ask for on the next iteration, if there is one */            luns = length / 8U;            if (luns > ISCSI_MAX_LUN) {                /* we only have buffer space for so many LUNs */                luns = ISCSI_MAX_LUN;                printk("iSCSI: session %p REPORT_LUNS length %u (%u entries) truncated to %u (%u entries)\n",                        session, length, (length / 8) - 1, (luns + 1) * 8U, luns);            }        }        else {            /* REPORT_LUNS failed, fall back to doing INQUIRY */            DEBUG_INIT1("iSCSI: session %p REPORT_LUNS failed, falling back to INQUIRY\n", session);            report_luns_failed = 1;            break;        }    } while (luns > last_luns);    if (signal_pending(current)) {        DEBUG_INIT1("iSCSI: session %p detect LUNs aborted by signal\n", session);        goto done;    }    if (report_luns_failed) {        /* if REPORT_LUNS failed, then either it's a SCSI-2 device         * that doesn't understand the command, or it's a SCSI-3         * device that only has one LUN and decided not to implement         * REPORT_LUNS.  In either case, we're safe just probing LUNs         * 0-7 with INQUIRY, since SCSI-2 can't have more than 8 LUNs,         * and SCSI-3 should do REPORT_LUNS if it has more than 1 LUN.         */        for (l = 0; l < 8; l++) {            sc->lun = l;            sc->request_buffer = c->buffer;            make_inquiry(sc, lun0_scsi_level);            /* we'll make a note of the LUN when the rx thread receives the response.             * No need to do it again here.             */            if (iscsi_do_cmnd(session, c, 6)) {                /* we do need to record the SCSI level so we can build inquiries properly though */                if (l == 0) {                    lun0_scsi_level = c->buffer[2] & 0x07;                    if (LOG_ENABLED(ISCSI_LOG_INIT))                        printk("iSCSI: session %p (%u %u %u %u) is SCSI level %d\n",                                session, sc->host->host_no, sc->channel, sc->target, sc->lun, lun0_scsi_level);                }            }            else {                /* just assume there's no LUN */            }            if (test_bit(SESSION_TERMINATING, &session->control_bits))                break;            if (signal_pending(current))                break;        }    } done:#if DEBUG_ALLOC    if (LOG_ENABLED(ISCSI_LOG_ALLOC))        printk("iSCSI: session %p hba %p host %p kfree iscsi cmnd %p, bufflen %u\n",                session, session->hba, session->hba->host, c, c->bufflen);#endif    kfree(c);}int iscsi_reset_lun_probing(void){    int ret = 0;    spin_lock(&iscsi_lun_probe_lock);    if ((iscsi_currently_probing == NULL) && (iscsi_lun_probe_head == NULL)) {        /* if we're not currently probing, reset */        DEBUG_INIT1("iSCSI: reset LUN probing at %lu\n", jiffies);        iscsi_next_probe = 0;        iscsi_lun_probe_start = 0;        mb();        ret = 1;    }    else {        DEBUG_INIT3("iSCSI: failed to reset LUN probing at %lu, currently %p, head %p\n",                     jiffies, iscsi_currently_probing, iscsi_lun_probe_head);    }    spin_unlock(&iscsi_lun_probe_lock);    return ret;}

⌨️ 快捷键说明

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