diff options
-rw-r--r-- | TODO | 3 | ||||
-rw-r--r-- | iscsi.conf | 14 | ||||
-rw-r--r-- | iscsi_control.c | 36 | ||||
-rw-r--r-- | iscsi_control.h | 6 | ||||
-rw-r--r-- | iscsi_if.h | 1 | ||||
-rw-r--r-- | iscsi_tcp.c | 22 | ||||
-rw-r--r-- | iscsi_tcp.h | 1 | ||||
-rwxr-xr-x | iscsiadm | 35 |
8 files changed, 75 insertions, 43 deletions
@@ -28,3 +28,6 @@ fixme: processing. * restructure header processing code into set of small functions. * prefetch in tcp_copy_bits(). +* support residual_count in case of scatter-gather Data-In. As of today, only + non-sg Scsi_Cmnd's are working. But I can amazing some target which will + send residual_count in the middle of scatter-gather Data-In. @@ -1,16 +1,16 @@ -target_name = iqn.2002-07.com.pyxtechnologies.target.s2io -target_portal = 10.16.16.223:3260,1 +target_name = iqn.2001-04.com.example:storage.disk2.sys1.xyz +target_portal = 10.16.16.227:3260,1 initiator_name = iqn.com.dima initiator_alias = dima-um -isid = '012345' -first_burst = 8192 -max_recv_dlength = 8192 -max_burst = 4096 +isid = 0x80.0x0000.0x00.0x0001 +first_burst = 262144 +max_recv_dlength = 65536 +max_burst = 262144 max_r2t = 1 max_cnx = 1 erl = 0 initial_r2t_en = 0 -imm_data_en = 0 +imm_data_en = 1 hdrdgst_en = 0 datadgst_en = 0 ifmarker_en = 0 diff --git a/iscsi_control.c b/iscsi_control.c index a51794d..c8547bc 100644 --- a/iscsi_control.c +++ b/iscsi_control.c @@ -27,7 +27,7 @@ static iscsi_provider_t provider_table[ISCSI_PROVIDER_MAX]; static iscsi_initiator_t initiator = { .sp.initiator_name = "<not specified>", .sp.initiator_alias = "<not specified>", - .sp.isid = {0,0,0,0,0,0}, + .sp.isid = 0x800000000000ULL, .sp.target_name = "<not specified>", .sp.target_alias = "<not specified>", .sp.target_portal = "<not specified>", @@ -60,7 +60,7 @@ static iscsi_initiator_t initiator = { static iscsi_param_t param_table[] = { {1, "initiator_name", &initiator.sp.initiator_name, 0, 0, 1}, {1, "initiator_alias", &initiator.sp.initiator_alias, 0, 0, 1}, - {1, "isid", &initiator.sp.isid, 0, 0, 0}, + {2, "isid", &initiator.sp.isid, 1, 0x8fffffffffffULL, 0}, {1, "target_name", &initiator.sp.target_name, 0, 0, 0}, {1, "target_alias", &initiator.sp.target_alias, 0, 0, 0}, {1, "target_portal", &initiator.sp.target_portal, 0, 0, 0}, @@ -321,10 +321,11 @@ iscsi_host_class_parameters_show(struct class_device *cdev, char *buf) session->p.target_address); count += sprintf(buf+count, "tsih = %d\n", session->p.tsih); count += sprintf(buf+count, "tpgt = %d\n", session->p.tpgt); - count += sprintf(buf+count, "isid = %02x.%02x.%02x.%02x.%02x.%02x\n", - session->p.isid[0], session->p.isid[1], - session->p.isid[2], session->p.isid[3], - session->p.isid[4], session->p.isid[5]); + count += sprintf(buf+count, "isid = 0x%02x.0x%04x.0x%02x.0x%04x\n", + (int)((session->p.isid & 0xffULL)), + (int)((session->p.isid & 0xffff00ULL)>>8), + (int)((session->p.isid & 0xff000000ULL)>>24), + (int)((session->p.isid & 0xffff00000000ULL)>>32)); count += sprintf(buf+count, "time2wait = %d\n", session->p.time2wait); count += sprintf(buf+count, "time2retain = %d\n", @@ -587,9 +588,7 @@ iscsi_add_connection(iscsi_provider_t *provider, int host_no, goto setparam_fail; if (provider->ops.start_cnx(cnx->handle)) { - provider->ops.destroy_cnx(cnx->handle); - kfree(cnx); - return -EIO; + goto start_cnx_fail; } cnx->cid = cid; @@ -603,6 +602,7 @@ iscsi_add_connection(iscsi_provider_t *provider, int host_no, return 0; +start_cnx_fail: setparam_fail: provider->ops.destroy_cnx(cnx->handle); bind_cnx_fail: @@ -679,6 +679,11 @@ iscsi_control_recv_pdu(iscsi_cnx_h handle, iscsi_hdr_t *hdr, char *data) iscsi_session_ctrl_t *session = cnx->session; struct list_head *lh, *n; + /* ignore failure during cnx start */ + if (!session) { + return ISCSI_ERR_SNX_FAILED; + } + /* free pending resources based on received statsn */ spin_lock(&session->freelock); list_for_each_safe(lh, n, &session->freequeue) { @@ -758,7 +763,10 @@ iscsi_host_class_initiator_parameters_show(struct class *class, char * buf) if (p->type == 0) { /* int type */ count += sprintf(buf+count, "%s = %d\n", p->key, *(int*)p->value); - } else { + } else if (p->type == 2) { /* 64-bit int type */ + count += sprintf(buf+count, "%s = %llu\n", p->key, + *(uint64_t*)p->value); + } else { /* string type */ count += sprintf(buf+count, "%s = %s\n", p->key, (char*)p->value); } @@ -798,6 +806,14 @@ iscsi_host_class_initiator_parameters_store(struct class *class, return count; } *(int*)p->value = ival; + } else if (p->type == 2) { /* 64-bit int type */ + uint64_t ival = simple_strtoull(sval, NULL, 0); + if (ival < (uint64_t)p->min || + ival > (uint64_t)p->max) { + printk("bad range '%s'\n", key); + return count; + } + *(uint64_t*)p->value = ival; } else { /* string type */ strncpy((char*)p->value, sval, strlen(sval)+1); } diff --git a/iscsi_control.h b/iscsi_control.h index 2fbdaa9..2fd6e90 100644 --- a/iscsi_control.h +++ b/iscsi_control.h @@ -98,7 +98,7 @@ typedef struct iscsi_cnx_ctrl { typedef struct iscsi_session_params { char initiator_name[ISCSI_NODE_NAME_MAX]; char initiator_alias[ISCSI_ALIAS_NAME_MAX]; - uint8_t isid[7]; + uint64_t isid; char target_name[ISCSI_NODE_NAME_MAX]; char target_alias[ISCSI_ALIAS_NAME_MAX]; char target_portal[ISCSI_PORTAL_MAX]; @@ -143,7 +143,7 @@ typedef struct iscsi_session_ctrl { char target_address[ISCSI_PORTAL_MAX]; uint16_t tpgt; uint16_t tsih; - uint8_t isid[6]; + uint64_t isid; uint16_t max_cnx; struct list_head connections; /* connections list */ @@ -174,7 +174,7 @@ typedef struct iscsi_param { int type; /* 0 - int, 1 - string */ char key[32]; void *value; - uint32_t min, max; /* range for int */ + uint64_t min, max; /* ranges for uint and uint64 */ int show; } iscsi_param_t; @@ -70,6 +70,7 @@ typedef enum { ISCSI_ERR_BAD_ITT = ISCSI_DP_ERR_BASE + 11, ISCSI_ERR_CNX_FAILED = ISCSI_DP_ERR_BASE + 12, ISCSI_ERR_R2TSN = ISCSI_DP_ERR_BASE + 13, + ISCSI_ERR_SNX_FAILED = ISCSI_DP_ERR_BASE + 14, } iscsi_err_e; /* diff --git a/iscsi_tcp.c b/iscsi_tcp.c index 8d94dff..2816e71 100644 --- a/iscsi_tcp.c +++ b/iscsi_tcp.c @@ -24,8 +24,8 @@ MODULE_DESCRIPTION("iSCSI/TCP data-path"); MODULE_LICENSE("GPL"); #define DEBUG_PREV_PDU -/* #define DEBUG_TCP */ -/* #define DEBUG_SCSI */ +#define DEBUG_TCP +#define DEBUG_SCSI #define DEBUG_ASSERT #ifdef DEBUG_TCP @@ -1103,11 +1103,11 @@ iscsi_data_recv(iscsi_conn_t *conn) } } } else { - if (iscsi_ctask_copy(conn, ctask, sc->request_buffer, - sc->request_bufflen)) { - rc = -EAGAIN; + if ((rc = iscsi_ctask_copy(conn, ctask, sc->request_buffer, + sc->request_bufflen)) == -EAGAIN) { goto exit; } + rc = 0; } /* check for nonexceptional status */ @@ -1297,10 +1297,7 @@ iscsi_cmd_rsp(iscsi_conn_t *conn, iscsi_cmd_task_t *ctask) rc = ISCSI_ERR_BAD_TARGET; goto fault; } else if (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW) { - sc->result = host_byte(DID_ERROR) | - status_byte(rhdr->cmd_status); - rc = ISCSI_ERR_BAD_TARGET; - goto fault; + sc->resid = ntohl(rhdr->residual_count); } } } else { @@ -1389,9 +1386,7 @@ iscsi_data_rsp(iscsi_conn_t *conn, iscsi_cmd_task_t *ctask) rhdr->cmd_status; return ISCSI_ERR_BAD_TARGET; } else if (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW) { - sc->result = (DID_ERROR << 16) | - rhdr->cmd_status; - return ISCSI_ERR_BAD_TARGET; + sc->resid = ntohl(rhdr->residual_count); } } @@ -2050,8 +2045,7 @@ iscsi_conn_create(iscsi_snx_h snxh, iscsi_cnx_h handle, } /* - * Do Logout request, terminate connection queus, free - * all associated resources + * Terminate connection queues, free all associated resources */ static void iscsi_conn_destroy(iscsi_cnx_h cnxh) diff --git a/iscsi_tcp.h b/iscsi_tcp.h index cd8ed7e..a736eff 100644 --- a/iscsi_tcp.h +++ b/iscsi_tcp.h @@ -191,7 +191,6 @@ typedef struct iscsi_session { /* control data */ struct scsi_host_template sht; struct Scsi_Host *host; - uint8_t isid[6]; int id; iscsi_conn_t *leadconn; /* Leading Conn. */ spinlock_t conn_lock; @@ -34,7 +34,7 @@ my $sysfs_path = "/sys/class/iscsi"; # my $initiator_name = "iqn.com.dima"; my $initiator_alias = "dima-um"; -my @isid = ('0', '1', '2', '3', '4', '5'); +my @isid = (0x80, 0x0000, 0x00, 0x0001); my $first_burst = 262144; my $max_recv_dlength = 65536; my $max_burst = 262144; @@ -172,7 +172,7 @@ sub padding { sub send_login_req { my ($cmdsn, $exp_statsn, $flags, $cid, $data) = @_; my $dlength = length($data); - my $loginpdu = pack('CCCCCCCCccccccnNnccNNNNNN', + my $loginpdu = pack('CCCCCCCCCnCnnNnccNNNNNN', 0x43, # C: opcode: Login + Immediate 0x87, # C: flags T, OP, FF 0, # C: max ver @@ -181,8 +181,7 @@ sub send_login_req { ($dlength >> 16) & 0xFF, # C: byte 0 of dlength ($dlength >> 8) & 0xFF, # C: byte 1 of dlength $dlength & 0xFF, # C: byte 2 of dlength - @isid[0],@isid[1],@isid[2],@isid[3],@isid[4],@isid[5], - # cccccc: isid + $isid[0],$isid[1],$isid[2],$isid[3], # CnCn: CID $tsih, # n: tsih 0, # N: itt $cid, # n: cid @@ -622,6 +621,24 @@ sub logout { operation("tcp session remove $sid") || exit 1; } +sub read_isid { + my ($in_isid) = @_; + my @out_isid; + + if ($in_isid =~ + /(0x)?([0-9a-fA-F]+)\.(0x)?([0-9a-fA-F]+)\.(0x)?([0-9a-fA-F]+)\.(0x)?([0-9a-fA-F]+)/) { + $out_isid[0] = $1 ? hex($2) : $2+0; + $out_isid[1] = $3 ? hex($4) : $4+0; + $out_isid[2] = $5 ? hex($6) : $6+0; + $out_isid[3] = $7 ? hex($8) : $8+0; + } else { + fatal "can not recognize ISID format! ". + "Expecting 'A.B.C.D', got '$in_isid'"; + } + + return @out_isid; +} + sub sysfs_save { setparam(-1, "initiator_name", $initiator_name); setparam(-1, "initiator_alias", $initiator_alias); @@ -660,7 +677,7 @@ sub sysfs_restore { $initiator_name = getparam(-1, "initiator_name"); $initiator_alias = getparam(-1, "initiator_alias"); - @isid = getparam($id, "isid"); + @isid = read_isid(getparam($id, "isid")); $tsih = getparam($id, "tsih"); $target_name = getparam($id, "target_name"); $target_alias = getparam($id, "target_alias"); @@ -701,7 +718,7 @@ sub config_read { $target_portal = $conf{target_portal}; $initiator_name = $conf{initiator_name}; $initiator_alias = $conf{initiator_alias}; - @isid = $conf{isid}; + @isid = read_isid($conf{isid}); $first_burst = $conf{first_burst}; $max_recv_dlength = $conf{max_recv_dlength}; $max_burst = $conf{max_burst}; @@ -895,16 +912,18 @@ if ($opt{v}) { } else { usage(); } + exit; } else { if ($opt{d}) { # # Do SendTargets method discovery # sendtargets_discovery(\&discovery_login_cb, $opt{d}); - } else { - show_sessions(); + exit; } } if ($opt{l}) { discovery_login_cb(0, $target_name, $target_portal); + exit; } +show_sessions(); |