@@ -193,6 +193,7 @@ type SCSITarget struct {
|
|||||||
LID int `json:"lid"`
|
LID int `json:"lid"`
|
||||||
State SCSITargetState `json:"state"`
|
State SCSITargetState `json:"state"`
|
||||||
Devices LUNMap `json:"-"`
|
Devices LUNMap `json:"-"`
|
||||||
|
LUN0 *SCSILu `json:"-"`
|
||||||
ITNexus []*ITNexus `json:"itnexus"`
|
ITNexus []*ITNexus `json:"itnexus"`
|
||||||
|
|
||||||
SCSITargetDriver interface{} `json:"-"`
|
SCSITargetDriver interface{} `json:"-"`
|
||||||
@@ -306,6 +307,7 @@ var (
|
|||||||
TYPE_RBC SCSIDeviceType = 0x0e
|
TYPE_RBC SCSIDeviceType = 0x0e
|
||||||
TYPE_OSD SCSIDeviceType = 0x11
|
TYPE_OSD SCSIDeviceType = 0x11
|
||||||
TYPE_NO_LUN SCSIDeviceType = 0x7f
|
TYPE_NO_LUN SCSIDeviceType = 0x7f
|
||||||
|
TYPE_UNKNOWN SCSIDeviceType = 0X1f
|
||||||
|
|
||||||
TYPE_PT SCSIDeviceType = 0xff
|
TYPE_PT SCSIDeviceType = 0xff
|
||||||
)
|
)
|
||||||
@@ -338,7 +340,7 @@ type ModePage struct {
|
|||||||
type SCSILu struct {
|
type SCSILu struct {
|
||||||
Address uint64
|
Address uint64
|
||||||
Size uint64
|
Size uint64
|
||||||
Lun uint64
|
UUID uint64
|
||||||
Path string
|
Path string
|
||||||
BsoFlags int
|
BsoFlags int
|
||||||
BlockShift uint
|
BlockShift uint
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import (
|
|||||||
* path format <protocol>:/absolute/file/path
|
* path format <protocol>:/absolute/file/path
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func NewSCSILu(device_uuid uint64, path string) (*api.SCSILu, error) {
|
func NewSCSILu(device_uuid uint64, path string, online bool) (*api.SCSILu, error) {
|
||||||
|
|
||||||
pathinfo := strings.SplitN(path, ":", 2)
|
pathinfo := strings.SplitN(path, ":", 2)
|
||||||
if len(pathinfo) < 2 {
|
if len(pathinfo) < 2 {
|
||||||
@@ -36,14 +36,13 @@ func NewSCSILu(device_uuid uint64, path string) (*api.SCSILu, error) {
|
|||||||
backendType := pathinfo[0]
|
backendType := pathinfo[0]
|
||||||
backendPath := pathinfo[1]
|
backendPath := pathinfo[1]
|
||||||
|
|
||||||
sbc := NewSBCDevice()
|
sbc := NewSBCDevice(api.TYPE_DISK)
|
||||||
backing, err := NewBackingStore(backendType)
|
backing, err := NewBackingStore(backendType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var lu = &api.SCSILu{
|
var lu = &api.SCSILu{
|
||||||
Lun: 0,
|
|
||||||
PerformCommand: luPerformCommand,
|
PerformCommand: luPerformCommand,
|
||||||
DeviceProtocol: sbc,
|
DeviceProtocol: sbc,
|
||||||
Storage: backing,
|
Storage: backing,
|
||||||
@@ -56,11 +55,29 @@ func NewSCSILu(device_uuid uint64, path string) (*api.SCSILu, error) {
|
|||||||
}
|
}
|
||||||
lu.Size = backing.Size(lu)
|
lu.Size = backing.Size(lu)
|
||||||
lu.DeviceProtocol.InitLu(lu)
|
lu.DeviceProtocol.InitLu(lu)
|
||||||
lu.Attrs.Online = true
|
lu.Attrs.Online = online
|
||||||
lu.Attrs.Lbppbe = 3
|
lu.Attrs.Lbppbe = 3
|
||||||
return lu, nil
|
return lu, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewLUN0() *api.SCSILu {
|
||||||
|
|
||||||
|
sbc := NewSBCDevice(api.TYPE_UNKNOWN)
|
||||||
|
backing, _ := NewBackingStore("null")
|
||||||
|
var lu = &api.SCSILu{
|
||||||
|
PerformCommand: luPerformCommand,
|
||||||
|
DeviceProtocol: sbc,
|
||||||
|
Storage: backing,
|
||||||
|
BlockShift: api.DefaultBlockShift,
|
||||||
|
}
|
||||||
|
|
||||||
|
lu.Size = backing.Size(lu)
|
||||||
|
lu.DeviceProtocol.InitLu(lu)
|
||||||
|
lu.Attrs.Online = false
|
||||||
|
lu.Attrs.Lbppbe = 3
|
||||||
|
return lu
|
||||||
|
}
|
||||||
|
|
||||||
func luPerformCommand(tid int, cmd *api.SCSICommand) api.SAMStat {
|
func luPerformCommand(tid int, cmd *api.SCSICommand) api.SAMStat {
|
||||||
op := int(cmd.SCB.Bytes()[0])
|
op := int(cmd.SCB.Bytes()[0])
|
||||||
fn := cmd.Device.DeviceProtocol.PerformCommand(op)
|
fn := cmd.Device.DeviceProtocol.PerformCommand(op)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ package scsi
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/gostor/gotgt/pkg/api"
|
"github.com/gostor/gotgt/pkg/api"
|
||||||
@@ -46,7 +46,7 @@ func (sbc SBCSCSIDeviceProtocol) PerformCommand(opcode int) interface{} {
|
|||||||
|
|
||||||
func (sbc SBCSCSIDeviceProtocol) InitLu(lu *api.SCSILu) error {
|
func (sbc SBCSCSIDeviceProtocol) InitLu(lu *api.SCSILu) error {
|
||||||
// init LU's phy attribute
|
// init LU's phy attribute
|
||||||
lu.Attrs.DeviceType = api.TYPE_DISK
|
lu.Attrs.DeviceType = sbc.DeviceType
|
||||||
lu.Attrs.Qualifier = false
|
lu.Attrs.Qualifier = false
|
||||||
lu.Attrs.Thinprovisioning = false
|
lu.Attrs.Thinprovisioning = false
|
||||||
lu.Attrs.Removable = false
|
lu.Attrs.Removable = false
|
||||||
@@ -54,13 +54,25 @@ func (sbc SBCSCSIDeviceProtocol) InitLu(lu *api.SCSILu) error {
|
|||||||
lu.Attrs.SWP = false
|
lu.Attrs.SWP = false
|
||||||
lu.Attrs.SenseFormat = false
|
lu.Attrs.SenseFormat = false
|
||||||
lu.Attrs.VendorID = "GOSTOR"
|
lu.Attrs.VendorID = "GOSTOR"
|
||||||
/*
|
|
||||||
lu.Attrs.SCSIID = fmt.Sprintf("GOSTOR %x%d", tgt.TID, lu.Lun)
|
|
||||||
lu.Attrs.SCSISN = fmt.Sprintf("beaf%d%d", tgt.TID, lu.Lun)
|
|
||||||
*/
|
|
||||||
lu.Attrs.SCSIID = fmt.Sprintf("GOSTOR%d", lu.Lun)
|
|
||||||
lu.Attrs.SCSISN = fmt.Sprintf("beaf%d", lu.Lun)
|
|
||||||
lu.Attrs.ProductID = "VIRTUAL-DISK"
|
lu.Attrs.ProductID = "VIRTUAL-DISK"
|
||||||
|
|
||||||
|
/*
|
||||||
|
SCSIID for PAGE83 T10 VENDOR IDENTIFICATION field
|
||||||
|
It is going to be the iSCSI target iqn name
|
||||||
|
leave it with a default target name
|
||||||
|
*/
|
||||||
|
|
||||||
|
lu.Attrs.SCSIID = "iqn.2016-09.com.gotgt.gostor:iscsi-tgt"
|
||||||
|
/*
|
||||||
|
The PRODUCT SERIAL NUMBER field contains
|
||||||
|
right-aligned ASCII data (see 4.3.1)
|
||||||
|
that is a vendor specific serial number.
|
||||||
|
If the product serial number is not available,
|
||||||
|
the device server shall return ASCII spaces (20h) in this field.
|
||||||
|
leave it with 4 spaces (20h)
|
||||||
|
*/
|
||||||
|
lu.Attrs.SCSISN = " "
|
||||||
|
|
||||||
lu.Attrs.VersionDesction = []uint16{
|
lu.Attrs.VersionDesction = []uint16{
|
||||||
0x04C0, // SBC-3 no version claimed
|
0x04C0, // SBC-3 no version claimed
|
||||||
0x0960, // iSCSI
|
0x0960, // iSCSI
|
||||||
@@ -104,10 +116,10 @@ func (sbc SBCSCSIDeviceProtocol) ExitLu(lu *api.SCSILu) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSBCDevice() api.SCSIDeviceProtocol {
|
func NewSBCDevice(deviceType api.SCSIDeviceType) api.SCSIDeviceProtocol {
|
||||||
var sbc = SBCSCSIDeviceProtocol{
|
var sbc = SBCSCSIDeviceProtocol{
|
||||||
BaseSCSIDeviceProtocol{
|
BaseSCSIDeviceProtocol{
|
||||||
Type: api.TYPE_DISK,
|
DeviceType: deviceType,
|
||||||
SCSIDeviceOps: []SCSIDeviceOperation{},
|
SCSIDeviceOps: []SCSIDeviceOperation{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -391,7 +403,8 @@ func SBCReserve(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func SBCRelease(host int, cmd *api.SCSICommand) api.SAMStat {
|
func SBCRelease(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||||
if err := deviceRelease(cmd.Target.TID, cmd.CommandITNID, cmd.Device.Lun, false); err != nil {
|
lun := *(*uint64)(unsafe.Pointer(&cmd.Lun))
|
||||||
|
if err := deviceRelease(cmd.Target.TID, cmd.CommandITNID, lun, false); err != nil {
|
||||||
return api.SAMStatReservationConflict
|
return api.SAMStatReservationConflict
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/gostor/gotgt/pkg/api"
|
"github.com/gostor/gotgt/pkg/api"
|
||||||
@@ -55,6 +56,7 @@ func (s *SCSITargetService) AddCommandQueue(tid int, scmd *api.SCSICommand) erro
|
|||||||
target *api.SCSITarget
|
target *api.SCSITarget
|
||||||
itn *api.ITNexus
|
itn *api.ITNexus
|
||||||
)
|
)
|
||||||
|
|
||||||
s.mutex.RLock()
|
s.mutex.RLock()
|
||||||
for _, t := range s.Targets {
|
for _, t := range s.Targets {
|
||||||
if t.TID == tid {
|
if t.TID == tid {
|
||||||
@@ -74,12 +76,20 @@ func (s *SCSITargetService) AddCommandQueue(tid int, scmd *api.SCSICommand) erro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
scmd.ITNexus = itn
|
scmd.ITNexus = itn
|
||||||
|
lun := *(*uint64)(unsafe.Pointer(&scmd.Lun))
|
||||||
|
scmd.Device = target.Devices[lun]
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO: scmd.Device = target.Devices[util.GetUnalignedUint64(scmd.Lun[:])]
|
|
||||||
*/
|
|
||||||
scmd.Device = target.Devices[0]
|
|
||||||
glog.V(2).Infof("scsi opcode: 0x%x, LUN: %d:", int(scmd.SCB.Bytes()[0]), binary.LittleEndian.Uint64(scmd.Lun[:]))
|
glog.V(2).Infof("scsi opcode: 0x%x, LUN: %d:", int(scmd.SCB.Bytes()[0]), binary.LittleEndian.Uint64(scmd.Lun[:]))
|
||||||
|
|
||||||
|
if scmd.Device == nil {
|
||||||
|
scmd.Device = target.LUN0
|
||||||
|
if lun != 0 {
|
||||||
|
BuildSenseData(scmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
|
||||||
|
scmd.Result = api.SAMStatCheckCondition.Stat
|
||||||
|
glog.Warningf("%v", api.SAMStatCheckCondition.Err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
result := scmd.Device.PerformCommand(tid, scmd)
|
result := scmd.Device.PerformCommand(tid, scmd)
|
||||||
if result != api.SAMStatGood {
|
if result != api.SAMStatGood {
|
||||||
scmd.Result = result.Stat
|
scmd.Result = result.Stat
|
||||||
@@ -100,7 +110,7 @@ type SCSIDeviceOperation struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type BaseSCSIDeviceProtocol struct {
|
type BaseSCSIDeviceProtocol struct {
|
||||||
Type api.SCSIDeviceType
|
DeviceType api.SCSIDeviceType
|
||||||
SCSIDeviceOps []SCSIDeviceOperation
|
SCSIDeviceOps []SCSIDeviceOperation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ func InitSCSILUMap(config *config.Config) error {
|
|||||||
defer globalSCSILUMap.mutex.Unlock()
|
defer globalSCSILUMap.mutex.Unlock()
|
||||||
|
|
||||||
for _, bs := range config.Storages {
|
for _, bs := range config.Storages {
|
||||||
lu, err := NewSCSILu(bs.DeviceID, bs.Path)
|
lu, err := NewSCSILu(bs.DeviceID, bs.Path, bs.Online)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("Init SCSI LU map error.")
|
return errors.New("Init SCSI LU map error.")
|
||||||
}
|
}
|
||||||
|
|||||||
130
pkg/scsi/spc.go
130
pkg/scsi/spc.go
@@ -21,8 +21,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/gostor/gotgt/pkg/api"
|
"github.com/gostor/gotgt/pkg/api"
|
||||||
@@ -55,6 +53,13 @@ const (
|
|||||||
PIV_ATA
|
PIV_ATA
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
VERSION_NOT_CLAIM = byte(0x00)
|
||||||
|
VERSION_WITHDRAW_STANDARD = byte(0x03)
|
||||||
|
VERSION_WITHDRAW_SPC2 = byte(0x04)
|
||||||
|
VERSION_WITHDRAW_SPC3 = byte(0x05)
|
||||||
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Code Set
|
* Code Set
|
||||||
*
|
*
|
||||||
@@ -62,7 +67,7 @@ const (
|
|||||||
* 2 - Designator field contains ASCII printable chars
|
* 2 - Designator field contains ASCII printable chars
|
||||||
* 3 - Designaotor field contains UTF-8
|
* 3 - Designaotor field contains UTF-8
|
||||||
*/
|
*/
|
||||||
type CodeSet int
|
type CodeSet byte
|
||||||
|
|
||||||
var (
|
var (
|
||||||
INQ_CODE_BIN CodeSet = 1
|
INQ_CODE_BIN CodeSet = 1
|
||||||
@@ -78,7 +83,7 @@ var (
|
|||||||
* 10b - Associated with SCSI Target device
|
* 10b - Associated with SCSI Target device
|
||||||
* 11b - Reserved
|
* 11b - Reserved
|
||||||
*/
|
*/
|
||||||
type AssociationField int
|
type AssociationField byte
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ASS_LU AssociationField = 0
|
ASS_LU AssociationField = 0
|
||||||
@@ -86,6 +91,56 @@ var (
|
|||||||
ASS_TGT_DEV AssociationField = 0x20
|
ASS_TGT_DEV AssociationField = 0x20
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Table 177 — PERIPHERAL QUALIFIER field
|
||||||
|
* Qualifier Description
|
||||||
|
* 000b - A peripheral device having the indicated peripheral
|
||||||
|
* device type is connected to this logical unit. If the device server is
|
||||||
|
* unable to determine whether or not a peripheral device is connected,
|
||||||
|
* then the device server also shall use this peripheral qualifier.
|
||||||
|
* This peripheral qualifier does not indicate that the peripheral
|
||||||
|
* device connected to the logical unit is ready for access.
|
||||||
|
* 001b - A peripheral device having the indicated peripheral device type
|
||||||
|
* is not connected to this logical unit. However, the device server is capable of
|
||||||
|
* supporting the indicated peripheral device type on this logical unit.
|
||||||
|
* 010b - Reserved
|
||||||
|
* 011b - The device server is not capable of supporting a
|
||||||
|
* peripheral device on this logical unit. For this peripheral
|
||||||
|
* qualifier the peripheral device type shall be set to 1Fh. All other peripheral
|
||||||
|
* device type values are reserved for this peripheral qualifier.
|
||||||
|
* 100b to 111b Vendor specific
|
||||||
|
*/
|
||||||
|
|
||||||
|
const (
|
||||||
|
PQ_DEVICE_CONNECTED = byte(0x00)
|
||||||
|
PQ_DEVICE_NOT_CONNECT = byte(0x01)
|
||||||
|
PQ_RESERVED = byte(0x02)
|
||||||
|
PQ_NOT_SUPPORT = byte(0x03)
|
||||||
|
)
|
||||||
|
|
||||||
|
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_BOTH = byte(0x30)
|
||||||
|
INQUIRY_3PC = byte(0x08)
|
||||||
|
INQUIRY_Reserved = byte(0x06)
|
||||||
|
INQUIRY_PROTECT = byte(0x01)
|
||||||
|
|
||||||
|
INQUIRY_NORM_ACA = byte(0x20)
|
||||||
|
INQUIRY_HISUP = byte(0x10)
|
||||||
|
INQUIRY_STANDARD_FORMAT = byte(0x02)
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ADDRESS_METHOD_PERIPHERAL_DEVICE = byte(0x00)
|
||||||
|
ADDRESS_METHOD_FLAT_SPACE = byte(0x01)
|
||||||
|
ADDRESS_METHOD_LOGICAL_UNIT = byte(0x02)
|
||||||
|
ADDRESS_METHOD_EXTENDED_LOGICAL_UNIT = byte(0x03)
|
||||||
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Designator type - SPC-4 Reference
|
* Designator type - SPC-4 Reference
|
||||||
*
|
*
|
||||||
@@ -123,7 +178,7 @@ func SPCLuOffline(lu *api.SCSILu) error {
|
|||||||
|
|
||||||
func SPCLuOnline(lu *api.SCSILu) error {
|
func SPCLuOnline(lu *api.SCSILu) error {
|
||||||
if luPreventRemoval(lu) {
|
if luPreventRemoval(lu) {
|
||||||
return fmt.Errorf("lu(%s) prevent removal", lu.Lun)
|
return fmt.Errorf("lu prevent removal")
|
||||||
}
|
}
|
||||||
|
|
||||||
lu.Attrs.Online = false
|
lu.Attrs.Online = false
|
||||||
@@ -142,14 +197,19 @@ func SPCInquiry(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
if scb[1]&0x01 > 0 {
|
if scb[1]&0x01 > 0 {
|
||||||
evpd = true
|
evpd = true
|
||||||
}
|
}
|
||||||
if reflect.DeepEqual(util.MarshalUint64(cmd.Device.Lun)[0:7], cmd.Lun[0:7]) {
|
|
||||||
|
if cmd.Device == nil {
|
||||||
b = (uint8(0) & 0x7) << 5
|
b = (uint8(0) & 0x7) << 5
|
||||||
b |= uint8(0) & 0x1f
|
b |= uint8(0) & 0x1f
|
||||||
}
|
|
||||||
glog.V(2).Infof("%v, %v", cmd.Device.Lun, *(*uint64)(unsafe.Pointer(&cmd.Lun)))
|
|
||||||
if cmd.Device.Lun != *(*uint64)(unsafe.Pointer(&cmd.Lun)) {
|
|
||||||
goto sense
|
goto sense
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cmd.Device.Attrs.Online {
|
||||||
|
b = (byte(PQ_DEVICE_CONNECTED) << 5) | byte(cmd.Device.Attrs.DeviceType)
|
||||||
|
} else {
|
||||||
|
b = (byte(PQ_DEVICE_NOT_CONNECT) << 5) | byte(cmd.Device.Attrs.DeviceType)
|
||||||
|
}
|
||||||
|
|
||||||
if evpd {
|
if evpd {
|
||||||
if pcode == 0x0 {
|
if pcode == 0x0 {
|
||||||
buf.WriteByte(b)
|
buf.WriteByte(b)
|
||||||
@@ -179,19 +239,22 @@ func SPCInquiry(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
buf.WriteByte(b)
|
buf.WriteByte(b)
|
||||||
b = 0
|
// RMB(0) LU_CONG(0)
|
||||||
buf.WriteByte(b)
|
buf.WriteByte(0x00)
|
||||||
buf.WriteByte(byte(1))
|
// version byte
|
||||||
b = 0x02
|
buf.WriteByte(VERSION_WITHDRAW_SPC3)
|
||||||
buf.WriteByte(b)
|
|
||||||
|
// Reserved, Reserved, NORMACA, HISUP, RESPONSE DATA FORMAT
|
||||||
|
buf.WriteByte(INQUIRY_HISUP | INQUIRY_STANDARD_FORMAT)
|
||||||
|
// ADDITIONAL LENGTH
|
||||||
buf.WriteByte(0x00)
|
buf.WriteByte(0x00)
|
||||||
// byte 5
|
// byte 5
|
||||||
b = 0
|
/*
|
||||||
b |= byte(1) << 4 & 0x30
|
* SCCS(0) AAC(0) TPGS(0) 3PC(0) PROTECT(0)
|
||||||
buf.WriteByte(b)
|
*/
|
||||||
|
buf.WriteByte(0x00)
|
||||||
// byte 6
|
// byte 6
|
||||||
b = 0
|
buf.WriteByte(0x00)
|
||||||
buf.WriteByte(b)
|
|
||||||
buf.WriteByte(0x02)
|
buf.WriteByte(0x02)
|
||||||
buf.Write([]byte{'1', '1', 'c', 'a', 'n', 's'})
|
buf.Write([]byte{'1', '1', 'c', 'a', 'n', 's'})
|
||||||
buf.WriteByte(0x00)
|
buf.WriteByte(0x00)
|
||||||
@@ -227,30 +290,43 @@ func SPCReportLuns(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
glog.Warningf("goto sense, allocationLength < 16")
|
glog.Warningf("goto sense, allocationLength < 16")
|
||||||
goto sense
|
goto sense
|
||||||
}
|
}
|
||||||
remainLength = allocationLength - 8
|
|
||||||
availLength = 8 * uint32(len(cmd.Target.Devices))
|
remainLength = allocationLength
|
||||||
|
if _, ok := cmd.Target.Devices[0]; !ok {
|
||||||
|
availLength = 8 * uint32(len(cmd.Target.Devices)+1)
|
||||||
|
} else {
|
||||||
|
availLength = 8 * uint32(len(cmd.Target.Devices))
|
||||||
|
}
|
||||||
|
|
||||||
|
// LUN list length
|
||||||
buf.Write(util.MarshalUint32(availLength))
|
buf.Write(util.MarshalUint32(availLength))
|
||||||
cmd.InSDBBuffer.Resid = int32(actualLength)
|
cmd.InSDBBuffer.Resid = int32(actualLength)
|
||||||
|
|
||||||
// Skip through to byte 8, Reserved
|
// Skip through to byte 8, Reserved
|
||||||
for i := 0; i < 4; i++ {
|
for i := 0; i < 4; i++ {
|
||||||
buf.WriteByte(0x00)
|
buf.WriteByte(0x00)
|
||||||
}
|
}
|
||||||
|
|
||||||
for lunumber, lu := range cmd.Target.Devices {
|
//For LUN0
|
||||||
glog.V(2).Infof("LUN: ", lunumber)
|
if _, ok := cmd.Target.Devices[0]; !ok {
|
||||||
|
buf.Write(util.MarshalUint64(0))
|
||||||
|
remainLength -= 8
|
||||||
|
}
|
||||||
|
|
||||||
|
for lun := range cmd.Target.Devices {
|
||||||
if remainLength > 0 {
|
if remainLength > 0 {
|
||||||
lun := lu.Lun
|
|
||||||
if lun > 0xff {
|
if lun > 0xff {
|
||||||
lun = 0x1 << 30
|
lun = (0x01 << 30) | (0x3fff&lun)<<16
|
||||||
} else {
|
} else {
|
||||||
lun = 0
|
lun = (0x3fff & lun) << 16
|
||||||
}
|
}
|
||||||
lun = (0x3fff & lun) << 16
|
|
||||||
lun = uint64(lun << 32)
|
lun = uint64(lun << 32)
|
||||||
|
|
||||||
buf.Write(util.MarshalUint64(lun))
|
buf.Write(util.MarshalUint64(lun))
|
||||||
remainLength -= 8
|
remainLength -= 8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.InSDBBuffer.Buffer = buf
|
cmd.InSDBBuffer.Buffer = buf
|
||||||
return api.SAMStatGood
|
return api.SAMStatGood
|
||||||
sense:
|
sense:
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ func TestSPCReportLuns(t *testing.T) {
|
|||||||
cmd.Device = device
|
cmd.Device = device
|
||||||
lu := new(api.SCSILu)
|
lu := new(api.SCSILu)
|
||||||
target := new(api.SCSITarget)
|
target := new(api.SCSITarget)
|
||||||
target.Devices = map[uint64]*api.SCSILu{lu.Lun: lu}
|
target.Devices = map[uint64]*api.SCSILu{0: lu}
|
||||||
cmd.Target = target
|
cmd.Target = target
|
||||||
cmd.SCB = &bytes.Buffer{}
|
cmd.SCB = &bytes.Buffer{}
|
||||||
cmd.SenseBuffer = &bytes.Buffer{}
|
cmd.SenseBuffer = &bytes.Buffer{}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package scsi
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/gostor/gotgt/pkg/api"
|
"github.com/gostor/gotgt/pkg/api"
|
||||||
@@ -35,20 +36,22 @@ func (s *SCSITargetService) NewSCSITarget(tid int, driverName, name string) (*ap
|
|||||||
}
|
}
|
||||||
s.Targets = append(s.Targets, target)
|
s.Targets = append(s.Targets, target)
|
||||||
target.Devices = GetTargetLUNMap(target.Name)
|
target.Devices = GetTargetLUNMap(target.Name)
|
||||||
|
target.LUN0 = NewLUN0()
|
||||||
return target, nil
|
return target, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func deviceReserve(cmd *api.SCSICommand) error {
|
func deviceReserve(cmd *api.SCSICommand) error {
|
||||||
var lu *api.SCSILu
|
var lu *api.SCSILu
|
||||||
for _, dev := range cmd.Target.Devices {
|
lun := *(*uint64)(unsafe.Pointer(&cmd.Lun))
|
||||||
if dev.Lun == cmd.Device.Lun {
|
|
||||||
lu = dev
|
for tgtLUN, lunDev := range cmd.Target.Devices {
|
||||||
|
if tgtLUN == lun {
|
||||||
|
lu = lunDev
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if lu == nil {
|
if lu == nil {
|
||||||
glog.Errorf("invalid target and lun %d %s", cmd.Target.TID, cmd.Device.Lun)
|
glog.Errorf("invalid target and lun %d %s", cmd.Target.TID, lun)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,8 +74,8 @@ func MarshalKVText(kv []KeyValue) []byte {
|
|||||||
|
|
||||||
func MarshalUint32(i uint32) []byte {
|
func MarshalUint32(i uint32) []byte {
|
||||||
var data []byte
|
var data []byte
|
||||||
for j := 0; j < 4; j++ {
|
for j := 24; j >= 0; j -= 8 {
|
||||||
b := byte(i >> uint(4*(3-j)) & 0xff)
|
b := byte(i >> uint32(j))
|
||||||
data = append(data, b)
|
data = append(data, b)
|
||||||
}
|
}
|
||||||
return data
|
return data
|
||||||
@@ -83,8 +83,8 @@ func MarshalUint32(i uint32) []byte {
|
|||||||
|
|
||||||
func MarshalUint64(i uint64) []byte {
|
func MarshalUint64(i uint64) []byte {
|
||||||
var data []byte
|
var data []byte
|
||||||
for j := 0; j < 8; j++ {
|
for j := 56; j >= 0; j -= 8 {
|
||||||
b := byte(i >> uint(8*(7-j)) & 0xff)
|
b := byte(i >> uint32(j))
|
||||||
data = append(data, b)
|
data = append(data, b)
|
||||||
}
|
}
|
||||||
return data
|
return data
|
||||||
|
|||||||
Reference in New Issue
Block a user