diff --git a/pkg/port/iscsit/cmd.go b/pkg/port/iscsit/cmd.go index e7f71b0..049f369 100644 --- a/pkg/port/iscsit/cmd.go +++ b/pkg/port/iscsit/cmd.go @@ -90,7 +90,7 @@ type ISCSICommand struct { Status byte SCSIResponse byte - // Data-In + // Data-In/Out HasStatus bool DataSN uint32 BufferOffset uint32 @@ -187,6 +187,11 @@ func parseHeader(data []byte) (*ISCSICommand, error) { m.CDB = data[32:48] m.ExpStatSN = uint32(ParseUint(data[28:32])) case OpSCSIResp: + case OpSCSIOut: + m.LUN = [8]uint8{data[9]} + m.ExpStatSN = uint32(ParseUint(data[28:32])) + m.DataSN = uint32(ParseUint(data[36:40])) + m.BufferOffset = uint32(ParseUint(data[40:44])) case OpLoginReq, OpTextReq, OpNoopOut, OpLogoutReq: m.Transit = m.Final m.Cont = data[1]&0x40 == 0x40 diff --git a/pkg/port/iscsit/conn.go b/pkg/port/iscsit/conn.go index c02aa32..0ac7f91 100644 --- a/pkg/port/iscsit/conn.go +++ b/pkg/port/iscsit/conn.go @@ -18,6 +18,7 @@ package iscsit import ( "net" + "sync" "github.com/gostor/gotgt/pkg/api" ) @@ -81,6 +82,8 @@ type iscsiConnection struct { txTask *iscsiTask authMethod AuthMethod + + readLock *sync.RWMutex } type taskState int @@ -101,6 +104,7 @@ type iscsiTask struct { func (c *iscsiConnection) init() { c.state = CONN_STATE_FREE c.refcount = 1 + c.readLock = new(sync.RWMutex) c.sessionParam = []ISCSISessionParam{} for _, param := range sessionKeys { c.sessionParam = append(c.sessionParam, ISCSISessionParam{Value: param.def}) diff --git a/pkg/port/iscsit/iscsid.go b/pkg/port/iscsit/iscsid.go index b67f5cf..5be7d10 100644 --- a/pkg/port/iscsit/iscsid.go +++ b/pkg/port/iscsit/iscsid.go @@ -110,6 +110,8 @@ func (s *ISCSITargetService) rxHandler(conn *iscsiConnection) { final bool = false cmd *ISCSICommand ) + conn.readLock.Lock() + defer conn.readLock.Unlock() if conn.state == CONN_STATE_SCSI { hdigest = conn.sessionParam[ISCSI_PARAM_HDRDGST_EN].Value & DIGEST_CRC32C ddigest = conn.sessionParam[ISCSI_PARAM_DATADGST_EN].Value & DIGEST_CRC32C @@ -124,6 +126,7 @@ func (s *ISCSITargetService) rxHandler(conn *iscsiConnection) { return } if length == 0 { + glog.Warningf("set connection to close") conn.state = CONN_STATE_CLOSE return } @@ -131,6 +134,7 @@ func (s *ISCSITargetService) rxHandler(conn *iscsiConnection) { cmd, err = parseHeader(buf) if err != nil { glog.Error(err) + glog.Warningf("set connection to close") conn.state = CONN_STATE_CLOSE return } @@ -162,10 +166,12 @@ func (s *ISCSITargetService) rxHandler(conn *iscsiConnection) { return } if length != dl { + glog.V(2).Infof("get length is %d, but expected %d", length, dl) + glog.Warningf("set connection to close") conn.state = CONN_STATE_CLOSE return } - cmd.RawData = buf[:cmd.DataLen] + cmd.RawData = buf[:length] conn.rxBuffer = append(conn.rxBuffer, buf...) final = true glog.Infof("got command: \n%s", cmd.String()) @@ -189,16 +195,19 @@ func (s *ISCSITargetService) rxHandler(conn *iscsiConnection) { glog.Infof("OpLoginReq") if err := s.iscsiExecLogin(conn); err != nil { glog.Error(err) + glog.Warningf("set connection to close") conn.state = CONN_STATE_CLOSE } case OpLogoutReq: glog.Infof("OpLogoutReq") if err := iscsiExecLogout(conn); err != nil { + glog.Warningf("set connection to close") conn.state = CONN_STATE_CLOSE } case OpTextReq: glog.Infof("OpTextReq") if err := s.iscsiExecText(conn); err != nil { + glog.Warningf("set connection to close") conn.state = CONN_STATE_CLOSE } default: @@ -426,8 +435,10 @@ func (s *ISCSITargetService) txHandler(conn *iscsiConnection) { } } + glog.Infof("connection state: %d", conn.state) switch conn.state { case CONN_STATE_CLOSE, CONN_STATE_EXIT: + glog.Warningf("set connection to close") conn.state = CONN_STATE_CLOSE case CONN_STATE_SECURITY_LOGIN: conn.state = CONN_STATE_LOGIN @@ -509,6 +520,32 @@ func (s *ISCSITargetService) scsiCommandHandler(conn *iscsiConnection) (err erro conn.txIOState = IOSTATE_TX_BHS iscsiExecTMFunction(conn) case OpSCSIOut: + glog.Infof("scsi out operation") + scmd := &api.SCSICommand{} + conn.req.Write = true + conn.req.CDB = []byte{api.Write_10} + task := &iscsiTask{conn: conn, cmd: conn.req, tag: conn.req.TaskTag, scmd: scmd} + conn.rxTask = task + if err = s.iscsiExecTask(task); err != nil { + return + } else { + conn.rxTask = nil + conn.txTask = &iscsiTask{conn: conn, cmd: conn.req, tag: conn.req.TaskTag, scmd: &api.SCSICommand{}} + conn.txIOState = IOSTATE_TX_BHS + conn.statSN += 1 + resp := &ISCSICommand{ + Immediate: true, + Final: true, + StatSN: req.ExpStatSN, + TaskTag: req.TaskTag, + ExpCmdSN: conn.session.ExpCmdSN, + MaxCmdSN: conn.session.ExpCmdSN + 10, + Status: scmd.Result, + SCSIResponse: 0x00, + HasStatus: true, + } + conn.resp = resp + } case OpNoopOut: conn.txTask = &iscsiTask{conn: conn, cmd: conn.req, tag: conn.req.TaskTag} conn.txIOState = IOSTATE_TX_BHS @@ -579,7 +616,7 @@ func (s *ISCSITargetService) iscsiTaskQueueHandler(task *iscsiTask) error { func (s *ISCSITargetService) iscsiExecTask(task *iscsiTask) error { cmd := task.cmd switch cmd.OpCode { - case OpSCSICmd: + case OpSCSICmd, OpSCSIOut: if cmd.Read { if cmd.Write { task.scmd.Direction = api.SCSIDataBidirection