📄 iscsi_main.c
字号:
msg.msg_iovlen = 1; /* set a timer, though we shouldn't really need one */ session->login_phase_timer = jiffies + (session->login_timeout * HZ); mb(); if (LOG_ENABLED(ISCSI_LOG_LOGIN)) { char *text = (char *)(pdu + 1); char *end = text + ntoh24(pdu->dlength); /* show the phases and tbit */ printk("iSCSI: session %p sending login pdu with current phase %d, next %d, tbit %d, dlength %d at %lu, timeout at %lu (%d seconds)\n", session, pdu->curr, pdu->next, pdu->tbit, ntoh24(pdu->dlength), jiffies, session->login_phase_timer, session->login_timeout); /* show all the text that we're sending */ while (text < end) { printk("iSCSI: session %p login text: %s\n", session, text); text += strlen(text); while ((text < end) && (*text == '\0')) text++; } } rc = iscsi_sendmsg(session, &msg, pdu_length); /* clear the timer */ session->login_phase_timer = 0; mb(); if (rc != pdu_length) { char *error; if ((rc < 0) && (error = iscsi_strerror(-rc)) && (error[0] != '\0')) printk("iSCSI: session %p failed to send login PDU, rc %d, %s\n", session, rc, iscsi_strerror(-rc)); else printk("iSCSI: session %p failed to send login PDU, rc %d\n", session, rc); return 0; } DEBUG_INIT5("iSCSI: session %p sent login pdu %p at %lu, length %d, dlength %d\n", session, pdu, jiffies, pdu_length, ntoh24(pdu->dlength)); return 1;}/* try to read an entire login PDU into the buffer, timing out after timeout seconds */int iscsi_recv_login_pdu(iscsi_session_t *session, struct IscsiLoginRspHdr *pdu, int max_pdu_length, int timeout){ struct msghdr msg; struct iovec iov; int rc = 0; int pdu_length; int ret = 0; if (max_pdu_length < sizeof(*pdu)) { printk("iSCSI: session %p, pdu %p max_pdu_length %d is too small to recv a login header\n", session, pdu, max_pdu_length); return 0; } /* set the timer to implement the timeout requested */ if (timeout) session->login_phase_timer = jiffies + (timeout * HZ); else session->login_phase_timer = 0; mb(); if (LOG_ENABLED(ISCSI_LOG_LOGIN)) { printk("iSCSI: session %p trying to recv login pdu at %lu, timeout at %lu (%d seconds)\n", session, jiffies, session->login_phase_timer, timeout); } /* read the PDU header */ memset(&iov, 0, sizeof(iov)); iov.iov_base = (void *)pdu; iov.iov_len = sizeof(*pdu); memset( &msg, 0, sizeof(struct msghdr) ); msg.msg_iov = &iov; msg.msg_iovlen = 1; rc = iscsi_recvmsg(session, &msg, sizeof(*pdu)); if (signal_pending(current)) { printk("iSCSI: session %p recv_login_pdu timed out at %lu\n", session, jiffies); goto done; } if (rc != sizeof(*pdu)) { if (rc < 0) { char *error = iscsi_strerror(-rc); if (error && error[0] != '\0') { printk("iSCSI: session %p recv_login_pdu failed to recv %d login PDU bytes, rc %d, %s\n", session, iov.iov_len, rc, iscsi_strerror(-rc)); } else { printk("iSCSI: session %p recv_login_pdu failed to recv %d login PDU bytes, rc %d\n", session, iov.iov_len, rc); } } else if (rc == 0) { printk("iSCSI: session %p recv_login_pdu: connection closed\n", session); } else { /* short reads should be impossible unless a signal occured, * which we already checked for. */ printk("iSCSI: bug - session %p recv_login_pdu, short read %d of %d\n", session, rc, sizeof(*pdu)); } goto done; } pdu_length = ntoh24(pdu->dlength); if (pdu_length) { char *nul = (char *)(pdu + 1); /* check for buffer overflow */ if (pdu_length > (max_pdu_length - sizeof(*pdu))) { printk("iSCSI: session %p recv_login_pdu can't read %d bytes of login PDU data, only %d bytes of buffer available\n", session, pdu_length, (max_pdu_length - sizeof(*pdu))); goto done; } /* handle PDU padding */ if (pdu_length % PAD_WORD_LEN) { int pad = PAD_WORD_LEN - (pdu_length % PAD_WORD_LEN); pdu_length += pad; } /* make sure data + pad + NUL fits in the buffer */ if (pdu_length + sizeof(*pdu) + 1 >= max_pdu_length) { printk("iSCSI: session %p recv_login_pdu failing, PDU size %d would overflow buffer size %d\n", session, pdu_length + sizeof(*pdu) + 1, max_pdu_length); goto done; } /* read the PDU's text data payload */ memset(&iov, 0, sizeof(iov)); iov.iov_base = (void *)(pdu + 1); iov.iov_len = max_pdu_length - sizeof(*pdu); memset( &msg, 0, sizeof(struct msghdr) ); msg.msg_iov = &iov; msg.msg_iovlen = 1; rc = iscsi_recvmsg(session, &msg, pdu_length); /* ensure NUL termination of the text */ nul += pdu_length; *nul = '\0'; if (signal_pending(current)) { printk("iSCSI: session %p recv_login_pdu timed out at %lu\n", session, jiffies); goto done; } if (rc != pdu_length) { if (rc < 0) { char *error = iscsi_strerror(-rc); if (error && error[0] != '\0') { printk("iSCSI: session %p recv_login_pdu failed to recv %d login data PDU bytes, rc %d, %s\n", session, pdu_length, rc, iscsi_strerror(-rc)); } else { printk("iSCSI: session %p recv_login_pdu failed to recv %d login data PDU bytes, rc %d\n", session, pdu_length, rc); } } else if (rc == 0) { printk("iSCSI: session %p recv_login_pdu: connection closed\n", session); } else { /* short reads should be impossible unless a signal occured, * which we already checked for. */ printk("iSCSI: bug - session %p recv_login_pdu, short read %d of %d\n", session, rc, pdu_length); } goto done; } } if (LOG_ENABLED(ISCSI_LOG_LOGIN)) { char *text = (char *)(pdu + 1); char *end = text + ntoh24(pdu->dlength); /* show the phases and tbit */ printk("iSCSI: session %p received login pdu response at %lu with current phase %d, next %d, tbit %d, dlength %d\n", session, jiffies, pdu->curr, pdu->next, pdu->tbit, ntoh24(pdu->dlength)); /* show all the text that we're sending */ while (text < end) { printk("iSCSI: session %p login resp text: %s\n", session, text); text += strlen(text); while ((text < end) && (*text == '\0')) text++; } } ret = 1; done: /* clear the timer */ session->login_phase_timer = 0; mb(); iscsi_handle_signals(session); return ret;}#if DEBUG_TRACEstatic voidiscsi_fill_trace(unsigned char type, Scsi_Cmnd *sc, iscsi_task_t *task, unsigned long data1, unsigned long data2){ iscsi_trace_entry_t *te; DECLARE_NOQUEUE_FLAGS; SPIN_LOCK_NOQUEUE(&iscsi_trace_lock); te = &trace_table[trace_index]; trace_index++; if ( trace_index >= ISCSI_TRACE_COUNT ) { trace_index = 0; } memset(te, 0x0, sizeof(*te)); te->type = type; if (sc) { te->cmd = sc->cmnd[0]; te->host = sc->host->host_no; te->channel = sc->channel; te->target = sc->target; te->lun = sc->lun; } if (task) { te->itt = task->itt; } te->data1 = data1; te->data2 = data2; te->jiffies = jiffies; SPIN_UNLOCK_NOQUEUE(&iscsi_trace_lock);}#endif/* FIXME: update for 16 byte CDBs, such as: lock unlock cache 16 pre-fetch 16 read 16 rebuild 16 regenerate 16 synchronize cache 16 verify 16 write 16 write and verify 16 write same 16 xdwrite extended 16 Then increase ISCSI_MAX_CMD_LEN to 16 in iscsi.h.*//* FIXME: for that matter, check the existing list for correctness */static intiscsi_set_direction(iscsi_task_t *task){ if (task && task->scsi_cmnd) switch (task->scsi_cmnd->cmnd[0]) { case TEST_UNIT_READY: case START_STOP: case REZERO_UNIT: case WRITE_FILEMARKS: case SPACE: case ERASE: case ALLOW_MEDIUM_REMOVAL: /* just control commands */ set_bit(ISCSI_TASK_CONTROL, &task->flags); return ISCSI_TASK_CONTROL; case WRITE_6: case WRITE_10: case WRITE_12: case 0x8a: /* WRITE_16 */ case 0x8e: /* write and verify 16 */ case 0x93: /* write same 16 */ case WRITE_LONG: case WRITE_SAME: case WRITE_BUFFER: case WRITE_VERIFY: case WRITE_VERIFY_12: case COMPARE: case COPY: case COPY_VERIFY: case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW: case SEARCH_EQUAL_12: case SEARCH_HIGH_12: case SEARCH_LOW_12: case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE: case MODE_SELECT: case MODE_SELECT_10: case LOG_SELECT: case SEND_DIAGNOSTIC: case CHANGE_DEFINITION: case UPDATE_BLOCK: case SET_WINDOW: case MEDIUM_SCAN: case SEND_VOLUME_TAG: case WRITE_LONG_2: set_bit(ISCSI_TASK_WRITE, &task->flags); return ISCSI_TASK_WRITE; default: set_bit(ISCSI_TASK_READ, &task->flags); return ISCSI_TASK_READ; } return -1;}/* tagged queueing */static voidiscsi_set_tag( Scsi_Cmnd *cmd, struct IscsiScsiCmdHdr *hdr ){ if ( cmd->device->tagged_supported ) { switch( cmd->tag ) { case HEAD_OF_QUEUE_TAG: hdr->flags.attr = ISCSI_ATTR_HEAD_OF_QUEUE; break; case ORDERED_QUEUE_TAG: hdr->flags.attr = ISCSI_ATTR_ORDERED; break; default: hdr->flags.attr = ISCSI_ATTR_SIMPLE; break; } } else hdr->flags.attr = ISCSI_ATTR_UNTAGGED;}void print_cmnd(Scsi_Cmnd *sc){ printk("iSCSI: Scsi_Cmnd %p to (%u %u %u %u), Cmd 0x%x\n" " done %p, scsi_done %p, host_scribble %p\n" " reqbuf %p, req_len %u\n" " buffer %p, bufflen %u\n" " use_sg %u, old_use_sg %u, sglist_len %u\n" " owner 0x%x, state 0x%x, eh_state 0x%x\n" " cmd_len %u, old_cmd_len %u, abort_reason 0x%x\n", sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], sc->done, sc->scsi_done, sc->host_scribble, sc->request_buffer, sc->request_bufflen, sc->buffer, sc->bufflen, sc->use_sg, sc->old_use_sg, sc->sglist_len, sc->owner, sc->state, sc->eh_state, sc->cmd_len, sc->old_cmd_len, sc->abort_reason); if (sc->cmd_len >= 12) printk("iSCSI: cdb %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x\n", sc->cmnd[0], sc->cmnd[1], sc->cmnd[2], sc->cmnd[3], sc->cmnd[4], sc->cmnd[5], sc->cmnd[6], sc->cmnd[7], sc->cmnd[8], sc->cmnd[9], sc->cmnd[10], sc->cmnd[11]); else if (sc->cmd_len >= 8) printk("iSCSI: cdb %02x%02x%02x%02x %02x%02x%02x%02x\n", sc->cmnd[0], sc->cmnd[1], sc->cmnd[2], sc->cmnd[3], sc->cmnd[4], sc->cmnd[5], sc->cmnd[6], sc->cmnd[7]); else if (sc->cmd_len >= 6) printk("iSCSI: cdb %02x%02x%02x%02x %02x%02x\n", sc->cmnd[0], sc->cmnd[1], sc->cmnd[2], sc->cmnd[3], sc->cmnd[4], sc->cmnd[5]); else if (sc->cmd_len >= 4) printk("iSCSI: cdb %02x%02x%02x%02x\n", sc->cmnd[0], sc->cmnd[1], sc->cmnd[2], sc->cmnd[3]); else if (sc->cmd_len >= 2) printk("iSCSI: cdb %02x%02x\n", sc->cmnd[0], sc->cmnd[1]); if (sc->use_sg && sc->request_buffer) { struct scatterlist *sglist = (struct scatterlist *)sc->request_buffer; int i; for (i = 0; i < sc->use_sg; i++) { printk("iSCSI: sglist %p[%02d] = addr %p, len %u\n", (struct scatterlist *)sc->request_buffer, i, sglist->address, sglist->length); sglist++; } }}#ifdef DEBUG/* caller must hold the session's scsi_cmnd_lock */static void print_session_cmnds(iscsi_session_t *session){ Scsi_Cmnd *search = session->scsi_cmnd_head; printk("iSCSI: session %p to %s unsent cmnd queue: head %p, tail %p, num %u\n", session, session->log_name, session->scsi_cmnd_head, session->scsi_cmnd_tail, atomic_read(&session->num_cmnds)); while (search) { printk("iSCSI: session %p u cmnd %p: state %4x, eh_state %4x, scribble %p, Cmd 0x%x to (%u %u %u %u)\n", session, search, search->state, search->eh_state, search->host_scribble, search->cmnd[0], search->host->host_no, search->channel, search->target, search->lun); search = (Scsi_Cmnd *)search->host_scribble; } printk("iSCSI: session %p to %s ignored cmnd queue: head %p, tail %p, num %u\n", session, session->log_name, session->ignored_cmnd_head, session->ignored_cmnd_tail, atomic_read(&session->num_ignored_cmnds)); search = session->ignored_cmnd_head; while (search) { printk("iSCSI: session %p i cmnd %p: state %4x, e
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -