diff --git a/pkg/api/types.go b/pkg/api/types.go index 3b6a247..a638277 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -166,6 +166,7 @@ var ( ) type SCSICommand struct { + OpCode byte Target *SCSITarget DeviceID uint64 Device *SCSILu diff --git a/pkg/port/iscsit/cmd.go b/pkg/port/iscsit/cmd.go index ea8232e..9b55174 100644 --- a/pkg/port/iscsit/cmd.go +++ b/pkg/port/iscsit/cmd.go @@ -20,7 +20,9 @@ import ( "bytes" "fmt" "strings" + "time" + "github.com/gostor/gotgt/pkg/api" "github.com/gostor/gotgt/pkg/util" log "github.com/sirupsen/logrus" ) @@ -93,6 +95,7 @@ type ISCSICommand struct { FinalInSeq bool Immediate bool TaskTag uint32 + StartTime time.Time ExpCmdSN, MaxCmdSN uint32 AHSLen int Resid uint32 @@ -124,6 +127,7 @@ type ISCSICommand struct { StatusDetail uint8 // SCSI commands + SCSIOpCode byte ExpectedDataLen uint32 CDB []byte Status byte @@ -225,6 +229,7 @@ func parseHeader(data []byte) (*ISCSICommand, error) { m.AHSLen = int(data[4]) * 4 m.DataLen = int(ParseUint(data[5:8])) m.TaskTag = uint32(ParseUint(data[16:20])) + m.StartTime = time.Now() switch m.OpCode { case OpSCSICmd: m.LUN = [8]byte{data[9]} @@ -234,6 +239,13 @@ func parseHeader(data []byte) (*ISCSICommand, error) { m.Write = data[1]&0x20 == 0x20 m.CDB = data[32:48] m.ExpStatSN = uint32(ParseUint(data[28:32])) + SCSIOpcode := api.SCSICommandType(m.SCSIOpCode) + switch SCSIOpcode { + case api.READ_6, api.READ_10, api.READ_12, api.READ_16: + m.Read = true + case api.WRITE_6, api.WRITE_10, api.WRITE_12, api.WRITE_16, api.WRITE_VERIFY, api.WRITE_VERIFY_12, api.WRITE_VERIFY_16: + m.Write = true + } fallthrough case OpSCSITaskReq: m.ReferencedTaskTag = uint32(ParseUint(data[20:24])) @@ -359,6 +371,9 @@ func (m *ISCSICommand) dataInBytes() []byte { copy(buf[40:], util.MarshalUint32(m.BufferOffset)) copy(buf[44:], util.MarshalUint32(m.Resid)) copy(buf[48:], m.RawData[m.BufferOffset:m.BufferOffset+uint32(m.DataLen)]) + if m.ExpectedDataLen != 0 { + copy(buf[48:], m.RawData[m.BufferOffset:m.BufferOffset+uint32(m.DataLen)]) + } return buf } diff --git a/pkg/port/iscsit/iscsid.go b/pkg/port/iscsit/iscsid.go index 5a265aa..fbc0720 100644 --- a/pkg/port/iscsit/iscsid.go +++ b/pkg/port/iscsit/iscsid.go @@ -594,6 +594,14 @@ func (s *ISCSITargetDriver) scsiCommandHandler(conn *iscsiConnection) (err error } task := &iscsiTask{conn: conn, cmd: conn.req, tag: conn.req.TaskTag, scmd: scmd} + task.scmd.OpCode = conn.req.SCSIOpCode + if scmd.Direction == api.SCSIDataBidirection { + task.scmd.Result = api.SAMStatCheckCondition.Stat + scsi.BuildSenseData(task.scmd, scsi.ILLEGAL_REQUEST, scsi.NO_ADDITIONAL_SENSE) + conn.buildRespPackage(OpSCSIResp, task) + conn.rxTask = nil + break + } if req.Write { task.r2tCount = int(req.ExpectedDataLen) - req.DataLen if !req.Final { @@ -649,7 +657,7 @@ func (s *ISCSITargetDriver) scsiCommandHandler(conn *iscsiConnection) (err error } return } else { - if scmd.Direction == api.SCSIDataRead && scmd.SenseBuffer == nil { + if scmd.Direction == api.SCSIDataRead && scmd.SenseBuffer == nil && req.ExpectedDataLen != 0 { conn.buildRespPackage(OpSCSIIn, task) } else { conn.buildRespPackage(OpSCSIResp, task) diff --git a/pkg/scsi/backingstore.go b/pkg/scsi/backingstore.go index 731b84a..10adff5 100644 --- a/pkg/scsi/backingstore.go +++ b/pkg/scsi/backingstore.go @@ -126,6 +126,11 @@ func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error, key } cmd.InSDBBuffer.Resid = uint32(length) copy(cmd.InSDBBuffer.Buffer, rbuf) + if cmd.InSDBBuffer.Length < uint32(length) { + key = ILLEGAL_REQUEST + asc = ASC_INVALID_FIELD_IN_CDB + goto sense + } case api.PRE_FETCH_10, api.PRE_FETCH_16: err = bs.DataAdvise(int64(offset), tl, util.POSIX_FADV_WILLNEED) if err != nil {