📄 iscsi_client.c
字号:
iscsi_session_t *s; unsigned int s_idx; // printk("iscsi_client - PID %d iscsi_client_detect(%p) ENTRY\n", current->pid, tpnt); /* probe should connect and login */ if ((s_idx = iscsi_client_probe()) >= 0) { // printk ("iscsi_client - probe success\n"); /* Found - create an instance of this controller */ shpnt = scsi_register(tpnt, 0); if (shpnt == NULL) { printk ("iscsi_client - iscsi_client_detect() SCSI Register failed :(\n"); return 0; } shpnt->this_id = ISCSI_CLIENT_SCSI_ID; s = &session[s_idx]; if (iscsi_client_start(s) != 0) { printk ("iscsi_client - iscsi_client_detect() Start failed :(\n"); scsi_unregister (shpnt); sock_release(s->connection[0].sock); return 0; } /* finally we'll store the session index as the unique_id */ shpnt->unique_id = s_idx; // printk("iscsi_client - PID %d iscsi_client_detect(%p) EXIT\n", current->pid, tpnt); return 1; } return 0;}int iscsi_client_command(Scsi_Cmnd * SCpnt){ // printk ("iscsi_client - PID %d iscsi_client_command(%p) ENTRY\n", current->pid, SCpnt); iscsi_client_queuecommand(SCpnt, iscsi_client_it_finished); /* Wait for the command to complete */ while (!SCpnt->SCp.Status) barrier(); // printk ("iscsi_client - PID %d iscsi_client_command(%p) EXIT\n", current->pid, SCpnt); return SCpnt->result;}/* NOTE: currently a scsi target AND a scsi host map to an iscsi_session * a scsi channal maps to an iscsi_connection. We need to check * this and figure out what we should do if we want multiple * hosts and multiple targets * * We probably need to have a hosts data structure encapsulating * the session data structure. Who cares for now. */int iscsi_client_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)){ iscsi_session_t *s; iscsi_connection_t *c; iscsi_header_t hdr; struct iovec iov[2]; u32 num_iov; // printk ("iscsi_client - PID %d iscsi_client_queuecommand(%p,%p) ENTRY\n", current->pid, SCpnt, done); /* zero out the header */ memset (&hdr, 0, ISCSI_HDR_SIZE); /* Verify the unique_id is a valid session */ if (SCpnt->host->unique_id > ISCSI_MAX_SESSIONS) { printk ("iscsi_client: iscsi_client_queuecommand() Bogus unique_id: %d\n", SCpnt->host->unique_id); return -1; } s = &session[SCpnt->host->unique_id]; /* verify the session is in use */ if (!s->in_use) { printk ("iscsi_client: iscsi_client_queuecommand() Session not in use\n"); return -1; } /* ok, now we'll use the channel as the connection index */ if (SCpnt->channel > ISCSI_MAX_CONNECTIONS) { printk ("iscsi_client: iscsi_client_queuecommand() Bogus channel: %d\n", SCpnt->channel); return -1; } c = &s->connection[SCpnt->channel]; /* ok now that we've dug out the appropriate connection to send over, * let's store the current_command away. Note this should be * an enqueue, but we're only support 1 outstanding command * at a time */ s->current_command = SCpnt; s->current_command->scsi_done = done; s->current_command->SCp.Status = 0; /* Finally, let's build a header and send on the pipe */ hdr.scsi_cmd.op = ISCSI_OP_SCSI_CMD; if (SCpnt->cmd_len > 16) hdr.scsi_cmd.add_cdb = SCpnt->cmd_len - 16; ASSERT (sizeof(SCpnt->lun) == 4) hdr.scsi_cmd.lun = SCpnt->lun; // printk ("iscsi_client - iscsi_client_queuecommand() Lun == %d,%d\n", SCpnt->lun, hdr.scsi_cmd.lun); hdr.scsi_cmd.itt = s->itt++; /* ??? check me */ hdr.scsi_cmd.exp_data_len = SCpnt->request_bufflen; hdr.scsi_cmd.cmd_rn = s->cmd_rn++; hdr.scsi_cmd.exp_stat_rn = c->stat_rn++; iov[0].iov_base = &hdr; iov[0].iov_len = 48; if (hdr.scsi_cmd.add_cdb) { memcpy (hdr.scsi_cmd.cdb, SCpnt->cmnd, 16); iov[1].iov_base = SCpnt->cmnd + 16; iov[1].iov_len = hdr.scsi_cmd.add_cdb; num_iov = 2; } else { memcpy (hdr.scsi_cmd.cdb, SCpnt->cmnd, SCpnt->cmd_len); num_iov = 1; } if (iscsi_sendv (c->sock, iov, num_iov) < 0) { printk ("iscsi_client: iscsi_client_queuecommand() sendv() failed\n"); } // printk ("iscsi_client - PID %d iscsi_client_queuecommand(%p,%p) EXIT\n", current->pid, SCpnt, done); return 0;}/* need to get rid of abort and reset and use the * new eh_x mechanisms */int iscsi_client_abort(Scsi_Cmnd * SCpnt){ printk ("iscsi_client - PID %d iscsi_client_abort(%p) ENTRY\n", current->pid, SCpnt); return SCSI_ABORT_SNOOZE;}int iscsi_client_reset(Scsi_Cmnd * SCpnt, unsigned int flags){ printk ("iscsi_client - PID %d iscsi_client_reset(%p,0x%x) ENTRY\n", current->pid, SCpnt, flags); return SCSI_RESET_PUNT;}/* lifted from sym53c416.c:sym53c416_bios_param */int iscsi_client_bios_param(Disk *disk, kdev_t dev, int *ip){ int size; printk ("iscsi_client - PID %d iscsi_client_bios_param(%p,%d,%p) ENTRY\n", current->pid, disk, dev, ip); size = disk->capacity; ip[0] = 64; /* heads */ ip[1] = 32; /* sectors */ if((ip[2] = size >> 11) > 1024) { /* cylinders, test for big disk */ ip[0] = 255; /* heads */ ip[1] = 63; /* sectors */ ip[2] = size / (255 * 63); /* cylinders */ } return 0;}/* Local definitions */static unsigned int iscsi_client_probe(void){ u16 port = ISCSI_PORT; u32 addr = 0x1401010a; /* cypher (10.1.1.20) */ // u32 addr = 0x0100007f; /* localhost (127.0.0.1) */ // u32 addr = 0x0101010a; /* morpheus (10.1.1.1) */ struct sockaddr_in sin; s32 error; u16 i; struct socket *sock; // printk ("iscsi_client - PID %d iscsi_client_probe() ENTRY\n", current->pid); /* find an open session */ for (i=0; i<ISCSI_MAX_SESSIONS; i++) { if (!session[i].in_use) break; } if (i==ISCSI_MAX_SESSIONS) { printk ("iscsi_client - iscsi_client_probe() No more sessions allowed\n"); return -1; } sock = session[i].connection[0].sock; error = sock_create(PF_INET,SOCK_STREAM,IPPROTO_TCP,&sock); if (error<0) { printk("iscsi_client - iscsi_client_probe() Error during creation of socket\n"); return -1; } sin.sin_family = AF_INET; /* somehow we need to get addr */ memcpy (&sin.sin_addr, &addr, sizeof(u32)); sin.sin_port = cpu_to_be16 (port); // printk ("iscsi_client - iscsi_client_probe() Attempting to connect to host\n"); error = sock->ops->connect(sock, (struct sockaddr *) &sin, sizeof(struct sockaddr_in), 0); if (error<0) { printk("iscsi_client - iscsi_client_probe() Error during connection of socket\n"); sock_release(sock); return -1; } session[i].in_use = TRUE; session[i].num_connections = 1; session[i].connection[0].sock = sock; // printk ("iscsi_client - PID %d iscsi_client_probe() EXIT\n", current->pid); return i;}static int iscsi_client_start (iscsi_session_t *s) { // printk ("iscsi_client - PID %d iscsi_client_start(%p) ENTRY\n", current->pid, s); /* allocate some memory for our use */ if ((scratch_pad = kmalloc (4096, GFP_KERNEL)) == NULL) { printk("iscsi_client - iscsi_client_start() Error during kmalloc() allocation\n"); return -1; } /* Before getting ahead of ourselves and launching helper threads, * let's login to the target and make sure we're in full-feature * mode */ if (iscsi_client_login(s, 0) != 0) { printk("iscsi_client - iscsi_client_start() Error during iscsi_client_login()\n"); kfree (scratch_pad); return -1; } // printk ("iscsi_client - PID %d iscsi_client_start(%p) EXIT\n", current->pid, s); return 0;}static int iscsi_client_login(iscsi_session_t *s, u16 c_idx){ iscsi_header_t header; struct iovec iov; s32 len; struct socket *sock; // printk ("iscsi_client - PID %d iscsi_client_login(%p,%d) ENTRY\n", current->pid, s, c_idx); sock = s->connection[c_idx].sock; ASSERT (sizeof(header) == 48); /* zero out header */ memset (&header, 0, ISCSI_HDR_SIZE); header.login_cmd.op = ISCSI_OP_LOGIN_CMD; /* spec doesn't yet define what version numbers should be * so we'll just use version 0 for now */ header.login_cmd.version_max = header.login_cmd.version_min = (u8) 0; header.login_cmd.len = 0; /* currently we only support 1 connection per session, so cid * is meaningless */ s->connection[c_idx].cid = header.login_cmd.cid = c_idx; /* if the session id hasn't yet been established, we know this is * the first connection in this session, so we'll generate * initial values for the session */ if (s->tsid == 0) { s->isid = header.login_cmd.isid = isid++; header.login_cmd.tsid = 0; s->cmd_rn = (header.login_cmd.init_cmd_rn = 1) + 1; s->itt = header.login_cmd.itt = 0; /* double check me */ } else { s->num_connections++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -