Merge pull request #93 from utkarshmani1997/jiva-integration

integrate openebs/jiva with gotgt
This commit is contained in:
Lei Xue
2019-11-21 19:15:33 +08:00
committed by GitHub
14 changed files with 474 additions and 78 deletions

View File

@@ -17,6 +17,7 @@ package api
import ( import (
"errors" "errors"
"io"
"sync" "sync"
uuid "github.com/satori/go.uuid" uuid "github.com/satori/go.uuid"
@@ -165,6 +166,7 @@ var (
) )
type SCSICommand struct { type SCSICommand struct {
OpCode byte
Target *SCSITarget Target *SCSITarget
DeviceID uint64 DeviceID uint64
Device *SCSILu Device *SCSILu
@@ -395,6 +397,9 @@ type SCSILu struct {
Storage BackingStore Storage BackingStore
DeviceProtocol SCSIDeviceProtocol DeviceProtocol SCSIDeviceProtocol
ModeBlockDescriptor []byte ModeBlockDescriptor []byte
SCSIVendorID string
SCSIProductID string
SCSIID string
PerformCommand CommandFunc PerformCommand CommandFunc
FinishCommand func(*SCSITarget, *SCSICommand) FinishCommand func(*SCSITarget, *SCSICommand)
@@ -406,3 +411,14 @@ type UnmapBlockDescriptor struct {
Offset uint64 Offset uint64
TL uint32 TL uint32
} }
type ReaderWriterAt interface {
io.ReaderAt
io.WriterAt
}
type RemoteBackingStore interface {
ReaderWriterAt
Sync() (int, error)
Unmap(int64, int64) (int, error)
}

View File

@@ -20,7 +20,9 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"strings" "strings"
"time"
"github.com/gostor/gotgt/pkg/api"
"github.com/gostor/gotgt/pkg/util" "github.com/gostor/gotgt/pkg/util"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
@@ -93,6 +95,7 @@ type ISCSICommand struct {
FinalInSeq bool FinalInSeq bool
Immediate bool Immediate bool
TaskTag uint32 TaskTag uint32
StartTime time.Time
ExpCmdSN, MaxCmdSN uint32 ExpCmdSN, MaxCmdSN uint32
AHSLen int AHSLen int
Resid uint32 Resid uint32
@@ -124,6 +127,7 @@ type ISCSICommand struct {
StatusDetail uint8 StatusDetail uint8
// SCSI commands // SCSI commands
SCSIOpCode byte
ExpectedDataLen uint32 ExpectedDataLen uint32
CDB []byte CDB []byte
Status byte Status byte
@@ -225,6 +229,7 @@ func parseHeader(data []byte) (*ISCSICommand, error) {
m.AHSLen = int(data[4]) * 4 m.AHSLen = int(data[4]) * 4
m.DataLen = int(ParseUint(data[5:8])) m.DataLen = int(ParseUint(data[5:8]))
m.TaskTag = uint32(ParseUint(data[16:20])) m.TaskTag = uint32(ParseUint(data[16:20]))
m.StartTime = time.Now()
switch m.OpCode { switch m.OpCode {
case OpSCSICmd: case OpSCSICmd:
m.LUN = [8]byte{data[9]} m.LUN = [8]byte{data[9]}
@@ -234,6 +239,14 @@ func parseHeader(data []byte) (*ISCSICommand, error) {
m.Write = data[1]&0x20 == 0x20 m.Write = data[1]&0x20 == 0x20
m.CDB = data[32:48] m.CDB = data[32:48]
m.ExpStatSN = uint32(ParseUint(data[28:32])) m.ExpStatSN = uint32(ParseUint(data[28:32]))
m.SCSIOpCode = m.CDB[0]
SCSIOpcode := api.SCSICommandType(m.SCSIOpCode)
switch SCSIOpcode {
case api.READ_6, api.READ_10, api.READ_12, api.READ_16:
m.Read = true
case api.WRITE_6, api.WRITE_10, api.WRITE_12, api.WRITE_16, api.WRITE_VERIFY, api.WRITE_VERIFY_12, api.WRITE_VERIFY_16:
m.Write = true
}
fallthrough fallthrough
case OpSCSITaskReq: case OpSCSITaskReq:
m.ReferencedTaskTag = uint32(ParseUint(data[20:24])) m.ReferencedTaskTag = uint32(ParseUint(data[20:24]))
@@ -358,7 +371,9 @@ func (m *ISCSICommand) dataInBytes() []byte {
copy(buf[36:], util.MarshalUint32(m.DataSN)) copy(buf[36:], util.MarshalUint32(m.DataSN))
copy(buf[40:], util.MarshalUint32(m.BufferOffset)) copy(buf[40:], util.MarshalUint32(m.BufferOffset))
copy(buf[44:], util.MarshalUint32(m.Resid)) copy(buf[44:], util.MarshalUint32(m.Resid))
copy(buf[48:], m.RawData[m.BufferOffset:m.BufferOffset+uint32(m.DataLen)]) if m.ExpectedDataLen != 0 {
copy(buf[48:], m.RawData[m.BufferOffset:m.BufferOffset+uint32(m.DataLen)])
}
return buf return buf
} }

View File

@@ -51,6 +51,7 @@ var (
) )
type iscsiConnection struct { type iscsiConnection struct {
ConnNum int
state int state int
authState int authState int
session *ISCSISession session *ISCSISession
@@ -96,12 +97,13 @@ const (
) )
type iscsiTask struct { type iscsiTask struct {
tag uint32 tag uint32
conn *iscsiConnection conn *iscsiConnection
cmd *ISCSICommand cmd *ISCSICommand
scmd *api.SCSICommand scmd *api.SCSICommand
state taskState state taskState
result byte expectedDataLength int64
result byte
offset int offset int
r2tCount int r2tCount int
@@ -154,6 +156,7 @@ func (conn *iscsiConnection) buildRespPackage(oc OpCode, task *iscsiTask) error
task = conn.rxTask task = conn.rxTask
} }
conn.resp = &ISCSICommand{ conn.resp = &ISCSICommand{
StartTime: conn.req.StartTime,
StatSN: conn.req.ExpStatSN, StatSN: conn.req.ExpStatSN,
TaskTag: conn.req.TaskTag, TaskTag: conn.req.TaskTag,
ExpCmdSN: conn.session.ExpCmdSN, ExpCmdSN: conn.session.ExpCmdSN,
@@ -164,6 +167,7 @@ func (conn *iscsiConnection) buildRespPackage(oc OpCode, task *iscsiTask) error
case OpReady: case OpReady:
conn.resp.OpCode = OpReady conn.resp.OpCode = OpReady
conn.resp.R2TSN = task.r2tSN conn.resp.R2TSN = task.r2tSN
conn.resp.Final = true
conn.resp.BufferOffset = uint32(task.offset) conn.resp.BufferOffset = uint32(task.offset)
conn.resp.DesiredLength = uint32(task.r2tCount) conn.resp.DesiredLength = uint32(task.r2tCount)
if val := conn.loginParam.sessionParam[ISCSI_PARAM_MAX_BURST].Value; task.r2tCount > int(val) { if val := conn.loginParam.sessionParam[ISCSI_PARAM_MAX_BURST].Value; task.r2tCount > int(val) {
@@ -171,6 +175,7 @@ func (conn *iscsiConnection) buildRespPackage(oc OpCode, task *iscsiTask) error
} }
case OpSCSIIn, OpSCSIResp: case OpSCSIIn, OpSCSIResp:
conn.resp.OpCode = oc conn.resp.OpCode = oc
conn.resp.SCSIOpCode = conn.req.SCSIOpCode
conn.resp.Immediate = true conn.resp.Immediate = true
conn.resp.Final = true conn.resp.Final = true
conn.resp.SCSIResponse = 0x00 conn.resp.SCSIResponse = 0x00

View File

@@ -22,6 +22,7 @@ import (
"os" "os"
"strconv" "strconv"
"sync" "sync"
"time"
"github.com/gostor/gotgt/pkg/api" "github.com/gostor/gotgt/pkg/api"
"github.com/gostor/gotgt/pkg/config" "github.com/gostor/gotgt/pkg/config"
@@ -35,15 +36,30 @@ const (
ISCSI_UNSPEC_TSIH = uint16(0) ISCSI_UNSPEC_TSIH = uint16(0)
) )
type ISCSITargetDriver struct { const (
SCSI *scsi.SCSITargetService STATE_INIT = iota
Name string STATE_RUNNING
iSCSITargets map[string]*ISCSITarget STATE_SHUTTING_DOWN
TSIHPool map[uint16]bool STATE_TERMINATE
TSIHPoolMutex sync.Mutex )
mu sync.Mutex var (
l net.Listener EnableStats bool
)
type ISCSITargetDriver struct {
SCSI *scsi.SCSITargetService
Name string
iSCSITargets map[string]*ISCSITarget
TSIHPool map[uint16]bool
TSIHPoolMutex sync.Mutex
isClientConnected bool
enableStats bool
mu *sync.RWMutex
l net.Listener
state uint8
OpCode int
TargetStats scsi.Stats
} }
func init() { func init() {
@@ -51,12 +67,19 @@ func init() {
} }
func NewISCSITargetDriver(base *scsi.SCSITargetService) (scsi.SCSITargetDriver, error) { func NewISCSITargetDriver(base *scsi.SCSITargetService) (scsi.SCSITargetDriver, error) {
return &ISCSITargetDriver{ driver := &ISCSITargetDriver{
Name: iSCSIDriverName, Name: iSCSIDriverName,
iSCSITargets: map[string]*ISCSITarget{}, iSCSITargets: map[string]*ISCSITarget{},
SCSI: base, SCSI: base,
TSIHPool: map[uint16]bool{0: true, 65535: true}, TSIHPool: map[uint16]bool{0: true, 65535: true},
}, nil mu: &sync.RWMutex{},
}
if EnableStats {
driver.enableStats = true
driver.TargetStats.SCSIIOCount = map[int]int64{}
}
return driver, nil
} }
func (s *ISCSITargetDriver) AllocTSIH() uint16 { func (s *ISCSITargetDriver) AllocTSIH() uint16 {
@@ -165,46 +188,72 @@ func (s *ISCSITargetDriver) Run() error {
s.mu.Lock() s.mu.Lock()
s.l = l s.l = l
s.mu.Unlock() s.mu.Unlock()
log.Infof("iSCSI service listening on: %v", s.l.Addr())
s.setState(STATE_RUNNING)
for { for {
log.Info("Listening ...")
conn, err := l.Accept() conn, err := l.Accept()
if err != nil { if err != nil {
if err, ok := err.(net.Error); ok { if err, ok := err.(net.Error); ok {
if !err.Temporary() { if !err.Temporary() {
log.Info("Closing ...") log.Warning("Closing connection with initiator...")
break break
} }
} }
log.Error(err) log.Error(err)
continue continue
} }
log.Info(conn.LocalAddr().String()) log.Info(conn.LocalAddr().String())
log.Info("Accepting ...") s.setClientStatus(true)
iscsiConn := &iscsiConnection{conn: conn, iscsiConn := &iscsiConnection{conn: conn,
loginParam: &iscsiLoginParam{}} loginParam: &iscsiLoginParam{}}
iscsiConn.init() iscsiConn.init()
iscsiConn.rxIOState = IOSTATE_RX_BHS iscsiConn.rxIOState = IOSTATE_RX_BHS
log.Infof("Target is connected to initiator: %s", conn.RemoteAddr().String())
log.Infof("connection is connected from %s...\n", conn.RemoteAddr().String())
// start a new thread to do with this command // start a new thread to do with this command
go s.handler(DATAIN, iscsiConn) go s.handler(DATAIN, iscsiConn)
} }
return nil return nil
} }
func (s *ISCSITargetDriver) setClientStatus(ok bool) {
s.isClientConnected = ok
}
func (s *ISCSITargetDriver) isInitiatorConnected() bool {
return s.isClientConnected
}
func (s *ISCSITargetDriver) Close() error { func (s *ISCSITargetDriver) Close() error {
s.mu.Lock() s.mu.Lock()
l := s.l l := s.l
s.setClientStatus(false)
s.mu.Unlock() s.mu.Unlock()
if l != nil { if l != nil {
return l.Close() s.setState(STATE_SHUTTING_DOWN)
if err := l.Close(); err != nil {
return err
}
s.setState(STATE_TERMINATE)
return nil
} }
return nil return nil
} }
func (s *ISCSITargetDriver) setState(st uint8) {
s.mu.Lock()
defer s.mu.Unlock()
s.state = st
}
func (s *ISCSITargetDriver) Resize(size uint64) error {
s.mu.Lock()
defer s.mu.Unlock()
return s.SCSI.Resize(size)
}
func (s *ISCSITargetDriver) handler(events byte, conn *iscsiConnection) { func (s *ISCSITargetDriver) handler(events byte, conn *iscsiConnection) {
if events&DATAIN != 0 { if events&DATAIN != 0 {
@@ -324,6 +373,7 @@ func (s *ISCSITargetDriver) rxHandler(conn *iscsiConnection) {
} }
case OpLogoutReq: case OpLogoutReq:
log.Debug("OpLogoutReq") log.Debug("OpLogoutReq")
s.setClientStatus(false)
if err := iscsiExecLogout(conn); err != nil { if err := iscsiExecLogout(conn); err != nil {
log.Warningf("set connection to close") log.Warningf("set connection to close")
conn.state = CONN_STATE_CLOSE conn.state = CONN_STATE_CLOSE
@@ -386,6 +436,7 @@ func (s *ISCSITargetDriver) iscsiExecLogin(conn *iscsiConnection) error {
} }
func iscsiExecLogout(conn *iscsiConnection) error { func iscsiExecLogout(conn *iscsiConnection) error {
log.Infof("Logout request received from initiator: %v", conn.conn.RemoteAddr().String())
cmd := conn.req cmd := conn.req
conn.resp = &ISCSICommand{ conn.resp = &ISCSICommand{
OpCode: OpLogoutResp, OpCode: OpLogoutResp,
@@ -473,6 +524,12 @@ func (s *ISCSITargetDriver) txHandler(conn *iscsiConnection) {
resp.DataSN = 0 resp.DataSN = 0
maxCount := conn.maxSeqCount maxCount := conn.maxSeqCount
if s.enableStats {
if resp.OpCode == OpSCSIResp || resp.OpCode == OpSCSIIn {
s.UpdateStats(conn)
}
}
/* send data splitted by segmentLen */ /* send data splitted by segmentLen */
SendRemainingData: SendRemainingData:
if resp.OpCode == OpSCSIIn { if resp.OpCode == OpSCSIIn {
@@ -573,6 +630,13 @@ func (s *ISCSITargetDriver) scsiCommandHandler(conn *iscsiConnection) (err error
switch req.OpCode { switch req.OpCode {
case OpSCSICmd: case OpSCSICmd:
log.Debugf("SCSI Command processing...") log.Debugf("SCSI Command processing...")
if s.enableStats {
if _, ok := s.TargetStats.SCSIIOCount[(int)(req.CDB[0])]; ok != false {
s.TargetStats.SCSIIOCount[(int)(req.CDB[0])] += 1
} else {
s.TargetStats.SCSIIOCount[(int)(req.CDB[0])] = 1
}
}
scmd := &api.SCSICommand{ scmd := &api.SCSICommand{
ITNexusID: conn.session.ITNexus.ID, ITNexusID: conn.session.ITNexus.ID,
SCB: req.CDB, SCB: req.CDB,
@@ -594,8 +658,17 @@ func (s *ISCSITargetDriver) scsiCommandHandler(conn *iscsiConnection) (err error
} }
task := &iscsiTask{conn: conn, cmd: conn.req, tag: conn.req.TaskTag, scmd: scmd} task := &iscsiTask{conn: conn, cmd: conn.req, tag: conn.req.TaskTag, scmd: scmd}
task.scmd.OpCode = conn.req.SCSIOpCode
if scmd.Direction == api.SCSIDataBidirection {
task.scmd.Result = api.SAMStatCheckCondition.Stat
scsi.BuildSenseData(task.scmd, scsi.ILLEGAL_REQUEST, scsi.NO_ADDITIONAL_SENSE)
conn.buildRespPackage(OpSCSIResp, task)
conn.rxTask = nil
break
}
if req.Write { if req.Write {
task.r2tCount = int(req.ExpectedDataLen) - req.DataLen task.r2tCount = int(req.ExpectedDataLen) - req.DataLen
task.expectedDataLength = int64(req.ExpectedDataLen)
if !req.Final { if !req.Final {
task.unsolCount = 1 task.unsolCount = 1
} }
@@ -649,7 +722,7 @@ func (s *ISCSITargetDriver) scsiCommandHandler(conn *iscsiConnection) (err error
} }
return return
} else { } else {
if scmd.Direction == api.SCSIDataRead && scmd.SenseBuffer == nil { if scmd.Direction == api.SCSIDataRead && scmd.SenseBuffer == nil && req.ExpectedDataLen != 0 {
conn.buildRespPackage(OpSCSIIn, task) conn.buildRespPackage(OpSCSIIn, task)
} else { } else {
conn.buildRespPackage(OpSCSIResp, task) conn.buildRespPackage(OpSCSIResp, task)
@@ -710,6 +783,7 @@ func (s *ISCSITargetDriver) scsiCommandHandler(conn *iscsiConnection) (err error
case OpNoopOut: case OpNoopOut:
iscsiExecNoopOut(conn) iscsiExecNoopOut(conn)
case OpLogoutReq: case OpLogoutReq:
s.setClientStatus(false)
conn.txTask = &iscsiTask{conn: conn, cmd: conn.req, tag: conn.req.TaskTag} conn.txTask = &iscsiTask{conn: conn, cmd: conn.req, tag: conn.req.TaskTag}
conn.txIOState = IOSTATE_TX_BHS conn.txIOState = IOSTATE_TX_BHS
iscsiExecLogout(conn) iscsiExecLogout(conn)
@@ -824,13 +898,31 @@ func (s *ISCSITargetDriver) iscsiExecTask(task *iscsiTask) error {
fallthrough fallthrough
case ISCSI_TM_FUNC_TARGET_WARM_RESET, ISCSI_TM_FUNC_TARGET_COLD_RESET, ISCSI_TM_FUNC_TASK_REASSIGN: case ISCSI_TM_FUNC_TARGET_WARM_RESET, ISCSI_TM_FUNC_TARGET_COLD_RESET, ISCSI_TM_FUNC_TASK_REASSIGN:
task.result = ISCSI_TMF_RSP_NOT_SUPPORTED task.result = ISCSI_TMF_RSP_NOT_SUPPORTED
return fmt.Errorf("The task function is not supported")
default: default:
task.result = ISCSI_TMF_RSP_REJECTED task.result = ISCSI_TMF_RSP_REJECTED
return fmt.Errorf("Unknown task function")
} }
// return response to initiator // return response to initiator
return task.conn.buildRespPackage(OpSCSITaskResp, task) return task.conn.buildRespPackage(OpSCSITaskResp, task)
} }
return nil return nil
} }
func (s *ISCSITargetDriver) Stats() scsi.Stats {
return s.TargetStats
}
func (s *ISCSITargetDriver) UpdateStats(conn *iscsiConnection) {
s.TargetStats.IsClientConnected = s.isClientConnected
switch api.SCSICommandType(conn.resp.SCSIOpCode) {
case api.READ_6, api.READ_10, api.READ_12, api.READ_16:
s.TargetStats.ReadIOPS += 1
s.TargetStats.TotalReadTime += int64(time.Since(conn.resp.StartTime))
s.TargetStats.TotalReadBlockCount += int64(conn.resp.ExpectedDataLen)
break
case api.WRITE_6, api.WRITE_10, api.WRITE_12, api.WRITE_16:
s.TargetStats.WriteIOPS += 1
s.TargetStats.TotalWriteTime += int64(time.Since(conn.resp.StartTime))
s.TargetStats.TotalWriteBlockCount += int64(conn.resp.ExpectedDataLen)
break
}
}

View File

@@ -152,8 +152,8 @@ func (conn *iscsiConnection) processLoginData() ([]util.KeyValue, error) {
conn.loginParam.iniCSG, conn.loginParam.iniNSG, conn.loginParam.iniTrans) conn.loginParam.iniCSG, conn.loginParam.iniNSG, conn.loginParam.iniTrans)
} }
} else { } else {
conn.loginParam.tgtNSG = LoginOperationalNegotiation conn.loginParam.tgtNSG = FullFeaturePhase
conn.loginParam.tgtTrans = false conn.loginParam.tgtTrans = true
} }
return negoKV, nil return negoKV, nil
} }

View File

@@ -184,13 +184,13 @@ func boolKeyInConv(value uint) string {
var sessionKeys map[string]*iscsiSessionKeys = map[string]*iscsiSessionKeys{ var sessionKeys map[string]*iscsiSessionKeys = map[string]*iscsiSessionKeys{
// ISCSI_PARAM_MAX_RECV_DLENGTH // ISCSI_PARAM_MAX_RECV_DLENGTH
"MaxRecvDataSegmentLength": {ISCSI_PARAM_MAX_RECV_DLENGTH, true, 32768, 512, 16777215, numberKeyConv, numberKeyInConv}, "MaxRecvDataSegmentLength": {ISCSI_PARAM_MAX_RECV_DLENGTH, true, 65536, 512, 16777215, numberKeyConv, numberKeyInConv},
// ISCSI_PARAM_HDRDGST_EN // ISCSI_PARAM_HDRDGST_EN
"HeaderDigest": {ISCSI_PARAM_HDRDGST_EN, false, DIGEST_NONE, DIGEST_NONE, DIGEST_ALL, digestKeyConv, digestKeyInConv}, "HeaderDigest": {ISCSI_PARAM_HDRDGST_EN, false, DIGEST_NONE, DIGEST_NONE, DIGEST_ALL, digestKeyConv, digestKeyInConv},
// ISCSI_PARAM_DATADGST_EN // ISCSI_PARAM_DATADGST_EN
"DataDigest": {ISCSI_PARAM_DATADGST_EN, false, DIGEST_NONE, DIGEST_NONE, DIGEST_ALL, digestKeyConv, digestKeyInConv}, "DataDigest": {ISCSI_PARAM_DATADGST_EN, false, DIGEST_NONE, DIGEST_NONE, DIGEST_ALL, digestKeyConv, digestKeyInConv},
// ISCSI_PARAM_INITIAL_R2T_EN // ISCSI_PARAM_INITIAL_R2T_EN
"InitialR2T": {ISCSI_PARAM_INITIAL_R2T_EN, false, 1, 0, 1, boolKeyConv, boolKeyInConv}, "InitialR2T": {ISCSI_PARAM_INITIAL_R2T_EN, true, 1, 0, 1, boolKeyConv, boolKeyInConv},
// ISCSI_PARAM_MAX_R2T // ISCSI_PARAM_MAX_R2T
"MaxOutstandingR2T": {ISCSI_PARAM_MAX_R2T, true, 1, 1, 65535, numberKeyConv, numberKeyInConv}, "MaxOutstandingR2T": {ISCSI_PARAM_MAX_R2T, true, 1, 1, 65535, numberKeyConv, numberKeyInConv},
// ISCSI_PARAM_IMM_DATA_EN // ISCSI_PARAM_IMM_DATA_EN
@@ -392,8 +392,8 @@ func (s *ISCSITargetDriver) BindISCSISession(conn *iscsiConnection) error {
} }
if newSess.SessionType == SESSION_NORMAL { if newSess.SessionType == SESSION_NORMAL {
log.Infof("New Session initiator name:%v,target name:%v,ISID:0x%x", log.Infof("Login request received from initiator: %v, Session type: %s, Target name:%v, ISID: 0x%x",
conn.loginParam.initiator, conn.loginParam.target, conn.loginParam.isid) conn.loginParam.initiator, "Normal", conn.loginParam.target, conn.loginParam.isid)
//register normal session //register normal session
itnexus := &api.ITNexus{uuid.NewV1(), GeniSCSIITNexusID(newSess)} itnexus := &api.ITNexus{uuid.NewV1(), GeniSCSIITNexusID(newSess)}
scsi.AddITNexus(&newSess.Target.SCSITarget, itnexus) scsi.AddITNexus(&newSess.Target.SCSITarget, itnexus)
@@ -404,6 +404,8 @@ func (s *ISCSITargetDriver) BindISCSISession(conn *iscsiConnection) error {
newSess.Target.Sessions[newSess.TSIH] = newSess newSess.Target.Sessions[newSess.TSIH] = newSess
newSess.Target.SessionsRWMutex.Unlock() newSess.Target.SessionsRWMutex.Unlock()
} else { } else {
log.Infof("Discovery request received from initiator: %v, Session type: %s, ISID: 0x%x",
conn.loginParam.initiator, "Discovery", conn.loginParam.isid)
conn.session = newSess conn.session = newSess
} }
} else { } else {

View File

@@ -125,6 +125,11 @@ func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error, key
bs.DataAdvise(int64(offset), int64(length), util.POSIX_FADV_NOREUSE) bs.DataAdvise(int64(offset), int64(length), util.POSIX_FADV_NOREUSE)
} }
cmd.InSDBBuffer.Resid = uint32(length) cmd.InSDBBuffer.Resid = uint32(length)
if cmd.InSDBBuffer.Length < uint32(length) {
key = ILLEGAL_REQUEST
asc = ASC_INVALID_FIELD_IN_CDB
goto sense
}
copy(cmd.InSDBBuffer.Buffer, rbuf) copy(cmd.InSDBBuffer.Buffer, rbuf)
case api.PRE_FETCH_10, api.PRE_FETCH_16: case api.PRE_FETCH_10, api.PRE_FETCH_16:
err = bs.DataAdvise(int64(offset), tl, util.POSIX_FADV_WILLNEED) err = bs.DataAdvise(int64(offset), tl, util.POSIX_FADV_WILLNEED)
@@ -148,7 +153,7 @@ write:
if err != nil { if err != nil {
log.Error(err) log.Error(err)
key = MEDIUM_ERROR key = MEDIUM_ERROR
asc = ASC_READ_ERROR asc = ASC_WRITE_ERROR
goto sense goto sense
} }
log.Debugf("write data at 0x%x for length %d", offset, len(wbuf)) log.Debugf("write data at 0x%x for length %d", offset, len(wbuf))
@@ -167,7 +172,7 @@ write:
if ((opcode != api.WRITE_6) && (scb[1]&0x8 != 0)) || (pg.Data[0]&0x04 == 0) { if ((opcode != api.WRITE_6) && (scb[1]&0x8 != 0)) || (pg.Data[0]&0x04 == 0) {
if err = bs.DataSync(int64(offset), tl); err != nil { if err = bs.DataSync(int64(offset), tl); err != nil {
key = MEDIUM_ERROR key = MEDIUM_ERROR
asc = ASC_READ_ERROR asc = ASC_WRITE_ERROR
goto sense goto sense
} }
} }

View File

@@ -0,0 +1,118 @@
/*
Copyright 2016 openebs 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 remote
import (
"fmt"
"github.com/gostor/gotgt/pkg/api"
"github.com/gostor/gotgt/pkg/scsi"
log "github.com/sirupsen/logrus"
)
var (
Size uint64
)
func init() {
scsi.RegisterBackingStore("RemBs", NewRemoteBackingStore)
}
// RemBackingStore
type RemBackingStore struct {
scsi.BaseBackingStore
// Remote backing store, remote server exposing
// read and write methods.
RemBs api.RemoteBackingStore
}
func NewRemoteBackingStore() (api.BackingStore, error) {
return &RemBackingStore{
BaseBackingStore: scsi.BaseBackingStore{
Name: "RemBs",
OflagsSupported: 0,
},
}, nil
}
func (bs *RemBackingStore) Open(dev *api.SCSILu, path string) error {
if Size == 0 {
return fmt.Errorf("Size is not initialized")
}
var err error
bs.DataSize = Size
bs.RemBs, err = scsi.GetTargetBSMap(path)
if err != nil {
return err
}
return nil
}
func (bs *RemBackingStore) Close(dev *api.SCSILu) error {
/* TODO return bs.File.Close()*/
return nil
}
func (bs *RemBackingStore) Init(dev *api.SCSILu, Opts string) error {
return nil
}
func (bs *RemBackingStore) Exit(dev *api.SCSILu) error {
return nil
}
func (bs *RemBackingStore) Size(dev *api.SCSILu) uint64 {
return bs.DataSize
}
func (bs *RemBackingStore) Read(offset, tl int64) ([]byte, error) {
tmpbuf := make([]byte, tl)
length, err := bs.RemBs.ReadAt(tmpbuf, offset)
if err != nil {
return nil, err
}
if length != len(tmpbuf) {
return nil, fmt.Errorf("Incomplete read expected:%d actual:%d", tl, length)
}
return tmpbuf, nil
}
func (bs *RemBackingStore) Write(wbuf []byte, offset int64) error {
length, err := bs.RemBs.WriteAt(wbuf, offset)
if err != nil {
log.Error(err)
return err
}
if length != len(wbuf) {
return fmt.Errorf("Incomplete write expected:%d actual:%d", len(wbuf), length)
}
return nil
}
func (bs *RemBackingStore) DataAdvise(offset, length int64, advise uint32) error {
return nil
}
func (bs *RemBackingStore) DataSync(offset, length int64) (err error) {
_, err = bs.RemBs.Sync()
return
}
func (bs *RemBackingStore) Unmap(bd []api.UnmapBlockDescriptor) (err error) {
//_, err = bs.RemBs.Unmap(int64(bd[0].Offset), int64(bd[0].TL))
return
}

View File

@@ -228,9 +228,10 @@ const (
NAA_IEEE_REGD_EXTD = byte(0x6) NAA_IEEE_REGD_EXTD = byte(0x6)
) )
const ( var (
SCSIVendorID = "GOSTOR" SCSIVendorID = "GOSTOR"
SCSIProductID = "GOTGT" SCSIProductID = "GOTGT"
SCSIID = "iqn.2016-09.com.gotgt.gostor:iscsi-tgt"
) )
/* /*

View File

@@ -28,6 +28,27 @@ type SCSITargetDriver interface {
NewTarget(string, *config.Config) error NewTarget(string, *config.Config) error
RereadTargetLUNMap() RereadTargetLUNMap()
Close() error Close() error
Resize(uint64) error
Stats() Stats
}
type Stats struct {
IsClientConnected bool
RevisionCounter int64
ReplicaCounter int64
SCSIIOCount map[int]int64
ReadIOPS int64
TotalReadTime int64
TotalReadBlockCount int64
WriteIOPS int64
TotalWriteTime int64
TotalWriteBlockCount int64
UsedLogicalBlocks int64
UsedBlocks int64
SectorSize int64
} }
type TargetDriverFunc func(*SCSITargetService) (SCSITargetDriver, error) type TargetDriverFunc func(*SCSITargetService) (SCSITargetDriver, error)

View File

@@ -37,6 +37,11 @@ const (
PR_EA_FN = (1 << 0) PR_EA_FN = (1 << 0)
) )
var (
EnableORWrite16 = true
EnablePersistentReservation = true
)
type SBCSCSIDeviceProtocol struct { type SBCSCSIDeviceProtocol struct {
BaseSCSIDeviceProtocol BaseSCSIDeviceProtocol
} }
@@ -76,7 +81,7 @@ func (sbc SBCSCSIDeviceProtocol) InitLu(lu *api.SCSILu) error {
leave it with a default target name leave it with a default target name
*/ */
lu.Attrs.SCSIID = "iqn.2016-09.com.gotgt.gostor:iscsi-tgt" lu.Attrs.SCSIID = SCSIID
/* /*
The PRODUCT SERIAL NUMBER field contains The PRODUCT SERIAL NUMBER field contains
right-aligned ASCII data (see 4.3.1) right-aligned ASCII data (see 4.3.1)
@@ -176,26 +181,29 @@ func NewSBCDevice(deviceType api.SCSIDeviceType) api.SCSIDeviceProtocol {
sbc.SCSIDeviceOps[api.MODE_SELECT_10] = NewSCSIDeviceOperation(SBCModeSelect, nil, PR_WE_FA|PR_EA_FA|PR_EA_FN|PR_WE_FN) sbc.SCSIDeviceOps[api.MODE_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.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, []*SCSIServiceAction{ if EnablePersistentReservation {
{ServiceAction: PR_IN_READ_KEYS, CommandPerformFunc: SPCPRReadKeys}, sbc.SCSIDeviceOps[api.PERSISTENT_RESERVE_IN] = NewSCSIDeviceOperation(SPCServiceAction, []*SCSIServiceAction{
{ServiceAction: PR_IN_READ_RESERVATION, CommandPerformFunc: SPCPRReadReservation}, {ServiceAction: PR_IN_READ_KEYS, CommandPerformFunc: SPCPRReadKeys},
{ServiceAction: PR_IN_REPORT_CAPABILITIES, CommandPerformFunc: SPCPRReportCapabilities}, {ServiceAction: PR_IN_READ_RESERVATION, CommandPerformFunc: SPCPRReadReservation},
}, 0) {ServiceAction: PR_IN_REPORT_CAPABILITIES, CommandPerformFunc: SPCPRReportCapabilities},
}, 0)
sbc.SCSIDeviceOps[api.PERSISTENT_RESERVE_OUT] = NewSCSIDeviceOperation(SPCServiceAction, []*SCSIServiceAction{
{ServiceAction: PR_OUT_REGISTER, CommandPerformFunc: SPCPRRegister},
{ServiceAction: PR_OUT_RESERVE, CommandPerformFunc: SPCPRReserve},
{ServiceAction: PR_OUT_RELEASE, CommandPerformFunc: SPCPRRelease},
{ServiceAction: PR_OUT_CLEAR, CommandPerformFunc: SPCPRClear},
{ServiceAction: PR_OUT_PREEMPT, CommandPerformFunc: SPCPRPreempt},
// {ServiceAction: PR_OUT_PREEMPT_AND_ABORT, CommandPerformFunc: SPCPRPreempt},
{ServiceAction: PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY, CommandPerformFunc: SPCPRRegister},
{ServiceAction: PR_OUT_REGISTER_AND_MOVE, CommandPerformFunc: SPCPRRegisterAndMove},
}, 0)
sbc.SCSIDeviceOps[api.PERSISTENT_RESERVE_OUT] = NewSCSIDeviceOperation(SPCServiceAction, []*SCSIServiceAction{
{ServiceAction: PR_OUT_REGISTER, CommandPerformFunc: SPCPRRegister},
{ServiceAction: PR_OUT_RESERVE, CommandPerformFunc: SPCPRReserve},
{ServiceAction: PR_OUT_RELEASE, CommandPerformFunc: SPCPRRelease},
{ServiceAction: PR_OUT_CLEAR, CommandPerformFunc: SPCPRClear},
{ServiceAction: PR_OUT_PREEMPT, CommandPerformFunc: SPCPRPreempt},
// {ServiceAction: PR_OUT_PREEMPT_AND_ABORT, CommandPerformFunc: SPCPRPreempt},
{ServiceAction: PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY, CommandPerformFunc: SPCPRRegister},
{ServiceAction: PR_OUT_REGISTER_AND_MOVE, CommandPerformFunc: SPCPRRegisterAndMove},
}, 0)
}
sbc.SCSIDeviceOps[api.READ_16] = NewSCSIDeviceOperation(SBCReadWrite, 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.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) if EnableORWrite16 {
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.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[api.VERIFY_16] = NewSCSIDeviceOperation(SBCVerify, nil, PR_EA_FA|PR_EA_FN)
@@ -459,7 +467,9 @@ func SBCReadWrite(host int, cmd *api.SCSICommand) api.SAMStat {
err, key, asc = bsPerformCommand(dev.Storage, cmd) err, key, asc = bsPerformCommand(dev.Storage, cmd)
if err != nil { if err != nil {
goto sense log.Errorf("Error from backend: %v", err)
BuildSenseData(cmd, key, asc)
return api.SAMStatBusy
} else { } else {
return api.SAMStatGood return api.SAMStatGood
} }
@@ -533,7 +543,9 @@ overflow:
cmd.InSDBBuffer.Resid = 8 cmd.InSDBBuffer.Resid = 8
return api.SAMStatGood return api.SAMStatGood
sense: sense:
cmd.InSDBBuffer.Resid = 0 if cmd.InSDBBuffer != nil {
cmd.InSDBBuffer.Resid = 0
}
BuildSenseData(cmd, key, asc) BuildSenseData(cmd, key, asc)
return api.SAMStatCheckCondition return api.SAMStatCheckCondition
} }
@@ -679,7 +691,9 @@ func SBCGetLbaStatus(host int, cmd *api.SCSICommand) api.SAMStat {
} }
return api.SAMStatGood return api.SAMStatGood
sense: sense:
cmd.InSDBBuffer.Resid = 0 if cmd.InSDBBuffer != nil {
cmd.InSDBBuffer.Resid = 0
}
BuildSenseData(cmd, key, asc) BuildSenseData(cmd, key, asc)
return api.SAMStatCheckCondition return api.SAMStatCheckCondition
} }

View File

@@ -53,6 +53,20 @@ func (s *SCSITargetService) GetTargetList() ([]api.SCSITarget, error) {
return result, nil return result, nil
} }
func (s *SCSITargetService) Resize(size uint64) error {
s.mutex.Lock()
//TODO for multiple LUNs
for _, t := range s.Targets {
if t.Devices != nil {
for i := range t.Devices {
t.Devices[i].Size = size
}
}
}
s.mutex.Unlock()
return nil
}
func (s *SCSITargetService) AddCommandQueue(tid int, scmd *api.SCSICommand) error { func (s *SCSITargetService) AddCommandQueue(tid int, scmd *api.SCSICommand) error {
var ( var (
target *api.SCSITarget target *api.SCSITarget
@@ -96,7 +110,7 @@ func (s *SCSITargetService) AddCommandQueue(tid int, scmd *api.SCSICommand) erro
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
log.Warnf("%v", result.Err) log.Warnf("opcode: %xh err: %v", scmd.OpCode, result.Err)
} }
return nil return nil
} }
@@ -128,9 +142,18 @@ func NewSCSIDeviceOperation(fn api.CommandFunc, sa []*SCSIServiceAction, pr uint
func BuildSenseData(cmd *api.SCSICommand, key byte, asc SCSISubError) { func BuildSenseData(cmd *api.SCSICommand, key byte, asc SCSISubError) {
senseBuffer := &bytes.Buffer{} senseBuffer := &bytes.Buffer{}
inBufLen, ok := SCSICDBBufXLength(cmd.SCB) inBufLen, ok := SCSICDBBufXLength(cmd.SCB)
var length uint32 = 0xa var (
length uint32 = 0xa
fixedFormat bool = true
)
if cmd.Device.Attrs.SenseFormat { if cmd.Device != nil {
if cmd.Device.Attrs.SenseFormat {
fixedFormat = false
}
}
if !fixedFormat {
// descriptor format // descriptor format
// current, not deferred // current, not deferred
senseBuffer.WriteByte(0x72) senseBuffer.WriteByte(0x72)

View File

@@ -17,6 +17,7 @@ limitations under the License.
package scsi package scsi
import ( import (
"errors"
"fmt" "fmt"
"strconv" "strconv"
"sync" "sync"
@@ -33,9 +34,15 @@ type SCSILUMap struct {
AllDevices api.LUNMap AllDevices api.LUNMap
// use target name as the key for target's LUN map // use target name as the key for target's LUN map
TargetsLUNMap map[string]api.LUNMap TargetsLUNMap map[string]api.LUNMap
TargetsBSMap map[string]api.RemoteBackingStore /* use target name as the key for target's Backing Store (temp) */
} }
var globalSCSILUMap = SCSILUMap{AllDevices: make(api.LUNMap), TargetsLUNMap: make(map[string]api.LUNMap)} var globalSCSILUMap = SCSILUMap{
AllDevices: make(api.LUNMap),
TargetsLUNMap: make(map[string]api.LUNMap),
TargetsBSMap: make(map[string]api.RemoteBackingStore),
}
type LUNMapping struct { type LUNMapping struct {
TargetName string TargetName string
@@ -71,6 +78,18 @@ func GetTargetLUNMap(tgtName string) api.LUNMap {
return lunMap return lunMap
} }
func GetTargetBSMap(tgtName string) (api.RemoteBackingStore, error) {
globalSCSILUMap.mutex.RLock()
defer globalSCSILUMap.mutex.RUnlock()
bs, ok := globalSCSILUMap.TargetsBSMap[tgtName]
if !ok {
return nil, errors.New("Remote backing store is not found in globalSCSILUMap")
}
return bs, nil
}
func AddBackendStorage(bs config.BackendStorage) error { func AddBackendStorage(bs config.BackendStorage) error {
globalSCSILUMap.mutex.Lock() globalSCSILUMap.mutex.Lock()
defer globalSCSILUMap.mutex.Unlock() defer globalSCSILUMap.mutex.Unlock()
@@ -130,3 +149,30 @@ func InitSCSILUMap(config *config.Config) error {
} }
return nil return nil
} }
func InitSCSILUMapEx(config *config.BackendStorage, tgtName string, lun uint64, bs api.RemoteBackingStore) error {
if bs == nil {
return errors.New("Remote backing store is nil")
}
globalSCSILUMap.mutex.Lock()
globalSCSILUMap.TargetsBSMap[tgtName] = bs
globalSCSILUMap.mutex.Unlock()
lu, err := NewSCSILu(config)
if err != nil {
return fmt.Errorf("Init SCSI LU map error, err: %v", err)
}
globalSCSILUMap.mutex.Lock()
globalSCSILUMap.AllDevices[config.DeviceID] = lu
globalSCSILUMap.mutex.Unlock()
mappingLUN(LUNMapping{
DeviceID: config.DeviceID,
LUN: lun,
TargetName: tgtName,
},
)
return nil
}

View File

@@ -28,8 +28,12 @@ import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
var (
EnableMultipath = true
)
func SPCIllegalOp(host int, cmd *api.SCSICommand) api.SAMStat { func SPCIllegalOp(host int, cmd *api.SCSICommand) api.SAMStat {
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB) BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_OP_CODE)
return api.SAMStatCheckCondition return api.SAMStatCheckCondition
} }
@@ -325,7 +329,11 @@ func SPCInquiry(host int, cmd *api.SCSICommand) api.SAMStat {
} }
//byte 5 //byte 5
//SCCS(0) AAC(0) TPGS(0) 3PC(0) PROTECT(0) //SCCS(0) AAC(0) TPGS(0) 3PC(0) PROTECT(0)
addBuf.WriteByte(INQUIRY_TPGS_IMPLICIT) if EnableMultipath {
addBuf.WriteByte(INQUIRY_TPGS_IMPLICIT)
} else {
addBuf.WriteByte(INQUIRY_TPGS_NO)
}
//byte 6 //byte 6
//ENCSERV(0) VS(0) MULTIP(0) ADDR16(0) //ENCSERV(0) VS(0) MULTIP(0) ADDR16(0)
addBuf.WriteByte(0x00) addBuf.WriteByte(0x00)
@@ -454,7 +462,9 @@ func SPCReportLuns(host int, cmd *api.SCSICommand) api.SAMStat {
copy(cmd.InSDBBuffer.Buffer, buf.Bytes()) copy(cmd.InSDBBuffer.Buffer, buf.Bytes())
return api.SAMStatGood return api.SAMStatGood
sense: sense:
cmd.InSDBBuffer.Resid = 0 if cmd.InSDBBuffer != nil {
cmd.InSDBBuffer.Resid = 0
}
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB) BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
return api.SAMStatCheckCondition return api.SAMStatCheckCondition
} }
@@ -467,7 +477,9 @@ func SPCStartStop(host int, cmd *api.SCSICommand) api.SAMStat {
return api.SAMStatReservationConflict return api.SAMStatReservationConflict
} }
cmd.InSDBBuffer.Resid = 0 if cmd.InSDBBuffer != nil {
cmd.InSDBBuffer.Resid = 0
}
scb := cmd.SCB scb := cmd.SCB
pwrcnd = scb[4] & 0xf0 pwrcnd = scb[4] & 0xf0
if pwrcnd != 0 { if pwrcnd != 0 {
@@ -662,7 +674,9 @@ func SPCSendDiagnostics(host int, cmd *api.SCSICommand) api.SAMStat {
return api.SAMStatGood return api.SAMStatGood
sense: sense:
cmd.InSDBBuffer.Resid = 0 if cmd.InSDBBuffer != nil {
cmd.InSDBBuffer.Resid = 0
}
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB) BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
return api.SAMStatCheckCondition return api.SAMStatCheckCondition
} }
@@ -711,7 +725,7 @@ func reportOpcodesAll(cmd *api.SCSICommand, rctd int) error {
} }
func reportOpcodeOne(cmd *api.SCSICommand, rctd int, opcode byte, rsa uint16, serviceAction bool) error { func reportOpcodeOne(cmd *api.SCSICommand, rctd int, opcode byte, rsa uint16, serviceAction bool) error {
return fmt.Errorf("non support") return fmt.Errorf("rsa: %xh, sa:%v not supported", rsa, serviceAction)
} }
func SPCReportSupportedOperationCodes(host int, cmd *api.SCSICommand) api.SAMStat { func SPCReportSupportedOperationCodes(host int, cmd *api.SCSICommand) api.SAMStat {
@@ -748,7 +762,9 @@ func SPCReportSupportedOperationCodes(host int, cmd *api.SCSICommand) api.SAMSta
return api.SAMStatGood return api.SAMStatGood
sense: sense:
cmd.InSDBBuffer.Resid = 0 if cmd.InSDBBuffer != nil {
cmd.InSDBBuffer.Resid = 0
}
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB) BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
return api.SAMStatCheckCondition return api.SAMStatCheckCondition
} }
@@ -764,7 +780,9 @@ func SPCServiceAction(host int, cmd *api.SCSICommand) api.SAMStat {
fnop := serviceAction.(*SCSIServiceAction) fnop := serviceAction.(*SCSIServiceAction)
return fnop.CommandPerformFunc(host, cmd) return fnop.CommandPerformFunc(host, cmd)
} }
cmd.InSDBBuffer.Resid = 0 if cmd.InSDBBuffer != nil {
cmd.InSDBBuffer.Resid = 0
}
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB) BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
return api.SAMStatCheckCondition return api.SAMStatCheckCondition
} }
@@ -797,7 +815,9 @@ func SPCPRReadKeys(host int, cmd *api.SCSICommand) api.SAMStat {
cmd.InSDBBuffer.Resid = uint32(additionLength) cmd.InSDBBuffer.Resid = uint32(additionLength)
return api.SAMStatGood return api.SAMStatGood
sense: sense:
cmd.InSDBBuffer.Resid = 0 if cmd.InSDBBuffer != nil {
cmd.InSDBBuffer.Resid = 0
}
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB) BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
return api.SAMStatCheckCondition return api.SAMStatCheckCondition
} }
@@ -853,7 +873,9 @@ func SPCPRReadReservation(host int, cmd *api.SCSICommand) api.SAMStat {
return api.SAMStatGood return api.SAMStatGood
sense: sense:
cmd.InSDBBuffer.Resid = 0 if cmd.InSDBBuffer != nil {
cmd.InSDBBuffer.Resid = 0
}
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB) BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
return api.SAMStatCheckCondition return api.SAMStatCheckCondition
} }
@@ -891,7 +913,9 @@ func SPCPRReportCapabilities(host int, cmd *api.SCSICommand) api.SAMStat {
cmd.InSDBBuffer.Resid = uint32(actualLength) cmd.InSDBBuffer.Resid = uint32(actualLength)
return api.SAMStatGood return api.SAMStatGood
sense: sense:
cmd.InSDBBuffer.Resid = 0 if cmd.InSDBBuffer != nil {
cmd.InSDBBuffer.Resid = 0
}
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB) BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
return api.SAMStatCheckCondition return api.SAMStatCheckCondition
} }
@@ -970,7 +994,9 @@ func SPCPRRegister(host int, cmd *api.SCSICommand) api.SAMStat {
return api.SAMStatGood return api.SAMStatGood
sense: sense:
cmd.InSDBBuffer.Resid = 0 if cmd.InSDBBuffer != nil {
cmd.InSDBBuffer.Resid = 0
}
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB) BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
return api.SAMStatCheckCondition return api.SAMStatCheckCondition
} }
@@ -1032,7 +1058,9 @@ func SPCPRReserve(host int, cmd *api.SCSICommand) api.SAMStat {
scsiResOp.Save(tgtName, devUUID) scsiResOp.Save(tgtName, devUUID)
return api.SAMStatGood return api.SAMStatGood
sense: sense:
cmd.InSDBBuffer.Resid = 0 if cmd.InSDBBuffer != nil {
cmd.InSDBBuffer.Resid = 0
}
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB) BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
return api.SAMStatCheckCondition return api.SAMStatCheckCondition
} }
@@ -1082,7 +1110,9 @@ func SPCPRRelease(host int, cmd *api.SCSICommand) api.SAMStat {
} }
if curRes.Scope != resScope || curRes.Type != resType { if curRes.Scope != resScope || curRes.Type != resType {
cmd.InSDBBuffer.Resid = 0 if cmd.InSDBBuffer != nil {
cmd.InSDBBuffer.Resid = 0
}
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_RELEASE_OF_PERSISTENT_RESERVATION) BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_RELEASE_OF_PERSISTENT_RESERVATION)
return api.SAMStatCheckCondition return api.SAMStatCheckCondition
} }
@@ -1113,7 +1143,9 @@ func SPCPRRelease(host int, cmd *api.SCSICommand) api.SAMStat {
scsiResOp.Save(tgtName, devUUID) scsiResOp.Save(tgtName, devUUID)
return api.SAMStatGood return api.SAMStatGood
sense: sense:
cmd.InSDBBuffer.Resid = 0 if cmd.InSDBBuffer != nil {
cmd.InSDBBuffer.Resid = 0
}
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB) BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
return api.SAMStatCheckCondition return api.SAMStatCheckCondition
} }
@@ -1167,7 +1199,9 @@ func SPCPRClear(host int, cmd *api.SCSICommand) api.SAMStat {
scsiResOp.Save(tgtName, devUUID) scsiResOp.Save(tgtName, devUUID)
return api.SAMStatGood return api.SAMStatGood
sense: sense:
cmd.InSDBBuffer.Resid = 0 if cmd.InSDBBuffer != nil {
cmd.InSDBBuffer.Resid = 0
}
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB) BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
return api.SAMStatCheckCondition return api.SAMStatCheckCondition
} }
@@ -1267,7 +1301,9 @@ func SPCPRPreempt(host int, cmd *api.SCSICommand) api.SAMStat {
scsiResOp.Save(tgtName, devUUID) scsiResOp.Save(tgtName, devUUID)
return api.SAMStatGood return api.SAMStatGood
sense: sense:
cmd.InSDBBuffer.Resid = 0 if cmd.InSDBBuffer != nil {
cmd.InSDBBuffer.Resid = 0
}
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB) BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
return api.SAMStatCheckCondition return api.SAMStatCheckCondition
} }
@@ -1353,7 +1389,9 @@ found:
scsiResOp.Save(tgtName, devUUID) scsiResOp.Save(tgtName, devUUID)
return api.SAMStatGood return api.SAMStatGood
sense: sense:
cmd.InSDBBuffer.Resid = 0 if cmd.InSDBBuffer != nil {
cmd.InSDBBuffer.Resid = 0
}
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB) BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
return api.SAMStatCheckCondition return api.SAMStatCheckCondition
} }