iSCSI/SCSI multi port/ALUA support
fix ALUA flag issue fix NNA flag issue fix fixed format sense data builder issue
This commit is contained in:
@@ -16,6 +16,10 @@ limitations under the License.
|
||||
|
||||
package scsi
|
||||
|
||||
import (
|
||||
"github.com/gostor/gotgt/pkg/util"
|
||||
)
|
||||
|
||||
type SCSIPRServiceAction byte
|
||||
type SCSIPRType byte
|
||||
|
||||
@@ -73,3 +77,39 @@ const (
|
||||
func SCSICDBGroupID(opcode byte) byte {
|
||||
return ((opcode >> 5) & 0x7)
|
||||
}
|
||||
|
||||
/*
|
||||
* Transfer Length (if any)
|
||||
* Parameter List Length (if any)
|
||||
* Allocation Length (if any)
|
||||
*/
|
||||
func SCSICDBBufXLength(scb []byte) (int64, bool) {
|
||||
var (
|
||||
opcode byte
|
||||
length int64
|
||||
group byte
|
||||
ok bool = true
|
||||
)
|
||||
opcode = scb[0]
|
||||
group = SCSICDBGroupID(opcode)
|
||||
|
||||
switch group {
|
||||
case CBD_GROUPID_0:
|
||||
length = int64(scb[4])
|
||||
case CBD_GROUPID_1, CBD_GROUPID_2:
|
||||
length = int64(util.GetUnalignedUint16(scb[7:9]))
|
||||
case CBD_GROUPID_3:
|
||||
if opcode == 0x7F {
|
||||
length = int64(scb[7])
|
||||
} else {
|
||||
ok = false
|
||||
}
|
||||
case CBD_GROUPID_4:
|
||||
length = int64(util.GetUnalignedUint32(scb[6:10]))
|
||||
case CBD_GROUPID_5:
|
||||
length = int64(util.GetUnalignedUint32(scb[10:14]))
|
||||
default:
|
||||
ok = false
|
||||
}
|
||||
return length, ok
|
||||
}
|
||||
|
||||
@@ -158,8 +158,8 @@ func NewSBCDevice(deviceType api.SCSIDeviceType) api.SCSIDeviceProtocol {
|
||||
|
||||
sbc.SCSIDeviceOps[api.MODE_SELECT_10] = NewSCSIDeviceOperation(SBCModeSelect, nil, PR_WE_FA|PR_EA_FA|PR_EA_FN|PR_WE_FN)
|
||||
sbc.SCSIDeviceOps[api.MODE_SENSE_10] = NewSCSIDeviceOperation(SBCModeSense, nil, PR_WE_FA|PR_WE_FN|PR_EA_FA|PR_EA_FN)
|
||||
sbc.SCSIDeviceOps[api.PERSISTENT_RESERVE_IN] = NewSCSIDeviceOperation(SPCServiceAction, nil, 0)
|
||||
sbc.SCSIDeviceOps[api.PERSISTENT_RESERVE_OUT] = NewSCSIDeviceOperation(SPCServiceAction, nil, 0)
|
||||
sbc.SCSIDeviceOps[api.PERSISTENT_RESERVE_IN] = NewSCSIDeviceOperation(SPCIllegalOp, nil, 0)
|
||||
sbc.SCSIDeviceOps[api.PERSISTENT_RESERVE_OUT] = NewSCSIDeviceOperation(SPCIllegalOp, nil, 0)
|
||||
|
||||
sbc.SCSIDeviceOps[api.READ_16] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_EA_FA|PR_EA_FN)
|
||||
sbc.SCSIDeviceOps[api.WRITE_16] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_EA_FA|PR_EA_FN|PR_WE_FA|PR_WE_FN)
|
||||
|
||||
@@ -124,6 +124,7 @@ func NewSCSIDeviceOperation(fn api.CommandFunc, sa *SCSIServiceAction, pr uint8)
|
||||
|
||||
func BuildSenseData(cmd *api.SCSICommand, key byte, asc SCSISubError) {
|
||||
senseBuffer := &bytes.Buffer{}
|
||||
inBufLen, ok := SCSICDBBufXLength(cmd.SCB.Bytes())
|
||||
|
||||
if cmd.Device.Attrs.SenseFormat {
|
||||
// descriptor format
|
||||
@@ -149,8 +150,19 @@ func BuildSenseData(cmd *api.SCSICommand, key byte, asc SCSISubError) {
|
||||
}
|
||||
senseBuffer.WriteByte((byte(asc) >> 8) & 0xff)
|
||||
senseBuffer.WriteByte(byte(asc) & 0xff)
|
||||
senseBuffer.WriteByte(0x00)
|
||||
senseBuffer.WriteByte(0x00)
|
||||
senseBuffer.WriteByte(0x00)
|
||||
senseBuffer.WriteByte(0x00)
|
||||
cmd.SenseLength = length + 8
|
||||
}
|
||||
if ok {
|
||||
if int64(len(senseBuffer.Bytes())) > inBufLen {
|
||||
senseBuffer.Truncate(int(inBufLen))
|
||||
}
|
||||
} else {
|
||||
glog.V(2).Infof("cannot calc cbd alloc length. truncate failed")
|
||||
}
|
||||
cmd.Result = key
|
||||
cmd.SenseBuffer = senseBuffer
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ func InitSCSILUMap(config *config.Config) error {
|
||||
globalSCSILUMap.AllDevices[bs.DeviceID] = lu
|
||||
}
|
||||
|
||||
for tgtName, tgt := range config.Targets {
|
||||
for tgtName, tgt := range config.ISCSITargets {
|
||||
for lunstr, deviceID := range tgt.LUNs {
|
||||
lun, err := strconv.ParseUint(lunstr, 10, 64)
|
||||
if err != nil {
|
||||
|
||||
@@ -122,8 +122,8 @@ const (
|
||||
INQUIRY_SCCS = byte(0x80)
|
||||
INQUIRY_AAC = byte(0x40)
|
||||
INQUIRY_TPGS_NO = byte(0x00)
|
||||
INQUIRY_TPGS_IMPLICIT = byte(0x20)
|
||||
INQUIRY_TPGS_EXPLICIT = byte(0x10)
|
||||
INQUIRY_TPGS_IMPLICIT = byte(0x10)
|
||||
INQUIRY_TPGS_EXPLICIT = byte(0x20)
|
||||
INQUIRY_TPGS_BOTH = byte(0x30)
|
||||
INQUIRY_3PC = byte(0x08)
|
||||
INQUIRY_Reserved = byte(0x06)
|
||||
@@ -189,11 +189,12 @@ const (
|
||||
|
||||
const (
|
||||
SCSI_VendorID = "GOSTOR"
|
||||
SCSI_ProductID = "GOTGT-VDISK"
|
||||
SCSI_ProductID = "GOTGT"
|
||||
)
|
||||
|
||||
func SPCIllegalOp(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
return api.SAMStatGood
|
||||
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
|
||||
return api.SAMStatCheckCondition
|
||||
}
|
||||
|
||||
func SPCLuOffline(lu *api.SCSILu) error {
|
||||
@@ -282,12 +283,16 @@ func InquiryPage0x83(host int, cmd *api.SCSICommand) (*bytes.Buffer, uint16) {
|
||||
buf = &bytes.Buffer{}
|
||||
descBuf = &bytes.Buffer{}
|
||||
data []byte = []byte{}
|
||||
pageLength uint16 = 0
|
||||
portName []byte
|
||||
pageLength uint16 = 0
|
||||
portID uint16 = cmd.RelTargetPortID
|
||||
portGroup uint16 = FindTargetGroup(cmd.Target, portID)
|
||||
targetPort *api.SCSITargetPort = FindTargetPort(cmd.Target, portID)
|
||||
)
|
||||
|
||||
//DESCRIPTOR 1 TARGET NAME
|
||||
descBuf.WriteByte((PIV_ISCSI << 4) | INQ_CODE_ASCII)
|
||||
descBuf.WriteByte(0x80 | ASS_TGT_PORT | DESG_VENDOR)
|
||||
descBuf.WriteByte(0x80 | (ASS_TGT_PORT << 4) | DESG_VENDOR)
|
||||
descBuf.WriteByte(0x00)
|
||||
//length
|
||||
descBuf.WriteByte(byte(len([]byte(cmd.Target.Name))))
|
||||
@@ -296,7 +301,7 @@ func InquiryPage0x83(host int, cmd *api.SCSICommand) (*bytes.Buffer, uint16) {
|
||||
|
||||
//DESCRIPTOR 2 NNA Locally
|
||||
descBuf.WriteByte((PIV_ISCSI << 4) | INQ_CODE_BIN)
|
||||
descBuf.WriteByte(0x80 | ASS_TGT_PORT | DESG_NAA)
|
||||
descBuf.WriteByte(0x80 | (ASS_LU << 4) | DESG_NAA)
|
||||
descBuf.WriteByte(0x00)
|
||||
//length
|
||||
descBuf.WriteByte(0x08)
|
||||
@@ -305,25 +310,37 @@ func InquiryPage0x83(host int, cmd *api.SCSICommand) (*bytes.Buffer, uint16) {
|
||||
|
||||
//TODO: Target Port Group(0x05), Relative Target port identifier(0x04)
|
||||
|
||||
/*
|
||||
//DESCRIPTOR 3 TPG
|
||||
descBuf.WriteByte((PIV_ISCSI << 4) | INQ_CODE_BIN)
|
||||
descBuf.WriteByte(0x80 | ASS_TGT_PORT | DESG_REL_TGT_PORT)
|
||||
descBuf.WriteByte(0x00)
|
||||
//length
|
||||
descBuf.WriteByte(0x08)
|
||||
//TPG
|
||||
binary.Write(descBuf, binary.BigEndian,)
|
||||
//DESCRIPTOR 3 TPG
|
||||
descBuf.WriteByte((PIV_ISCSI << 4) | INQ_CODE_BIN)
|
||||
descBuf.WriteByte(0x80 | (ASS_TGT_PORT << 4) | DESG_TGT_PORT_GRP)
|
||||
descBuf.WriteByte(0x00)
|
||||
//length
|
||||
descBuf.WriteByte(0x04)
|
||||
//TPG
|
||||
descBuf.WriteByte(0x00)
|
||||
descBuf.WriteByte(0x00)
|
||||
binary.Write(descBuf, binary.BigEndian, portGroup)
|
||||
|
||||
//DESCRIPTOR 4 RTPI
|
||||
descBuf.WriteByte((PIV_ISCSI << 4) | INQ_CODE_BIN)
|
||||
descBuf.WriteByte(0x80 | ASS_TGT_PORT | DESG_NAA)
|
||||
descBuf.WriteByte(0x00)
|
||||
//length
|
||||
descBuf.WriteByte(0x08)
|
||||
//RTPGI
|
||||
binary.Write(descBuf, binary.BigEndian,)
|
||||
*/
|
||||
//DESCRIPTOR 4 Relative Target Port ID
|
||||
descBuf.WriteByte((PIV_ISCSI << 4) | INQ_CODE_BIN)
|
||||
descBuf.WriteByte(0x80 | (ASS_TGT_PORT << 4) | DESG_REL_TGT_PORT)
|
||||
descBuf.WriteByte(0x00)
|
||||
//length
|
||||
descBuf.WriteByte(0x04)
|
||||
//RTPGI
|
||||
descBuf.WriteByte(0x00)
|
||||
descBuf.WriteByte(0x00)
|
||||
binary.Write(descBuf, binary.BigEndian, portID)
|
||||
|
||||
//DESCRIPTOR 5 SCSI Name,Port
|
||||
portName = util.StringToByte(targetPort.TargetPortName, 4, 256)
|
||||
descBuf.WriteByte((PIV_ISCSI << 4) | INQ_CODE_UTF8)
|
||||
descBuf.WriteByte(0x80 | (ASS_TGT_PORT << 4) | DESG_SCSI)
|
||||
descBuf.WriteByte(0x00)
|
||||
//length
|
||||
descBuf.WriteByte(byte(len(portName)))
|
||||
//RTPGI
|
||||
descBuf.Write(portName)
|
||||
|
||||
data = descBuf.Bytes()
|
||||
pageLength = uint16(len(data))
|
||||
@@ -395,7 +412,7 @@ func SPCInquiry(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
} else {
|
||||
//byte 5
|
||||
//SCCS(0) AAC(0) TPGS(0) 3PC(0) PROTECT(0)
|
||||
addBuf.WriteByte(0x00)
|
||||
addBuf.WriteByte(INQUIRY_TPGS_IMPLICIT)
|
||||
//byte 6
|
||||
//ENCSERV(0) VS(0) MULTIP(0) ADDR16(0)
|
||||
addBuf.WriteByte(0x00)
|
||||
|
||||
@@ -31,15 +31,40 @@ func (s *SCSITargetService) NewSCSITarget(tid int, driverName, name string) (*ap
|
||||
|
||||
// verify the low level driver
|
||||
var target = &api.SCSITarget{
|
||||
Name: name,
|
||||
TID: tid,
|
||||
Name: name,
|
||||
TID: tid,
|
||||
TargetPortGroups: []*api.TargetPortGroup{},
|
||||
}
|
||||
tpg := &api.TargetPortGroup{0, []*api.SCSITargetPort{}}
|
||||
s.Targets = append(s.Targets, target)
|
||||
target.Devices = GetTargetLUNMap(target.Name)
|
||||
target.LUN0 = NewLUN0()
|
||||
target.TargetPortGroups = append(target.TargetPortGroups, tpg)
|
||||
return target, nil
|
||||
}
|
||||
|
||||
func FindTargetGroup(target *api.SCSITarget, relPortID uint16) uint16 {
|
||||
for _, tpg := range target.TargetPortGroups {
|
||||
for _, port := range tpg.TargetPortGroup {
|
||||
if port.RelativeTargetPortID == relPortID {
|
||||
return tpg.GroupID
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func FindTargetPort(target *api.SCSITarget, relPortID uint16) *api.SCSITargetPort {
|
||||
for _, tpg := range target.TargetPortGroups {
|
||||
for _, port := range tpg.TargetPortGroup {
|
||||
if port.RelativeTargetPortID == relPortID {
|
||||
return port
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func deviceReserve(cmd *api.SCSICommand) error {
|
||||
var lu *api.SCSILu
|
||||
lun := *(*uint64)(unsafe.Pointer(&cmd.Lun))
|
||||
|
||||
Reference in New Issue
Block a user