run the basic process with iscsi driver

This commit is contained in:
Lei Xue
2016-05-02 22:11:33 +08:00
parent d770eb33ac
commit c5d68b38b2
17 changed files with 948 additions and 633 deletions

58
citd.go
View File

@@ -19,13 +19,69 @@ package main
import (
"net"
"os"
"reflect"
"github.com/golang/glog"
"github.com/gostor/gotgt/pkg/api"
"github.com/gostor/gotgt/pkg/scsi"
)
func main() {
_, err := net.Listen("tcp", ":3260")
l, err := net.Listen("tcp", ":3260")
if err != nil {
glog.Error(err)
os.Exit(1)
}
defer l.Close()
t, err := scsi.NewTarget(0, "iscsi", "test-iscsi-target")
if err != nil {
glog.Error(err)
os.Exit(1)
}
conns := make(map[string]net.Conn)
for {
glog.Info("Listening ...")
conn, err := l.Accept()
checkError(err, "Accept")
glog.Info("Accepting ...")
conns[conn.RemoteAddr().String()] = conn
// start a new thread to do with this command
go Handler(conn, t)
}
}
func checkError(err error, info string) (res bool) {
if err != nil {
glog.Error(info + " " + err.Error())
return false
}
return true
}
func Handler(conn net.Conn, tgt *api.SCSITarget) {
glog.Infof("connection is connected from %s...\n", conn.RemoteAddr().String())
buf := make([]byte, 1024)
for {
lenght, err := conn.Read(buf)
if checkError(err, "Connection") == false {
conn.Close()
break
}
if lenght > 0 {
buf[lenght] = 0
}
v := reflect.ValueOf(tgt.SCSITargetDriver)
iscsit := v.MethodByName("ProcessCommand")
in := make([]reflect.Value, 1)
in[0] = reflect.ValueOf(buf[0:lenght])
res := iscsit.Call(in)[0]
b := res.Bytes()
glog.Infof("%s\n", string(b))
conn.Write(b)
}
}

307
pkg/api/types.go Normal file
View File

@@ -0,0 +1,307 @@
package api
import (
"bytes"
"errors"
)
type SCSICommandType byte
var (
TEST_UNIT_READY SCSICommandType = 0x00
REZERO_UNIT SCSICommandType = 0x01
REQUEST_SENSE SCSICommandType = 0x03
FORMAT_UNIT SCSICommandType = 0x04
READ_BLOCK_LIMITS SCSICommandType = 0x05
REASSIGN_BLOCKS SCSICommandType = 0x07
INITIALIZE_ELEMENT_STATUS SCSICommandType = 0x07
READ_6 SCSICommandType = 0x08
WRITE_6 SCSICommandType = 0x0a
SEEK_6 SCSICommandType = 0x0b
READ_REVERSE SCSICommandType = 0x0f
WRITE_FILEMARKS SCSICommandType = 0x10
SPACE SCSICommandType = 0x11
INQUIRY SCSICommandType = 0x12
RECOVER_BUFFERED_DATA SCSICommandType = 0x14
MODE_SELECT SCSICommandType = 0x15
RESERVE SCSICommandType = 0x16
RELEASE SCSICommandType = 0x17
COPY SCSICommandType = 0x18
ERASE SCSICommandType = 0x19
MODE_SENSE SCSICommandType = 0x1a
START_STOP SCSICommandType = 0x1b
RECEIVE_DIAGNOSTIC SCSICommandType = 0x1c
SEND_DIAGNOSTIC SCSICommandType = 0x1d
ALLOW_MEDIUM_REMOVAL SCSICommandType = 0x1e
SET_WINDOW SCSICommandType = 0x24
READ_CAPACITY SCSICommandType = 0x25
READ_10 SCSICommandType = 0x28
WRITE_10 SCSICommandType = 0x2a
SEEK_10 SCSICommandType = 0x2b
POSITION_TO_ELEMENT SCSICommandType = 0x2b
WRITE_VERIFY SCSICommandType = 0x2e
VERIFY_10 SCSICommandType = 0x2f
SEARCH_HIGH SCSICommandType = 0x30
SEARCH_EQUAL SCSICommandType = 0x31
SEARCH_LOW SCSICommandType = 0x32
SET_LIMITS SCSICommandType = 0x33
PRE_FETCH_10 SCSICommandType = 0x34
READ_POSITION SCSICommandType = 0x34
SYNCHRONIZE_CACHE SCSICommandType = 0x35
LOCK_UNLOCK_CACHE SCSICommandType = 0x36
READ_DEFECT_DATA SCSICommandType = 0x37
INITIALIZE_ELEMENT_STATUS_WITH_RANGE SCSICommandType = 0x37
MEDIUM_SCAN SCSICommandType = 0x38
COMPARE SCSICommandType = 0x39
COPY_VERIFY SCSICommandType = 0x3a
WRITE_BUFFER SCSICommandType = 0x3b
READ_BUFFER SCSICommandType = 0x3c
UPDATE_BLOCK SCSICommandType = 0x3d
READ_LONG SCSICommandType = 0x3e
WRITE_LONG SCSICommandType = 0x3f
CHANGE_DEFINITION SCSICommandType = 0x40
WRITE_SAME SCSICommandType = 0x41
UNMAP SCSICommandType = 0x42
READ_TOC SCSICommandType = 0x43
GET_CONFIGURATION SCSICommandType = 0x46
LOG_SELECT SCSICommandType = 0x4c
LOG_SENSE SCSICommandType = 0x4d
READ_DISK_INFO SCSICommandType = 0x51
READ_TRACK_INFO SCSICommandType = 0x52
MODE_SELECT_10 SCSICommandType = 0x55
RESERVE_10 SCSICommandType = 0x56
RELEASE_10 SCSICommandType = 0x57
MODE_SENSE_10 SCSICommandType = 0x5a
CLOSE_TRACK SCSICommandType = 0x5b
READ_BUFFER_CAP SCSICommandType = 0x5c
PERSISTENT_RESERVE_IN SCSICommandType = 0x5e
PERSISTENT_RESERVE_OUT SCSICommandType = 0x5f
VARLEN_CDB SCSICommandType = 0x7f
READ_16 SCSICommandType = 0x88
COMPARE_AND_WRITE SCSICommandType = 0x89
WRITE_16 SCSICommandType = 0x8a
ORWRITE_16 SCSICommandType = 0x8b
WRITE_VERIFY_16 SCSICommandType = 0x8e
VERIFY_16 SCSICommandType = 0x8f
PRE_FETCH_16 SCSICommandType = 0x90
SYNCHRONIZE_CACHE_16 SCSICommandType = 0x91
WRITE_SAME_16 SCSICommandType = 0x93
SERVICE_ACTION_IN SCSICommandType = 0x9e
SAI_READ_CAPACITY_16 SCSICommandType = 0x10
SAI_GET_LBA_STATUS SCSICommandType = 0x12
REPORT_LUNS SCSICommandType = 0xa0
MAINT_PROTOCOL_IN SCSICommandType = 0xa3
MOVE_MEDIUM SCSICommandType = 0xa5
EXCHANGE_MEDIUM SCSICommandType = 0xa6
READ_12 SCSICommandType = 0xa8
WRITE_12 SCSICommandType = 0xaa
GET_PERFORMACE SCSICommandType = 0xac
READ_DVD_STRUCTURE SCSICommandType = 0xad
WRITE_VERIFY_12 SCSICommandType = 0xae
VERIFY_12 SCSICommandType = 0xaf
SEARCH_HIGH_12 SCSICommandType = 0xb0
SEARCH_EQUAL_12 SCSICommandType = 0xb1
SEARCH_LOW_12 SCSICommandType = 0xb2
READ_ELEMENT_STATUS SCSICommandType = 0xb8
SEND_VOLUME_TAG SCSICommandType = 0xb6
SET_STREAMING SCSICommandType = 0xb6
SET_CD_SPEED SCSICommandType = 0xbb
WRITE_LONG_2 SCSICommandType = 0xea
)
type SCSITargetState int
var (
TargetOnline SCSITargetState = 1
TargetReady SCSITargetState = 2
)
type SCSIDataDirection int
const (
SCSIDataNone = iota
SCSIDataWrite
SCSIDataRead
SCSIDataBidirection
)
type SCSIDataBuffer struct {
Buffer *bytes.Buffer
Length uint32
TransferLength uint32
Resid int32
}
type SCSICommand struct {
Target *SCSITarget
DeviceID uint64
Device *SCSILu
State uint64
Direction SCSIDataDirection
InSDBBuffer SCSIDataBuffer
OutSDBBuffer SCSIDataBuffer
// Command ITN ID
CommandITNID uint64
Offset uint64
TL uint32
SCB *bytes.Buffer
SCBLength int
Lun []uint8
Attribute int
Tag uint64
Result byte
SenseBuffer *bytes.Buffer
SenseLength uint32
ITNexus *ITNexus
ITNexusLuInfo *ITNexusLuInfo
}
type ITNexus struct {
ID uint64
Ctime uint64
Commands []SCSICommand
Target *SCSITarget
Host int
Info string
}
type ITNexusLuInfo struct {
Lu *SCSILu
ID uint64
Prevent int
}
type SCSITarget struct {
Name string
TID int
LID int
State SCSITargetState
Devices []SCSILu
ITNexus []ITNexus
SCSITargetDriver interface{}
}
type SCSITargetDriverState int
const (
// just registered
SCSI_DRIVER_REGD = iota
// initialized ok
SCSI_DRIVER_INIT
// failed to initialize
SCSI_DRIVER_ERR
// exited
SCSI_DRIVER_EXIT
)
type SCSITargetDriverCommon struct {
Name string
State SCSITargetDriverState
DefaultBST string
}
type SCSILuPhyAttribute struct {
SCSIID string
SCSISN string
NumID uint64
VendorID string
ProductID string
ProductRev string
VersionDesction []uint16
// Peripheral device type
DeviceType uint
// Peripheral Qualifier
Qualifier bool
// Removable media
Removable bool
// Read Only media
Readonly bool
// Software Write Protect
SWP bool
// Use thin-provisioning for this LUN
Thinprovisioning bool
// Logical Unit online
Online bool
// Descrptor format sense data supported
SenseFormat bool
// Logical blocks per physical block exponent
Lbppbe int
// Do not update it automatically when the backing file changes
NoLbppbe int
// Lowest aligned LBA
LowestAlignedLBA int
}
var (
DefaultBlockShift int = 9
DefaultSenseBufferSize int = 252
)
var (
SAM_STAT_GOOD byte = 0x00
SAM_STAT_CHECK_CONDITION byte = 0x02
SAM_STAT_CONDITION_MET byte = 0x04
SAM_STAT_BUSY byte = 0x08
SAM_STAT_INTERMEDIATE byte = 0x10
SAM_STAT_INTERMEDIATE_CONDITION_MET byte = 0x14
SAM_STAT_RESERVATION_CONFLICT byte = 0x18
SAM_STAT_COMMAND_TERMINATED byte = 0x22
SAM_STAT_TASK_SET_FULL byte = 0x28
SAM_STAT_ACA_ACTIVE byte = 0x30
SAM_STAT_TASK_ABORTED byte = 0x40
)
type SAMStat struct {
Stat byte
Err error
}
var (
SAMStatGood = SAMStat{SAM_STAT_GOOD, nil}
SAMStatCheckCondition = SAMStat{SAM_STAT_CHECK_CONDITION, errors.New("check condition")}
SAMStatConditionMet = SAMStat{SAM_STAT_CONDITION_MET, errors.New("condition met")}
SAMStatBusy = SAMStat{SAM_STAT_BUSY, errors.New("busy")}
SAMStatIntermediate = SAMStat{SAM_STAT_INTERMEDIATE, errors.New("intermediate")}
SAMStatIntermediateConditionMet = SAMStat{SAM_STAT_INTERMEDIATE_CONDITION_MET, errors.New("intermediate condition met")}
SAMStatReservationConflict = SAMStat{SAM_STAT_RESERVATION_CONFLICT, errors.New("reservation conflict")}
SAMStatCommandTerminated = SAMStat{SAM_STAT_COMMAND_TERMINATED, errors.New("command terminated")}
SAMStatTaskSetFull = SAMStat{SAM_STAT_TASK_SET_FULL, errors.New("task set full")}
SAMStatAcaActive = SAMStat{SAM_STAT_ACA_ACTIVE, errors.New("aca active")}
SAMStatTaskAborted = SAMStat{SAM_STAT_TASK_ABORTED, errors.New("task aborted")}
)
type SCSIDeviceType byte
var (
TYPE_DISK SCSIDeviceType = 0x00
TYPE_TAPE SCSIDeviceType = 0x01
TYPE_PRINTER SCSIDeviceType = 0x02
TYPE_PROCESSOR SCSIDeviceType = 0x03
TYPE_WORM SCSIDeviceType = 0x04
TYPE_MMC SCSIDeviceType = 0x05
TYPE_SCANNER SCSIDeviceType = 0x06
TYPE_MOD SCSIDeviceType = 0x07
TYPE_MEDIUM_CHANGER SCSIDeviceType = 0x08
TYPE_COMM SCSIDeviceType = 0x09
TYPE_RAID SCSIDeviceType = 0x0c
TYPE_ENCLOSURE SCSIDeviceType = 0x0d
TYPE_RBC SCSIDeviceType = 0x0e
TYPE_OSD SCSIDeviceType = 0x11
TYPE_NO_LUN SCSIDeviceType = 0x7f
TYPE_PT SCSIDeviceType = 0xff
)
type SCSILu struct {
FD int
Address uint64
Size uint64
Lun uint64
Path string
BsoFlags int
BlockShift uint
ReserveID uint64
Attrs SCSILuPhyAttribute
}

70
pkg/port/interfaces.go Normal file
View File

@@ -0,0 +1,70 @@
package port
import (
"github.com/gostor/gotgt/pkg/api"
"github.com/gostor/gotgt/pkg/port/iscsit"
)
type SCSITargetDriver interface {
Init() error
Exit() error
CreateTarget(target *api.SCSITarget) error
DestroyTarget(target *api.SCSITarget) error
CreatePortal(name string) error
DestroyPortal(name string) error
CreateLu(lu *api.SCSILu) error
GetLu(lun uint8) (uint64, error)
ProcessCommand(buf []byte) ([]byte, error)
CommandNotify(nid uint64, result int, cmd *api.SCSICommand) error
}
type fakeSCSITargetDriver struct {
api.SCSITargetDriverCommon
}
func (fake *fakeSCSITargetDriver) Init() error {
return nil
}
func (fake *fakeSCSITargetDriver) Exit() error {
return nil
}
func (fake *fakeSCSITargetDriver) CreateTarget(target *api.SCSITarget) error {
return nil
}
func (fake *fakeSCSITargetDriver) DestroyTarget(target *api.SCSITarget) error {
return nil
}
func (fake *fakeSCSITargetDriver) CreatePortal(name string) error {
return nil
}
func (fake *fakeSCSITargetDriver) DestroyPortal(name string) error {
return nil
}
func (fake *fakeSCSITargetDriver) CreateLu(lu *api.SCSILu) error {
return nil
}
func (fake *fakeSCSITargetDriver) GetLun(lun uint8) (uint64, error) {
return 0, nil
}
func (fake *fakeSCSITargetDriver) CommandNotify(nid uint64, result int, cmd *api.SCSICommand) error {
return nil
}
func (fake *fakeSCSITargetDriver) ProcessCommand(buf []byte) ([]byte, error) {
return []byte(""), nil
}
func NewTargetDriver(driver string, tgt *api.SCSITarget) SCSITargetDriver {
if driver == "iscsi" {
return iscsit.NewISCSITarget(tgt)
}
return nil
}

View File

@@ -1,26 +1,8 @@
/*
Copyright 2015 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.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package packet implements the iSCSI PDU packet format as specified in
// rfc7143 section 11.
package iscsit
import (
"bytes"
"fmt"
"io"
"strings"
)
@@ -70,15 +52,7 @@ var opCodeMap = map[OpCode]string{
OpReject: "Reject",
}
func (c OpCode) String() string {
s := opCodeMap[c]
if s == "" {
s = fmt.Sprintf("Unknown Code: %x", int(c))
}
return s
}
type Message struct {
type ISCSICommand struct {
OpCode OpCode
RawHeader []byte
DataLen int
@@ -109,8 +83,8 @@ type Message struct {
// SCSI commands
ExpectedDataLen uint32
CDB []byte
Status Status
SCSIResponse Response
Status byte
SCSIResponse byte
// Data-In
HasStatus bool
@@ -118,23 +92,23 @@ type Message struct {
BufferOffset uint32
}
func (m *Message) Bytes() []byte {
switch m.OpCode {
func (cmd *ISCSICommand) Bytes() []byte {
switch cmd.OpCode {
case OpLoginResp:
return m.loginRespBytes()
return cmd.loginRespBytes()
case OpLogoutResp:
return m.logoutRespBytes()
return cmd.logoutRespBytes()
case OpSCSIResp:
return m.scsiCmdRespBytes()
return cmd.scsiCmdRespBytes()
case OpSCSIIn:
return m.dataInBytes()
return cmd.dataInBytes()
}
return nil
}
func (m *Message) String() string {
func (m *ISCSICommand) String() string {
var s []string
s = append(s, fmt.Sprintf("Op: %v", m.OpCode))
s = append(s, fmt.Sprintf("Op: %v", opCodeMap[m.OpCode]))
s = append(s, fmt.Sprintf("Final = %v", m.Final))
s = append(s, fmt.Sprintf("Immediate = %v", m.Immediate))
s = append(s, fmt.Sprintf("Data Segment Length = %d", m.DataLen))
@@ -171,37 +145,6 @@ func (m *Message) String() string {
return strings.Join(s, "\n")
}
// Response composes a reply to the given message with the appropriate bits set.
func (m *Message) Response(r *Message) {
r.TaskTag = m.TaskTag
r.ConnID = m.ConnID
r.ISID = m.ISID
}
func Next(r io.Reader) (*Message, error) {
buf := make([]byte, 48) // TODO: sync.Pool
if _, err := io.ReadFull(r, buf); err != nil {
return nil, err
}
m, err := parseHeader(buf)
if err != nil {
return nil, err
}
m.RawHeader = buf
if m.DataLen > 0 {
dl := m.DataLen
for dl%4 > 0 {
dl++
}
data := make([]byte, dl)
if _, err := io.ReadFull(r, data); err != nil {
return nil, err
}
m.RawData = data[:m.DataLen]
}
return m, nil
}
// parseUint parses the given slice as a network-byte-ordered integer. If
// there are more than 8 bytes in data, it overflows.
func ParseUint(data []byte) uint64 {
@@ -220,13 +163,12 @@ func MarshalUint64(i uint64) []byte {
}
return data
}
func parseHeader(data []byte) (*Message, error) {
func parseHeader(data []byte) (*ISCSICommand, error) {
if len(data) != 48 {
return nil, fmt.Errorf("garbled header")
}
// TODO: sync.Pool
m := &Message{}
m := &ISCSICommand{}
m.Immediate = 0x40&data[0] == 0x40
m.OpCode = OpCode(data[0] & 0x3f)
m.Final = 0x80&data[1] == 0x80
@@ -274,3 +216,197 @@ func parseHeader(data []byte) (*Message, error) {
}
return m, nil
}
func (m *ISCSICommand) scsiCmdRespBytes() []byte {
// rfc7143 11.4
buf := &bytes.Buffer{}
buf.WriteByte(byte(OpSCSIResp))
buf.WriteByte(0x80) // 11.4.1 = wtf
buf.WriteByte(byte(m.SCSIResponse))
buf.WriteByte(byte(m.Status))
// Skip through to byte 16
for i := 0; i < 3*4; i++ {
buf.WriteByte(0x00)
}
buf.Write(MarshalUint64(uint64(m.TaskTag))[4:])
for i := 0; i < 4; i++ {
buf.WriteByte(0x00)
}
buf.Write(MarshalUint64(uint64(m.StatSN))[4:])
buf.Write(MarshalUint64(uint64(m.ExpCmdSN))[4:])
buf.Write(MarshalUint64(uint64(m.MaxCmdSN))[4:])
for i := 0; i < 3*4; i++ {
buf.WriteByte(0x00)
}
return buf.Bytes()
}
func (m *ISCSICommand) dataInBytes() []byte {
// rfc7143 11.7
buf := &bytes.Buffer{}
buf.WriteByte(byte(OpSCSIIn))
var b byte
b = 0x80
if m.HasStatus {
b |= 0x01
}
buf.WriteByte(b)
buf.WriteByte(0x00)
if m.HasStatus {
b = byte(m.Status)
}
buf.WriteByte(b)
buf.WriteByte(0x00) // 4
buf.Write(MarshalUint64(uint64(len(m.RawData)))[5:]) // 5-8
buf.WriteByte(0x00)
buf.WriteByte(byte(m.LUN))
// Skip through to byte 16
for i := 0; i < 6; i++ {
buf.WriteByte(0x00)
}
buf.Write(MarshalUint64(uint64(m.TaskTag))[4:])
for i := 0; i < 4; i++ {
// 11.7.4
buf.WriteByte(0xff)
}
buf.Write(MarshalUint64(uint64(m.StatSN))[4:])
buf.Write(MarshalUint64(uint64(m.ExpCmdSN))[4:])
buf.Write(MarshalUint64(uint64(m.MaxCmdSN))[4:])
buf.Write(MarshalUint64(uint64(m.DataSN))[4:])
buf.Write(MarshalUint64(uint64(m.BufferOffset))[4:])
for i := 0; i < 4; i++ {
buf.WriteByte(0x00)
}
buf.Write(m.RawData)
dl := len(m.RawData)
for dl%4 > 0 {
dl++
buf.WriteByte(0x00)
}
return buf.Bytes()
}
type InquiryData struct {
PeripheralQualifier int
PeripheralType int
Removable bool
Version int
SupportsACA bool
Hierarchical bool
SupportsSCC bool
HasACC bool
TargetGroupSupport int
ThirdPartyCopy bool
Protect bool
EnclosureServices bool
Multiport bool
MediaChanger bool
Vendor [8]byte
Product [16]byte
RevisionLevel [4]byte
SerialNumber uint64
}
func (id *InquiryData) bytes() []byte {
buf := &bytes.Buffer{}
var b byte
b = (uint8(id.PeripheralQualifier) << 5) & 0xe0
b |= uint8(id.PeripheralType) & 0x1f
buf.WriteByte(b)
b = 0
if id.Removable {
b = 0x80
}
buf.WriteByte(b)
buf.WriteByte(byte(id.Version))
b = 0x02
if id.SupportsACA {
b |= 0x20
}
if id.Hierarchical {
b |= 0x10
}
buf.WriteByte(b)
buf.WriteByte(0x00)
// byte 5
b = 0
if id.SupportsSCC {
b |= 0x80
}
if id.HasACC {
b |= 0x40
}
b |= byte(id.TargetGroupSupport) << 4 & 0x30
if id.ThirdPartyCopy {
b |= 0x08
}
if id.Protect {
b |= 0x01
}
buf.WriteByte(b)
// byte 6
b = 0
if id.EnclosureServices {
b |= 0x40
}
if id.Multiport {
b |= 0x10
}
if id.MediaChanger {
b |= 0x08
}
buf.WriteByte(b)
buf.WriteByte(0x02)
buf.Write(id.Vendor[:])
buf.Write(id.Product[:])
buf.Write(id.RevisionLevel[:])
buf.Write(MarshalUint64(id.SerialNumber))
for i := 0; i < 12; i++ {
buf.WriteByte(0x00)
}
data := buf.Bytes()
data[4] = byte(len(data) - 4)
return data
}
type Capacity struct {
LBA uint64
Blocksize uint32
ProtectionType uint8
PIExponent uint8
LogicalExponent uint8
ThinProvisioned bool
ThinProvReturnsZeros bool
LowestLBA uint16
}
func (c *Capacity) bytes() []byte {
// table 111
// http://www.seagate.com/staticfiles/support/disc/manuals/Interface%20manuals/100293068c.pdf
buf := &bytes.Buffer{}
buf.Write(MarshalUint64(c.LBA))
buf.Write(MarshalUint64(uint64(c.Blocksize))[4:])
var b byte
if c.ProtectionType > 0 {
b |= 0x01
b |= c.ProtectionType << 1
b &= 0x0f
}
buf.WriteByte(b)
b = c.PIExponent << 4
b |= c.LogicalExponent
buf.WriteByte(b)
lowLBA := MarshalUint64(uint64(c.LowestLBA))[6:]
lowLBA[0] &= 0x3f
if c.ThinProvisioned {
lowLBA[0] &= 0x80
}
if c.ThinProvReturnsZeros {
lowLBA[0] &= 0x40
}
return buf.Bytes()
}

View File

@@ -17,6 +17,11 @@ limitations under the License.
// iSCSI Target Driver
package iscsit
import (
"github.com/gostor/gotgt/pkg/api"
"github.com/gostor/gotgt/pkg/util"
)
type ISCSIDiscoveryMethod string
var (
@@ -33,9 +38,11 @@ type ISCSIRedirectInfo struct {
}
type ISCSITarget struct {
*api.SCSITarget
api.SCSITargetDriverCommon
Sessions []*ISCSISession
SessionParam []ISCSISessionParam
TID int
Alias string
MaxSessions int
RedirectInfo ISCSIRedirectInfo
@@ -44,41 +51,128 @@ type ISCSITarget struct {
NopCount int
}
type ISCSITargetDriver struct {
SCSITargetDriver
func NewISCSITarget(target *api.SCSITarget) *ISCSITarget {
return &ISCSITarget{
SCSITarget: target,
}
}
func (tgt *ISCSITargetDriver) Init() error {
func (tgt *ISCSITarget) Init() error {
return nil
}
func (tgt *ISCSITargetDriver) Exit() error {
func (tgt *ISCSITarget) Exit() error {
return nil
}
func (tgt *ISCSITargetDriver) CreateTarget(target *SCSITarget) error {
func (tgt *ISCSITarget) CreateTarget(target *api.SCSITarget) error {
return nil
}
func (tgt *ISCSITargetDriver) DestroyTarget(target *SCSITarget) error {
func (tgt *ISCSITarget) DestroyTarget(target *api.SCSITarget) error {
return nil
}
func (tgt *ISCSITargetDriver) CreatePortal(name string) error {
func (tgt *ISCSITarget) CreatePortal(name string) error {
return nil
}
func (tgt *ISCSITargetDriver) DestroyPortal(name string) error {
func (tgt *ISCSITarget) DestroyPortal(name string) error {
return nil
}
func (tgt *ISCSITargetDriver) CreateLu(lu *SCSILu) error {
func (tgt *ISCSITarget) CreateLu(lu *api.SCSILu) error {
return nil
}
func (tgt *ISCSITargetDriver) GetLun(lun uint8) (uint64, error) {
func (tgt *ISCSITarget) GetLu(lun uint8) (uint64, error) {
return 0, nil
}
func (tgt *ISCSITargetDriver) CommandNotify(nid uint64, result int, cmd *SCSICommand) error {
func (tgt *ISCSITarget) CommandNotify(nid uint64, result int, cmd *api.SCSICommand) error {
return nil
}
func (tgt *ISCSITarget) ProcessCommand(buf []byte) ([]byte, error) {
b := make([]byte, 48) // TODO: sync.Pool
b = buf[0:48]
m, err := parseHeader(b)
if err != nil {
return nil, err
}
m.RawHeader = b
if m.DataLen > 0 {
m.RawData = buf[48:m.DataLen]
}
resp := &ISCSICommand{}
switch m.OpCode {
case OpLoginReq:
resp = &ISCSICommand{
OpCode: OpLoginResp,
Transit: true,
NSG: FullFeaturePhase,
StatSN: m.ExpStatSN,
TaskTag: m.TaskTag,
ExpCmdSN: m.CmdSN,
MaxCmdSN: m.CmdSN,
RawData: util.MarshalKVText(map[string]string{
"HeaderDigest": "None",
"DataDigest": "None",
}),
}
break
case OpSCSICmd:
resp = &ISCSICommand{
OpCode: OpSCSIResp,
Final: true,
StatSN: m.ExpStatSN,
TaskTag: m.TaskTag,
ExpCmdSN: m.CmdSN + 1,
MaxCmdSN: m.CmdSN + 10,
}
switch api.SCSICommandType(m.CDB[0]) {
case api.TEST_UNIT_READY:
// test unit ready
resp.Status = api.SAM_STAT_GOOD
resp.SCSIResponse = 0x01
break
case api.READ_CAPACITY:
resp.OpCode = OpSCSIIn
resp.HasStatus = true
var data []byte
data = append(data, MarshalUint64(uint64(0))[4:]...)
data = append(data, MarshalUint64(uint64(0))[4:]...)
resp.RawData = data
break
case api.SERVICE_ACTION_IN:
resp.OpCode = OpSCSIIn
resp.HasStatus = true
sa := m.CDB[1] & 0x1f
switch sa {
case 0x10:
c := &Capacity{}
resp.RawData = c.bytes()
}
break
case api.INQUIRY:
resp.OpCode = OpSCSIIn
resp.HasStatus = true
alloc := int(ParseUint(m.CDB[3:5]))
inq := &InquiryData{
Vendor: [8]byte{'1', '1', 'c', 'a', 'n', 's'},
Product: [16]byte{'c', 'o', 'f', 'f', 'e', 'e'},
RevisionLevel: [4]byte{'1', '.', '0'},
SerialNumber: 52,
}
if len(inq.bytes()) >= alloc {
resp.RawData = inq.bytes()[:alloc]
} else {
resp.RawData = inq.bytes()
}
break
default:
break
}
}
b1 := resp.Bytes()
return b1, nil
}

View File

@@ -1,24 +1,8 @@
/*
Copyright 2015 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.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package iscsit
import "bytes"
func (m *Message) loginRespBytes() []byte {
func (m *ISCSICommand) loginRespBytes() []byte {
// rfc7143 11.13
buf := &bytes.Buffer{}
// byte 0

View File

@@ -1,24 +1,8 @@
/*
Copyright 2015 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.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package iscsit
import "bytes"
func (m *Message) logoutRespBytes() []byte {
func (m *ISCSICommand) logoutRespBytes() []byte {
buf := &bytes.Buffer{}
buf.WriteByte(byte(OpLogoutResp))
buf.WriteByte(0x80)

View File

@@ -42,6 +42,9 @@ type ISCSISession struct {
Rdma int
}
type ISCSIHeader struct {
}
type ISCSIPdu struct {
Bhs ISCSIHeader
AhsSize uint
@@ -78,7 +81,7 @@ func NewISCSISession() (*ISCSISession, error) {
tsih += uint16(b[0]) << 8
tsih += uint16(b[1])
return &Session{
return &ISCSISession{
Tsih: tsih,
}, nil
}

View File

@@ -16,7 +16,11 @@ limitations under the License.
package scsi
import "fmt"
import (
"fmt"
"github.com/gostor/gotgt/pkg/api"
)
type BaseBackingStore struct {
Name string
@@ -25,11 +29,11 @@ type BaseBackingStore struct {
}
type BackingStore interface {
Open(dev *SCSILu, path string, fd *int, size *uint64) error
Close(dev *SCSILu) error
Init(dev *SCSILu, Opts string) error
Exit(dev *SCSILu) error
CommandSubmit(cmd *SCSICommand) error
Open(dev *api.SCSILu, path string, fd *int, size *uint64) error
Close(dev *api.SCSILu) error
Init(dev *api.SCSILu, Opts string) error
Exit(dev *api.SCSILu) error
CommandSubmit(cmd *api.SCSICommand) error
}
type BackingStoreFunc func() (BackingStore, error)
@@ -55,22 +59,22 @@ type fakeBackingStore struct {
BaseBackingStore
}
func (fake *fakeBackingStore) Open(dev *SCSILu, path string, fd *int, size *uint64) error {
func (fake *fakeBackingStore) Open(dev *api.SCSILu, path string, fd *int, size *uint64) error {
return nil
}
func (fake *fakeBackingStore) Close(dev *SCSILu) error {
func (fake *fakeBackingStore) Close(dev *api.SCSILu) error {
return nil
}
func (fake *fakeBackingStore) Init(dev *SCSILu, Opts string) error {
func (fake *fakeBackingStore) Init(dev *api.SCSILu, Opts string) error {
return nil
}
func (fake *fakeBackingStore) Exit(dev *SCSILu) error {
func (fake *fakeBackingStore) Exit(dev *api.SCSILu) error {
return nil
}
func (fake *fakeBackingStore) CommandSubmit(cmd *SCSICommand) error {
func (fake *fakeBackingStore) CommandSubmit(cmd *api.SCSICommand) error {
return nil
}

View File

@@ -16,7 +16,11 @@ limitations under the License.
package backingstore
import "github.com/gostor/gotgt/pkg/scsi"
import (
"github.com/gostor/gotgt/pkg/scsi"
"github.com/golang/glog"
)
func init() {
scsi.RegisterBackingStore("null", new)
@@ -35,6 +39,7 @@ func new() (scsi.BackingStore, error) {
}
func (bs *NullBackingStore) Open(dev *SCSILu, path string, fd *int, size *uint64) error {
glog.V(1).Infof("NULL backing store open, size: %d", size)
return nil
}
@@ -51,5 +56,6 @@ func (bs *NullBackingStore) Exit(dev *SCSILu) error {
}
func (bs *NullBackingStore) CommandSubmit(cmd *SCSICommand) error {
cmd.Result = SAM_STAT_GOOD
return nil
}

View File

@@ -16,113 +16,6 @@ limitations under the License.
package scsi
import "bytes"
type SCSICommandType byte
var (
TEST_UNIT_READY SCSICommandType = 0x00
REZERO_UNIT SCSICommandType = 0x01
REQUEST_SENSE SCSICommandType = 0x03
FORMAT_UNIT SCSICommandType = 0x04
READ_BLOCK_LIMITS SCSICommandType = 0x05
REASSIGN_BLOCKS SCSICommandType = 0x07
INITIALIZE_ELEMENT_STATUS SCSICommandType = 0x07
READ_6 SCSICommandType = 0x08
WRITE_6 SCSICommandType = 0x0a
SEEK_6 SCSICommandType = 0x0b
READ_REVERSE SCSICommandType = 0x0f
WRITE_FILEMARKS SCSICommandType = 0x10
SPACE SCSICommandType = 0x11
INQUIRY SCSICommandType = 0x12
RECOVER_BUFFERED_DATA SCSICommandType = 0x14
MODE_SELECT SCSICommandType = 0x15
RESERVE SCSICommandType = 0x16
RELEASE SCSICommandType = 0x17
COPY SCSICommandType = 0x18
ERASE SCSICommandType = 0x19
MODE_SENSE SCSICommandType = 0x1a
START_STOP SCSICommandType = 0x1b
RECEIVE_DIAGNOSTIC SCSICommandType = 0x1c
SEND_DIAGNOSTIC SCSICommandType = 0x1d
ALLOW_MEDIUM_REMOVAL SCSICommandType = 0x1e
SET_WINDOW SCSICommandType = 0x24
READ_CAPACITY SCSICommandType = 0x25
READ_10 SCSICommandType = 0x28
WRITE_10 SCSICommandType = 0x2a
SEEK_10 SCSICommandType = 0x2b
POSITION_TO_ELEMENT SCSICommandType = 0x2b
WRITE_VERIFY SCSICommandType = 0x2e
VERIFY_10 SCSICommandType = 0x2f
SEARCH_HIGH SCSICommandType = 0x30
SEARCH_EQUAL SCSICommandType = 0x31
SEARCH_LOW SCSICommandType = 0x32
SET_LIMITS SCSICommandType = 0x33
PRE_FETCH_10 SCSICommandType = 0x34
READ_POSITION SCSICommandType = 0x34
SYNCHRONIZE_CACHE SCSICommandType = 0x35
LOCK_UNLOCK_CACHE SCSICommandType = 0x36
READ_DEFECT_DATA SCSICommandType = 0x37
INITIALIZE_ELEMENT_STATUS_WITH_RANGE SCSICommandType = 0x37
MEDIUM_SCAN SCSICommandType = 0x38
COMPARE SCSICommandType = 0x39
COPY_VERIFY SCSICommandType = 0x3a
WRITE_BUFFER SCSICommandType = 0x3b
READ_BUFFER SCSICommandType = 0x3c
UPDATE_BLOCK SCSICommandType = 0x3d
READ_LONG SCSICommandType = 0x3e
WRITE_LONG SCSICommandType = 0x3f
CHANGE_DEFINITION SCSICommandType = 0x40
WRITE_SAME SCSICommandType = 0x41
UNMAP SCSICommandType = 0x42
READ_TOC SCSICommandType = 0x43
GET_CONFIGURATION SCSICommandType = 0x46
LOG_SELECT SCSICommandType = 0x4c
LOG_SENSE SCSICommandType = 0x4d
READ_DISK_INFO SCSICommandType = 0x51
READ_TRACK_INFO SCSICommandType = 0x52
MODE_SELECT_10 SCSICommandType = 0x55
RESERVE_10 SCSICommandType = 0x56
RELEASE_10 SCSICommandType = 0x57
MODE_SENSE_10 SCSICommandType = 0x5a
CLOSE_TRACK SCSICommandType = 0x5b
READ_BUFFER_CAP SCSICommandType = 0x5c
PERSISTENT_RESERVE_IN SCSICommandType = 0x5e
PERSISTENT_RESERVE_OUT SCSICommandType = 0x5f
VARLEN_CDB SCSICommandType = 0x7f
READ_16 SCSICommandType = 0x88
COMPARE_AND_WRITE SCSICommandType = 0x89
WRITE_16 SCSICommandType = 0x8a
ORWRITE_16 SCSICommandType = 0x8b
WRITE_VERIFY_16 SCSICommandType = 0x8e
VERIFY_16 SCSICommandType = 0x8f
PRE_FETCH_16 SCSICommandType = 0x90
SYNCHRONIZE_CACHE_16 SCSICommandType = 0x91
WRITE_SAME_16 SCSICommandType = 0x93
SERVICE_ACTION_IN SCSICommandType = 0x9e
SAI_READ_CAPACITY_16 SCSICommandType = 0x10
SAI_GET_LBA_STATUS SCSICommandType = 0x12
REPORT_LUNS SCSICommandType = 0xa0
MAINT_PROTOCOL_IN SCSICommandType = 0xa3
MOVE_MEDIUM SCSICommandType = 0xa5
EXCHANGE_MEDIUM SCSICommandType = 0xa6
READ_12 SCSICommandType = 0xa8
WRITE_12 SCSICommandType = 0xaa
GET_PERFORMACE SCSICommandType = 0xac
READ_DVD_STRUCTURE SCSICommandType = 0xad
WRITE_VERIFY_12 SCSICommandType = 0xae
VERIFY_12 SCSICommandType = 0xaf
SEARCH_HIGH_12 SCSICommandType = 0xb0
SEARCH_EQUAL_12 SCSICommandType = 0xb1
SEARCH_LOW_12 SCSICommandType = 0xb2
READ_ELEMENT_STATUS SCSICommandType = 0xb8
SEND_VOLUME_TAG SCSICommandType = 0xb6
SET_STREAMING SCSICommandType = 0xb6
SET_CD_SPEED SCSICommandType = 0xbb
WRITE_LONG_2 SCSICommandType = 0xea
)
type SCSIPRServiceAction byte
type SCSIPRType byte
@@ -155,15 +48,6 @@ var (
PR_TYPE_EXCLUSIVE_ACCESS_ALLREG SCSIPRType = 0x08
)
type SCSIDataDirection int
const (
SCSIDataNone = iota
SCSIDataWrite
SCSIDataRead
SCSIDataBidirection
)
const (
CBD_GROUPID_0 = iota
CBD_GROUPID_1
@@ -186,37 +70,6 @@ const (
CDB_GROUP7 = 0 /* vendor specific */
)
type SCSIDataBuffer struct {
Buffer *bytes.Buffer
Length uint32
TransferLength uint32
Resid int32
}
type SCSICommand struct {
Target *SCSITarget
DeviceID uint64
Device *SCSILu
State uint64
Direction SCSIDataDirection
InSDBBuffer SCSIDataBuffer
OutSDBBuffer SCSIDataBuffer
// Command ITN ID
CommandITNID uint64
Offset uint64
TL uint32
SCB *bytes.Buffer
SCBLength int
Lun []uint8
Attribute int
Tag uint64
Result int
SenseBuffer *bytes.Buffer
SenseLength uint32
ITNexus *ITNexus
ITNexusLuInfo *ITNexusLuInfo
}
func SCSICDBGroupID(opcode byte) byte {
return ((opcode >> 5) & 0x7)
}

View File

@@ -16,76 +16,3 @@ limitations under the License.
// Target Driver Interface
package scsi
type SCSITargetDriverState int
const (
// just registered
SCSI_DRIVER_REGD = iota
// initialized ok
SCSI_DRIVER_INIT
// failed to initialize
SCSI_DRIVER_ERR
// exited
SCSI_DRIVER_EXIT
)
type SCSITargetDriver struct {
Name string
State SCSITargetDriverState
DefaultBST string
Targets []*SCSITarget
}
type SCSITargetDriverOps interface {
Init() error
Exit() error
CreateTarget(target *SCSITarget) error
DestroyTarget(target *SCSITarget) error
CreatePortal(name string) error
DestroyPortal(name string) error
CreateLu(lu *SCSILu) error
GetLu(lun uint8) (uint64, error)
CommandNotify(nid uint64, result int, cmd *SCSICommand) error
}
type fakeSCSITargetDriver struct {
SCSITargetDriver
}
func (fake *fakeSCSITargetDriver) Init() error {
return nil
}
func (fake *fakeSCSITargetDriver) Exit() error {
return nil
}
func (fake *fakeSCSITargetDriver) CreateTarget(target *SCSITarget) error {
return nil
}
func (fake *fakeSCSITargetDriver) DestroyTarget(target *SCSITarget) error {
return nil
}
func (fake *fakeSCSITargetDriver) CreatePortal(name string) error {
return nil
}
func (fake *fakeSCSITargetDriver) DestroyPortal(name string) error {
return nil
}
func (fake *fakeSCSITargetDriver) CreateLu(lu *SCSILu) error {
return nil
}
func (fake *fakeSCSITargetDriver) GetLun(lun uint8) (uint64, error) {
return 0, nil
}
func (fake *fakeSCSITargetDriver) CommandNotify(nid uint64, result int, cmd *SCSICommand) error {
return nil
}

View File

@@ -16,58 +16,22 @@ limitations under the License.
package scsi
type SCSILuPhyAttribute struct {
SCSIID string
SCSISN string
NumID uint64
VendorID string
ProductID string
ProductRev string
VersionDesction []uint16
// Peripheral device type
DeviceType uint
// Peripheral Qualifier
Qualifier bool
// Removable media
Removable bool
// Read Only media
Readonly bool
// Software Write Protect
SWP bool
// Use thin-provisioning for this LUN
Thinprovisioning bool
// Logical Unit online
Online bool
// Descrptor format sense data supported
SenseFormat bool
// Logical blocks per physical block exponent
Lbppbe int
// Do not update it automatically when the backing file changes
NoLbppbe int
// Lowest aligned LBA
LowestAlignedLBA int
}
import "github.com/gostor/gotgt/pkg/api"
type SCSILuOps struct {
*api.SCSILu
type SCSILu struct {
FD int
Address uint64
Size uint64
Lun uint64
Path string
BsoFlags int
BlockShift uint
ReserveID uint64
DeviceProtocol SCSIDeviceProtocol
Storage *BackingStore
Target *SCSITarget
Attrs SCSILuPhyAttribute
Target *api.SCSITarget
Attrs api.SCSILuPhyAttribute
// function handler for command performing and finishing
PerformCommand CommandFunc
FinishCommand func(*SCSITarget, *SCSICommand)
FinishCommand func(*api.SCSITarget, *api.SCSICommand)
}
func luPreventRemoval(lu *SCSILu) bool {
func luPreventRemoval(lu *api.SCSILu) bool {
// TODO
return false
}

View File

@@ -17,96 +17,109 @@ limitations under the License.
// SCSI block command processing
package scsi
import "encoding/binary"
import (
"encoding/binary"
"github.com/gostor/gotgt/pkg/api"
)
const (
PR_SPECIAL = (1 << 5)
PR_WE_FA = (1 << 4)
PR_EA_FA = (1 << 3)
PR_RR_FR = (1 << 2)
PR_WE_FN = (1 << 1)
PR_EA_FN = (1 << 0)
)
type SBCSCSIDeviceProtocol struct {
BaseSCSIDeviceProtocol
}
func (sbc *SBCSCSIDeviceProtocol) InitLu(lu *SCSILu) error {
func (sbc *SBCSCSIDeviceProtocol) InitLu(lu *api.SCSILu) error {
return nil
}
func (sbc *SBCSCSIDeviceProtocol) ExitLu(lu *SCSILu) error {
func (sbc *SBCSCSIDeviceProtocol) ExitLu(lu *api.SCSILu) error {
return nil
}
func (sbc *SBCSCSIDeviceProtocol) ConfigLu(lu *SCSILu) error {
func (sbc *SBCSCSIDeviceProtocol) ConfigLu(lu *api.SCSILu) error {
return nil
}
func (sbc *SBCSCSIDeviceProtocol) OnlineLu(lu *SCSILu) error {
func (sbc *SBCSCSIDeviceProtocol) OnlineLu(lu *api.SCSILu) error {
return nil
}
func (sbc *SBCSCSIDeviceProtocol) OfflineLu(lu *SCSILu) error {
func (sbc *SBCSCSIDeviceProtocol) OfflineLu(lu *api.SCSILu) error {
return nil
}
func NewSBCDevice() SBCSCSIDeviceProtocol {
var sbc = SBCSCSIDeviceProtocol{
BaseSCSIDeviceProtocol{
Type: TYPE_DISK,
Type: api.TYPE_DISK,
SCSIDeviceOps: make([]SCSIDeviceOperation, 256),
},
}
for i := 0; i <= 256; i++ {
sbc.SCSIDeviceOps = append(sbc.SCSIDeviceOps, NewSCSIDeviceOperation(SPCIllegalOp, nil, 0))
}
sbc.SCSIDeviceOps[TEST_UNIT_READY] = NewSCSIDeviceOperation(SPCTestUnit, nil, 0)
sbc.SCSIDeviceOps[REQUEST_SENSE] = NewSCSIDeviceOperation(SPCRequestSense, nil, 0)
sbc.SCSIDeviceOps[FORMAT_UNIT] = NewSCSIDeviceOperation(SBCFormatUnit, nil, 0)
sbc.SCSIDeviceOps[READ_6] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_EA_FA|PR_EA_FN)
sbc.SCSIDeviceOps[WRITE_6] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_EA_FA|PR_EA_FN|PR_WE_FA|PR_WE_FN)
sbc.SCSIDeviceOps[INQUIRY] = NewSCSIDeviceOperation(SPCInquiry, nil, 0)
sbc.SCSIDeviceOps[MODE_SELECT] = NewSCSIDeviceOperation(SBCModeSelect, nil, PR_WE_FA|PR_EA_FA|PR_WE_FN|PR_EA_FN)
sbc.SCSIDeviceOps[RESERVE] = NewSCSIDeviceOperation(SBCReserve, nil, 0)
sbc.SCSIDeviceOps[RELEASE] = NewSCSIDeviceOperation(SBCRelease, nil, 0)
sbc.SCSIDeviceOps[api.TEST_UNIT_READY] = NewSCSIDeviceOperation(SPCTestUnit, nil, 0)
sbc.SCSIDeviceOps[api.REQUEST_SENSE] = NewSCSIDeviceOperation(SPCRequestSense, nil, 0)
sbc.SCSIDeviceOps[api.FORMAT_UNIT] = NewSCSIDeviceOperation(SBCFormatUnit, nil, 0)
sbc.SCSIDeviceOps[api.READ_6] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_EA_FA|PR_EA_FN)
sbc.SCSIDeviceOps[api.WRITE_6] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_EA_FA|PR_EA_FN|PR_WE_FA|PR_WE_FN)
sbc.SCSIDeviceOps[api.INQUIRY] = NewSCSIDeviceOperation(SPCInquiry, nil, 0)
sbc.SCSIDeviceOps[api.MODE_SELECT] = NewSCSIDeviceOperation(SBCModeSelect, nil, PR_WE_FA|PR_EA_FA|PR_WE_FN|PR_EA_FN)
sbc.SCSIDeviceOps[api.RESERVE] = NewSCSIDeviceOperation(SBCReserve, nil, 0)
sbc.SCSIDeviceOps[api.RELEASE] = NewSCSIDeviceOperation(SBCRelease, nil, 0)
sbc.SCSIDeviceOps[MODE_SENSE] = NewSCSIDeviceOperation(SBCModeSense, nil, PR_WE_FA|PR_EA_FA|PR_EA_FN|PR_WE_FN)
sbc.SCSIDeviceOps[START_STOP] = NewSCSIDeviceOperation(SPCStartStop, nil, PR_SPECIAL)
sbc.SCSIDeviceOps[SEND_DIAGNOSTIC] = NewSCSIDeviceOperation(SPCSendDiagnostics, nil, 0)
sbc.SCSIDeviceOps[api.MODE_SENSE] = NewSCSIDeviceOperation(SBCModeSense, nil, PR_WE_FA|PR_EA_FA|PR_EA_FN|PR_WE_FN)
sbc.SCSIDeviceOps[api.START_STOP] = NewSCSIDeviceOperation(SPCStartStop, nil, PR_SPECIAL)
sbc.SCSIDeviceOps[api.SEND_DIAGNOSTIC] = NewSCSIDeviceOperation(SPCSendDiagnostics, nil, 0)
sbc.SCSIDeviceOps[ALLOW_MEDIUM_REMOVAL] = NewSCSIDeviceOperation(SPCPreventAllowMediaRemoval, nil, 0)
sbc.SCSIDeviceOps[READ_CAPACITY] = NewSCSIDeviceOperation(SBCReadCapacity, nil, 0)
sbc.SCSIDeviceOps[READ_10] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_EA_FA|PR_EA_FN)
sbc.SCSIDeviceOps[WRITE_10] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_WE_FA|PR_EA_FA|PR_EA_FN|PR_WE_FN)
sbc.SCSIDeviceOps[WRITE_VERIFY] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_EA_FA|PR_EA_FN)
sbc.SCSIDeviceOps[VERIFY_10] = NewSCSIDeviceOperation(SBCVerify, nil, PR_EA_FA|PR_EA_FN)
sbc.SCSIDeviceOps[api.ALLOW_MEDIUM_REMOVAL] = NewSCSIDeviceOperation(SPCPreventAllowMediaRemoval, nil, 0)
sbc.SCSIDeviceOps[api.READ_CAPACITY] = NewSCSIDeviceOperation(SBCReadCapacity, nil, 0)
sbc.SCSIDeviceOps[api.READ_10] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_EA_FA|PR_EA_FN)
sbc.SCSIDeviceOps[api.WRITE_10] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_WE_FA|PR_EA_FA|PR_EA_FN|PR_WE_FN)
sbc.SCSIDeviceOps[api.WRITE_VERIFY] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_EA_FA|PR_EA_FN)
sbc.SCSIDeviceOps[api.VERIFY_10] = NewSCSIDeviceOperation(SBCVerify, nil, PR_EA_FA|PR_EA_FN)
sbc.SCSIDeviceOps[PRE_FETCH_10] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_EA_FA|PR_EA_FN)
sbc.SCSIDeviceOps[SYNCHRONIZE_CACHE] = NewSCSIDeviceOperation(SBCSyncCache, nil, PR_WE_FA|PR_EA_FA|PR_WE_FN|PR_EA_FN)
sbc.SCSIDeviceOps[api.PRE_FETCH_10] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_EA_FA|PR_EA_FN)
sbc.SCSIDeviceOps[api.SYNCHRONIZE_CACHE] = NewSCSIDeviceOperation(SBCSyncCache, nil, PR_WE_FA|PR_EA_FA|PR_WE_FN|PR_EA_FN)
sbc.SCSIDeviceOps[WRITE_SAME] = NewSCSIDeviceOperation(SBCReadWrite, nil, 0)
sbc.SCSIDeviceOps[UNMAP] = NewSCSIDeviceOperation(SBCUnmap, nil, 0)
sbc.SCSIDeviceOps[api.WRITE_SAME] = NewSCSIDeviceOperation(SBCReadWrite, nil, 0)
sbc.SCSIDeviceOps[api.UNMAP] = NewSCSIDeviceOperation(SBCUnmap, nil, 0)
sbc.SCSIDeviceOps[MODE_SELECT_10] = NewSCSIDeviceOperation(SBCModeSelect, nil, PR_WE_FA|PR_EA_FA|PR_EA_FN|PR_WE_FN)
sbc.SCSIDeviceOps[MODE_SENSE_10] = NewSCSIDeviceOperation(SBCModeSense, nil, PR_WE_FA|PR_WE_FN|PR_EA_FA|PR_EA_FN)
sbc.SCSIDeviceOps[PERSISTENT_RESERVE_IN] = NewSCSIDeviceOperation(SPCServiceAction, nil, 0)
sbc.SCSIDeviceOps[PERSISTENT_RESERVE_OUT] = NewSCSIDeviceOperation(SPCServiceAction, nil, 0)
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[READ_16] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_EA_FA|PR_EA_FN)
sbc.SCSIDeviceOps[WRITE_16] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_EA_FA|PR_EA_FN|PR_WE_FA|PR_WE_FN)
sbc.SCSIDeviceOps[ORWRITE_16] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_EA_FA|PR_EA_FN)
sbc.SCSIDeviceOps[WRITE_VERIFY_16] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_EA_FA|PR_EA_FN)
sbc.SCSIDeviceOps[VERIFY_16] = NewSCSIDeviceOperation(SBCVerify, nil, PR_EA_FA|PR_EA_FN)
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)
sbc.SCSIDeviceOps[api.ORWRITE_16] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_EA_FA|PR_EA_FN)
sbc.SCSIDeviceOps[api.WRITE_VERIFY_16] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_EA_FA|PR_EA_FN)
sbc.SCSIDeviceOps[api.VERIFY_16] = NewSCSIDeviceOperation(SBCVerify, nil, PR_EA_FA|PR_EA_FN)
sbc.SCSIDeviceOps[PRE_FETCH_16] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_EA_FA|PR_EA_FN)
sbc.SCSIDeviceOps[SYNCHRONIZE_CACHE_16] = NewSCSIDeviceOperation(SBCSyncCache, nil, PR_EA_FA|PR_EA_FN|PR_WE_FA|PR_WE_FN)
sbc.SCSIDeviceOps[WRITE_SAME_16] = NewSCSIDeviceOperation(SBCReadWrite, nil, 0)
sbc.SCSIDeviceOps[SERVICE_ACTION_IN] = NewSCSIDeviceOperation(SPCServiceAction, nil, 0)
sbc.SCSIDeviceOps[api.PRE_FETCH_16] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_EA_FA|PR_EA_FN)
sbc.SCSIDeviceOps[api.SYNCHRONIZE_CACHE_16] = NewSCSIDeviceOperation(SBCSyncCache, nil, PR_EA_FA|PR_EA_FN|PR_WE_FA|PR_WE_FN)
sbc.SCSIDeviceOps[api.WRITE_SAME_16] = NewSCSIDeviceOperation(SBCReadWrite, nil, 0)
sbc.SCSIDeviceOps[api.SERVICE_ACTION_IN] = NewSCSIDeviceOperation(SPCServiceAction, nil, 0)
sbc.SCSIDeviceOps[REPORT_LUNS] = NewSCSIDeviceOperation(SPCReportLuns, nil, 0)
sbc.SCSIDeviceOps[EXCHANGE_MEDIUM] = NewSCSIDeviceOperation(SPCServiceAction, nil, 0)
sbc.SCSIDeviceOps[READ_12] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_EA_FA|PR_EA_FN)
sbc.SCSIDeviceOps[WRITE_12] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_WE_FA|PR_EA_FA|PR_WE_FA|PR_WE_FN)
sbc.SCSIDeviceOps[WRITE_VERIFY_12] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_EA_FA|PR_EA_FN)
sbc.SCSIDeviceOps[VERIFY_12] = NewSCSIDeviceOperation(SBCVerify, nil, PR_EA_FA|PR_EA_FN)
sbc.SCSIDeviceOps[api.REPORT_LUNS] = NewSCSIDeviceOperation(SPCReportLuns, nil, 0)
sbc.SCSIDeviceOps[api.EXCHANGE_MEDIUM] = NewSCSIDeviceOperation(SPCServiceAction, nil, 0)
sbc.SCSIDeviceOps[api.READ_12] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_EA_FA|PR_EA_FN)
sbc.SCSIDeviceOps[api.WRITE_12] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_WE_FA|PR_EA_FA|PR_WE_FA|PR_WE_FN)
sbc.SCSIDeviceOps[api.WRITE_VERIFY_12] = NewSCSIDeviceOperation(SBCReadWrite, nil, PR_EA_FA|PR_EA_FN)
sbc.SCSIDeviceOps[api.VERIFY_12] = NewSCSIDeviceOperation(SBCVerify, nil, PR_EA_FA|PR_EA_FN)
return sbc
}
func SBCModeSelect(host int, cmd *SCSICommand) SAMStat {
return SAMStatGood
func SBCModeSelect(host int, cmd *api.SCSICommand) api.SAMStat {
return api.SAMStatGood
}
func SBCModeSense(host int, cmd *SCSICommand) SAMStat {
func SBCModeSense(host int, cmd *api.SCSICommand) api.SAMStat {
// DPOFUA = 0x10
var deviceSpecific uint8 = 0x10
@@ -129,7 +142,7 @@ func SBCModeSense(host int, cmd *SCSICommand) SAMStat {
data.WriteByte(deviceSpecific)
}
return SAMStatGood
return api.SAMStatGood
}
// The FORMAT UNIT command requests that the device server format the medium into application client
@@ -137,14 +150,14 @@ func SBCModeSense(host int, cmd *SCSICommand) SAMStat {
// in the last mode parameter block descriptor in a MODE SELECT command (see SPC-3). In addition,
// the device server may certify the medium and create control structures for the management of the medium and defects.
// The degree that the medium is altered by this command is vendor-specific.
func SBCFormatUnit(host int, cmd *SCSICommand) SAMStat {
func SBCFormatUnit(host int, cmd *api.SCSICommand) api.SAMStat {
var (
key = ILLEGAL_REQUEST
asc = ASC_INVALID_FIELD_IN_CDB
)
if err := deviceReserve(cmd); err != nil {
return SAMStatReservationConflict
return api.SAMStatReservationConflict
}
if !cmd.Device.Attrs.Online {
@@ -172,33 +185,33 @@ func SBCFormatUnit(host int, cmd *SCSICommand) SAMStat {
goto sense
}
return SAMStatGood
return api.SAMStatGood
sense:
BuildSenseData(cmd, key, asc)
return SAMStatCheckCondition
return api.SAMStatCheckCondition
}
func SBCUnmap(host int, cmd *SCSICommand) SAMStat {
return SAMStatGood
func SBCUnmap(host int, cmd *api.SCSICommand) api.SAMStat {
return api.SAMStatGood
}
func SBCReadWrite(host int, cmd *SCSICommand) SAMStat {
return SAMStatGood
func SBCReadWrite(host int, cmd *api.SCSICommand) api.SAMStat {
return api.SAMStatGood
}
func SBCReserve(host int, cmd *SCSICommand) SAMStat {
func SBCReserve(host int, cmd *api.SCSICommand) api.SAMStat {
if err := deviceReserve(cmd); err != nil {
return SAMStatReservationConflict
return api.SAMStatReservationConflict
}
return SAMStatGood
return api.SAMStatGood
}
func SBCRelease(host int, cmd *SCSICommand) SAMStat {
func SBCRelease(host int, cmd *api.SCSICommand) api.SAMStat {
if err := deviceRelease(cmd.Target.TID, cmd.CommandITNID, cmd.Device.Lun, false); err != nil {
return SAMStatReservationConflict
return api.SAMStatReservationConflict
}
return SAMStatGood
return api.SAMStatGood
}
// The READ CAPACITY (10) command requests that the device server transfer 8 bytes of parameter data
@@ -206,7 +219,7 @@ func SBCRelease(host int, cmd *SCSICommand) SAMStat {
// This command may be processed as if it has a HEAD OF QUEUE task attribute. If the logical unit supports
// protection information, the application client should use the READ CAPACITY (16) command instead of
// the READ CAPACITY (10) command.
func SBCReadCapacity(host int, cmd *SCSICommand) SAMStat {
func SBCReadCapacity(host int, cmd *api.SCSICommand) api.SAMStat {
var (
scb = cmd.SCB.Bytes()
key = ILLEGAL_REQUEST
@@ -242,15 +255,15 @@ func SBCReadCapacity(host int, cmd *SCSICommand) SAMStat {
binary.Write(data, binary.BigEndian, uint32(1<<bshift))
overflow:
cmd.InSDBBuffer.Resid = 8
return SAMStatGood
return api.SAMStatGood
sense:
cmd.InSDBBuffer.Resid = 0
BuildSenseData(cmd, key, asc)
return SAMStatCheckCondition
return api.SAMStatCheckCondition
}
// The VERIFY (10) command requests that the device server verify the specified logical block(s) on the medium.
func SBCVerify(host int, cmd *SCSICommand) SAMStat {
func SBCVerify(host int, cmd *api.SCSICommand) api.SAMStat {
var (
key = ILLEGAL_REQUEST
asc = ASC_INVALID_FIELD_IN_CDB
@@ -270,30 +283,30 @@ func SBCVerify(host int, cmd *SCSICommand) SAMStat {
if cmd.SCB.Bytes()[1]&0x02 == 0 {
// no data compare with the media
return SAMStatGood
return api.SAMStatGood
}
// TODO
sense:
cmd.InSDBBuffer.Resid = 0
BuildSenseData(cmd, key, asc)
return SAMStatCheckCondition
return api.SAMStatCheckCondition
}
func SBCReadCapacity16(host int, cmd *SCSICommand) SAMStat {
return SAMStatGood
func SBCReadCapacity16(host int, cmd *api.SCSICommand) api.SAMStat {
return api.SAMStatGood
}
func SBCGetLbaStatus(host int, cmd *SCSICommand) SAMStat {
return SAMStatGood
func SBCGetLbaStatus(host int, cmd *api.SCSICommand) api.SAMStat {
return api.SAMStatGood
}
func SBCServiceAction(host int, cmd *SCSICommand) SAMStat {
return SAMStatGood
func SBCServiceAction(host int, cmd *api.SCSICommand) api.SAMStat {
return api.SAMStatGood
}
// The SYNCHRONIZE CACHE (10) command requests that the device server ensure that
// the specified logical blocks have their most recent data values recorded in
// non-volatile cache and/or on the medium, based on the SYNC_NV bit.
func SBCSyncCache(host int, cmd *SCSICommand) SAMStat {
return SAMStatGood
func SBCSyncCache(host int, cmd *api.SCSICommand) api.SAMStat {
return api.SAMStatGood
}

View File

@@ -16,70 +16,9 @@ limitations under the License.
package scsi
import "errors"
import "github.com/gostor/gotgt/pkg/api"
var (
DefaultBlockShift int = 9
DefaultSenseBufferSize int = 252
)
type SCSIDeviceType byte
var (
SAM_STAT_GOOD byte = 0x00
SAM_STAT_CHECK_CONDITION byte = 0x02
SAM_STAT_CONDITION_MET byte = 0x04
SAM_STAT_BUSY byte = 0x08
SAM_STAT_INTERMEDIATE byte = 0x10
SAM_STAT_INTERMEDIATE_CONDITION_MET byte = 0x14
SAM_STAT_RESERVATION_CONFLICT byte = 0x18
SAM_STAT_COMMAND_TERMINATED byte = 0x22
SAM_STAT_TASK_SET_FULL byte = 0x28
SAM_STAT_ACA_ACTIVE byte = 0x30
SAM_STAT_TASK_ABORTED byte = 0x40
)
type SAMStat struct {
Stat byte
Err error
}
var (
SAMStatGood = SAMStat{SAM_STAT_GOOD, nil}
SAMStatCheckCondition = SAMStat{SAM_STAT_CHECK_CONDITION, errors.New("check condition")}
SAMStatConditionMet = SAMStat{SAM_STAT_CONDITION_MET, errors.New("condition met")}
SAMStatBusy = SAMStat{SAM_STAT_BUSY, errors.New("busy")}
SAMStatIntermediate = SAMStat{SAM_STAT_INTERMEDIATE, errors.New("intermediate")}
SAMStatIntermediateConditionMet = SAMStat{SAM_STAT_INTERMEDIATE_CONDITION_MET, errors.New("intermediate condition met")}
SAMStatReservationConflict = SAMStat{SAM_STAT_RESERVATION_CONFLICT, errors.New("reservation conflict")}
SAMStatCommandTerminated = SAMStat{SAM_STAT_COMMAND_TERMINATED, errors.New("command terminated")}
SAMStatTaskSetFull = SAMStat{SAM_STAT_TASK_SET_FULL, errors.New("task set full")}
SAMStatAcaActive = SAMStat{SAM_STAT_ACA_ACTIVE, errors.New("aca active")}
SAMStatTaskAborted = SAMStat{SAM_STAT_TASK_ABORTED, errors.New("task aborted")}
)
var (
TYPE_DISK SCSIDeviceType = 0x00
TYPE_TAPE SCSIDeviceType = 0x01
TYPE_PRINTER SCSIDeviceType = 0x02
TYPE_PROCESSOR SCSIDeviceType = 0x03
TYPE_WORM SCSIDeviceType = 0x04
TYPE_MMC SCSIDeviceType = 0x05
TYPE_SCANNER SCSIDeviceType = 0x06
TYPE_MOD SCSIDeviceType = 0x07
TYPE_MEDIUM_CHANGER SCSIDeviceType = 0x08
TYPE_COMM SCSIDeviceType = 0x09
TYPE_RAID SCSIDeviceType = 0x0c
TYPE_ENCLOSURE SCSIDeviceType = 0x0d
TYPE_RBC SCSIDeviceType = 0x0e
TYPE_OSD SCSIDeviceType = 0x11
TYPE_NO_LUN SCSIDeviceType = 0x7f
TYPE_PT SCSIDeviceType = 0xff
)
type CommandFunc func(host int, cmd *SCSICommand) SAMStat
type CommandFunc func(host int, cmd *api.SCSICommand) api.SAMStat
type SCSIServiceAction struct {
ServiceAction uint32
@@ -93,16 +32,16 @@ type SCSIDeviceOperation struct {
}
type BaseSCSIDeviceProtocol struct {
Type SCSIDeviceType
Type api.SCSIDeviceType
SCSIDeviceOps []SCSIDeviceOperation
}
type SCSIDeviceProtocol interface {
InitLu(lu *SCSILu) error
ExitLu(lu *SCSILu) error
ConfigLu(lu *SCSILu) error
OnlineLu(lu *SCSILu) error
OfflineLu(lu *SCSILu) error
InitLu(lu *api.SCSILu) error
ExitLu(lu *api.SCSILu) error
ConfigLu(lu *api.SCSILu) error
OnlineLu(lu *api.SCSILu) error
OfflineLu(lu *api.SCSILu) error
}
func NewSCSIDeviceOperation(fn CommandFunc, sa *SCSIServiceAction, pr uint8) SCSIDeviceOperation {
@@ -113,7 +52,7 @@ func NewSCSIDeviceOperation(fn CommandFunc, sa *SCSIServiceAction, pr uint8) SCS
}
}
func BuildSenseData(cmd *SCSICommand, key byte, asc SCSISubError) {
func BuildSenseData(cmd *api.SCSICommand, key byte, asc SCSISubError) {
senseBuffer := cmd.SenseBuffer
if cmd.Device.Attrs.SenseFormat {
// descriptor format

View File

@@ -22,6 +22,7 @@ import (
"encoding/binary"
"fmt"
"github.com/gostor/gotgt/pkg/api"
"github.com/gostor/gotgt/pkg/util"
)
@@ -108,16 +109,16 @@ const (
DESG_SCSI
)
func SPCIllegalOp(host int, cmd *SCSICommand) SAMStat {
return SAMStatGood
func SPCIllegalOp(host int, cmd *api.SCSICommand) api.SAMStat {
return api.SAMStatGood
}
func SPCLuOffline(lu *SCSILu) error {
func SPCLuOffline(lu *api.SCSILu) error {
lu.Attrs.Online = true
return nil
}
func SPCLuOnline(lu *SCSILu) error {
func SPCLuOnline(lu *api.SCSILu) error {
if luPreventRemoval(lu) {
return fmt.Errorf("lu(%s) prevent removal", lu.Lun)
}
@@ -126,11 +127,11 @@ func SPCLuOnline(lu *SCSILu) error {
return nil
}
func SPCInquiry(host int, cmd *SCSICommand) SAMStat {
return SAMStatGood
func SPCInquiry(host int, cmd *api.SCSICommand) api.SAMStat {
return api.SAMStatGood
}
func SPCReportLuns(host int, cmd *SCSICommand) SAMStat {
func SPCReportLuns(host int, cmd *api.SCSICommand) api.SAMStat {
var (
remainLength uint32
actualLength uint32 = 8
@@ -171,26 +172,26 @@ func SPCReportLuns(host int, cmd *SCSICommand) SAMStat {
remainLength -= 8
}
}
return SAMStatGood
return api.SAMStatGood
sense:
cmd.InSDBBuffer.Resid = 0
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
return SAMStatCheckCondition
return api.SAMStatCheckCondition
}
func SPCStartStop(host int, cmd *SCSICommand) SAMStat {
func SPCStartStop(host int, cmd *api.SCSICommand) api.SAMStat {
var (
pwrcnd, loej, start byte
)
if err := deviceReserve(cmd); err != nil {
return SAMStatReservationConflict
return api.SAMStatReservationConflict
}
cmd.InSDBBuffer.Resid = 0
scb := cmd.SCB.Bytes()
pwrcnd = scb[4] & 0xf0
if pwrcnd != 0 {
return SAMStatGood
return api.SAMStatGood
}
loej = scb[4] & 0x02
@@ -205,7 +206,7 @@ func SPCStartStop(host int, cmd *SCSICommand) SAMStat {
// !online == media is not present
BuildSenseData(cmd, NOT_READY, ASC_MEDIUM_REMOVAL_PREVENTED)
}
return SAMStatCheckCondition
return api.SAMStatCheckCondition
}
SPCLuOffline(cmd.Device)
}
@@ -213,15 +214,15 @@ func SPCStartStop(host int, cmd *SCSICommand) SAMStat {
SPCLuOnline(cmd.Device)
}
return SAMStatGood
return api.SAMStatGood
}
func SPCTestUnit(host int, cmd *SCSICommand) SAMStat {
func SPCTestUnit(host int, cmd *api.SCSICommand) api.SAMStat {
if err := deviceReserve(cmd); err != nil {
return SAMStatReservationConflict
return api.SAMStatReservationConflict
}
if cmd.Device.Attrs.Online {
return SAMStatGood
return api.SAMStatGood
}
if cmd.Device.Attrs.Removable {
BuildSenseData(cmd, NOT_READY, ASC_MEDIUM_NOT_PRESENT)
@@ -229,46 +230,46 @@ func SPCTestUnit(host int, cmd *SCSICommand) SAMStat {
BuildSenseData(cmd, NOT_READY, ASC_BECOMING_READY)
}
return SAMStatCheckCondition
return api.SAMStatCheckCondition
}
func SPCPreventAllowMediaRemoval(host int, cmd *SCSICommand) SAMStat {
func SPCPreventAllowMediaRemoval(host int, cmd *api.SCSICommand) api.SAMStat {
if err := deviceReserve(cmd); err != nil {
return SAMStatReservationConflict
return api.SAMStatReservationConflict
}
// PREVENT_MASK = 0x03
cmd.ITNexusLuInfo.Prevent = int(cmd.SCB.Bytes()[4] & 0x03)
return SAMStatGood
return api.SAMStatGood
}
// SPCModeSense Implement SCSI op MODE SENSE(6) and MODE SENSE(10)
// Reference : SPC4r11
// 6.11 - MODE SENSE(6)
// 6.12 - MODE SENSE(10)
func SPCModeSense(host int, cmd *SCSICommand) SAMStat {
return SAMStatGood
func SPCModeSense(host int, cmd *api.SCSICommand) api.SAMStat {
return api.SAMStatGood
}
func SPCSendDiagnostics(host int, cmd *SCSICommand) SAMStat {
func SPCSendDiagnostics(host int, cmd *api.SCSICommand) api.SAMStat {
// we only support SELF-TEST==1
if cmd.SCB.Bytes()[1]&0x04 == 0 {
goto sense
}
return SAMStatGood
return api.SAMStatGood
sense:
cmd.InSDBBuffer.Resid = 0
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
return SAMStatCheckCondition
return api.SAMStatCheckCondition
}
// This is useful for the various commands using the SERVICE ACTION format.
func SPCServiceAction(host int, cmd *SCSICommand) SAMStat {
func SPCServiceAction(host int, cmd *api.SCSICommand) api.SAMStat {
// TODO
return SAMStatGood
return api.SAMStatGood
}
func SPCPRReadKeys(host int, cmd *SCSICommand) SAMStat {
func SPCPRReadKeys(host int, cmd *api.SCSICommand) api.SAMStat {
allocationLength := util.GetUnalignedUint32(cmd.SCB.Bytes()[7:9])
if allocationLength < 8 {
goto sense
@@ -280,14 +281,14 @@ func SPCPRReadKeys(host int, cmd *SCSICommand) SAMStat {
sense:
cmd.InSDBBuffer.Resid = 0
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
return SAMStatCheckCondition
return api.SAMStatCheckCondition
}
func SPCPRReadReservation(host int, cmd *SCSICommand) SAMStat {
return SAMStatGood
func SPCPRReadReservation(host int, cmd *api.SCSICommand) api.SAMStat {
return api.SAMStatGood
}
func SPCPRReportCapabilities(host int, cmd *SCSICommand) SAMStat {
func SPCPRReportCapabilities(host int, cmd *api.SCSICommand) api.SAMStat {
var (
buf []byte = make([]byte, 8)
availLength uint32 = 8
@@ -324,38 +325,38 @@ func SPCPRReportCapabilities(host int, cmd *SCSICommand) SAMStat {
actualLength = availLength
}
cmd.InSDBBuffer.Resid = int32(actualLength)
return SAMStatGood
return api.SAMStatGood
sense:
cmd.InSDBBuffer.Resid = 0
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
return SAMStatCheckCondition
return api.SAMStatCheckCondition
}
func SPCPRRegister(host int, cmd *SCSICommand) SAMStat {
return SAMStatGood
func SPCPRRegister(host int, cmd *api.SCSICommand) api.SAMStat {
return api.SAMStatGood
}
func SPCPRReserve(host int, cmd *SCSICommand) SAMStat {
return SAMStatGood
func SPCPRReserve(host int, cmd *api.SCSICommand) api.SAMStat {
return api.SAMStatGood
}
func SPCPRRelease(host int, cmd *SCSICommand) SAMStat {
return SAMStatGood
func SPCPRRelease(host int, cmd *api.SCSICommand) api.SAMStat {
return api.SAMStatGood
}
func SPCPRClear(host int, cmd *SCSICommand) SAMStat {
return SAMStatGood
func SPCPRClear(host int, cmd *api.SCSICommand) api.SAMStat {
return api.SAMStatGood
}
func SPCPRPreempt(host int, cmd *SCSICommand) SAMStat {
return SAMStatGood
func SPCPRPreempt(host int, cmd *api.SCSICommand) api.SAMStat {
return api.SAMStatGood
}
func SPCPRRegisterAndMove(host int, cmd *SCSICommand) SAMStat {
return SAMStatGood
func SPCPRRegisterAndMove(host int, cmd *api.SCSICommand) api.SAMStat {
return api.SAMStatGood
}
func SPCRequestSense(host int, cmd *SCSICommand) SAMStat {
func SPCRequestSense(host int, cmd *api.SCSICommand) api.SAMStat {
var (
allocationLength uint32
actualLength uint32
@@ -378,5 +379,5 @@ func SPCRequestSense(host int, cmd *SCSICommand) SAMStat {
cmd.SenseBuffer = &bytes.Buffer{}
cmd.SenseLength = 0
return SAMStatGood
return api.SAMStatGood
}

View File

@@ -20,50 +20,24 @@ import (
"fmt"
"github.com/golang/glog"
"github.com/gostor/gotgt/pkg/api"
"github.com/gostor/gotgt/pkg/port"
)
type SCSITargetState int
func NewTarget(tid int, driverName, name string) (*api.SCSITarget, error) {
// verify the target ID
var (
TargetOnline SCSITargetState = 1
TargetReady SCSITargetState = 2
)
// verify the target's Name
const (
PR_SPECIAL = (1 << 5)
PR_WE_FA = (1 << 4)
PR_EA_FA = (1 << 3)
PR_RR_FR = (1 << 2)
PR_WE_FN = (1 << 1)
PR_EA_FN = (1 << 0)
)
type ITNexus struct {
ID uint64
Ctime uint64
Commands []SCSICommand
Target *SCSITarget
Host int
Info string
// verify the low level driver
var target = &api.SCSITarget{Name: name, TID: tid}
var tgt = port.NewTargetDriver(driverName, target)
target.SCSITargetDriver = tgt
return target, nil
}
type ITNexusLuInfo struct {
Lu *SCSILu
ID uint64
Prevent int
}
type SCSITarget struct {
Name string
TID int
LID int
State SCSITargetState
Devices []SCSILu
ITNexus []ITNexus
}
func deviceReserve(cmd *SCSICommand) error {
var lu *SCSILu
func deviceReserve(cmd *api.SCSICommand) error {
var lu *api.SCSILu
for _, dev := range cmd.Target.Devices {
if dev.Lun == cmd.Device.Lun {
lu = &dev