Merge pull request #93 from utkarshmani1997/jiva-integration
integrate openebs/jiva with gotgt
This commit is contained in:
@@ -17,6 +17,7 @@ package api
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"sync"
|
||||
|
||||
uuid "github.com/satori/go.uuid"
|
||||
@@ -165,6 +166,7 @@ var (
|
||||
)
|
||||
|
||||
type SCSICommand struct {
|
||||
OpCode byte
|
||||
Target *SCSITarget
|
||||
DeviceID uint64
|
||||
Device *SCSILu
|
||||
@@ -395,6 +397,9 @@ type SCSILu struct {
|
||||
Storage BackingStore
|
||||
DeviceProtocol SCSIDeviceProtocol
|
||||
ModeBlockDescriptor []byte
|
||||
SCSIVendorID string
|
||||
SCSIProductID string
|
||||
SCSIID string
|
||||
|
||||
PerformCommand CommandFunc
|
||||
FinishCommand func(*SCSITarget, *SCSICommand)
|
||||
@@ -406,3 +411,14 @@ type UnmapBlockDescriptor struct {
|
||||
Offset uint64
|
||||
TL uint32
|
||||
}
|
||||
|
||||
type ReaderWriterAt interface {
|
||||
io.ReaderAt
|
||||
io.WriterAt
|
||||
}
|
||||
|
||||
type RemoteBackingStore interface {
|
||||
ReaderWriterAt
|
||||
Sync() (int, error)
|
||||
Unmap(int64, int64) (int, error)
|
||||
}
|
||||
|
||||
@@ -20,7 +20,9 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gostor/gotgt/pkg/api"
|
||||
"github.com/gostor/gotgt/pkg/util"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
@@ -93,6 +95,7 @@ type ISCSICommand struct {
|
||||
FinalInSeq bool
|
||||
Immediate bool
|
||||
TaskTag uint32
|
||||
StartTime time.Time
|
||||
ExpCmdSN, MaxCmdSN uint32
|
||||
AHSLen int
|
||||
Resid uint32
|
||||
@@ -124,6 +127,7 @@ type ISCSICommand struct {
|
||||
StatusDetail uint8
|
||||
|
||||
// SCSI commands
|
||||
SCSIOpCode byte
|
||||
ExpectedDataLen uint32
|
||||
CDB []byte
|
||||
Status byte
|
||||
@@ -225,6 +229,7 @@ func parseHeader(data []byte) (*ISCSICommand, error) {
|
||||
m.AHSLen = int(data[4]) * 4
|
||||
m.DataLen = int(ParseUint(data[5:8]))
|
||||
m.TaskTag = uint32(ParseUint(data[16:20]))
|
||||
m.StartTime = time.Now()
|
||||
switch m.OpCode {
|
||||
case OpSCSICmd:
|
||||
m.LUN = [8]byte{data[9]}
|
||||
@@ -234,6 +239,14 @@ func parseHeader(data []byte) (*ISCSICommand, error) {
|
||||
m.Write = data[1]&0x20 == 0x20
|
||||
m.CDB = data[32:48]
|
||||
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
|
||||
case OpSCSITaskReq:
|
||||
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[40:], util.MarshalUint32(m.BufferOffset))
|
||||
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
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ var (
|
||||
)
|
||||
|
||||
type iscsiConnection struct {
|
||||
ConnNum int
|
||||
state int
|
||||
authState int
|
||||
session *ISCSISession
|
||||
@@ -96,12 +97,13 @@ const (
|
||||
)
|
||||
|
||||
type iscsiTask struct {
|
||||
tag uint32
|
||||
conn *iscsiConnection
|
||||
cmd *ISCSICommand
|
||||
scmd *api.SCSICommand
|
||||
state taskState
|
||||
result byte
|
||||
tag uint32
|
||||
conn *iscsiConnection
|
||||
cmd *ISCSICommand
|
||||
scmd *api.SCSICommand
|
||||
state taskState
|
||||
expectedDataLength int64
|
||||
result byte
|
||||
|
||||
offset int
|
||||
r2tCount int
|
||||
@@ -154,6 +156,7 @@ func (conn *iscsiConnection) buildRespPackage(oc OpCode, task *iscsiTask) error
|
||||
task = conn.rxTask
|
||||
}
|
||||
conn.resp = &ISCSICommand{
|
||||
StartTime: conn.req.StartTime,
|
||||
StatSN: conn.req.ExpStatSN,
|
||||
TaskTag: conn.req.TaskTag,
|
||||
ExpCmdSN: conn.session.ExpCmdSN,
|
||||
@@ -164,6 +167,7 @@ func (conn *iscsiConnection) buildRespPackage(oc OpCode, task *iscsiTask) error
|
||||
case OpReady:
|
||||
conn.resp.OpCode = OpReady
|
||||
conn.resp.R2TSN = task.r2tSN
|
||||
conn.resp.Final = true
|
||||
conn.resp.BufferOffset = uint32(task.offset)
|
||||
conn.resp.DesiredLength = uint32(task.r2tCount)
|
||||
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:
|
||||
conn.resp.OpCode = oc
|
||||
conn.resp.SCSIOpCode = conn.req.SCSIOpCode
|
||||
conn.resp.Immediate = true
|
||||
conn.resp.Final = true
|
||||
conn.resp.SCSIResponse = 0x00
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gostor/gotgt/pkg/api"
|
||||
"github.com/gostor/gotgt/pkg/config"
|
||||
@@ -35,15 +36,30 @@ const (
|
||||
ISCSI_UNSPEC_TSIH = uint16(0)
|
||||
)
|
||||
|
||||
type ISCSITargetDriver struct {
|
||||
SCSI *scsi.SCSITargetService
|
||||
Name string
|
||||
iSCSITargets map[string]*ISCSITarget
|
||||
TSIHPool map[uint16]bool
|
||||
TSIHPoolMutex sync.Mutex
|
||||
const (
|
||||
STATE_INIT = iota
|
||||
STATE_RUNNING
|
||||
STATE_SHUTTING_DOWN
|
||||
STATE_TERMINATE
|
||||
)
|
||||
|
||||
mu sync.Mutex
|
||||
l net.Listener
|
||||
var (
|
||||
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() {
|
||||
@@ -51,12 +67,19 @@ func init() {
|
||||
}
|
||||
|
||||
func NewISCSITargetDriver(base *scsi.SCSITargetService) (scsi.SCSITargetDriver, error) {
|
||||
return &ISCSITargetDriver{
|
||||
driver := &ISCSITargetDriver{
|
||||
Name: iSCSIDriverName,
|
||||
iSCSITargets: map[string]*ISCSITarget{},
|
||||
SCSI: base,
|
||||
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 {
|
||||
@@ -165,46 +188,72 @@ func (s *ISCSITargetDriver) Run() error {
|
||||
s.mu.Lock()
|
||||
s.l = l
|
||||
s.mu.Unlock()
|
||||
log.Infof("iSCSI service listening on: %v", s.l.Addr())
|
||||
|
||||
s.setState(STATE_RUNNING)
|
||||
for {
|
||||
log.Info("Listening ...")
|
||||
conn, err := l.Accept()
|
||||
if err != nil {
|
||||
if err, ok := err.(net.Error); ok {
|
||||
if !err.Temporary() {
|
||||
log.Info("Closing ...")
|
||||
log.Warning("Closing connection with initiator...")
|
||||
break
|
||||
}
|
||||
}
|
||||
log.Error(err)
|
||||
continue
|
||||
}
|
||||
|
||||
log.Info(conn.LocalAddr().String())
|
||||
log.Info("Accepting ...")
|
||||
s.setClientStatus(true)
|
||||
|
||||
iscsiConn := &iscsiConnection{conn: conn,
|
||||
loginParam: &iscsiLoginParam{}}
|
||||
|
||||
iscsiConn.init()
|
||||
iscsiConn.rxIOState = IOSTATE_RX_BHS
|
||||
|
||||
log.Infof("connection is connected from %s...\n", conn.RemoteAddr().String())
|
||||
log.Infof("Target is connected to initiator: %s", conn.RemoteAddr().String())
|
||||
// start a new thread to do with this command
|
||||
go s.handler(DATAIN, iscsiConn)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ISCSITargetDriver) setClientStatus(ok bool) {
|
||||
s.isClientConnected = ok
|
||||
}
|
||||
|
||||
func (s *ISCSITargetDriver) isInitiatorConnected() bool {
|
||||
return s.isClientConnected
|
||||
}
|
||||
func (s *ISCSITargetDriver) Close() error {
|
||||
s.mu.Lock()
|
||||
l := s.l
|
||||
s.setClientStatus(false)
|
||||
s.mu.Unlock()
|
||||
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
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
if events&DATAIN != 0 {
|
||||
@@ -324,6 +373,7 @@ func (s *ISCSITargetDriver) rxHandler(conn *iscsiConnection) {
|
||||
}
|
||||
case OpLogoutReq:
|
||||
log.Debug("OpLogoutReq")
|
||||
s.setClientStatus(false)
|
||||
if err := iscsiExecLogout(conn); err != nil {
|
||||
log.Warningf("set connection to close")
|
||||
conn.state = CONN_STATE_CLOSE
|
||||
@@ -386,6 +436,7 @@ func (s *ISCSITargetDriver) iscsiExecLogin(conn *iscsiConnection) error {
|
||||
}
|
||||
|
||||
func iscsiExecLogout(conn *iscsiConnection) error {
|
||||
log.Infof("Logout request received from initiator: %v", conn.conn.RemoteAddr().String())
|
||||
cmd := conn.req
|
||||
conn.resp = &ISCSICommand{
|
||||
OpCode: OpLogoutResp,
|
||||
@@ -473,6 +524,12 @@ func (s *ISCSITargetDriver) txHandler(conn *iscsiConnection) {
|
||||
resp.DataSN = 0
|
||||
maxCount := conn.maxSeqCount
|
||||
|
||||
if s.enableStats {
|
||||
if resp.OpCode == OpSCSIResp || resp.OpCode == OpSCSIIn {
|
||||
s.UpdateStats(conn)
|
||||
}
|
||||
}
|
||||
|
||||
/* send data splitted by segmentLen */
|
||||
SendRemainingData:
|
||||
if resp.OpCode == OpSCSIIn {
|
||||
@@ -573,6 +630,13 @@ func (s *ISCSITargetDriver) scsiCommandHandler(conn *iscsiConnection) (err error
|
||||
switch req.OpCode {
|
||||
case OpSCSICmd:
|
||||
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{
|
||||
ITNexusID: conn.session.ITNexus.ID,
|
||||
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.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 {
|
||||
task.r2tCount = int(req.ExpectedDataLen) - req.DataLen
|
||||
task.expectedDataLength = int64(req.ExpectedDataLen)
|
||||
if !req.Final {
|
||||
task.unsolCount = 1
|
||||
}
|
||||
@@ -649,7 +722,7 @@ func (s *ISCSITargetDriver) scsiCommandHandler(conn *iscsiConnection) (err error
|
||||
}
|
||||
return
|
||||
} else {
|
||||
if scmd.Direction == api.SCSIDataRead && scmd.SenseBuffer == nil {
|
||||
if scmd.Direction == api.SCSIDataRead && scmd.SenseBuffer == nil && req.ExpectedDataLen != 0 {
|
||||
conn.buildRespPackage(OpSCSIIn, task)
|
||||
} else {
|
||||
conn.buildRespPackage(OpSCSIResp, task)
|
||||
@@ -710,6 +783,7 @@ func (s *ISCSITargetDriver) scsiCommandHandler(conn *iscsiConnection) (err error
|
||||
case OpNoopOut:
|
||||
iscsiExecNoopOut(conn)
|
||||
case OpLogoutReq:
|
||||
s.setClientStatus(false)
|
||||
conn.txTask = &iscsiTask{conn: conn, cmd: conn.req, tag: conn.req.TaskTag}
|
||||
conn.txIOState = IOSTATE_TX_BHS
|
||||
iscsiExecLogout(conn)
|
||||
@@ -824,13 +898,31 @@ func (s *ISCSITargetDriver) iscsiExecTask(task *iscsiTask) error {
|
||||
fallthrough
|
||||
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
|
||||
return fmt.Errorf("The task function is not supported")
|
||||
default:
|
||||
task.result = ISCSI_TMF_RSP_REJECTED
|
||||
return fmt.Errorf("Unknown task function")
|
||||
}
|
||||
// return response to initiator
|
||||
return task.conn.buildRespPackage(OpSCSITaskResp, task)
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,8 +152,8 @@ func (conn *iscsiConnection) processLoginData() ([]util.KeyValue, error) {
|
||||
conn.loginParam.iniCSG, conn.loginParam.iniNSG, conn.loginParam.iniTrans)
|
||||
}
|
||||
} else {
|
||||
conn.loginParam.tgtNSG = LoginOperationalNegotiation
|
||||
conn.loginParam.tgtTrans = false
|
||||
conn.loginParam.tgtNSG = FullFeaturePhase
|
||||
conn.loginParam.tgtTrans = true
|
||||
}
|
||||
return negoKV, nil
|
||||
}
|
||||
|
||||
@@ -184,13 +184,13 @@ func boolKeyInConv(value uint) string {
|
||||
|
||||
var sessionKeys map[string]*iscsiSessionKeys = map[string]*iscsiSessionKeys{
|
||||
// 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
|
||||
"HeaderDigest": {ISCSI_PARAM_HDRDGST_EN, false, DIGEST_NONE, DIGEST_NONE, DIGEST_ALL, digestKeyConv, digestKeyInConv},
|
||||
// ISCSI_PARAM_DATADGST_EN
|
||||
"DataDigest": {ISCSI_PARAM_DATADGST_EN, false, DIGEST_NONE, DIGEST_NONE, DIGEST_ALL, digestKeyConv, digestKeyInConv},
|
||||
// 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
|
||||
"MaxOutstandingR2T": {ISCSI_PARAM_MAX_R2T, true, 1, 1, 65535, numberKeyConv, numberKeyInConv},
|
||||
// ISCSI_PARAM_IMM_DATA_EN
|
||||
@@ -392,8 +392,8 @@ func (s *ISCSITargetDriver) BindISCSISession(conn *iscsiConnection) error {
|
||||
}
|
||||
|
||||
if newSess.SessionType == SESSION_NORMAL {
|
||||
log.Infof("New Session initiator name:%v,target name:%v,ISID:0x%x",
|
||||
conn.loginParam.initiator, conn.loginParam.target, conn.loginParam.isid)
|
||||
log.Infof("Login request received from initiator: %v, Session type: %s, Target name:%v, ISID: 0x%x",
|
||||
conn.loginParam.initiator, "Normal", conn.loginParam.target, conn.loginParam.isid)
|
||||
//register normal session
|
||||
itnexus := &api.ITNexus{uuid.NewV1(), GeniSCSIITNexusID(newSess)}
|
||||
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.SessionsRWMutex.Unlock()
|
||||
} 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
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
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)
|
||||
case api.PRE_FETCH_10, api.PRE_FETCH_16:
|
||||
err = bs.DataAdvise(int64(offset), tl, util.POSIX_FADV_WILLNEED)
|
||||
@@ -148,7 +153,7 @@ write:
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
key = MEDIUM_ERROR
|
||||
asc = ASC_READ_ERROR
|
||||
asc = ASC_WRITE_ERROR
|
||||
goto sense
|
||||
}
|
||||
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 err = bs.DataSync(int64(offset), tl); err != nil {
|
||||
key = MEDIUM_ERROR
|
||||
asc = ASC_READ_ERROR
|
||||
asc = ASC_WRITE_ERROR
|
||||
goto sense
|
||||
}
|
||||
}
|
||||
|
||||
118
pkg/scsi/backingstore/remote/remote.go
Normal file
118
pkg/scsi/backingstore/remote/remote.go
Normal 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
|
||||
}
|
||||
@@ -228,9 +228,10 @@ const (
|
||||
NAA_IEEE_REGD_EXTD = byte(0x6)
|
||||
)
|
||||
|
||||
const (
|
||||
var (
|
||||
SCSIVendorID = "GOSTOR"
|
||||
SCSIProductID = "GOTGT"
|
||||
SCSIID = "iqn.2016-09.com.gotgt.gostor:iscsi-tgt"
|
||||
)
|
||||
|
||||
/*
|
||||
|
||||
@@ -28,6 +28,27 @@ type SCSITargetDriver interface {
|
||||
NewTarget(string, *config.Config) error
|
||||
RereadTargetLUNMap()
|
||||
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)
|
||||
|
||||
@@ -37,6 +37,11 @@ const (
|
||||
PR_EA_FN = (1 << 0)
|
||||
)
|
||||
|
||||
var (
|
||||
EnableORWrite16 = true
|
||||
EnablePersistentReservation = true
|
||||
)
|
||||
|
||||
type SBCSCSIDeviceProtocol struct {
|
||||
BaseSCSIDeviceProtocol
|
||||
}
|
||||
@@ -76,7 +81,7 @@ func (sbc SBCSCSIDeviceProtocol) InitLu(lu *api.SCSILu) error {
|
||||
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
|
||||
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_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{
|
||||
{ServiceAction: PR_IN_READ_KEYS, CommandPerformFunc: SPCPRReadKeys},
|
||||
{ServiceAction: PR_IN_READ_RESERVATION, CommandPerformFunc: SPCPRReadReservation},
|
||||
{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)
|
||||
if EnablePersistentReservation {
|
||||
sbc.SCSIDeviceOps[api.PERSISTENT_RESERVE_IN] = NewSCSIDeviceOperation(SPCServiceAction, []*SCSIServiceAction{
|
||||
{ServiceAction: PR_IN_READ_KEYS, CommandPerformFunc: SPCPRReadKeys},
|
||||
{ServiceAction: PR_IN_READ_RESERVATION, CommandPerformFunc: SPCPRReadReservation},
|
||||
{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.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)
|
||||
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.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)
|
||||
if err != nil {
|
||||
goto sense
|
||||
log.Errorf("Error from backend: %v", err)
|
||||
BuildSenseData(cmd, key, asc)
|
||||
return api.SAMStatBusy
|
||||
} else {
|
||||
return api.SAMStatGood
|
||||
}
|
||||
@@ -533,7 +543,9 @@ overflow:
|
||||
cmd.InSDBBuffer.Resid = 8
|
||||
return api.SAMStatGood
|
||||
sense:
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
if cmd.InSDBBuffer != nil {
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
}
|
||||
BuildSenseData(cmd, key, asc)
|
||||
return api.SAMStatCheckCondition
|
||||
}
|
||||
@@ -679,7 +691,9 @@ func SBCGetLbaStatus(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
}
|
||||
return api.SAMStatGood
|
||||
sense:
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
if cmd.InSDBBuffer != nil {
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
}
|
||||
BuildSenseData(cmd, key, asc)
|
||||
return api.SAMStatCheckCondition
|
||||
}
|
||||
|
||||
@@ -53,6 +53,20 @@ func (s *SCSITargetService) GetTargetList() ([]api.SCSITarget, error) {
|
||||
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 {
|
||||
var (
|
||||
target *api.SCSITarget
|
||||
@@ -96,7 +110,7 @@ func (s *SCSITargetService) AddCommandQueue(tid int, scmd *api.SCSICommand) erro
|
||||
result := scmd.Device.PerformCommand(tid, scmd)
|
||||
if result != api.SAMStatGood {
|
||||
scmd.Result = result.Stat
|
||||
log.Warnf("%v", result.Err)
|
||||
log.Warnf("opcode: %xh err: %v", scmd.OpCode, result.Err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -128,9 +142,18 @@ func NewSCSIDeviceOperation(fn api.CommandFunc, sa []*SCSIServiceAction, pr uint
|
||||
func BuildSenseData(cmd *api.SCSICommand, key byte, asc SCSISubError) {
|
||||
senseBuffer := &bytes.Buffer{}
|
||||
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
|
||||
// current, not deferred
|
||||
senseBuffer.WriteByte(0x72)
|
||||
|
||||
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package scsi
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"sync"
|
||||
@@ -33,9 +34,15 @@ type SCSILUMap struct {
|
||||
AllDevices api.LUNMap
|
||||
// use target name as the key for target's LUN map
|
||||
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 {
|
||||
TargetName string
|
||||
@@ -71,6 +78,18 @@ func GetTargetLUNMap(tgtName string) api.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 {
|
||||
globalSCSILUMap.mutex.Lock()
|
||||
defer globalSCSILUMap.mutex.Unlock()
|
||||
@@ -130,3 +149,30 @@ func InitSCSILUMap(config *config.Config) error {
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
@@ -28,8 +28,12 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var (
|
||||
EnableMultipath = true
|
||||
)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -325,7 +329,11 @@ func SPCInquiry(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
}
|
||||
//byte 5
|
||||
//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
|
||||
//ENCSERV(0) VS(0) MULTIP(0) ADDR16(0)
|
||||
addBuf.WriteByte(0x00)
|
||||
@@ -454,7 +462,9 @@ func SPCReportLuns(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
copy(cmd.InSDBBuffer.Buffer, buf.Bytes())
|
||||
return api.SAMStatGood
|
||||
sense:
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
if cmd.InSDBBuffer != nil {
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
}
|
||||
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
|
||||
return api.SAMStatCheckCondition
|
||||
}
|
||||
@@ -467,7 +477,9 @@ func SPCStartStop(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
return api.SAMStatReservationConflict
|
||||
}
|
||||
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
if cmd.InSDBBuffer != nil {
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
}
|
||||
scb := cmd.SCB
|
||||
pwrcnd = scb[4] & 0xf0
|
||||
if pwrcnd != 0 {
|
||||
@@ -662,7 +674,9 @@ func SPCSendDiagnostics(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
|
||||
return api.SAMStatGood
|
||||
sense:
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
if cmd.InSDBBuffer != nil {
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
}
|
||||
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
|
||||
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 {
|
||||
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 {
|
||||
@@ -748,7 +762,9 @@ func SPCReportSupportedOperationCodes(host int, cmd *api.SCSICommand) api.SAMSta
|
||||
return api.SAMStatGood
|
||||
|
||||
sense:
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
if cmd.InSDBBuffer != nil {
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
}
|
||||
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
|
||||
return api.SAMStatCheckCondition
|
||||
}
|
||||
@@ -764,7 +780,9 @@ func SPCServiceAction(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
fnop := serviceAction.(*SCSIServiceAction)
|
||||
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)
|
||||
return api.SAMStatCheckCondition
|
||||
}
|
||||
@@ -797,7 +815,9 @@ func SPCPRReadKeys(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
cmd.InSDBBuffer.Resid = uint32(additionLength)
|
||||
return api.SAMStatGood
|
||||
sense:
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
if cmd.InSDBBuffer != nil {
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
}
|
||||
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
|
||||
return api.SAMStatCheckCondition
|
||||
}
|
||||
@@ -853,7 +873,9 @@ func SPCPRReadReservation(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
return api.SAMStatGood
|
||||
|
||||
sense:
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
if cmd.InSDBBuffer != nil {
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
}
|
||||
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
|
||||
return api.SAMStatCheckCondition
|
||||
}
|
||||
@@ -891,7 +913,9 @@ func SPCPRReportCapabilities(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
cmd.InSDBBuffer.Resid = uint32(actualLength)
|
||||
return api.SAMStatGood
|
||||
sense:
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
if cmd.InSDBBuffer != nil {
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
}
|
||||
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
|
||||
return api.SAMStatCheckCondition
|
||||
}
|
||||
@@ -970,7 +994,9 @@ func SPCPRRegister(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
return api.SAMStatGood
|
||||
|
||||
sense:
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
if cmd.InSDBBuffer != nil {
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
}
|
||||
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
|
||||
return api.SAMStatCheckCondition
|
||||
}
|
||||
@@ -1032,7 +1058,9 @@ func SPCPRReserve(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
scsiResOp.Save(tgtName, devUUID)
|
||||
return api.SAMStatGood
|
||||
sense:
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
if cmd.InSDBBuffer != nil {
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
}
|
||||
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
|
||||
return api.SAMStatCheckCondition
|
||||
}
|
||||
@@ -1082,7 +1110,9 @@ func SPCPRRelease(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
}
|
||||
|
||||
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)
|
||||
return api.SAMStatCheckCondition
|
||||
}
|
||||
@@ -1113,7 +1143,9 @@ func SPCPRRelease(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
scsiResOp.Save(tgtName, devUUID)
|
||||
return api.SAMStatGood
|
||||
sense:
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
if cmd.InSDBBuffer != nil {
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
}
|
||||
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
|
||||
return api.SAMStatCheckCondition
|
||||
}
|
||||
@@ -1167,7 +1199,9 @@ func SPCPRClear(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
scsiResOp.Save(tgtName, devUUID)
|
||||
return api.SAMStatGood
|
||||
sense:
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
if cmd.InSDBBuffer != nil {
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
}
|
||||
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
|
||||
return api.SAMStatCheckCondition
|
||||
}
|
||||
@@ -1267,7 +1301,9 @@ func SPCPRPreempt(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
scsiResOp.Save(tgtName, devUUID)
|
||||
return api.SAMStatGood
|
||||
sense:
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
if cmd.InSDBBuffer != nil {
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
}
|
||||
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
|
||||
return api.SAMStatCheckCondition
|
||||
}
|
||||
@@ -1353,7 +1389,9 @@ found:
|
||||
scsiResOp.Save(tgtName, devUUID)
|
||||
return api.SAMStatGood
|
||||
sense:
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
if cmd.InSDBBuffer != nil {
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
}
|
||||
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
|
||||
return api.SAMStatCheckCondition
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user