Merge pull request #19 from orzhang/dummy_lun0

1) add dummy lun0
This commit is contained in:
Lei Xue
2016-10-08 16:14:34 +08:00
committed by GitHub
9 changed files with 180 additions and 59 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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