diff --git a/pkg/api/types.go b/pkg/api/types.go index 938478c..e0fcfcf 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.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. @@ -148,7 +148,7 @@ type SCSIDataBuffer struct { Buffer *bytes.Buffer Length uint32 TransferLength uint32 - Resid int32 + Resid uint32 } type SCSICommandState uint64 @@ -364,6 +364,7 @@ type ModePage struct { PageCode uint8 // Sub page code SubPageCode uint8 + Size uint8 // Rest of mode page info Data []byte } @@ -378,17 +379,18 @@ type SCSIReservation struct { } type SCSILu struct { - Address uint64 - Size uint64 - UUID uint64 - Path string - BsoFlags int - BlockShift uint - ReserveID uuid.UUID - Attrs SCSILuPhyAttribute - ModePages []ModePage - Storage BackingStore - DeviceProtocol SCSIDeviceProtocol + Address uint64 + Size uint64 + UUID uint64 + Path string + BsoFlags int + BlockShift uint + ReserveID uuid.UUID + Attrs SCSILuPhyAttribute + ModePages []ModePage + Storage BackingStore + DeviceProtocol SCSIDeviceProtocol + ModeBlockDescriptor []byte PerformCommand CommandFunc FinishCommand func(*SCSITarget, *SCSICommand) diff --git a/pkg/port/iscsit/cmd.go b/pkg/port/iscsit/cmd.go index d583eba..91789fd 100644 --- a/pkg/port/iscsit/cmd.go +++ b/pkg/port/iscsit/cmd.go @@ -94,6 +94,7 @@ type ISCSICommand struct { TaskTag uint32 ExpCmdSN, MaxCmdSN uint32 AHSLen int + Resid uint32 // Connection ID. ConnID uint16 @@ -278,7 +279,11 @@ func (m *ISCSICommand) scsiCmdRespBytes() []byte { // rfc7143 11.4 buf := &bytes.Buffer{} buf.WriteByte(byte(OpSCSIResp)) - buf.WriteByte(0x80) // 11.4.1 = wtf + var flag byte = 0x80 + if m.Resid > 0 { + flag |= 0x02 + } + buf.WriteByte(flag) buf.WriteByte(byte(m.SCSIResponse)) buf.WriteByte(byte(m.Status)) @@ -295,9 +300,10 @@ func (m *ISCSICommand) scsiCmdRespBytes() []byte { buf.Write(util.MarshalUint64(uint64(m.StatSN))[4:]) buf.Write(util.MarshalUint64(uint64(m.ExpCmdSN))[4:]) buf.Write(util.MarshalUint64(uint64(m.MaxCmdSN))[4:]) - for i := 0; i < 3*4; i++ { + for i := 0; i < 2*4; i++ { buf.WriteByte(0x00) } + buf.Write(util.MarshalUint64(uint64(m.Resid))[4:]) buf.Write(m.RawData) dl := len(m.RawData) for dl%4 > 0 { @@ -312,20 +318,22 @@ func (m *ISCSICommand) dataInBytes() []byte { // rfc7143 11.7 buf := &bytes.Buffer{} buf.WriteByte(byte(OpSCSIIn)) - var b byte - b = 0x0 + var flag byte if m.FinalInSeq || m.Final == true { - b |= 0x80 + flag |= 0x80 } if m.HasStatus && m.Final == true { - b |= 0x01 + flag |= 0x01 } - buf.WriteByte(b) + if m.Resid > 0 { + flag |= 0x02 + } + buf.WriteByte(flag) buf.WriteByte(0x00) if m.HasStatus && m.Final == true { - b = byte(m.Status) + flag = byte(m.Status) } - buf.WriteByte(b) + buf.WriteByte(flag) buf.WriteByte(0x00) // 4 @@ -344,9 +352,7 @@ func (m *ISCSICommand) dataInBytes() []byte { buf.Write(util.MarshalUint64(uint64(m.MaxCmdSN))[4:]) buf.Write(util.MarshalUint64(uint64(m.DataSN))[4:]) buf.Write(util.MarshalUint64(uint64(m.BufferOffset))[4:]) - for i := 0; i < 4; i++ { - buf.WriteByte(0x00) - } + 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 { diff --git a/pkg/port/iscsit/conn.go b/pkg/port/iscsit/conn.go index 2746281..657c2c0 100644 --- a/pkg/port/iscsit/conn.go +++ b/pkg/port/iscsit/conn.go @@ -182,6 +182,7 @@ func (conn *iscsiConnection) buildRespPackage(oc OpCode, task *iscsiTask) error resp.RawData = append(length[2:4], scmd.SenseBuffer.Bytes()...) } 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 } else { diff --git a/pkg/port/iscsit/iscsid.go b/pkg/port/iscsit/iscsid.go index 8c21c4e..ea26028 100644 --- a/pkg/port/iscsit/iscsid.go +++ b/pkg/port/iscsit/iscsid.go @@ -678,7 +678,7 @@ func (s *ISCSITargetDriver) iscsiTaskQueueHandler(task *iscsiTask) error { return s.iscsiExecTask(task) } cmdsn := cmd.CmdSN - log.Debugf("CmdSN of command is %d, ExpCmdSN of session is %d", cmdsn, sess.ExpCmdSN) + log.Debugf("CmdSN of command is %d", cmdsn) if cmdsn == sess.ExpCmdSN { retry: cmdsn += 1 diff --git a/pkg/scsi/sbc.go b/pkg/scsi/sbc.go index 9868f09..3dc1662 100644 --- a/pkg/scsi/sbc.go +++ b/pkg/scsi/sbc.go @@ -96,20 +96,25 @@ func (sbc SBCSCSIDeviceProtocol) InitLu(lu *api.SCSILu) error { } pages := []api.ModePage{} // Vendor uniq - However most apps seem to call for mode page 0 - pages = append(pages, api.ModePage{0, 0, []byte{}}) + //pages = append(pages, api.ModePage{0, 0, []byte{}}) // Disconnect page - pages = append(pages, api.ModePage{2, 0, []byte{0x80, 0x80, 0, 0xa, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}) + pages = append(pages, api.ModePage{2, 0, 14, []byte{0x80, 0x80, 0, 0xa, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}) // Caching Page - pages = append(pages, api.ModePage{8, 0, []byte{0x14, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, 0, 0, 0, 0}}) + pages = append(pages, api.ModePage{8, 0, 18, []byte{0x14, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, 0, 0, 0, 0, 0x4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}) // Control page - pages = append(pages, api.ModePage{0x0a, 0, []byte{2, 0x10, 0, 0, 0, 0, 0, 0, 2, 0}}) + pages = append(pages, api.ModePage{0x0a, 0, 10, []byte{2, 0x10, 0, 0, 0, 0, 0, 0, 2, 0, 0x08, 0, 0, 0, 0, 0, 0, 0}}) // Control Extensions mode page: TCMOS:1 - pages = append(pages, api.ModePage{0x0a, 1, []byte{0x04, 0x00, 0x00}}) + pages = append(pages, api.ModePage{0x0a, 1, 0x1c, []byte{0x04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}) // Informational Exceptions Control page - pages = append(pages, api.ModePage{0x1c, 0, []byte{8, 0, 0, 0, 0, 0, 0, 0, 0, 0}}) + pages = append(pages, api.ModePage{0x1c, 0, 10, []byte{8, 0, 0, 0, 0, 0, 0, 0, 0, 0}}) lu.ModePages = pages + mbd := util.MarshalUint32(uint32(0xffffffff)) + if size := lu.Size >> lu.BlockShift; size>>32 == 0 { + mbd = util.MarshalUint32(uint32(size)) + } + lu.ModeBlockDescriptor = append(mbd, util.MarshalUint32(uint32(1<> 6 subpcode = scb[3] blkDesctionLen = 0 key = ILLEGAL_REQUEST asc = ASC_INVALID_FIELD_IN_CDB + data []byte + allocLen uint32 + remainLen uint32 + i uint32 ) if dbd == 0 { blkDesctionLen = 8 @@ -489,11 +493,91 @@ func SPCModeSense(host int, cmd *api.SCSICommand) api.SAMStat { asc = ASC_SAVING_PARMS_UNSUP goto sense } - _ = dbd - _ = pcode - _ = subpcode - _ = mode6 - _ = blkDesctionLen + if mode6 { + allocLen = uint32(scb[4]) + // set header + for i = 0; i < 4 && i < allocLen; i++ { + data = append(data, 0x00) + } + } else { + allocLen = uint32(util.GetUnalignedUint16(scb[7:9])) + // set header + for i = 0; i < 8 && i < allocLen; i++ { + data = append(data, 0x00) + } + } + remainLen = allocLen - uint32(len(data)) + if dbd == 0 && remainLen >= 8 { + data = append(data, cmd.Device.ModeBlockDescriptor...) + } + if pcode == 0x3f { + for _, pg := range cmd.Device.ModePages { + if pg.SubPageCode == 0 { + if remainLen < 2+uint32(pg.Size) { + break + } + data = append(data, pg.PageCode) + data = append(data, pg.Size) + } else { + if remainLen < 4+uint32(pg.Size) { + break + } + data = append(data, pg.PageCode|0x40) + data = append(data, pg.SubPageCode) + data = append(data, (pg.Size>>8)&0xff) + data = append(data, pg.Size&0xff) + } + if pctrl == 1 { + data = append(data, pg.Data[pg.Size:]...) + } else { + data = append(data, pg.Data[:pg.Size]...) + } + } + } else { + var pg *api.ModePage + for _, p := range cmd.Device.ModePages { + if p.PageCode == pcode && p.SubPageCode == subpcode { + pg = &p + break + } + } + if pg == nil { + goto sense + } + if remainLen >= 2+uint32(pg.Size) { + if pg.SubPageCode == 0 { + data = append(data, pg.PageCode) + data = append(data, pg.Size) + if pctrl == 1 { + data = append(data, pg.Data[pg.Size:]...) + } else { + data = append(data, pg.Data[:pg.Size]...) + } + } else if remainLen >= 4+uint32(pg.Size) { + data = append(data, pg.PageCode|0x40) + data = append(data, pg.SubPageCode) + data = append(data, (pg.Size>>8)&0xff) + data = append(data, pg.Size&0xff) + if pctrl == 1 { + data = append(data, pg.Data[pg.Size:]...) + } else { + data = append(data, pg.Data[:pg.Size]...) + } + } + + } + } + if mode6 { + data[0] = uint8(len(data) - 1) + data[3] = uint8(blkDesctionLen) + } else { + data[0] = uint8((len(data) - 2) >> 8) + data[1] = uint8(len(data) - 2) + data[6] = uint8(blkDesctionLen >> 8) + data[7] = uint8(blkDesctionLen) + } + cmd.InSDBBuffer.Resid = uint32(len(data)) + cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data) return api.SAMStatGood sense: BuildSenseData(cmd, key, asc) @@ -660,7 +744,7 @@ func SPCPRReadKeys(host int, cmd *api.SCSICommand) api.SAMStat { cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data) } - cmd.InSDBBuffer.Resid = int32(additionLength) + cmd.InSDBBuffer.Resid = uint32(additionLength) return api.SAMStatGood sense: cmd.InSDBBuffer.Resid = 0 @@ -715,7 +799,7 @@ func SPCPRReadReservation(host int, cmd *api.SCSICommand) api.SAMStat { cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data) } - cmd.InSDBBuffer.Resid = int32(additionLength) + cmd.InSDBBuffer.Resid = uint32(additionLength) return api.SAMStatGood sense: @@ -760,7 +844,7 @@ func SPCPRReportCapabilities(host int, cmd *api.SCSICommand) api.SAMStat { } else { actualLength = availLength } - cmd.InSDBBuffer.Resid = int32(actualLength) + cmd.InSDBBuffer.Resid = uint32(actualLength) return api.SAMStatGood sense: cmd.InSDBBuffer.Resid = 0 @@ -1257,7 +1341,7 @@ func SPCRequestSense(host int, cmd *api.SCSICommand) api.SAMStat { if cmd.SenseBuffer != nil { data.Write(cmd.SenseBuffer.Bytes()[:actualLength]) } - cmd.InSDBBuffer.Resid = int32(actualLength) + cmd.InSDBBuffer.Resid = uint32(actualLength) cmd.InSDBBuffer.Buffer = data // reset sense buffer in cmnd