fix some issues for SCSI command
This commit is contained in:
@@ -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");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -51,14 +51,12 @@ func NewBackingStore(name string) (api.BackingStore, error) {
|
|||||||
return f()
|
return f()
|
||||||
}
|
}
|
||||||
|
|
||||||
func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error) {
|
func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error, key byte, asc SCSISubError) {
|
||||||
var (
|
var (
|
||||||
scb = cmd.SCB.Bytes()
|
scb = cmd.SCB.Bytes()
|
||||||
offset = cmd.Offset
|
offset = cmd.Offset
|
||||||
opcode = api.SCSICommandType(scb[0])
|
opcode = api.SCSICommandType(scb[0])
|
||||||
lu = cmd.Device
|
lu = cmd.Device
|
||||||
key = ILLEGAL_REQUEST
|
|
||||||
asc = ASC_INVALID_FIELD_IN_CDB
|
|
||||||
wbuf []byte = []byte{}
|
wbuf []byte = []byte{}
|
||||||
tl int64 = int64(cmd.TL)
|
tl int64 = int64(cmd.TL)
|
||||||
rbuf = make([]byte, tl)
|
rbuf = make([]byte, tl)
|
||||||
@@ -66,6 +64,8 @@ func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error) {
|
|||||||
doVerify bool = false
|
doVerify bool = false
|
||||||
doWrite bool = false
|
doWrite bool = false
|
||||||
)
|
)
|
||||||
|
key = HARDWARE_ERROR
|
||||||
|
asc = ASC_INTERNAL_TGT_FAILURE
|
||||||
switch opcode {
|
switch opcode {
|
||||||
case api.ORWRITE_16:
|
case api.ORWRITE_16:
|
||||||
tmpbuf := []byte{}
|
tmpbuf := []byte{}
|
||||||
@@ -181,13 +181,13 @@ verify:
|
|||||||
bs.DataAdvise(int64(offset), int64(length), util.POSIX_FADV_WILLNEED)
|
bs.DataAdvise(int64(offset), int64(length), util.POSIX_FADV_WILLNEED)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil, key, asc
|
||||||
sense:
|
sense:
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
return err
|
return err, key, asc
|
||||||
}
|
}
|
||||||
|
|
||||||
err = fmt.Errorf("sense data encounter, key: %v, asc: %v", key, asc)
|
err = fmt.Errorf("sense data encounter, key: %v, asc: %v", key, asc)
|
||||||
return err
|
return err, key, asc
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
|||||||
+64
-22
@@ -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");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -339,14 +339,12 @@ func SBCReadWrite(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
case api.READ_10, api.READ_12, api.READ_16, api.WRITE_10, api.WRITE_12, api.WRITE_16, api.ORWRITE_16,
|
case api.READ_10, api.READ_12, api.READ_16, api.WRITE_10, api.WRITE_12, api.WRITE_16, api.ORWRITE_16,
|
||||||
api.WRITE_VERIFY, api.WRITE_VERIFY_12, api.WRITE_VERIFY_16, api.COMPARE_AND_WRITE:
|
api.WRITE_VERIFY, api.WRITE_VERIFY_12, api.WRITE_VERIFY_16, api.COMPARE_AND_WRITE:
|
||||||
// We only support protection information type 0
|
// We only support protection information type 0
|
||||||
/*
|
if scb[1]&0xe0 != 0 {
|
||||||
if scb[1]&0xe0 != 0 {
|
key = ILLEGAL_REQUEST
|
||||||
key = ILLEGAL_REQUEST
|
asc = ASC_INVALID_FIELD_IN_CDB
|
||||||
asc = ASC_INVALID_FIELD_IN_CDB
|
log.Warnf("sense data(ILLEGAL_REQUEST,ASC_INVALID_FIELD_IN_CDB) encounter")
|
||||||
log.Warnf("sense")
|
goto sense
|
||||||
goto sense
|
}
|
||||||
}
|
|
||||||
*/
|
|
||||||
if cmd.OutSDBBuffer.Buffer == nil {
|
if cmd.OutSDBBuffer.Buffer == nil {
|
||||||
cmd.OutSDBBuffer.Buffer = &bytes.Buffer{}
|
cmd.OutSDBBuffer.Buffer = &bytes.Buffer{}
|
||||||
}
|
}
|
||||||
@@ -384,7 +382,7 @@ func SBCReadWrite(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
api.PRE_FETCH_10, api.PRE_FETCH_16, api.COMPARE_AND_WRITE:
|
api.PRE_FETCH_10, api.PRE_FETCH_16, api.COMPARE_AND_WRITE:
|
||||||
key = DATA_PROTECT
|
key = DATA_PROTECT
|
||||||
asc = ASC_WRITE_PROTECT
|
asc = ASC_WRITE_PROTECT
|
||||||
log.Warnf("sense")
|
log.Warnf("sense data(data protect) and asc(ASC_WRITE_PROTECT) encounter")
|
||||||
goto sense
|
goto sense
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -397,14 +395,14 @@ func SBCReadWrite(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
if lba+uint64(tl) < lba || lba+uint64(tl) > dev.Size>>dev.BlockShift {
|
if lba+uint64(tl) < lba || lba+uint64(tl) > dev.Size>>dev.BlockShift {
|
||||||
key = ILLEGAL_REQUEST
|
key = ILLEGAL_REQUEST
|
||||||
asc = ASC_LBA_OUT_OF_RANGE
|
asc = ASC_LBA_OUT_OF_RANGE
|
||||||
log.Warnf("sense: lba: %d, tl: %d, size: %d", lba, tl, dev.Size>>dev.BlockShift)
|
log.Warnf("sense data(ILLEGAL_REQUEST,ASC_LBA_OUT_OF_RANGE) encounter: lba: %d, tl: %d, size: %d", lba, tl, dev.Size>>dev.BlockShift)
|
||||||
goto sense
|
goto sense
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if lba >= dev.Size>>dev.BlockShift {
|
if lba >= dev.Size>>dev.BlockShift {
|
||||||
key = ILLEGAL_REQUEST
|
key = ILLEGAL_REQUEST
|
||||||
asc = ASC_LBA_OUT_OF_RANGE
|
asc = ASC_LBA_OUT_OF_RANGE
|
||||||
log.Warnf("sense")
|
log.Warnf("sense data(ILLEGAL_REQUEST,ASC_LBA_OUT_OF_RANGE) encounter: lba: %d, size: %d", lba, dev.Size>>dev.BlockShift)
|
||||||
goto sense
|
goto sense
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -435,11 +433,9 @@ func SBCReadWrite(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
err = bsPerformCommand(dev.Storage, cmd)
|
err, key, asc = bsPerformCommand(dev.Storage, cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
goto sense
|
||||||
key = HARDWARE_ERROR
|
|
||||||
asc = ASC_INTERNAL_TGT_FAILURE
|
|
||||||
} else {
|
} else {
|
||||||
return api.SAMStatGood
|
return api.SAMStatGood
|
||||||
}
|
}
|
||||||
@@ -577,14 +573,11 @@ func SBCVerify(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
|
|
||||||
cmd.Offset = lba << dev.BlockShift
|
cmd.Offset = lba << dev.BlockShift
|
||||||
cmd.TL = tl << dev.BlockShift
|
cmd.TL = tl << dev.BlockShift
|
||||||
err = bsPerformCommand(dev.Storage, cmd)
|
err, key, asc = bsPerformCommand(dev.Storage, cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
goto sense
|
||||||
key = HARDWARE_ERROR
|
|
||||||
asc = ASC_INTERNAL_TGT_FAILURE
|
|
||||||
} else {
|
|
||||||
return api.SAMStatGood
|
|
||||||
}
|
}
|
||||||
|
return api.SAMStatGood
|
||||||
sense:
|
sense:
|
||||||
cmd.InSDBBuffer.Resid = 0
|
cmd.InSDBBuffer.Resid = 0
|
||||||
BuildSenseData(cmd, key, asc)
|
BuildSenseData(cmd, key, asc)
|
||||||
@@ -616,7 +609,54 @@ func SBCReadCapacity16(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func SBCGetLbaStatus(host int, cmd *api.SCSICommand) api.SAMStat {
|
func SBCGetLbaStatus(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||||
|
var (
|
||||||
|
key = ILLEGAL_REQUEST
|
||||||
|
asc = ASC_INVALID_FIELD_IN_CDB
|
||||||
|
dev = cmd.Device
|
||||||
|
scb = cmd.SCB.Bytes()
|
||||||
|
lba uint64
|
||||||
|
tl uint32
|
||||||
|
)
|
||||||
|
if dev.Attrs.Removable && !dev.Attrs.Online {
|
||||||
|
key = NOT_READY
|
||||||
|
asc = ASC_MEDIUM_NOT_PRESENT
|
||||||
|
goto sense
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmd.SCB.Bytes()[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 {
|
||||||
|
// no data compare with the media
|
||||||
|
return api.SAMStatGood
|
||||||
|
}
|
||||||
|
lba = getSCSIReadWriteOffset(scb)
|
||||||
|
tl = getSCSIReadWriteCount(scb)
|
||||||
|
// Verify that we are not doing i/o beyond the end-of-lun
|
||||||
|
if tl != 0 {
|
||||||
|
if lba+uint64(tl) < lba || lba+uint64(tl) > dev.Size>>dev.BlockShift {
|
||||||
|
key = ILLEGAL_REQUEST
|
||||||
|
asc = ASC_LBA_OUT_OF_RANGE
|
||||||
|
log.Warnf("sense: lba: %d, tl: %d, size: %d", lba, tl, dev.Size>>dev.BlockShift)
|
||||||
|
goto sense
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if lba >= dev.Size>>dev.BlockShift {
|
||||||
|
key = ILLEGAL_REQUEST
|
||||||
|
asc = ASC_LBA_OUT_OF_RANGE
|
||||||
|
log.Warnf("sense")
|
||||||
|
goto sense
|
||||||
|
}
|
||||||
|
}
|
||||||
return api.SAMStatGood
|
return api.SAMStatGood
|
||||||
|
sense:
|
||||||
|
cmd.InSDBBuffer.Resid = 0
|
||||||
|
BuildSenseData(cmd, key, asc)
|
||||||
|
return api.SAMStatCheckCondition
|
||||||
}
|
}
|
||||||
|
|
||||||
func SBCServiceAction(host int, cmd *api.SCSICommand) api.SAMStat {
|
func SBCServiceAction(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||||
@@ -626,6 +666,8 @@ func SBCServiceAction(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
return SBCReadCapacity(host, cmd)
|
return SBCReadCapacity(host, cmd)
|
||||||
case api.SAI_READ_CAPACITY_16:
|
case api.SAI_READ_CAPACITY_16:
|
||||||
return SBCReadCapacity16(host, cmd)
|
return SBCReadCapacity16(host, cmd)
|
||||||
|
case api.SAI_GET_LBA_STATUS:
|
||||||
|
return SBCGetLbaStatus(host, cmd)
|
||||||
}
|
}
|
||||||
return api.SAMStatGood
|
return api.SAMStatGood
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -149,8 +149,8 @@ func BuildSenseData(cmd *api.SCSICommand, key byte, asc SCSISubError) {
|
|||||||
for i := 0; i < 4; i++ {
|
for i := 0; i < 4; i++ {
|
||||||
senseBuffer.WriteByte(0x00)
|
senseBuffer.WriteByte(0x00)
|
||||||
}
|
}
|
||||||
senseBuffer.WriteByte((byte(asc) >> 8) & 0xff)
|
senseBuffer.WriteByte(byte((uint16(asc) >> 8) & 0xff))
|
||||||
senseBuffer.WriteByte(byte(asc) & 0xff)
|
senseBuffer.WriteByte(byte(asc & 0x00ff))
|
||||||
for i := 0; i < 4; i++ {
|
for i := 0; i < 4; i++ {
|
||||||
senseBuffer.WriteByte(0x00)
|
senseBuffer.WriteByte(0x00)
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -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");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -566,7 +566,7 @@ func reportOpcodesAll(cmd *api.SCSICommand, rctd int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func reportOpcodeOne(cmd *api.SCSICommand, rctd int, opcode byte, rsa uint16, serviceAction bool) error {
|
func reportOpcodeOne(cmd *api.SCSICommand, rctd int, opcode byte, rsa uint16, serviceAction bool) error {
|
||||||
return nil
|
return fmt.Errorf("non support")
|
||||||
}
|
}
|
||||||
|
|
||||||
func SPCReportSupportedOperationCodes(host int, cmd *api.SCSICommand) api.SAMStat {
|
func SPCReportSupportedOperationCodes(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||||
@@ -731,7 +731,7 @@ func SPCPRReportCapabilities(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
actualLength uint32 = 0
|
actualLength uint32 = 0
|
||||||
data *bytes.Buffer = cmd.InSDBBuffer.Buffer
|
data *bytes.Buffer = cmd.InSDBBuffer.Buffer
|
||||||
)
|
)
|
||||||
allocationLength := util.GetUnalignedUint32(cmd.SCB.Bytes()[7:9])
|
allocationLength := uint32(util.GetUnalignedUint16(cmd.SCB.Bytes()[7:9]))
|
||||||
if allocationLength < 8 {
|
if allocationLength < 8 {
|
||||||
goto sense
|
goto sense
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user