This commit is contained in:
Lei Xue
2017-07-31 21:47:38 +08:00
parent 957564305a
commit 4ae643e9f8
12 changed files with 258 additions and 221 deletions

View File

@@ -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,16 @@ 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)
scb = cmd.SCB
offset = cmd.Offset
opcode = api.SCSICommandType(scb[0])
lu = cmd.Device
length int
doVerify bool = false
doWrite bool = false
wbuf []byte
tl int64 = int64(cmd.TL)
rbuf []byte = pool.NewBuffer(int(tl))
)
key = HARDWARE_ERROR
asc = ASC_INTERNAL_TGT_FAILURE
@@ -75,9 +76,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,8 +93,12 @@ 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:
@@ -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:
@@ -138,7 +149,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 {
@@ -171,11 +182,14 @@ verify:
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
} else {
log.Warnf("%v", wbuf)
log.Warnf("%v", rbuf)
}
if scb[1]&0x10 != 0 {
bs.DataAdvise(int64(offset), int64(length), util.POSIX_FADV_WILLNEED)

View File

@@ -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)

View File

@@ -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))
//overflow:
copy(cmd.InSDBBuffer.Buffer[4:], util.MarshalUint32(uint32(1<<bshift)))
overflow:
cmd.InSDBBuffer.Resid = 8
cmd.InSDBBuffer.Buffer = data
return api.SAMStatGood
sense:
cmd.InSDBBuffer.Resid = 0
@@ -537,7 +521,7 @@ func SBCVerify(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
err error
@@ -548,14 +532,14 @@ func SBCVerify(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
}
@@ -587,7 +571,6 @@ func SBCVerify(host int, cmd *api.SCSICommand) api.SAMStat {
}
return api.SAMStatGood
sense:
cmd.InSDBBuffer.Resid = 0
BuildSenseData(cmd, key, asc)
return api.SAMStatCheckCondition
}
@@ -602,17 +585,19 @@ sense:
*/
func SBCReadCapacity16(host int, cmd *api.SCSICommand) api.SAMStat {
var (
data = &bytes.Buffer{}
bshift = cmd.Device.BlockShift
size = cmd.Device.Size >> 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<<bshift))
val := (cmd.Device.Attrs.Lbppbe << 16) | cmd.Device.Attrs.LowestAlignedLBA
data.Write(util.MarshalUint32(uint32(val)))
binary.Write(data, binary.BigEndian, uint64(0))
binary.Write(data, binary.BigEndian, uint64(0))
cmd.InSDBBuffer.Buffer = data
allocationLength = util.GetUnalignedUint32(cmd.SCB[10:14])
copy(cmd.InSDBBuffer.Buffer, util.MarshalUint64(uint64(size-1)))
if allocationLength > 12 {
copy(cmd.InSDBBuffer.Buffer[8:], util.MarshalUint32(uint32(1<<bshift)))
if allocationLength > 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)

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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")
}