diff --git a/pkg/api/types.go b/pkg/api/types.go index e0fcfcf..9b533a0 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -16,7 +16,6 @@ limitations under the License. package api import ( - "bytes" "errors" "sync" @@ -144,8 +143,13 @@ const ( SCSIDataBidirection ) +type SenseBuffer struct { + Buffer []byte + Length uint32 +} + type SCSIDataBuffer struct { - Buffer *bytes.Buffer + Buffer []byte Length uint32 TransferLength uint32 Resid uint32 @@ -166,21 +170,20 @@ type SCSICommand struct { Device *SCSILu State SCSICommandState Direction SCSIDataDirection - InSDBBuffer SCSIDataBuffer - OutSDBBuffer SCSIDataBuffer + InSDBBuffer *SCSIDataBuffer + OutSDBBuffer *SCSIDataBuffer RelTargetPortID uint16 // Command ITN ID ITNexusID uuid.UUID Offset uint64 TL uint32 - SCB *bytes.Buffer + SCB []byte SCBLength int Lun [8]uint8 Attribute int Tag uint64 Result byte - SenseBuffer *bytes.Buffer - SenseLength uint32 + SenseBuffer *SenseBuffer ITNexus *ITNexus ITNexusLuInfo *ITNexusLuInfo } diff --git a/pkg/port/iscsit/cmd.go b/pkg/port/iscsit/cmd.go index 4c275be..2ebb3c2 100644 --- a/pkg/port/iscsit/cmd.go +++ b/pkg/port/iscsit/cmd.go @@ -278,7 +278,7 @@ func parseHeader(data []byte) (*ISCSICommand, error) { func (m *ISCSICommand) scsiCmdRespBytes() []byte { // rfc7143 11.4 - buf := &bytes.Buffer{} + buf := bytes.Buffer{} buf.WriteByte(byte(OpSCSIResp)) var flag byte = 0x80 if m.Resid > 0 { @@ -321,8 +321,12 @@ func (m *ISCSICommand) scsiCmdRespBytes() []byte { func (m *ISCSICommand) dataInBytes() []byte { // rfc7143 11.7 - buf := &bytes.Buffer{} - buf.WriteByte(byte(OpSCSIIn)) + dl := m.DataLen + for dl%4 > 0 { + dl++ + } + var buf = make([]byte, (48 + dl)) + buf[0] = byte(OpSCSIIn) var flag byte if m.FinalInSeq || m.Final == true { flag |= 0x80 @@ -334,48 +338,33 @@ func (m *ISCSICommand) dataInBytes() []byte { if m.Resid > 0 { if m.Resid > m.ExpectedDataLen { flag |= 0x04 - } else { + } else if m.Resid < m.ExpectedDataLen { flag |= 0x02 } } - buf.WriteByte(flag) - buf.WriteByte(0x00) + buf[1] = flag + //buf.WriteByte(0x00) if m.HasStatus && m.Final == true { flag = byte(m.Status) } - buf.WriteByte(flag) - - buf.WriteByte(0x00) // 4 - - buf.Write(util.MarshalUint64(uint64(m.DataLen))[5:]) // 5-8 + //buf.WriteByte(flag) + buf[3] = flag + copy(buf[5:], util.MarshalUint64(uint64(m.DataLen))[5:]) // Skip through to byte 16 Since A bit is not set 11.7.4 - for i := 0; i < 8; i++ { - buf.WriteByte(0x00) - } - buf.Write(util.MarshalUint64(uint64(m.TaskTag))[4:]) - for i := 0; i < 4; i++ { - // 11.7.4 - buf.WriteByte(0xff) - } - buf.Write(util.MarshalUint64(uint64(m.StatSN))[4:]) - buf.Write(util.MarshalUint64(uint64(m.ExpCmdSN))[4:]) - buf.Write(util.MarshalUint64(uint64(m.MaxCmdSN))[4:]) - buf.Write(util.MarshalUint64(uint64(m.DataSN))[4:]) - buf.Write(util.MarshalUint64(uint64(m.BufferOffset))[4:]) - buf.Write(util.MarshalUint64(uint64(m.Resid))[4:]) - buf.Write(m.RawData[m.BufferOffset : m.BufferOffset+uint32(m.DataLen)]) - dl := m.DataLen - for dl%4 > 0 { - dl++ - buf.WriteByte(0x00) - } + copy(buf[16:], util.MarshalUint32(m.TaskTag)) + copy(buf[24:], util.MarshalUint32(m.StatSN)) + copy(buf[28:], util.MarshalUint32(m.ExpCmdSN)) + copy(buf[32:], util.MarshalUint32(m.MaxCmdSN)) + copy(buf[36:], util.MarshalUint32(m.DataSN)) + 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)]) - return buf.Bytes() + return buf } func (m *ISCSICommand) textRespBytes() []byte { - buf := &bytes.Buffer{} - + buf := bytes.Buffer{} buf.WriteByte(byte(OpTextResp)) var b byte if m.Final { @@ -415,8 +404,7 @@ func (m *ISCSICommand) textRespBytes() []byte { } func (m *ISCSICommand) noopInBytes() []byte { - buf := &bytes.Buffer{} - + buf := bytes.Buffer{} buf.WriteByte(byte(OpNoopIn)) var b byte b |= 0x80 @@ -452,7 +440,7 @@ func (m *ISCSICommand) noopInBytes() []byte { func (m *ISCSICommand) scsiTMFRespBytes() []byte { // rfc7143 11.6 - buf := &bytes.Buffer{} + buf := bytes.Buffer{} buf.WriteByte(byte(OpSCSITaskResp)) buf.WriteByte(0x80) buf.WriteByte(m.Result) @@ -477,9 +465,8 @@ func (m *ISCSICommand) scsiTMFRespBytes() []byte { } func (m *ISCSICommand) r2tRespBytes() []byte { - // rfc7143 11.8 - buf := &bytes.Buffer{} + buf := bytes.Buffer{} buf.WriteByte(byte(OpReady)) var b byte if m.Final { diff --git a/pkg/port/iscsit/conn.go b/pkg/port/iscsit/conn.go index 5330375..d74fd5e 100644 --- a/pkg/port/iscsit/conn.go +++ b/pkg/port/iscsit/conn.go @@ -125,13 +125,12 @@ func (c *iscsiConnection) init() { sort.Sort(c.loginParam.sessionParam) } -func (c *iscsiConnection) readData(size int) ([]byte, int, error) { - var buf = make([]byte, size) +func (c *iscsiConnection) readData(buf []byte) (int, error) { length, err := io.ReadFull(c.conn, buf) if err != nil { - return nil, -1, err + return -1, err } - return buf, length, nil + return length, nil } func (c *iscsiConnection) write(resp []byte) (int, error) { @@ -154,7 +153,7 @@ func (conn *iscsiConnection) buildRespPackage(oc OpCode, task *iscsiTask) error if task == nil { task = conn.rxTask } - resp := &ISCSICommand{ + conn.resp = &ISCSICommand{ StatSN: conn.req.ExpStatSN, TaskTag: conn.req.TaskTag, ExpCmdSN: conn.session.ExpCmdSN, @@ -163,52 +162,55 @@ func (conn *iscsiConnection) buildRespPackage(oc OpCode, task *iscsiTask) error } switch oc { case OpReady: - resp.OpCode = OpReady - resp.R2TSN = task.r2tSN - resp.BufferOffset = uint32(task.offset) - resp.DesiredLength = uint32(task.r2tCount) + conn.resp.OpCode = OpReady + conn.resp.R2TSN = task.r2tSN + conn.resp.BufferOffset = uint32(task.offset) + conn.resp.DesiredLength = uint32(task.r2tCount) if val := conn.loginParam.sessionParam[ISCSI_PARAM_MAX_BURST].Value; task.r2tCount > int(val) { - resp.DesiredLength = uint32(val) + conn.resp.DesiredLength = uint32(val) } case OpSCSIIn, OpSCSIResp: - resp.OpCode = oc - resp.Immediate = true - resp.Final = true - resp.SCSIResponse = 0x00 - resp.HasStatus = true + conn.resp.OpCode = oc + conn.resp.Immediate = true + conn.resp.Final = true + conn.resp.SCSIResponse = 0x00 + conn.resp.HasStatus = true scmd := task.scmd - resp.Status = scmd.Result + conn.resp.Status = scmd.Result if scmd.Result != 0 && scmd.SenseBuffer != nil { - length := util.MarshalUint32(uint32(scmd.SenseLength)) - resp.RawData = append(length[2:4], scmd.SenseBuffer.Bytes()...) + length := util.MarshalUint32(scmd.SenseBuffer.Length) + conn.resp.RawData = append(length[2:4], scmd.SenseBuffer.Buffer...) } else if scmd.Direction == api.SCSIDataRead || scmd.Direction == api.SCSIDataWrite { - if scmd.InSDBBuffer.Buffer != nil { - resp.Resid = scmd.InSDBBuffer.Resid - buf := scmd.InSDBBuffer.Buffer.Bytes() - resp.RawData = buf + if scmd.InSDBBuffer != nil { + conn.resp.Resid = scmd.InSDBBuffer.Resid + if conn.resp.Resid != 0 && conn.resp.Resid < scmd.InSDBBuffer.Length { + conn.resp.RawData = scmd.InSDBBuffer.Buffer[:conn.resp.Resid] + } else { + conn.resp.RawData = scmd.InSDBBuffer.Buffer + } } else { - resp.RawData = []byte{} + conn.resp.RawData = []byte{} } } case OpNoopIn, OpReject: - resp.OpCode = oc - resp.Final = true - resp.NSG = FullFeaturePhase - resp.ExpCmdSN = conn.req.CmdSN + 1 + conn.resp.OpCode = oc + conn.resp.Final = true + conn.resp.NSG = FullFeaturePhase + conn.resp.ExpCmdSN = conn.req.CmdSN + 1 case OpSCSITaskResp: - resp.OpCode = oc - resp.Final = true - resp.NSG = FullFeaturePhase - resp.ExpCmdSN = conn.req.CmdSN + 1 - resp.Result = task.result + conn.resp.OpCode = oc + conn.resp.Final = true + conn.resp.NSG = FullFeaturePhase + conn.resp.ExpCmdSN = conn.req.CmdSN + 1 + conn.resp.Result = task.result case OpLoginResp: - resp.OpCode = OpLoginResp - resp.Transit = conn.loginParam.tgtTrans - resp.CSG = conn.req.CSG - resp.NSG = conn.loginParam.tgtNSG - resp.ExpCmdSN = conn.req.CmdSN - resp.MaxCmdSN = conn.req.CmdSN + conn.resp.OpCode = OpLoginResp + conn.resp.Transit = conn.loginParam.tgtTrans + conn.resp.CSG = conn.req.CSG + conn.resp.NSG = conn.loginParam.tgtNSG + conn.resp.ExpCmdSN = conn.req.CmdSN + conn.resp.MaxCmdSN = conn.req.CmdSN negoKeys, err := conn.processLoginData() if err != nil { return err @@ -217,11 +219,10 @@ func (conn *iscsiConnection) buildRespPackage(oc OpCode, task *iscsiTask) error negoKeys = loginKVDeclare(conn, negoKeys) conn.loginParam.keyDeclared = true } - resp.RawData = util.MarshalKVText(negoKeys) + conn.resp.RawData = util.MarshalKVText(negoKeys) conn.txTask = nil } - conn.resp = resp return nil } diff --git a/pkg/port/iscsit/iscsid.go b/pkg/port/iscsit/iscsid.go index 1bb7c8f..e551b3d 100644 --- a/pkg/port/iscsit/iscsid.go +++ b/pkg/port/iscsit/iscsid.go @@ -17,7 +17,6 @@ limitations under the License. package iscsit import ( - "bytes" "fmt" "net" "os" @@ -29,6 +28,7 @@ import ( "github.com/gostor/gotgt/pkg/config" "github.com/gostor/gotgt/pkg/scsi" "github.com/gostor/gotgt/pkg/util" + "github.com/gostor/gotgt/pkg/util/pool" ) const ( @@ -156,7 +156,6 @@ func (s *ISCSITargetDriver) Run() error { log.Error(err) os.Exit(1) } - defer l.Close() for { log.Info("Listening ...") @@ -178,6 +177,7 @@ func (s *ISCSITargetDriver) Run() error { // start a new thread to do with this command go s.handler(DATAIN, iscsiConn) } + l.Close() return nil } @@ -203,6 +203,9 @@ func (s *ISCSITargetDriver) rxHandler(conn *iscsiConnection) { ddigest uint = 0 final bool = false cmd *ISCSICommand + buf []byte = make([]byte, BHS_SIZE) + length int + err error ) conn.readLock.Lock() defer conn.readLock.Unlock() @@ -214,7 +217,7 @@ func (s *ISCSITargetDriver) rxHandler(conn *iscsiConnection) { switch conn.rxIOState { case IOSTATE_RX_BHS: log.Debug("rx handler: IOSTATE_RX_BHS") - buf, length, err := conn.readData(BHS_SIZE) + length, err = conn.readData(buf) if err != nil { log.Error(err) return @@ -224,7 +227,6 @@ func (s *ISCSITargetDriver) rxHandler(conn *iscsiConnection) { conn.state = CONN_STATE_CLOSE return } - conn.rxBuffer = buf cmd, err = parseHeader(buf) if err != nil { log.Error(err) @@ -237,8 +239,10 @@ func (s *ISCSITargetDriver) rxHandler(conn *iscsiConnection) { conn.rxIOState = IOSTATE_RX_INIT_AHS break } - log.Debugf("got command: \n%s", cmd.String()) - log.Debugf("got buffer: %v", buf) + if log.GetLevel() == log.DebugLevel { + log.Debugf("got command: \n%s", cmd.String()) + log.Debugf("got buffer: %v", buf) + } final = true case IOSTATE_RX_INIT_AHS: conn.rxIOState = IOSTATE_RX_DATA @@ -254,16 +258,15 @@ func (s *ISCSITargetDriver) rxHandler(conn *iscsiConnection) { return } dl := ((cmd.DataLen + DataPadding - 1) / DataPadding) * DataPadding - buf := []byte{} + cmd.RawData = pool.NewBuffer(dl) length := 0 for length < dl { - b, l, err := conn.readData(dl - length) + l, err := conn.readData(cmd.RawData[length:]) if err != nil { log.Error(err) return } length += l - buf = append(buf, b...) } if length != dl { log.Debugf("get length is %d, but expected %d", length, dl) @@ -271,10 +274,7 @@ func (s *ISCSITargetDriver) rxHandler(conn *iscsiConnection) { conn.state = CONN_STATE_CLOSE return } - cmd.RawData = buf[:length] - conn.rxBuffer = append(conn.rxBuffer, buf...) final = true - log.Debugf("got command: \n%s", cmd.String()) default: log.Errorf("error %d %d\n", conn.state, conn.rxIOState) return @@ -474,10 +474,12 @@ SendRemainingData: for { switch conn.txIOState { case IOSTATE_TX_BHS: - log.Debug("ready to write response") - log.Debugf("response is %s", resp.String()) + if log.GetLevel() == log.DebugLevel { + log.Debug("ready to write response") + log.Debugf("response is %s", resp.String()) + } if l, err := conn.write(resp.Bytes()); err != nil { - log.Error(err) + log.Errorf("failed to write data to client: %v", err) return } else { conn.txIOState = IOSTATE_TX_INIT_AHS @@ -536,7 +538,7 @@ SendRemainingData: case CONN_STATE_SCSI: conn.txTask = nil default: - log.Warnf("unexpected connection state: %d", conn.state) + log.Warnf("unexpected connection state: %v", conn.State()) conn.rxIOState = IOSTATE_RX_BHS s.handler(DATAIN, conn) } @@ -547,21 +549,48 @@ func (s *ISCSITargetDriver) scsiCommandHandler(conn *iscsiConnection) (err error switch req.OpCode { case OpSCSICmd: log.Debugf("SCSI Command processing...") - scmd := &api.SCSICommand{} + scmd := &api.SCSICommand{ + ITNexusID: conn.session.ITNexus.ID, + SCB: req.CDB, + SCBLength: len(req.CDB), + Lun: req.LUN, + Tag: uint64(req.TaskTag), + RelTargetPortID: conn.session.TPGT, + } + if req.Read { + if req.Write { + scmd.Direction = api.SCSIDataBidirection + } else { + scmd.Direction = api.SCSIDataRead + } + } else { + if req.Write { + scmd.Direction = api.SCSIDataWrite + } + } + task := &iscsiTask{conn: conn, cmd: conn.req, tag: conn.req.TaskTag, scmd: scmd} if req.Write { - task.offset = req.DataLen task.r2tCount = int(req.ExpectedDataLen) - req.DataLen if !req.Final { task.unsolCount = 1 } + // new buffer for the data out + if scmd.OutSDBBuffer == nil { + blen := int(req.ExpectedDataLen) + if blen == 0 { + blen = int(req.DataLen) + } + scmd.OutSDBBuffer = &api.SCSIDataBuffer{ + Length: uint32(blen), + Buffer: pool.NewBuffer(blen), + } + } log.Debugf("SCSI write, R2T count: %d, unsol Count: %d, offset: %d", task.r2tCount, task.unsolCount, task.offset) - if task.scmd.OutSDBBuffer.Buffer == nil { - task.scmd.OutSDBBuffer.Buffer = bytes.NewBuffer([]byte{}) - } if conn.session.SessionParam[ISCSI_PARAM_IMM_DATA_EN].Value == 1 { - task.scmd.OutSDBBuffer.Buffer.Write(conn.req.RawData) + copy(scmd.OutSDBBuffer.Buffer[task.offset:], conn.req.RawData) + task.offset += conn.req.DataLen } if task.r2tCount > 0 { // prepare to receive more data @@ -579,6 +608,11 @@ func (s *ISCSITargetDriver) scsiCommandHandler(conn *iscsiConnection) (err error return nil } } + } else if scmd.InSDBBuffer == nil { + scmd.InSDBBuffer = &api.SCSIDataBuffer{ + Length: uint32(req.ExpectedDataLen), + Buffer: pool.NewBuffer(int(req.ExpectedDataLen)), + } } task.offset = 0 conn.rxTask = task @@ -616,9 +650,9 @@ func (s *ISCSITargetDriver) scsiCommandHandler(conn *iscsiConnection) (err error log.Error(err) return } - task.offset = task.offset + conn.req.DataLen + copy(task.scmd.OutSDBBuffer.Buffer[task.offset:], conn.req.RawData) + task.offset += conn.req.DataLen task.r2tCount = task.r2tCount - conn.req.DataLen - task.scmd.OutSDBBuffer.Buffer.Write(conn.req.RawData) log.Debugf("Final: %v", conn.req.Final) log.Debugf("r2tCount: %v", task.r2tCount) if !conn.req.Final { @@ -722,27 +756,7 @@ func (s *ISCSITargetDriver) iscsiExecTask(task *iscsiTask) error { cmd := task.cmd switch cmd.OpCode { case OpSCSICmd, OpSCSIOut: - if cmd.Read { - if cmd.Write { - task.scmd.Direction = api.SCSIDataBidirection - } else { - task.scmd.Direction = api.SCSIDataRead - } - } else { - if cmd.Write { - task.scmd.Direction = api.SCSIDataWrite - } - } - task.scmd.ITNexusID = task.conn.session.ITNexus.ID - task.scmd.SCB = bytes.NewBuffer(cmd.CDB) - task.scmd.SCBLength = len(cmd.CDB) - task.scmd.Lun = cmd.LUN - task.scmd.Tag = uint64(cmd.TaskTag) - task.scmd.RelTargetPortID = task.conn.session.TPGT task.state = taskSCSI - if task.scmd.OutSDBBuffer.Buffer == nil { - task.scmd.OutSDBBuffer.Buffer = bytes.NewBuffer(cmd.RawData) - } // add scsi target process queue err := s.SCSI.AddCommandQueue(task.conn.session.Target.SCSITarget.TID, task.scmd) if err != nil { diff --git a/pkg/scsi/backingstore.go b/pkg/scsi/backingstore.go index 1ee1172..7cf0315 100644 --- a/pkg/scsi/backingstore.go +++ b/pkg/scsi/backingstore.go @@ -24,6 +24,7 @@ import ( log "github.com/Sirupsen/logrus" "github.com/gostor/gotgt/pkg/api" "github.com/gostor/gotgt/pkg/util" + "github.com/gostor/gotgt/pkg/util/pool" ) type BaseBackingStore struct { @@ -53,16 +54,15 @@ func NewBackingStore(name string) (api.BackingStore, error) { func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error, key byte, asc SCSISubError) { var ( - scb = cmd.SCB.Bytes() - offset = cmd.Offset - opcode = api.SCSICommandType(scb[0]) - lu = cmd.Device - wbuf []byte = []byte{} - tl int64 = int64(cmd.TL) - rbuf = make([]byte, tl) - length int - doVerify bool = false - doWrite bool = false + scb = cmd.SCB + offset = cmd.Offset + opcode = api.SCSICommandType(scb[0]) + lu = cmd.Device + length int + doVerify bool = false + doWrite bool = false + rbuf, wbuf []byte + tl int64 = int64(cmd.TL) ) key = HARDWARE_ERROR asc = ASC_INTERNAL_TGT_FAILURE @@ -75,9 +75,10 @@ func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error, key asc = ASC_READ_ERROR break } - cmd.InSDBBuffer.Buffer = bytes.NewBuffer(tmpbuf) - - wbuf = cmd.OutSDBBuffer.Buffer.Bytes() + copy(cmd.InSDBBuffer.Buffer, tmpbuf) + if cmd.OutSDBBuffer != nil { + wbuf = cmd.OutSDBBuffer.Buffer + } doWrite = true goto write case api.COMPARE_AND_WRITE: @@ -91,14 +92,19 @@ func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error, key break case api.WRITE_VERIFY, api.WRITE_VERIFY_12, api.WRITE_VERIFY_16: doVerify = true + fallthrough case api.WRITE_6, api.WRITE_10, api.WRITE_12, api.WRITE_16: - wbuf = cmd.OutSDBBuffer.Buffer.Bytes() + // For stupid client which does not set WRITE flag + if cmd.OutSDBBuffer != nil { + wbuf = cmd.OutSDBBuffer.Buffer + } doWrite = true goto write case api.WRITE_SAME, api.WRITE_SAME_16: // TODO break case api.READ_6, api.READ_10, api.READ_12, api.READ_16: + rbuf = pool.NewBuffer(int(tl)) rbuf, err = bs.Read(int64(offset), tl) if err != nil && err != io.EOF { key = MEDIUM_ERROR @@ -113,7 +119,8 @@ func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error, key if (opcode != api.READ_6) && (scb[1]&0x10 != 0) { bs.DataAdvise(int64(offset), int64(length), util.POSIX_FADV_NOREUSE) } - cmd.InSDBBuffer.Buffer = bytes.NewBuffer(rbuf) + cmd.InSDBBuffer.Resid = uint32(length) + copy(cmd.InSDBBuffer.Buffer, rbuf) case api.PRE_FETCH_10, api.PRE_FETCH_16: err = bs.DataAdvise(int64(offset), tl, util.POSIX_FADV_WILLNEED) if err != nil { @@ -121,6 +128,10 @@ func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error, key asc = ASC_READ_ERROR } case api.VERIFY_10, api.VERIFY_12, api.VERIFY_16: + // For stupid client which does not set WRITE flag + if cmd.OutSDBBuffer != nil { + wbuf = cmd.OutSDBBuffer.Buffer + } doVerify = true goto verify case api.UNMAP: @@ -130,7 +141,6 @@ func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error, key } write: if doWrite { - // hack: wbuf = []byte("hello world!") err = bs.Write(wbuf, int64(offset)) if err != nil { log.Error(err) @@ -138,7 +148,7 @@ write: asc = ASC_READ_ERROR goto sense } - log.Debugf("write data at %d for length %d", offset, len(wbuf)) + log.Debugf("write data at 0x%x for length %d", offset, len(wbuf)) var pg *api.ModePage for _, p := range lu.ModePages { if p.PageCode == 0x08 && p.SubPageCode == 0 { @@ -165,14 +175,15 @@ write: } verify: if doVerify { + rbuf = pool.NewBuffer(int(tl)) rbuf, err = bs.Read(int64(offset), tl) if err != nil { key = MEDIUM_ERROR asc = ASC_READ_ERROR goto sense } - if !bytes.Equal(cmd.OutSDBBuffer.Buffer.Bytes(), rbuf) { - err = fmt.Errorf("verify fail between out buffer and read buffer") + if !bytes.Equal(wbuf, rbuf) { + err = fmt.Errorf("verify fail between out buffer[length=%d] and read buffer[length=%d]", len(wbuf), len(rbuf)) key = MISCOMPARE asc = ASC_MISCOMPARE_DURING_VERIFY_OPERATION goto sense diff --git a/pkg/scsi/lun.go b/pkg/scsi/lun.go index 23f2664..a7a8afa 100644 --- a/pkg/scsi/lun.go +++ b/pkg/scsi/lun.go @@ -83,7 +83,7 @@ func GetReservation(dev *api.SCSILu, nexusID uint64) *api.SCSIReservation { } func luPerformCommand(tid int, cmd *api.SCSICommand) api.SAMStat { - op := int(cmd.SCB.Bytes()[0]) + op := int(cmd.SCB[0]) fn := cmd.Device.DeviceProtocol.PerformCommand(op) if fn != nil { fnop := fn.(SCSIDeviceOperation) diff --git a/pkg/scsi/sbc.go b/pkg/scsi/sbc.go index 0a6179b..ad54aec 100644 --- a/pkg/scsi/sbc.go +++ b/pkg/scsi/sbc.go @@ -18,8 +18,6 @@ limitations under the License. package scsi import ( - "bytes" - "encoding/binary" "fmt" "unsafe" @@ -235,18 +233,11 @@ func SBCModeSense(host int, cmd *api.SCSICommand) api.SAMStat { deviceSpecific |= 0x80 } - buf := cmd.InSDBBuffer.Buffer - data := []byte{0x00, 0x00, 0x00, 0x00} - if buf != nil { - data = buf.Bytes() - } - - if cmd.SCB.Bytes()[0] == 0x1a { - data[2] = deviceSpecific + if cmd.SCB[0] == 0x1a { + cmd.InSDBBuffer.Buffer[2] = deviceSpecific } else { - data[3] = deviceSpecific + cmd.InSDBBuffer.Buffer[3] = deviceSpecific } - cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data) return api.SAMStatGood } @@ -284,15 +275,15 @@ func SBCFormatUnit(host int, cmd *api.SCSICommand) api.SAMStat { goto sense } - if cmd.SCB.Bytes()[1]&0x80 != 0 { + if cmd.SCB[1]&0x80 != 0 { // we dont support format protection information goto sense } - if cmd.SCB.Bytes()[1]&0x10 != 0 { + if cmd.SCB[1]&0x10 != 0 { // we dont support format data goto sense } - if cmd.SCB.Bytes()[1]&0x07 != 0 { + if cmd.SCB[1]&0x07 != 0 { // defect list format must be 0 goto sense } @@ -330,7 +321,7 @@ func SBCReadWrite(host int, cmd *api.SCSICommand) api.SAMStat { key = ILLEGAL_REQUEST asc = ASC_INVALID_FIELD_IN_CDB dev = cmd.Device - scb = cmd.SCB.Bytes() + scb = cmd.SCB opcode = api.SCSICommandType(scb[0]) lba uint64 tl uint32 @@ -353,9 +344,6 @@ func SBCReadWrite(host int, cmd *api.SCSICommand) api.SAMStat { log.Warnf("sense data(ILLEGAL_REQUEST,ASC_INVALID_FIELD_IN_CDB) encounter") goto sense } - if cmd.OutSDBBuffer.Buffer == nil { - cmd.OutSDBBuffer.Buffer = &bytes.Buffer{} - } case api.WRITE_SAME, api.WRITE_SAME_16: // We dont support resource-provisioning so ANCHOR bit == 1 is an error. if scb[1]&0x10 != 0 { @@ -482,10 +470,9 @@ func SBCRelease(host int, cmd *api.SCSICommand) api.SAMStat { */ func SBCReadCapacity(host int, cmd *api.SCSICommand) api.SAMStat { var ( - scb = cmd.SCB.Bytes() + scb = cmd.SCB key = ILLEGAL_REQUEST asc = ASC_LUN_NOT_SUPPORTED - data = &bytes.Buffer{} bshift = cmd.Device.BlockShift size = cmd.Device.Size >> bshift ) @@ -501,24 +488,21 @@ func SBCReadCapacity(host int, cmd *api.SCSICommand) api.SAMStat { goto sense } - /* - if cmd.InSDBBuffer.Length < 8 { - goto overflow - } - */ + if cmd.InSDBBuffer.Length < 8 { + goto overflow + } // data[0] = (size >> 32) ? __cpu_to_be32(0xffffffff) : __cpu_to_be32(size - 1); if size>>32 != 0 { - binary.Write(data, binary.BigEndian, uint32(0xffffffff)) + copy(cmd.InSDBBuffer.Buffer, util.MarshalUint32(uint32(0xffffffff))) } else { - binary.Write(data, binary.BigEndian, uint32(size-1)) + copy(cmd.InSDBBuffer.Buffer, util.MarshalUint32(uint32(size-1))) } // data[1] = __cpu_to_be32(1U << bshift); - binary.Write(data, binary.BigEndian, uint32(1<> bshift + bshift = cmd.Device.BlockShift + size = cmd.Device.Size >> bshift + allocationLength uint32 ) - data.Write(util.MarshalUint64(uint64(size - 1))) - binary.Write(data, binary.BigEndian, uint32(1< 12 { + copy(cmd.InSDBBuffer.Buffer[8:], util.MarshalUint32(uint32(1< 16 { + val := (cmd.Device.Attrs.Lbppbe << 16) | cmd.Device.Attrs.LowestAlignedLBA + copy(cmd.InSDBBuffer.Buffer[12:], util.MarshalUint32(uint32(val))) + } + } return api.SAMStatGood } @@ -621,7 +606,7 @@ func SBCGetLbaStatus(host int, cmd *api.SCSICommand) api.SAMStat { key = ILLEGAL_REQUEST asc = ASC_INVALID_FIELD_IN_CDB dev = cmd.Device - scb = cmd.SCB.Bytes() + scb = cmd.SCB lba uint64 tl uint32 ) @@ -631,14 +616,14 @@ func SBCGetLbaStatus(host int, cmd *api.SCSICommand) api.SAMStat { goto sense } - if cmd.SCB.Bytes()[1]&0xe0 != 0 { + if scb[1]&0xe0 != 0 { // We only support protection information type 0 key = ILLEGAL_REQUEST asc = ASC_INVALID_FIELD_IN_CDB goto sense } - if cmd.SCB.Bytes()[1]&0x02 == 0 { + if scb[1]&0x02 == 0 { // no data compare with the media return api.SAMStatGood } @@ -668,7 +653,7 @@ sense: } func SBCServiceAction(host int, cmd *api.SCSICommand) api.SAMStat { - opcode := api.SCSICommandType(cmd.SCB.Bytes()[1] & 0x1f) + opcode := api.SCSICommandType(cmd.SCB[1] & 0x1f) switch opcode { case api.READ_CAPACITY: return SBCReadCapacity(host, cmd) diff --git a/pkg/scsi/scsi.go b/pkg/scsi/scsi.go index 132d54c..4ebe293 100644 --- a/pkg/scsi/scsi.go +++ b/pkg/scsi/scsi.go @@ -80,7 +80,7 @@ func (s *SCSITargetService) AddCommandQueue(tid int, scmd *api.SCSICommand) erro lun := *(*uint64)(unsafe.Pointer(&scmd.Lun)) scmd.Device = target.Devices[lun] - log.Debugf("scsi opcode: 0x%x, LUN: %d", int(scmd.SCB.Bytes()[0]), binary.LittleEndian.Uint64(scmd.Lun[:])) + log.Debugf("scsi opcode: 0x%x, LUN: %d", int(scmd.SCB[0]), binary.LittleEndian.Uint64(scmd.Lun[:])) if scmd.Device == nil { scmd.Device = target.LUN0 @@ -91,6 +91,7 @@ func (s *SCSITargetService) AddCommandQueue(tid int, scmd *api.SCSICommand) erro return nil } } + result := scmd.Device.PerformCommand(tid, scmd) if result != api.SAMStatGood { scmd.Result = result.Stat @@ -125,7 +126,8 @@ func NewSCSIDeviceOperation(fn api.CommandFunc, sa []*SCSIServiceAction, pr uint func BuildSenseData(cmd *api.SCSICommand, key byte, asc SCSISubError) { senseBuffer := &bytes.Buffer{} - inBufLen, ok := SCSICDBBufXLength(cmd.SCB.Bytes()) + inBufLen, ok := SCSICDBBufXLength(cmd.SCB) + var length uint32 = 0xa if cmd.Device.Attrs.SenseFormat { // descriptor format @@ -134,10 +136,9 @@ func BuildSenseData(cmd *api.SCSICommand, key byte, asc SCSISubError) { senseBuffer.WriteByte(key) senseBuffer.WriteByte((byte(asc) >> 8) & 0xff) senseBuffer.WriteByte(byte(asc) & 0xff) - cmd.SenseLength = 8 + length = 8 } else { // fixed format - var length uint32 = 0xa // current, not deferred senseBuffer.WriteByte(0x70) senseBuffer.WriteByte(0x00) @@ -154,10 +155,10 @@ func BuildSenseData(cmd *api.SCSICommand, key byte, asc SCSISubError) { for i := 0; i < 4; i++ { senseBuffer.WriteByte(0x00) } - cmd.SenseLength = length + 8 + length += 8 } if ok { - if int64(len(senseBuffer.Bytes())) > inBufLen { + if int64(length) > inBufLen { log.Warnf("sense buffer is bigger than in buffer") senseBuffer.Truncate(int(inBufLen)) } @@ -165,7 +166,7 @@ func BuildSenseData(cmd *api.SCSICommand, key byte, asc SCSISubError) { log.Debugf("cannot calc cbd alloc length. truncate failed") } cmd.Result = key - cmd.SenseBuffer = senseBuffer + cmd.SenseBuffer = &api.SenseBuffer{senseBuffer.Bytes(), length} } func getSCSIReadWriteOffset(scb []byte) uint64 { diff --git a/pkg/scsi/spc.go b/pkg/scsi/spc.go index 88162db..cc1bc7e 100644 --- a/pkg/scsi/spc.go +++ b/pkg/scsi/spc.go @@ -204,7 +204,7 @@ func SPCInquiry(host int, cmd *api.SCSICommand) api.SAMStat { addBuf = &bytes.Buffer{} addBufData []byte = []byte{} //b byte = 0x75 - scb []byte = cmd.SCB.Bytes() + scb []byte = cmd.SCB pcode byte = scb[2] evpd bool = false @@ -227,22 +227,19 @@ func SPCInquiry(host int, cmd *api.SCSICommand) api.SAMStat { switch pcode { case 0x00: buf, _ = InquiryPage0x00(host, cmd) - case 0x80: buf, _ = InquiryPage0x80(host, cmd) - case 0x83: buf, _ = InquiryPage0x83(host, cmd) - default: goto sense } data = buf.Bytes() if int(allocationLength) < len(data) { - cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data[0:allocationLength]) + copy(cmd.InSDBBuffer.Buffer, data[0:allocationLength]) cmd.InSDBBuffer.Resid = uint32(len(data)) } else { - cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data[0:]) + copy(cmd.InSDBBuffer.Buffer, data[0:]) } } else { if pcode != 0 { @@ -304,9 +301,11 @@ func SPCInquiry(host int, cmd *api.SCSICommand) api.SAMStat { buf.Write(addBufData) data = buf.Bytes() if allocationLength < uint16(additionLength) { - cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data[0:allocationLength]) + cmd.InSDBBuffer.Resid = uint32(allocationLength) + copy(cmd.InSDBBuffer.Buffer, data[0:allocationLength]) } else { - cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data[0:]) + cmd.InSDBBuffer.Resid = uint32(len(data)) + copy(cmd.InSDBBuffer.Buffer, data[0:]) } } @@ -331,10 +330,9 @@ func SPCReportLuns(host int, cmd *api.SCSICommand) api.SAMStat { availLength uint32 = 0 allocationLength uint32 buf *bytes.Buffer = &bytes.Buffer{} - scb *bytes.Buffer = cmd.SCB ) // Get Allocation Length - allocationLength = util.GetUnalignedUint32(scb.Bytes()[6:10]) + allocationLength = util.GetUnalignedUint32(cmd.SCB[6:10]) if allocationLength < 16 { log.Warn("goto sense, allocationLength < 16") goto sense @@ -376,7 +374,7 @@ func SPCReportLuns(host int, cmd *api.SCSICommand) api.SAMStat { } } - cmd.InSDBBuffer.Buffer = buf + copy(cmd.InSDBBuffer.Buffer, buf.Bytes()) return api.SAMStatGood sense: cmd.InSDBBuffer.Resid = 0 @@ -393,7 +391,7 @@ func SPCStartStop(host int, cmd *api.SCSICommand) api.SAMStat { } cmd.InSDBBuffer.Resid = 0 - scb := cmd.SCB.Bytes() + scb := cmd.SCB pwrcnd = scb[4] & 0xf0 if pwrcnd != 0 { return api.SAMStatGood @@ -452,7 +450,7 @@ func SPCPreventAllowMediaRemoval(host int, cmd *api.SCSICommand) api.SAMStat { return api.SAMStatReservationConflict } // PREVENT_MASK = 0x03 - cmd.ITNexusLuInfo.Prevent = int(cmd.SCB.Bytes()[4] & 0x03) + cmd.ITNexusLuInfo.Prevent = int(cmd.SCB[4] & 0x03) return api.SAMStatGood } @@ -467,7 +465,7 @@ func SPCPreventAllowMediaRemoval(host int, cmd *api.SCSICommand) api.SAMStat { */ func SPCModeSense(host int, cmd *api.SCSICommand) api.SAMStat { var ( - scb = cmd.SCB.Bytes() + scb = cmd.SCB mode6 = (scb[0] == 0x1a) dbd = scb[1] & 0x8 // Disable Block Descriptors pcode = scb[2] & 0x3f @@ -574,7 +572,7 @@ func SPCModeSense(host int, cmd *api.SCSICommand) api.SAMStat { if rlen := uint32(len(data)); rlen < allocLen { cmd.InSDBBuffer.Resid = rlen } - cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data) + copy(cmd.InSDBBuffer.Buffer, data) return api.SAMStatGood sense: BuildSenseData(cmd, key, asc) @@ -591,7 +589,7 @@ sense: */ func SPCSendDiagnostics(host int, cmd *api.SCSICommand) api.SAMStat { // we only support SELF-TEST==1 - if cmd.SCB.Bytes()[1]&0x04 == 0 { + if cmd.SCB[1]&0x04 == 0 { goto sense } @@ -640,9 +638,8 @@ func reportOpcodesAll(cmd *api.SCSICommand, rctd int) error { } } } - buf := util.MarshalUint32(uint32(len(data) - 4)) - buf = append(buf, data[4:]...) - cmd.InSDBBuffer.Buffer = bytes.NewBuffer(buf) + copy(cmd.InSDBBuffer.Buffer, util.MarshalUint32(uint32(len(data)-4))) + copy(cmd.InSDBBuffer.Buffer[4:], data[4:]) return nil } @@ -651,7 +648,7 @@ func reportOpcodeOne(cmd *api.SCSICommand, rctd int, opcode byte, rsa uint16, se } func SPCReportSupportedOperationCodes(host int, cmd *api.SCSICommand) api.SAMStat { - scb := cmd.SCB.Bytes() + scb := cmd.SCB reporting_options := scb[2] & 0x07 opcode := scb[3] rctd := int(scb[2] & 0x80) @@ -692,54 +689,43 @@ sense: // This is useful for the various commands using the SERVICE ACTION format. func SPCServiceAction(host int, cmd *api.SCSICommand) api.SAMStat { - scb := cmd.SCB.Bytes() + scb := cmd.SCB opcode := int(scb[0]) action := uint8(scb[1] & 0x1F) serviceAction := cmd.Device.DeviceProtocol.PerformServiceAction(opcode, action) - if serviceAction == nil { - cmd.InSDBBuffer.Resid = 0 - BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB) - return api.SAMStatCheckCondition - } else { + if serviceAction != nil { fnop := serviceAction.(*SCSIServiceAction) return fnop.CommandPerformFunc(host, cmd) } + cmd.InSDBBuffer.Resid = 0 + BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB) + return api.SAMStatCheckCondition } func SPCPRReadKeys(host int, cmd *api.SCSICommand) api.SAMStat { var ( - buf = &bytes.Buffer{} - data []byte = []byte{} - addBuf = &bytes.Buffer{} + addBuf []byte = []byte{} allocationLength uint16 additionLength uint32 + l int = 0 ) tgtName := cmd.Target.Name devUUID := cmd.Device.UUID scsiResOp := GetSCSIReservationOperator() PRGeneration, _ := scsiResOp.GetPRGeneration(tgtName, devUUID) resList := scsiResOp.GetReservationList(tgtName, devUUID) - length, _ := SCSICDBBufXLength(cmd.SCB.Bytes()) - - allocationLength = uint16(length) if allocationLength < 8 { goto sense } for _, res := range resList { - addBuf.Write(util.MarshalUint64(res.Key)) + addBuf = append(addBuf, util.MarshalUint64(res.Key)...) } - additionLength = uint32(len(addBuf.Bytes())) + additionLength = uint32(len(addBuf)) - buf.Write(util.MarshalUint32(PRGeneration)) - buf.Write(util.MarshalUint32(additionLength)) - buf.Write(addBuf.Bytes()) - data = buf.Bytes() - if allocationLength < uint16(additionLength) { - cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data[0:allocationLength]) - } else { - cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data) - } + l += copy(cmd.InSDBBuffer.Buffer[l:], util.MarshalUint32(PRGeneration)) + l += copy(cmd.InSDBBuffer.Buffer[l:], util.MarshalUint32(additionLength)) + l += copy(cmd.InSDBBuffer.Buffer[l:], addBuf) cmd.InSDBBuffer.Resid = uint32(additionLength) return api.SAMStatGood @@ -763,7 +749,7 @@ func SPCPRReadReservation(host int, cmd *api.SCSICommand) api.SAMStat { PRGeneration, _ := scsiResOp.GetPRGeneration(tgtName, devUUID) curRes := scsiResOp.GetCurrentReservation(tgtName, devUUID) - length, _ := SCSICDBBufXLength(cmd.SCB.Bytes()) + length, _ := SCSICDBBufXLength(cmd.SCB) allocationLength = uint16(length) if allocationLength < 8 { goto sense @@ -791,9 +777,9 @@ func SPCPRReadReservation(host int, cmd *api.SCSICommand) api.SAMStat { buf.Write(addBuf.Bytes()) data = buf.Bytes() if allocationLength < uint16(additionLength) { - cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data[0:allocationLength]) + copy(cmd.InSDBBuffer.Buffer, data[0:allocationLength]) } else { - cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data) + copy(cmd.InSDBBuffer.Buffer, data) } cmd.InSDBBuffer.Resid = uint32(additionLength) @@ -807,40 +793,34 @@ sense: func SPCPRReportCapabilities(host int, cmd *api.SCSICommand) api.SAMStat { var ( - buf []byte = make([]byte, 8) - availLength uint32 = 8 - actualLength uint32 = 0 - data *bytes.Buffer = cmd.InSDBBuffer.Buffer + availLength uint32 = 8 + actualLength uint32 = 0 ) - allocationLength := uint32(util.GetUnalignedUint16(cmd.SCB.Bytes()[7:9])) + allocationLength := uint32(util.GetUnalignedUint16(cmd.SCB[7:9])) if allocationLength < 8 { goto sense } if cmd.InSDBBuffer.Length < allocationLength { goto sense } - binary.BigEndian.PutUint16(buf[0:2], uint16(8)) + copy(cmd.InSDBBuffer.Buffer, util.MarshalUint16(uint16(8))) // Persistent Reservation Type Mask format // Type Mask Valid (TMV) - buf[3] |= 0x80 + cmd.InSDBBuffer.Buffer[3] |= 0x80 // PR_TYPE_EXCLUSIVE_ACCESS_ALLREG - buf[4] |= 0x80 + cmd.InSDBBuffer.Buffer[4] |= 0x80 // PR_TYPE_EXCLUSIVE_ACCESS_REGONLY - buf[4] |= 0x40 + cmd.InSDBBuffer.Buffer[4] |= 0x40 // PR_TYPE_WRITE_EXCLUSIVE_REGONLY - buf[4] |= 0x20 + cmd.InSDBBuffer.Buffer[4] |= 0x20 // PR_TYPE_EXCLUSIVE_ACCESS - buf[4] |= 0x08 + cmd.InSDBBuffer.Buffer[4] |= 0x08 // PR_TYPE_WRITE_EXCLUSIVE - buf[4] |= 0x02 + cmd.InSDBBuffer.Buffer[4] |= 0x02 // PR_TYPE_EXCLUSIVE_ACCESS_ALLREG - buf[5] |= 0x01 + cmd.InSDBBuffer.Buffer[5] |= 0x01 - if err := binary.Write(data, binary.BigEndian, buf); err != nil { - goto sense - } else { - actualLength = availLength - } + actualLength = availLength cmd.InSDBBuffer.Resid = uint32(actualLength) return api.SAMStatGood sense: @@ -852,9 +832,9 @@ sense: func reservationCheck(host int, cmd *api.SCSICommand) bool { var ( paramLen uint32 - buf []byte = cmd.OutSDBBuffer.Buffer.Bytes() + buf []byte = cmd.OutSDBBuffer.Buffer ) - length, _ := SCSICDBBufXLength(cmd.SCB.Bytes()) + length, _ := SCSICDBBufXLength(cmd.SCB) paramLen = uint32(length) if paramLen != 24 { return false @@ -871,8 +851,8 @@ func reservationCheck(host int, cmd *api.SCSICommand) bool { func SPCPRRegister(host int, cmd *api.SCSICommand) api.SAMStat { var ( - buf []byte = cmd.OutSDBBuffer.Buffer.Bytes() - scb []byte = cmd.SCB.Bytes() + buf []byte = cmd.OutSDBBuffer.Buffer + scb []byte = cmd.SCB ignoreKey bool = false ok bool = false resKey uint64 @@ -930,7 +910,7 @@ sense: func SPCPRReserve(host int, cmd *api.SCSICommand) api.SAMStat { var ( - scb []byte = cmd.SCB.Bytes() + scb []byte = cmd.SCB curRes *api.SCSIReservation res *api.SCSIReservation ok bool = false @@ -992,8 +972,8 @@ sense: func SPCPRRelease(host int, cmd *api.SCSICommand) api.SAMStat { var ( - buf []byte = cmd.OutSDBBuffer.Buffer.Bytes() - scb []byte = cmd.SCB.Bytes() + buf []byte = cmd.OutSDBBuffer.Buffer + scb []byte = cmd.SCB curRes *api.SCSIReservation res *api.SCSIReservation resList []*api.SCSIReservation @@ -1073,7 +1053,7 @@ sense: func SPCPRClear(host int, cmd *api.SCSICommand) api.SAMStat { var ( - buf []byte = cmd.OutSDBBuffer.Buffer.Bytes() + buf []byte = cmd.OutSDBBuffer.Buffer curRes *api.SCSIReservation res *api.SCSIReservation ok bool = false @@ -1127,8 +1107,8 @@ sense: func SPCPRPreempt(host int, cmd *api.SCSICommand) api.SAMStat { var ( - buf []byte = cmd.OutSDBBuffer.Buffer.Bytes() - scb []byte = cmd.SCB.Bytes() + buf []byte = cmd.OutSDBBuffer.Buffer + scb []byte = cmd.SCB ok bool = false resKey uint64 sAResKey uint64 @@ -1227,8 +1207,8 @@ sense: func SPCPRRegisterAndMove(host int, cmd *api.SCSICommand) api.SAMStat { var ( - buf []byte = cmd.OutSDBBuffer.Buffer.Bytes() - scb []byte = cmd.SCB.Bytes() + buf []byte = cmd.OutSDBBuffer.Buffer + scb []byte = cmd.SCB resKey uint64 sAResKey uint64 curRes, dstReg, res *api.SCSIReservation @@ -1322,28 +1302,23 @@ func SPCRequestSense(host int, cmd *api.SCSICommand) api.SAMStat { var ( allocationLength uint32 actualLength uint32 - data = &bytes.Buffer{} ) - allocationLength = util.GetUnalignedUint32(cmd.SCB.Bytes()[4:8]) + allocationLength = util.GetUnalignedUint32(cmd.SCB[4:8]) if allocationLength > cmd.InSDBBuffer.Length { allocationLength = cmd.InSDBBuffer.Length } BuildSenseData(cmd, NO_SENSE, NO_ADDITIONAL_SENSE) - if cmd.SenseLength < allocationLength { - actualLength = cmd.SenseLength + if cmd.SenseBuffer.Length < allocationLength { + actualLength = cmd.SenseBuffer.Length } else { actualLength = allocationLength } - if cmd.SenseBuffer != nil { - data.Write(cmd.SenseBuffer.Bytes()[:actualLength]) - } + copy(cmd.InSDBBuffer.Buffer, cmd.SenseBuffer.Buffer[:actualLength]) cmd.InSDBBuffer.Resid = uint32(actualLength) - cmd.InSDBBuffer.Buffer = data // reset sense buffer in cmnd - cmd.SenseBuffer = &bytes.Buffer{} - cmd.SenseLength = 0 + cmd.SenseBuffer = &api.SenseBuffer{} return api.SAMStatGood } diff --git a/pkg/scsi/spc_test.go b/pkg/scsi/spc_test.go index d6779f6..4b47774 100644 --- a/pkg/scsi/spc_test.go +++ b/pkg/scsi/spc_test.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The GoStor Authors All rights reserved. +Copyright 2017 The GoStor Authors All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -35,26 +35,28 @@ func TestSPCReportLuns(t *testing.T) { target := new(api.SCSITarget) target.Devices = map[uint64]*api.SCSILu{0: lu} cmd.Target = target - cmd.SCB = &bytes.Buffer{} - cmd.SenseBuffer = &bytes.Buffer{} + scb := &bytes.Buffer{} + cmd.InSDBBuffer = &api.SCSIDataBuffer{} cmd.InSDBBuffer.Length = 16 - cmd.InSDBBuffer.Buffer = &bytes.Buffer{} - cmd.SCB.WriteByte(byte(api.REPORT_LUNS)) + cmd.InSDBBuffer.Buffer = []byte{} + scb.WriteByte(byte(api.REPORT_LUNS)) for i := 0; i < 5; i++ { - cmd.SCB.WriteByte(0x00) + scb.WriteByte(0x00) } - binary.Write(cmd.SCB, binary.BigEndian, uint32(16)) + binary.Write(scb, binary.BigEndian, uint32(16)) + cmd.SCB = scb.Bytes() if err := SPCReportLuns(0, cmd); err.Err != nil { t.Errorf("Expected not error, but got %v", err) } - cmd.SCB = &bytes.Buffer{} - cmd.SCB.WriteByte(byte(api.REPORT_LUNS)) + scb = &bytes.Buffer{} + scb.WriteByte(byte(api.REPORT_LUNS)) for i := 0; i < 5; i++ { - cmd.SCB.WriteByte(0x00) + scb.WriteByte(0x00) } - binary.Write(cmd.SCB, binary.BigEndian, uint32(10)) + binary.Write(scb, binary.BigEndian, uint32(10)) + cmd.SCB = scb.Bytes() if err := SPCReportLuns(0, cmd); err.Err == nil { t.Error("Expected error, but got nothing") } diff --git a/pkg/util/pool/pool.go b/pkg/util/pool/pool.go new file mode 100644 index 0000000..5e922a3 --- /dev/null +++ b/pkg/util/pool/pool.go @@ -0,0 +1,34 @@ +/* +Copyright 2017 The GoStor Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package pool provides memory pool for buffer. +package pool + +import "sync" + +var bytePool sync.Pool = sync.Pool{} + +func NewBuffer(size int) []byte { + bytePool.New = func() interface{} { + return make([]byte, size) + } + + return bytePool.Get().([]byte) +} + +func ReleaseBuffer(b []byte) { + bytePool.Put(b) +} diff --git a/pkg/util/util.go b/pkg/util/util.go index 4b74570..5ef830f 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -73,6 +73,15 @@ func MarshalKVText(kv []KeyValue) []byte { return data } +func MarshalUint16(i uint16) []byte { + var data []byte + for j := 8; j >= 0; j -= 8 { + b := byte(i >> uint16(j)) + data = append(data, b) + } + return data +} + func MarshalUint32(i uint32) []byte { var data []byte for j := 24; j >= 0; j -= 8 { @@ -82,13 +91,14 @@ func MarshalUint32(i uint32) []byte { return data } -func MarshalUint64(i uint64) []byte { - var data []byte +func MarshalUint64(v uint64) []byte { + var data = [8]byte{} + var i = 0 for j := 56; j >= 0; j -= 8 { - b := byte(i >> uint32(j)) - data = append(data, b) + data[i] = byte(v >> uint32(j)) + i++ } - return data + return data[0:8] } func StringToByte(str string, align int, maxlength int) []byte {