📄 iscsi_client.c
字号:
header.login_cmd.isid = s->isid; header.login_cmd.tsid = s->tsid; header.login_cmd.init_cmd_rn = s->cmd_rn++; header.login_cmd.itt = s->itt; } iov.iov_base = &header; iov.iov_len = sizeof(header); /* ship the message */ // printk ("iscsi_client - iscsi_client_login() Sending login cmd\n"); if (iscsi_sendv (sock, &iov, 1) < 0) { printk ("iscsi_client - iscsi_client_login() Failed to send login message\n"); return -1; } /* get a response */ // printk ("iscsi_client - iscsi_client_login() Reading login rsp\n"); if ((len = iscsi_read_header (sock, &header)) < 0) { printk ("iscsi_client - iscsi_client_login() Failed to recieve login response\n"); return -1; } if (len > 0) { printk ("iscsi_client - iscsi_client_login() Extra data during login\n"); } if (header.login_rsp.op != ISCSI_OP_LOGIN_RSP) { printk ("iscsi_client - iscsi_client_login() Bad response during login:\n"); printk ("iscsi_client - iscsi_client_login() rsp op: %d\n",header.login_rsp.op); iscsi_print_header (&header); return -1; } /* verify the target accepted our login */ if (header.login_rsp.status != ISCSI_LOGIN_ACCEPT) { printk ("iscsi_client - iscsi_client_login() Login not accepted reason: %d\n", header.login_rsp.status); return -1; } /* verify that we're using version 1 * (was 0, since the UNH implementations use 1, we'll use it too) */ if (header.login_rsp.version_active != 1) { printk ("iscsi_client - iscsi_client_login() Unsupported version rquested\n"); return -1; } /* make sure final flag bit is set */ if (!(header.login_rsp.F_reserved1 & ISCSI_F_BIT)) { printk ("iscsi_client - iscsi_client_login() Login Response Final Bit not set\n"); return -1; } if (s->cmd_rn != header.login_rsp.exp_cmd_rn) { printk ("iscsi_client - iscsi_client_login() Command out of order. Recieved %d expecting %d\n", header.login_rsp.exp_cmd_rn, s->cmd_rn); } // printk ("iscsi_client - iscsi_client_login() Login Accepted\n"); /* should be all set, finish initializing... */ if (s->tsid == 0) { s->tsid = header.login_rsp.tsid; } s->connection[c_idx].stat_rn = header.login_rsp.init_stat_rn; s->max_cmd_rn = header.login_rsp.max_cmd_rn; s->connection[c_idx].in_use = TRUE; s->connection[c_idx].s = s; /* we need an extra thread to handle reading */ // printk ("iscsi_client - iscsi_client_login() Creating reader thread for (%p)\n", &s->connection[c_idx]); s->connection[c_idx].reader = kernel_thread(iscsi_client_reader, &s->connection[c_idx], CLONE_FS | CLONE_FILES | CLONE_SIGHAND); if (s->connection[c_idx].reader <= 1) { printk ("iscsi_client - iscsi_client_login() Error during thread creation\n"); return -1; } // printk ("iscsi_client - PID %d iscsi_client_login(%p,%d) EXIT\n", current->pid, s, c_idx); return 0;}static int iscsi_client_reader(void *connection){ s32 len; iscsi_header_t hdr; iscsi_connection_t *c = connection; struct sock *sk; // printk ("iscsi_client - PID %d iscsi_client_reader(%p) ENTRY\n", current->pid, c); sk = c->sock->sk; while (1) { if (!c->in_use) { printk ("iscsi_client - iscsi_client_reader() reader_thread on unused connection\n"); return -1; } if (sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT) { printk ("iscsi_client - iscsi_client_reader() abnormal connection teardown\n"); iscsi_close_connection (c); return -1; } if ( skb_queue_empty(&(sk->receive_queue)) ) { /* nothing to do, wait on tcp. This is mostly grabbed * from tcp_data_wait() which is not globally defined. * I'm paranoid about blocking on a read, so we'll * wait on tcp's sleep queue */ DECLARE_WAITQUEUE(wait, current); // printk ("iscsi_client - iscsi_client_reader() no data, going to sleep\n"); lock_sock(sk); add_wait_queue(sk->sleep, &wait); set_current_state(TASK_INTERRUPTIBLE); set_bit(SOCK_ASYNC_WAITDATA, &sk->socket->flags); release_sock(sk); schedule(); lock_sock(sk); clear_bit(SOCK_ASYNC_WAITDATA, &sk->socket->flags); remove_wait_queue(sk->sleep, &wait); set_current_state(TASK_RUNNING); release_sock(sk); // printk ("iscsi_client - iscsi_client_reader() WOKEN UP!\n"); } else { /* if we manage to get here, that means * the connection has some data * waiting to be read from * its socket. We'll read a header * and then call the dispatcher */ if ((len=iscsi_read_header(c->sock, &hdr)) >= 0) { iscsi_client_dispatch (c, hdr, len); } } }}static int iscsi_client_dispatch (iscsi_connection_t *c, iscsi_header_t hdr, s32 bytes_to_read){ s32 bytes_read = 0; unsigned long int flags; s32 current_write; s32 total_written = 0; struct scatterlist *sg_lst; int sg_off; int write_off; int sg_cnt; iscsi_header_t rsp; struct iovec iov[ISCSI_CLIENT_SG_TABLE_SIZE + 4]; u16 num_iov; s32 bytes_to_write; iscsi_session_t *s = c->s; // printk ("iscsi_client - PID %d iscsi_client_dispatch(%p,_,%d) ENTRY\n", current->pid, c, bytes_to_read); /* ok let's parse the header and figure out what to do */ switch (hdr.scsi_cmd.op) { case ISCSI_OP_NOP_IN: printk ("iscsi_client - I don't know how to handle" " NOP_IN yet\n"); if (bytes_to_read != 0) { printk ("iscsi_client - Leftover bytes in" " NOP_IN %d\n", bytes_to_read); while (bytes_to_read) { if ((bytes_read = iscsi_read (c->sock, scratch_pad, bytes_to_read)) == -1) { break; } bytes_to_read -= bytes_read; } return -1; } return 0; break; case ISCSI_OP_SCSI_RSP: // printk ("iscsi_client - iscsi_client_dispatch() - RX SCSI_RSP\n"); s->current_command->result = hdr.scsi_rsp.status; s->current_command->resid = hdr.scsi_rsp.resid_cnt; // printk ("iscsi_client - iscsi_client_dispatch() - Processing rsp buf %p\n", s->current_command->request_buffer); /* DUMP_DATA (s->current_command->request_buffer, s->current_command->request_bufflen); */ if ((hdr.scsi_rsp.status & STATUS_MASK) != GOOD) { printk ("iscsi_client - iscsi_client_dispatch() - BAD STATUS on RX\n"); if (bytes_to_read != hdr.scsi_rsp.sense_len) { printk ("iscsi_client - sense_length != length in SCSI_RSP\n"); } if (bytes_to_read > SCSI_SENSE_BUFFERSIZE) { printk ("iscsi_client - sense_length > SCSI_SENSE_BUFFERSIZE\n"); iscsi_read (c->sock, s->current_command->sense_buffer, SCSI_SENSE_BUFFERSIZE); iscsi_read (c->sock, scratch_pad, bytes_to_read - SCSI_SENSE_BUFFERSIZE); } else { iscsi_read (c->sock, s->current_command->sense_buffer, bytes_to_read); } } // printk ("iscsi_client - iscsi_client_dispatch() - calling done()\n"); spin_lock_irqsave(&io_request_lock, flags); s->current_command->scsi_done(s->current_command); spin_unlock_irqrestore(&io_request_lock, flags); // printk ("iscsi_client - iscsi_client_dispatch() - done() returned\n"); return 0; break; case ISCSI_OP_TASK_RSP: printk ("iscsi_client - I don't know how to handle" " TASK_RSP yet\n"); if (bytes_to_read != 0) { printk ("iscsi_client - Leftover bytes in" " TASK_RSP %d\n", bytes_to_read); while (bytes_to_read) { if ((bytes_read = iscsi_read (c->sock, scratch_pad, bytes_to_read)) == -1) { break; } bytes_to_read -= bytes_read; } return -1; } return 0; break; case ISCSI_OP_LOGIN_RSP: printk ("iscsi_client - Recieved LOGIN_RSP during" "full feature phase\n"); if (bytes_to_read != 0) { printk ("iscsi_client - Leftover bytes in" " LOGIN_RSP %d\n", bytes_to_read); while (bytes_to_read) { if ((bytes_read = iscsi_read (c->sock, scratch_pad, bytes_to_read)) == -1) { break; } bytes_to_read -= bytes_read; } } return -1; break; case ISCSI_OP_TEXT_RSP: printk ("iscsi_client - I don't know how to handle" " TEXT_RSP yet\n"); if (bytes_to_read != 0) { printk ("iscsi_client - Leftover bytes in" " TEXT_RSP %d\n", bytes_to_read); while (bytes_to_read) { if ((bytes_read = iscsi_read (c->sock, scratch_pad, bytes_to_read)) == -1) { break; } bytes_to_read -= bytes_read; } return -1; } return 0; break; case ISCSI_OP_READ_DATA: /* we're not setting the P-bit in the flags field so we don't need to bother with * ttt. The spec doesnt say if this should be all zeros or all ones like it should * be if its not used when recieving an R2T message. We'll assume all 1's for now. * Data numbering is optional, and since we don't support NOP messages yet * we won't support Data numbering */ /* for now we'll ignore just about everything except what we really need */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -