perf
This commit is contained in:
@@ -16,7 +16,6 @@ limitations under the License.
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"errors"
|
"errors"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@@ -144,8 +143,13 @@ const (
|
|||||||
SCSIDataBidirection
|
SCSIDataBidirection
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type SenseBuffer struct {
|
||||||
|
Buffer []byte
|
||||||
|
Length uint32
|
||||||
|
}
|
||||||
|
|
||||||
type SCSIDataBuffer struct {
|
type SCSIDataBuffer struct {
|
||||||
Buffer *bytes.Buffer
|
Buffer []byte
|
||||||
Length uint32
|
Length uint32
|
||||||
TransferLength uint32
|
TransferLength uint32
|
||||||
Resid uint32
|
Resid uint32
|
||||||
@@ -166,21 +170,20 @@ type SCSICommand struct {
|
|||||||
Device *SCSILu
|
Device *SCSILu
|
||||||
State SCSICommandState
|
State SCSICommandState
|
||||||
Direction SCSIDataDirection
|
Direction SCSIDataDirection
|
||||||
InSDBBuffer SCSIDataBuffer
|
InSDBBuffer *SCSIDataBuffer
|
||||||
OutSDBBuffer SCSIDataBuffer
|
OutSDBBuffer *SCSIDataBuffer
|
||||||
RelTargetPortID uint16
|
RelTargetPortID uint16
|
||||||
// Command ITN ID
|
// Command ITN ID
|
||||||
ITNexusID uuid.UUID
|
ITNexusID uuid.UUID
|
||||||
Offset uint64
|
Offset uint64
|
||||||
TL uint32
|
TL uint32
|
||||||
SCB *bytes.Buffer
|
SCB []byte
|
||||||
SCBLength int
|
SCBLength int
|
||||||
Lun [8]uint8
|
Lun [8]uint8
|
||||||
Attribute int
|
Attribute int
|
||||||
Tag uint64
|
Tag uint64
|
||||||
Result byte
|
Result byte
|
||||||
SenseBuffer *bytes.Buffer
|
SenseBuffer *SenseBuffer
|
||||||
SenseLength uint32
|
|
||||||
ITNexus *ITNexus
|
ITNexus *ITNexus
|
||||||
ITNexusLuInfo *ITNexusLuInfo
|
ITNexusLuInfo *ITNexusLuInfo
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -334,7 +334,7 @@ func (m *ISCSICommand) dataInBytes() []byte {
|
|||||||
if m.Resid > 0 {
|
if m.Resid > 0 {
|
||||||
if m.Resid > m.ExpectedDataLen {
|
if m.Resid > m.ExpectedDataLen {
|
||||||
flag |= 0x04
|
flag |= 0x04
|
||||||
} else {
|
} else if m.Resid < m.ExpectedDataLen {
|
||||||
flag |= 0x02
|
flag |= 0x02
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import (
|
|||||||
|
|
||||||
"github.com/gostor/gotgt/pkg/api"
|
"github.com/gostor/gotgt/pkg/api"
|
||||||
"github.com/gostor/gotgt/pkg/util"
|
"github.com/gostor/gotgt/pkg/util"
|
||||||
|
"github.com/gostor/gotgt/pkg/util/pool"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -126,7 +127,7 @@ func (c *iscsiConnection) init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *iscsiConnection) readData(size int) ([]byte, int, error) {
|
func (c *iscsiConnection) readData(size int) ([]byte, int, error) {
|
||||||
var buf = make([]byte, size)
|
var buf = pool.NewBuffer(size)
|
||||||
length, err := io.ReadFull(c.conn, buf)
|
length, err := io.ReadFull(c.conn, buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, -1, err
|
return nil, -1, err
|
||||||
@@ -179,13 +180,16 @@ func (conn *iscsiConnection) buildRespPackage(oc OpCode, task *iscsiTask) error
|
|||||||
scmd := task.scmd
|
scmd := task.scmd
|
||||||
resp.Status = scmd.Result
|
resp.Status = scmd.Result
|
||||||
if scmd.Result != 0 && scmd.SenseBuffer != nil {
|
if scmd.Result != 0 && scmd.SenseBuffer != nil {
|
||||||
length := util.MarshalUint32(uint32(scmd.SenseLength))
|
length := util.MarshalUint32(scmd.SenseBuffer.Length)
|
||||||
resp.RawData = append(length[2:4], scmd.SenseBuffer.Bytes()...)
|
resp.RawData = append(length[2:4], scmd.SenseBuffer.Buffer...)
|
||||||
} else if scmd.Direction == api.SCSIDataRead || scmd.Direction == api.SCSIDataWrite {
|
} else if scmd.Direction == api.SCSIDataRead || scmd.Direction == api.SCSIDataWrite {
|
||||||
if scmd.InSDBBuffer.Buffer != nil {
|
if scmd.InSDBBuffer != nil {
|
||||||
resp.Resid = scmd.InSDBBuffer.Resid
|
resp.Resid = scmd.InSDBBuffer.Resid
|
||||||
buf := scmd.InSDBBuffer.Buffer.Bytes()
|
if resp.Resid != 0 && resp.Resid < scmd.InSDBBuffer.Length {
|
||||||
resp.RawData = buf
|
resp.RawData = scmd.InSDBBuffer.Buffer[:resp.Resid]
|
||||||
|
} else {
|
||||||
|
resp.RawData = scmd.InSDBBuffer.Buffer
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
resp.RawData = []byte{}
|
resp.RawData = []byte{}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ limitations under the License.
|
|||||||
package iscsit
|
package iscsit
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
@@ -29,6 +28,7 @@ import (
|
|||||||
"github.com/gostor/gotgt/pkg/config"
|
"github.com/gostor/gotgt/pkg/config"
|
||||||
"github.com/gostor/gotgt/pkg/scsi"
|
"github.com/gostor/gotgt/pkg/scsi"
|
||||||
"github.com/gostor/gotgt/pkg/util"
|
"github.com/gostor/gotgt/pkg/util"
|
||||||
|
"github.com/gostor/gotgt/pkg/util/pool"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -203,6 +203,9 @@ func (s *ISCSITargetDriver) rxHandler(conn *iscsiConnection) {
|
|||||||
ddigest uint = 0
|
ddigest uint = 0
|
||||||
final bool = false
|
final bool = false
|
||||||
cmd *ISCSICommand
|
cmd *ISCSICommand
|
||||||
|
buf []byte = make([]byte, BHS_SIZE)
|
||||||
|
length int
|
||||||
|
err error
|
||||||
)
|
)
|
||||||
conn.readLock.Lock()
|
conn.readLock.Lock()
|
||||||
defer conn.readLock.Unlock()
|
defer conn.readLock.Unlock()
|
||||||
@@ -214,7 +217,7 @@ func (s *ISCSITargetDriver) rxHandler(conn *iscsiConnection) {
|
|||||||
switch conn.rxIOState {
|
switch conn.rxIOState {
|
||||||
case IOSTATE_RX_BHS:
|
case IOSTATE_RX_BHS:
|
||||||
log.Debug("rx handler: IOSTATE_RX_BHS")
|
log.Debug("rx handler: IOSTATE_RX_BHS")
|
||||||
buf, length, err := conn.readData(BHS_SIZE)
|
buf, length, err = conn.readData(BHS_SIZE)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
return
|
return
|
||||||
@@ -224,7 +227,7 @@ func (s *ISCSITargetDriver) rxHandler(conn *iscsiConnection) {
|
|||||||
conn.state = CONN_STATE_CLOSE
|
conn.state = CONN_STATE_CLOSE
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
conn.rxBuffer = buf
|
//conn.rxBuffer = buf
|
||||||
cmd, err = parseHeader(buf)
|
cmd, err = parseHeader(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
@@ -237,8 +240,10 @@ func (s *ISCSITargetDriver) rxHandler(conn *iscsiConnection) {
|
|||||||
conn.rxIOState = IOSTATE_RX_INIT_AHS
|
conn.rxIOState = IOSTATE_RX_INIT_AHS
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
log.Debugf("got command: \n%s", cmd.String())
|
if log.GetLevel() == log.DebugLevel {
|
||||||
log.Debugf("got buffer: %v", buf)
|
log.Debugf("got command: \n%s", cmd.String())
|
||||||
|
log.Debugf("got buffer: %v", buf)
|
||||||
|
}
|
||||||
final = true
|
final = true
|
||||||
case IOSTATE_RX_INIT_AHS:
|
case IOSTATE_RX_INIT_AHS:
|
||||||
conn.rxIOState = IOSTATE_RX_DATA
|
conn.rxIOState = IOSTATE_RX_DATA
|
||||||
@@ -254,7 +259,7 @@ func (s *ISCSITargetDriver) rxHandler(conn *iscsiConnection) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
dl := ((cmd.DataLen + DataPadding - 1) / DataPadding) * DataPadding
|
dl := ((cmd.DataLen + DataPadding - 1) / DataPadding) * DataPadding
|
||||||
buf := []byte{}
|
cmd.RawData = pool.NewBuffer(dl)
|
||||||
length := 0
|
length := 0
|
||||||
for length < dl {
|
for length < dl {
|
||||||
b, l, err := conn.readData(dl - length)
|
b, l, err := conn.readData(dl - length)
|
||||||
@@ -262,8 +267,8 @@ func (s *ISCSITargetDriver) rxHandler(conn *iscsiConnection) {
|
|||||||
log.Error(err)
|
log.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
copy(cmd.RawData[length:], b)
|
||||||
length += l
|
length += l
|
||||||
buf = append(buf, b...)
|
|
||||||
}
|
}
|
||||||
if length != dl {
|
if length != dl {
|
||||||
log.Debugf("get length is %d, but expected %d", length, dl)
|
log.Debugf("get length is %d, but expected %d", length, dl)
|
||||||
@@ -271,10 +276,7 @@ func (s *ISCSITargetDriver) rxHandler(conn *iscsiConnection) {
|
|||||||
conn.state = CONN_STATE_CLOSE
|
conn.state = CONN_STATE_CLOSE
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cmd.RawData = buf[:length]
|
|
||||||
conn.rxBuffer = append(conn.rxBuffer, buf...)
|
|
||||||
final = true
|
final = true
|
||||||
log.Debugf("got command: \n%s", cmd.String())
|
|
||||||
default:
|
default:
|
||||||
log.Errorf("error %d %d\n", conn.state, conn.rxIOState)
|
log.Errorf("error %d %d\n", conn.state, conn.rxIOState)
|
||||||
return
|
return
|
||||||
@@ -547,21 +549,48 @@ 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...")
|
||||||
scmd := &api.SCSICommand{}
|
scmd := &api.SCSICommand{
|
||||||
|
ITNexusID: conn.session.ITNexus.ID,
|
||||||
|
SCB: req.CDB,
|
||||||
|
SCBLength: len(req.CDB),
|
||||||
|
Lun: req.LUN,
|
||||||
|
Tag: uint64(req.TaskTag),
|
||||||
|
RelTargetPortID: conn.session.TPGT,
|
||||||
|
}
|
||||||
|
if req.Read {
|
||||||
|
if req.Write {
|
||||||
|
scmd.Direction = api.SCSIDataBidirection
|
||||||
|
} else {
|
||||||
|
scmd.Direction = api.SCSIDataRead
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if req.Write {
|
||||||
|
scmd.Direction = api.SCSIDataWrite
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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}
|
||||||
if req.Write {
|
if req.Write {
|
||||||
task.offset = req.DataLen
|
|
||||||
task.r2tCount = int(req.ExpectedDataLen) - req.DataLen
|
task.r2tCount = int(req.ExpectedDataLen) - req.DataLen
|
||||||
if !req.Final {
|
if !req.Final {
|
||||||
task.unsolCount = 1
|
task.unsolCount = 1
|
||||||
}
|
}
|
||||||
|
// new buffer for the data out
|
||||||
|
if scmd.OutSDBBuffer == nil {
|
||||||
|
blen := int(req.ExpectedDataLen)
|
||||||
|
if blen == 0 {
|
||||||
|
blen = int(req.DataLen)
|
||||||
|
}
|
||||||
|
scmd.OutSDBBuffer = &api.SCSIDataBuffer{
|
||||||
|
Length: uint32(blen),
|
||||||
|
Buffer: pool.NewBuffer(blen),
|
||||||
|
}
|
||||||
|
}
|
||||||
log.Debugf("SCSI write, R2T count: %d, unsol Count: %d, offset: %d", task.r2tCount, task.unsolCount, task.offset)
|
log.Debugf("SCSI write, R2T count: %d, unsol Count: %d, offset: %d", task.r2tCount, task.unsolCount, task.offset)
|
||||||
|
|
||||||
if task.scmd.OutSDBBuffer.Buffer == nil {
|
|
||||||
task.scmd.OutSDBBuffer.Buffer = bytes.NewBuffer([]byte{})
|
|
||||||
}
|
|
||||||
if conn.session.SessionParam[ISCSI_PARAM_IMM_DATA_EN].Value == 1 {
|
if conn.session.SessionParam[ISCSI_PARAM_IMM_DATA_EN].Value == 1 {
|
||||||
task.scmd.OutSDBBuffer.Buffer.Write(conn.req.RawData)
|
copy(scmd.OutSDBBuffer.Buffer[task.offset:], conn.req.RawData)
|
||||||
|
task.offset += conn.req.DataLen
|
||||||
}
|
}
|
||||||
if task.r2tCount > 0 {
|
if task.r2tCount > 0 {
|
||||||
// prepare to receive more data
|
// prepare to receive more data
|
||||||
@@ -579,6 +608,11 @@ func (s *ISCSITargetDriver) scsiCommandHandler(conn *iscsiConnection) (err error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if scmd.InSDBBuffer == nil {
|
||||||
|
scmd.InSDBBuffer = &api.SCSIDataBuffer{
|
||||||
|
Length: uint32(req.ExpectedDataLen),
|
||||||
|
Buffer: pool.NewBuffer(int(req.ExpectedDataLen)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
task.offset = 0
|
task.offset = 0
|
||||||
conn.rxTask = task
|
conn.rxTask = task
|
||||||
@@ -616,9 +650,9 @@ func (s *ISCSITargetDriver) scsiCommandHandler(conn *iscsiConnection) (err error
|
|||||||
log.Error(err)
|
log.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
task.offset = task.offset + conn.req.DataLen
|
copy(task.scmd.OutSDBBuffer.Buffer[task.offset:], conn.req.RawData)
|
||||||
|
task.offset += conn.req.DataLen
|
||||||
task.r2tCount = task.r2tCount - conn.req.DataLen
|
task.r2tCount = task.r2tCount - conn.req.DataLen
|
||||||
task.scmd.OutSDBBuffer.Buffer.Write(conn.req.RawData)
|
|
||||||
log.Debugf("Final: %v", conn.req.Final)
|
log.Debugf("Final: %v", conn.req.Final)
|
||||||
log.Debugf("r2tCount: %v", task.r2tCount)
|
log.Debugf("r2tCount: %v", task.r2tCount)
|
||||||
if !conn.req.Final {
|
if !conn.req.Final {
|
||||||
@@ -722,27 +756,7 @@ func (s *ISCSITargetDriver) iscsiExecTask(task *iscsiTask) error {
|
|||||||
cmd := task.cmd
|
cmd := task.cmd
|
||||||
switch cmd.OpCode {
|
switch cmd.OpCode {
|
||||||
case OpSCSICmd, OpSCSIOut:
|
case OpSCSICmd, OpSCSIOut:
|
||||||
if cmd.Read {
|
|
||||||
if cmd.Write {
|
|
||||||
task.scmd.Direction = api.SCSIDataBidirection
|
|
||||||
} else {
|
|
||||||
task.scmd.Direction = api.SCSIDataRead
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if cmd.Write {
|
|
||||||
task.scmd.Direction = api.SCSIDataWrite
|
|
||||||
}
|
|
||||||
}
|
|
||||||
task.scmd.ITNexusID = task.conn.session.ITNexus.ID
|
|
||||||
task.scmd.SCB = bytes.NewBuffer(cmd.CDB)
|
|
||||||
task.scmd.SCBLength = len(cmd.CDB)
|
|
||||||
task.scmd.Lun = cmd.LUN
|
|
||||||
task.scmd.Tag = uint64(cmd.TaskTag)
|
|
||||||
task.scmd.RelTargetPortID = task.conn.session.TPGT
|
|
||||||
task.state = taskSCSI
|
task.state = taskSCSI
|
||||||
if task.scmd.OutSDBBuffer.Buffer == nil {
|
|
||||||
task.scmd.OutSDBBuffer.Buffer = bytes.NewBuffer(cmd.RawData)
|
|
||||||
}
|
|
||||||
// add scsi target process queue
|
// add scsi target process queue
|
||||||
err := s.SCSI.AddCommandQueue(task.conn.session.Target.SCSITarget.TID, task.scmd)
|
err := s.SCSI.AddCommandQueue(task.conn.session.Target.SCSITarget.TID, task.scmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import (
|
|||||||
log "github.com/Sirupsen/logrus"
|
log "github.com/Sirupsen/logrus"
|
||||||
"github.com/gostor/gotgt/pkg/api"
|
"github.com/gostor/gotgt/pkg/api"
|
||||||
"github.com/gostor/gotgt/pkg/util"
|
"github.com/gostor/gotgt/pkg/util"
|
||||||
|
"github.com/gostor/gotgt/pkg/util/pool"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BaseBackingStore struct {
|
type BaseBackingStore struct {
|
||||||
@@ -53,16 +54,16 @@ func NewBackingStore(name string) (api.BackingStore, error) {
|
|||||||
|
|
||||||
func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error, key byte, asc SCSISubError) {
|
func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error, key byte, asc SCSISubError) {
|
||||||
var (
|
var (
|
||||||
scb = cmd.SCB.Bytes()
|
scb = cmd.SCB
|
||||||
offset = cmd.Offset
|
offset = cmd.Offset
|
||||||
opcode = api.SCSICommandType(scb[0])
|
opcode = api.SCSICommandType(scb[0])
|
||||||
lu = cmd.Device
|
lu = cmd.Device
|
||||||
wbuf []byte = []byte{}
|
|
||||||
tl int64 = int64(cmd.TL)
|
|
||||||
rbuf = make([]byte, tl)
|
|
||||||
length int
|
length int
|
||||||
doVerify bool = false
|
doVerify bool = false
|
||||||
doWrite bool = false
|
doWrite bool = false
|
||||||
|
wbuf []byte
|
||||||
|
tl int64 = int64(cmd.TL)
|
||||||
|
rbuf []byte = pool.NewBuffer(int(tl))
|
||||||
)
|
)
|
||||||
key = HARDWARE_ERROR
|
key = HARDWARE_ERROR
|
||||||
asc = ASC_INTERNAL_TGT_FAILURE
|
asc = ASC_INTERNAL_TGT_FAILURE
|
||||||
@@ -75,9 +76,10 @@ func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error, key
|
|||||||
asc = ASC_READ_ERROR
|
asc = ASC_READ_ERROR
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
cmd.InSDBBuffer.Buffer = bytes.NewBuffer(tmpbuf)
|
copy(cmd.InSDBBuffer.Buffer, tmpbuf)
|
||||||
|
if cmd.OutSDBBuffer != nil {
|
||||||
wbuf = cmd.OutSDBBuffer.Buffer.Bytes()
|
wbuf = cmd.OutSDBBuffer.Buffer
|
||||||
|
}
|
||||||
doWrite = true
|
doWrite = true
|
||||||
goto write
|
goto write
|
||||||
case api.COMPARE_AND_WRITE:
|
case api.COMPARE_AND_WRITE:
|
||||||
@@ -91,8 +93,12 @@ func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error, key
|
|||||||
break
|
break
|
||||||
case api.WRITE_VERIFY, api.WRITE_VERIFY_12, api.WRITE_VERIFY_16:
|
case api.WRITE_VERIFY, api.WRITE_VERIFY_12, api.WRITE_VERIFY_16:
|
||||||
doVerify = true
|
doVerify = true
|
||||||
|
fallthrough
|
||||||
case api.WRITE_6, api.WRITE_10, api.WRITE_12, api.WRITE_16:
|
case api.WRITE_6, api.WRITE_10, api.WRITE_12, api.WRITE_16:
|
||||||
wbuf = cmd.OutSDBBuffer.Buffer.Bytes()
|
// For stupid client which does not set WRITE flag
|
||||||
|
if cmd.OutSDBBuffer != nil {
|
||||||
|
wbuf = cmd.OutSDBBuffer.Buffer
|
||||||
|
}
|
||||||
doWrite = true
|
doWrite = true
|
||||||
goto write
|
goto write
|
||||||
case api.WRITE_SAME, api.WRITE_SAME_16:
|
case api.WRITE_SAME, api.WRITE_SAME_16:
|
||||||
@@ -113,7 +119,8 @@ func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error, key
|
|||||||
if (opcode != api.READ_6) && (scb[1]&0x10 != 0) {
|
if (opcode != api.READ_6) && (scb[1]&0x10 != 0) {
|
||||||
bs.DataAdvise(int64(offset), int64(length), util.POSIX_FADV_NOREUSE)
|
bs.DataAdvise(int64(offset), int64(length), util.POSIX_FADV_NOREUSE)
|
||||||
}
|
}
|
||||||
cmd.InSDBBuffer.Buffer = bytes.NewBuffer(rbuf)
|
cmd.InSDBBuffer.Resid = uint32(length)
|
||||||
|
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)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -121,6 +128,10 @@ func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error, key
|
|||||||
asc = ASC_READ_ERROR
|
asc = ASC_READ_ERROR
|
||||||
}
|
}
|
||||||
case api.VERIFY_10, api.VERIFY_12, api.VERIFY_16:
|
case api.VERIFY_10, api.VERIFY_12, api.VERIFY_16:
|
||||||
|
// For stupid client which does not set WRITE flag
|
||||||
|
if cmd.OutSDBBuffer != nil {
|
||||||
|
wbuf = cmd.OutSDBBuffer.Buffer
|
||||||
|
}
|
||||||
doVerify = true
|
doVerify = true
|
||||||
goto verify
|
goto verify
|
||||||
case api.UNMAP:
|
case api.UNMAP:
|
||||||
@@ -138,7 +149,7 @@ write:
|
|||||||
asc = ASC_READ_ERROR
|
asc = ASC_READ_ERROR
|
||||||
goto sense
|
goto sense
|
||||||
}
|
}
|
||||||
log.Debugf("write data at %d for length %d", offset, len(wbuf))
|
log.Debugf("write data at 0x%x for length %d", offset, len(wbuf))
|
||||||
var pg *api.ModePage
|
var pg *api.ModePage
|
||||||
for _, p := range lu.ModePages {
|
for _, p := range lu.ModePages {
|
||||||
if p.PageCode == 0x08 && p.SubPageCode == 0 {
|
if p.PageCode == 0x08 && p.SubPageCode == 0 {
|
||||||
@@ -171,11 +182,14 @@ verify:
|
|||||||
asc = ASC_READ_ERROR
|
asc = ASC_READ_ERROR
|
||||||
goto sense
|
goto sense
|
||||||
}
|
}
|
||||||
if !bytes.Equal(cmd.OutSDBBuffer.Buffer.Bytes(), rbuf) {
|
if !bytes.Equal(wbuf, rbuf) {
|
||||||
err = fmt.Errorf("verify fail between out buffer and read buffer")
|
err = fmt.Errorf("verify fail between out buffer[length=%d] and read buffer[length=%d]", len(wbuf), len(rbuf))
|
||||||
key = MISCOMPARE
|
key = MISCOMPARE
|
||||||
asc = ASC_MISCOMPARE_DURING_VERIFY_OPERATION
|
asc = ASC_MISCOMPARE_DURING_VERIFY_OPERATION
|
||||||
goto sense
|
goto sense
|
||||||
|
} else {
|
||||||
|
log.Warnf("%v", wbuf)
|
||||||
|
log.Warnf("%v", rbuf)
|
||||||
}
|
}
|
||||||
if scb[1]&0x10 != 0 {
|
if scb[1]&0x10 != 0 {
|
||||||
bs.DataAdvise(int64(offset), int64(length), util.POSIX_FADV_WILLNEED)
|
bs.DataAdvise(int64(offset), int64(length), util.POSIX_FADV_WILLNEED)
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ func GetReservation(dev *api.SCSILu, nexusID uint64) *api.SCSIReservation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func luPerformCommand(tid int, cmd *api.SCSICommand) api.SAMStat {
|
func luPerformCommand(tid int, cmd *api.SCSICommand) api.SAMStat {
|
||||||
op := int(cmd.SCB.Bytes()[0])
|
op := int(cmd.SCB[0])
|
||||||
fn := cmd.Device.DeviceProtocol.PerformCommand(op)
|
fn := cmd.Device.DeviceProtocol.PerformCommand(op)
|
||||||
if fn != nil {
|
if fn != nil {
|
||||||
fnop := fn.(SCSIDeviceOperation)
|
fnop := fn.(SCSIDeviceOperation)
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ limitations under the License.
|
|||||||
package scsi
|
package scsi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
@@ -235,18 +233,11 @@ func SBCModeSense(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
deviceSpecific |= 0x80
|
deviceSpecific |= 0x80
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := cmd.InSDBBuffer.Buffer
|
if cmd.SCB[0] == 0x1a {
|
||||||
data := []byte{0x00, 0x00, 0x00, 0x00}
|
cmd.InSDBBuffer.Buffer[2] = deviceSpecific
|
||||||
if buf != nil {
|
|
||||||
data = buf.Bytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
if cmd.SCB.Bytes()[0] == 0x1a {
|
|
||||||
data[2] = deviceSpecific
|
|
||||||
} else {
|
} else {
|
||||||
data[3] = deviceSpecific
|
cmd.InSDBBuffer.Buffer[3] = deviceSpecific
|
||||||
}
|
}
|
||||||
cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data)
|
|
||||||
|
|
||||||
return api.SAMStatGood
|
return api.SAMStatGood
|
||||||
}
|
}
|
||||||
@@ -284,15 +275,15 @@ func SBCFormatUnit(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
goto sense
|
goto sense
|
||||||
}
|
}
|
||||||
|
|
||||||
if cmd.SCB.Bytes()[1]&0x80 != 0 {
|
if cmd.SCB[1]&0x80 != 0 {
|
||||||
// we dont support format protection information
|
// we dont support format protection information
|
||||||
goto sense
|
goto sense
|
||||||
}
|
}
|
||||||
if cmd.SCB.Bytes()[1]&0x10 != 0 {
|
if cmd.SCB[1]&0x10 != 0 {
|
||||||
// we dont support format data
|
// we dont support format data
|
||||||
goto sense
|
goto sense
|
||||||
}
|
}
|
||||||
if cmd.SCB.Bytes()[1]&0x07 != 0 {
|
if cmd.SCB[1]&0x07 != 0 {
|
||||||
// defect list format must be 0
|
// defect list format must be 0
|
||||||
goto sense
|
goto sense
|
||||||
}
|
}
|
||||||
@@ -330,7 +321,7 @@ func SBCReadWrite(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
key = ILLEGAL_REQUEST
|
key = ILLEGAL_REQUEST
|
||||||
asc = ASC_INVALID_FIELD_IN_CDB
|
asc = ASC_INVALID_FIELD_IN_CDB
|
||||||
dev = cmd.Device
|
dev = cmd.Device
|
||||||
scb = cmd.SCB.Bytes()
|
scb = cmd.SCB
|
||||||
opcode = api.SCSICommandType(scb[0])
|
opcode = api.SCSICommandType(scb[0])
|
||||||
lba uint64
|
lba uint64
|
||||||
tl uint32
|
tl uint32
|
||||||
@@ -353,9 +344,6 @@ func SBCReadWrite(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
log.Warnf("sense data(ILLEGAL_REQUEST,ASC_INVALID_FIELD_IN_CDB) encounter")
|
log.Warnf("sense data(ILLEGAL_REQUEST,ASC_INVALID_FIELD_IN_CDB) encounter")
|
||||||
goto sense
|
goto sense
|
||||||
}
|
}
|
||||||
if cmd.OutSDBBuffer.Buffer == nil {
|
|
||||||
cmd.OutSDBBuffer.Buffer = &bytes.Buffer{}
|
|
||||||
}
|
|
||||||
case api.WRITE_SAME, api.WRITE_SAME_16:
|
case api.WRITE_SAME, api.WRITE_SAME_16:
|
||||||
// We dont support resource-provisioning so ANCHOR bit == 1 is an error.
|
// We dont support resource-provisioning so ANCHOR bit == 1 is an error.
|
||||||
if scb[1]&0x10 != 0 {
|
if scb[1]&0x10 != 0 {
|
||||||
@@ -482,10 +470,9 @@ func SBCRelease(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
*/
|
*/
|
||||||
func SBCReadCapacity(host int, cmd *api.SCSICommand) api.SAMStat {
|
func SBCReadCapacity(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||||
var (
|
var (
|
||||||
scb = cmd.SCB.Bytes()
|
scb = cmd.SCB
|
||||||
key = ILLEGAL_REQUEST
|
key = ILLEGAL_REQUEST
|
||||||
asc = ASC_LUN_NOT_SUPPORTED
|
asc = ASC_LUN_NOT_SUPPORTED
|
||||||
data = &bytes.Buffer{}
|
|
||||||
bshift = cmd.Device.BlockShift
|
bshift = cmd.Device.BlockShift
|
||||||
size = cmd.Device.Size >> bshift
|
size = cmd.Device.Size >> bshift
|
||||||
)
|
)
|
||||||
@@ -501,24 +488,21 @@ func SBCReadCapacity(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
goto sense
|
goto sense
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if cmd.InSDBBuffer.Length < 8 {
|
||||||
if cmd.InSDBBuffer.Length < 8 {
|
goto overflow
|
||||||
goto overflow
|
}
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// data[0] = (size >> 32) ? __cpu_to_be32(0xffffffff) : __cpu_to_be32(size - 1);
|
// data[0] = (size >> 32) ? __cpu_to_be32(0xffffffff) : __cpu_to_be32(size - 1);
|
||||||
if size>>32 != 0 {
|
if size>>32 != 0 {
|
||||||
binary.Write(data, binary.BigEndian, uint32(0xffffffff))
|
copy(cmd.InSDBBuffer.Buffer, util.MarshalUint32(uint32(0xffffffff)))
|
||||||
} else {
|
} else {
|
||||||
binary.Write(data, binary.BigEndian, uint32(size-1))
|
copy(cmd.InSDBBuffer.Buffer, util.MarshalUint32(uint32(size-1)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// data[1] = __cpu_to_be32(1U << bshift);
|
// data[1] = __cpu_to_be32(1U << bshift);
|
||||||
binary.Write(data, binary.BigEndian, uint32(1<<bshift))
|
copy(cmd.InSDBBuffer.Buffer[4:], util.MarshalUint32(uint32(1<<bshift)))
|
||||||
//overflow:
|
overflow:
|
||||||
cmd.InSDBBuffer.Resid = 8
|
cmd.InSDBBuffer.Resid = 8
|
||||||
cmd.InSDBBuffer.Buffer = data
|
|
||||||
return api.SAMStatGood
|
return api.SAMStatGood
|
||||||
sense:
|
sense:
|
||||||
cmd.InSDBBuffer.Resid = 0
|
cmd.InSDBBuffer.Resid = 0
|
||||||
@@ -537,7 +521,7 @@ func SBCVerify(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
key = ILLEGAL_REQUEST
|
key = ILLEGAL_REQUEST
|
||||||
asc = ASC_INVALID_FIELD_IN_CDB
|
asc = ASC_INVALID_FIELD_IN_CDB
|
||||||
dev = cmd.Device
|
dev = cmd.Device
|
||||||
scb = cmd.SCB.Bytes()
|
scb = cmd.SCB
|
||||||
lba uint64
|
lba uint64
|
||||||
tl uint32
|
tl uint32
|
||||||
err error
|
err error
|
||||||
@@ -548,14 +532,14 @@ func SBCVerify(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
goto sense
|
goto sense
|
||||||
}
|
}
|
||||||
|
|
||||||
if cmd.SCB.Bytes()[1]&0xe0 != 0 {
|
if scb[1]&0xe0 != 0 {
|
||||||
// We only support protection information type 0
|
// We only support protection information type 0
|
||||||
key = ILLEGAL_REQUEST
|
key = ILLEGAL_REQUEST
|
||||||
asc = ASC_INVALID_FIELD_IN_CDB
|
asc = ASC_INVALID_FIELD_IN_CDB
|
||||||
goto sense
|
goto sense
|
||||||
}
|
}
|
||||||
|
|
||||||
if cmd.SCB.Bytes()[1]&0x02 == 0 {
|
if scb[1]&0x02 == 0 {
|
||||||
// no data compare with the media
|
// no data compare with the media
|
||||||
return api.SAMStatGood
|
return api.SAMStatGood
|
||||||
}
|
}
|
||||||
@@ -587,7 +571,6 @@ func SBCVerify(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
}
|
}
|
||||||
return api.SAMStatGood
|
return api.SAMStatGood
|
||||||
sense:
|
sense:
|
||||||
cmd.InSDBBuffer.Resid = 0
|
|
||||||
BuildSenseData(cmd, key, asc)
|
BuildSenseData(cmd, key, asc)
|
||||||
return api.SAMStatCheckCondition
|
return api.SAMStatCheckCondition
|
||||||
}
|
}
|
||||||
@@ -602,17 +585,19 @@ sense:
|
|||||||
*/
|
*/
|
||||||
func SBCReadCapacity16(host int, cmd *api.SCSICommand) api.SAMStat {
|
func SBCReadCapacity16(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||||
var (
|
var (
|
||||||
data = &bytes.Buffer{}
|
bshift = cmd.Device.BlockShift
|
||||||
bshift = cmd.Device.BlockShift
|
size = cmd.Device.Size >> bshift
|
||||||
size = cmd.Device.Size >> bshift
|
allocationLength uint32
|
||||||
)
|
)
|
||||||
data.Write(util.MarshalUint64(uint64(size - 1)))
|
allocationLength = util.GetUnalignedUint32(cmd.SCB[10:14])
|
||||||
binary.Write(data, binary.BigEndian, uint32(1<<bshift))
|
copy(cmd.InSDBBuffer.Buffer, util.MarshalUint64(uint64(size-1)))
|
||||||
val := (cmd.Device.Attrs.Lbppbe << 16) | cmd.Device.Attrs.LowestAlignedLBA
|
if allocationLength > 12 {
|
||||||
data.Write(util.MarshalUint32(uint32(val)))
|
copy(cmd.InSDBBuffer.Buffer[8:], util.MarshalUint32(uint32(1<<bshift)))
|
||||||
binary.Write(data, binary.BigEndian, uint64(0))
|
if allocationLength > 16 {
|
||||||
binary.Write(data, binary.BigEndian, uint64(0))
|
val := (cmd.Device.Attrs.Lbppbe << 16) | cmd.Device.Attrs.LowestAlignedLBA
|
||||||
cmd.InSDBBuffer.Buffer = data
|
copy(cmd.InSDBBuffer.Buffer[12:], util.MarshalUint32(uint32(val)))
|
||||||
|
}
|
||||||
|
}
|
||||||
return api.SAMStatGood
|
return api.SAMStatGood
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -621,7 +606,7 @@ func SBCGetLbaStatus(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
key = ILLEGAL_REQUEST
|
key = ILLEGAL_REQUEST
|
||||||
asc = ASC_INVALID_FIELD_IN_CDB
|
asc = ASC_INVALID_FIELD_IN_CDB
|
||||||
dev = cmd.Device
|
dev = cmd.Device
|
||||||
scb = cmd.SCB.Bytes()
|
scb = cmd.SCB
|
||||||
lba uint64
|
lba uint64
|
||||||
tl uint32
|
tl uint32
|
||||||
)
|
)
|
||||||
@@ -631,14 +616,14 @@ func SBCGetLbaStatus(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
goto sense
|
goto sense
|
||||||
}
|
}
|
||||||
|
|
||||||
if cmd.SCB.Bytes()[1]&0xe0 != 0 {
|
if scb[1]&0xe0 != 0 {
|
||||||
// We only support protection information type 0
|
// We only support protection information type 0
|
||||||
key = ILLEGAL_REQUEST
|
key = ILLEGAL_REQUEST
|
||||||
asc = ASC_INVALID_FIELD_IN_CDB
|
asc = ASC_INVALID_FIELD_IN_CDB
|
||||||
goto sense
|
goto sense
|
||||||
}
|
}
|
||||||
|
|
||||||
if cmd.SCB.Bytes()[1]&0x02 == 0 {
|
if scb[1]&0x02 == 0 {
|
||||||
// no data compare with the media
|
// no data compare with the media
|
||||||
return api.SAMStatGood
|
return api.SAMStatGood
|
||||||
}
|
}
|
||||||
@@ -668,7 +653,7 @@ sense:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func SBCServiceAction(host int, cmd *api.SCSICommand) api.SAMStat {
|
func SBCServiceAction(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||||
opcode := api.SCSICommandType(cmd.SCB.Bytes()[1] & 0x1f)
|
opcode := api.SCSICommandType(cmd.SCB[1] & 0x1f)
|
||||||
switch opcode {
|
switch opcode {
|
||||||
case api.READ_CAPACITY:
|
case api.READ_CAPACITY:
|
||||||
return SBCReadCapacity(host, cmd)
|
return SBCReadCapacity(host, cmd)
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ func (s *SCSITargetService) AddCommandQueue(tid int, scmd *api.SCSICommand) erro
|
|||||||
lun := *(*uint64)(unsafe.Pointer(&scmd.Lun))
|
lun := *(*uint64)(unsafe.Pointer(&scmd.Lun))
|
||||||
scmd.Device = target.Devices[lun]
|
scmd.Device = target.Devices[lun]
|
||||||
|
|
||||||
log.Debugf("scsi opcode: 0x%x, LUN: %d", int(scmd.SCB.Bytes()[0]), binary.LittleEndian.Uint64(scmd.Lun[:]))
|
log.Debugf("scsi opcode: 0x%x, LUN: %d", int(scmd.SCB[0]), binary.LittleEndian.Uint64(scmd.Lun[:]))
|
||||||
|
|
||||||
if scmd.Device == nil {
|
if scmd.Device == nil {
|
||||||
scmd.Device = target.LUN0
|
scmd.Device = target.LUN0
|
||||||
@@ -91,6 +91,7 @@ func (s *SCSITargetService) AddCommandQueue(tid int, scmd *api.SCSICommand) erro
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result := scmd.Device.PerformCommand(tid, scmd)
|
result := scmd.Device.PerformCommand(tid, scmd)
|
||||||
if result != api.SAMStatGood {
|
if result != api.SAMStatGood {
|
||||||
scmd.Result = result.Stat
|
scmd.Result = result.Stat
|
||||||
@@ -125,7 +126,8 @@ 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.Bytes())
|
inBufLen, ok := SCSICDBBufXLength(cmd.SCB)
|
||||||
|
var length uint32 = 0xa
|
||||||
|
|
||||||
if cmd.Device.Attrs.SenseFormat {
|
if cmd.Device.Attrs.SenseFormat {
|
||||||
// descriptor format
|
// descriptor format
|
||||||
@@ -134,10 +136,9 @@ func BuildSenseData(cmd *api.SCSICommand, key byte, asc SCSISubError) {
|
|||||||
senseBuffer.WriteByte(key)
|
senseBuffer.WriteByte(key)
|
||||||
senseBuffer.WriteByte((byte(asc) >> 8) & 0xff)
|
senseBuffer.WriteByte((byte(asc) >> 8) & 0xff)
|
||||||
senseBuffer.WriteByte(byte(asc) & 0xff)
|
senseBuffer.WriteByte(byte(asc) & 0xff)
|
||||||
cmd.SenseLength = 8
|
length = 8
|
||||||
} else {
|
} else {
|
||||||
// fixed format
|
// fixed format
|
||||||
var length uint32 = 0xa
|
|
||||||
// current, not deferred
|
// current, not deferred
|
||||||
senseBuffer.WriteByte(0x70)
|
senseBuffer.WriteByte(0x70)
|
||||||
senseBuffer.WriteByte(0x00)
|
senseBuffer.WriteByte(0x00)
|
||||||
@@ -154,10 +155,10 @@ func BuildSenseData(cmd *api.SCSICommand, key byte, asc SCSISubError) {
|
|||||||
for i := 0; i < 4; i++ {
|
for i := 0; i < 4; i++ {
|
||||||
senseBuffer.WriteByte(0x00)
|
senseBuffer.WriteByte(0x00)
|
||||||
}
|
}
|
||||||
cmd.SenseLength = length + 8
|
length += 8
|
||||||
}
|
}
|
||||||
if ok {
|
if ok {
|
||||||
if int64(len(senseBuffer.Bytes())) > inBufLen {
|
if int64(length) > inBufLen {
|
||||||
log.Warnf("sense buffer is bigger than in buffer")
|
log.Warnf("sense buffer is bigger than in buffer")
|
||||||
senseBuffer.Truncate(int(inBufLen))
|
senseBuffer.Truncate(int(inBufLen))
|
||||||
}
|
}
|
||||||
@@ -165,7 +166,7 @@ func BuildSenseData(cmd *api.SCSICommand, key byte, asc SCSISubError) {
|
|||||||
log.Debugf("cannot calc cbd alloc length. truncate failed")
|
log.Debugf("cannot calc cbd alloc length. truncate failed")
|
||||||
}
|
}
|
||||||
cmd.Result = key
|
cmd.Result = key
|
||||||
cmd.SenseBuffer = senseBuffer
|
cmd.SenseBuffer = &api.SenseBuffer{senseBuffer.Bytes(), length}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSCSIReadWriteOffset(scb []byte) uint64 {
|
func getSCSIReadWriteOffset(scb []byte) uint64 {
|
||||||
|
|||||||
147
pkg/scsi/spc.go
147
pkg/scsi/spc.go
@@ -204,7 +204,7 @@ func SPCInquiry(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
addBuf = &bytes.Buffer{}
|
addBuf = &bytes.Buffer{}
|
||||||
addBufData []byte = []byte{}
|
addBufData []byte = []byte{}
|
||||||
//b byte = 0x75
|
//b byte = 0x75
|
||||||
scb []byte = cmd.SCB.Bytes()
|
scb []byte = cmd.SCB
|
||||||
pcode byte = scb[2]
|
pcode byte = scb[2]
|
||||||
evpd bool = false
|
evpd bool = false
|
||||||
|
|
||||||
@@ -227,22 +227,19 @@ func SPCInquiry(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
switch pcode {
|
switch pcode {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
buf, _ = InquiryPage0x00(host, cmd)
|
buf, _ = InquiryPage0x00(host, cmd)
|
||||||
|
|
||||||
case 0x80:
|
case 0x80:
|
||||||
buf, _ = InquiryPage0x80(host, cmd)
|
buf, _ = InquiryPage0x80(host, cmd)
|
||||||
|
|
||||||
case 0x83:
|
case 0x83:
|
||||||
buf, _ = InquiryPage0x83(host, cmd)
|
buf, _ = InquiryPage0x83(host, cmd)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
goto sense
|
goto sense
|
||||||
}
|
}
|
||||||
data = buf.Bytes()
|
data = buf.Bytes()
|
||||||
if int(allocationLength) < len(data) {
|
if int(allocationLength) < len(data) {
|
||||||
cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data[0:allocationLength])
|
copy(cmd.InSDBBuffer.Buffer, data[0:allocationLength])
|
||||||
cmd.InSDBBuffer.Resid = uint32(len(data))
|
cmd.InSDBBuffer.Resid = uint32(len(data))
|
||||||
} else {
|
} else {
|
||||||
cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data[0:])
|
copy(cmd.InSDBBuffer.Buffer, data[0:])
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if pcode != 0 {
|
if pcode != 0 {
|
||||||
@@ -304,9 +301,11 @@ func SPCInquiry(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
buf.Write(addBufData)
|
buf.Write(addBufData)
|
||||||
data = buf.Bytes()
|
data = buf.Bytes()
|
||||||
if allocationLength < uint16(additionLength) {
|
if allocationLength < uint16(additionLength) {
|
||||||
cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data[0:allocationLength])
|
cmd.InSDBBuffer.Resid = uint32(allocationLength)
|
||||||
|
copy(cmd.InSDBBuffer.Buffer, data[0:allocationLength])
|
||||||
} else {
|
} else {
|
||||||
cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data[0:])
|
cmd.InSDBBuffer.Resid = uint32(len(data))
|
||||||
|
copy(cmd.InSDBBuffer.Buffer, data[0:])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,10 +330,9 @@ func SPCReportLuns(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
availLength uint32 = 0
|
availLength uint32 = 0
|
||||||
allocationLength uint32
|
allocationLength uint32
|
||||||
buf *bytes.Buffer = &bytes.Buffer{}
|
buf *bytes.Buffer = &bytes.Buffer{}
|
||||||
scb *bytes.Buffer = cmd.SCB
|
|
||||||
)
|
)
|
||||||
// Get Allocation Length
|
// Get Allocation Length
|
||||||
allocationLength = util.GetUnalignedUint32(scb.Bytes()[6:10])
|
allocationLength = util.GetUnalignedUint32(cmd.SCB[6:10])
|
||||||
if allocationLength < 16 {
|
if allocationLength < 16 {
|
||||||
log.Warn("goto sense, allocationLength < 16")
|
log.Warn("goto sense, allocationLength < 16")
|
||||||
goto sense
|
goto sense
|
||||||
@@ -376,7 +374,7 @@ func SPCReportLuns(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.InSDBBuffer.Buffer = buf
|
copy(cmd.InSDBBuffer.Buffer, buf.Bytes())
|
||||||
return api.SAMStatGood
|
return api.SAMStatGood
|
||||||
sense:
|
sense:
|
||||||
cmd.InSDBBuffer.Resid = 0
|
cmd.InSDBBuffer.Resid = 0
|
||||||
@@ -393,7 +391,7 @@ func SPCStartStop(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cmd.InSDBBuffer.Resid = 0
|
cmd.InSDBBuffer.Resid = 0
|
||||||
scb := cmd.SCB.Bytes()
|
scb := cmd.SCB
|
||||||
pwrcnd = scb[4] & 0xf0
|
pwrcnd = scb[4] & 0xf0
|
||||||
if pwrcnd != 0 {
|
if pwrcnd != 0 {
|
||||||
return api.SAMStatGood
|
return api.SAMStatGood
|
||||||
@@ -452,7 +450,7 @@ func SPCPreventAllowMediaRemoval(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
return api.SAMStatReservationConflict
|
return api.SAMStatReservationConflict
|
||||||
}
|
}
|
||||||
// PREVENT_MASK = 0x03
|
// PREVENT_MASK = 0x03
|
||||||
cmd.ITNexusLuInfo.Prevent = int(cmd.SCB.Bytes()[4] & 0x03)
|
cmd.ITNexusLuInfo.Prevent = int(cmd.SCB[4] & 0x03)
|
||||||
return api.SAMStatGood
|
return api.SAMStatGood
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -467,7 +465,7 @@ func SPCPreventAllowMediaRemoval(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
*/
|
*/
|
||||||
func SPCModeSense(host int, cmd *api.SCSICommand) api.SAMStat {
|
func SPCModeSense(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||||
var (
|
var (
|
||||||
scb = cmd.SCB.Bytes()
|
scb = cmd.SCB
|
||||||
mode6 = (scb[0] == 0x1a)
|
mode6 = (scb[0] == 0x1a)
|
||||||
dbd = scb[1] & 0x8 // Disable Block Descriptors
|
dbd = scb[1] & 0x8 // Disable Block Descriptors
|
||||||
pcode = scb[2] & 0x3f
|
pcode = scb[2] & 0x3f
|
||||||
@@ -574,7 +572,7 @@ func SPCModeSense(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
if rlen := uint32(len(data)); rlen < allocLen {
|
if rlen := uint32(len(data)); rlen < allocLen {
|
||||||
cmd.InSDBBuffer.Resid = rlen
|
cmd.InSDBBuffer.Resid = rlen
|
||||||
}
|
}
|
||||||
cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data)
|
copy(cmd.InSDBBuffer.Buffer, data)
|
||||||
return api.SAMStatGood
|
return api.SAMStatGood
|
||||||
sense:
|
sense:
|
||||||
BuildSenseData(cmd, key, asc)
|
BuildSenseData(cmd, key, asc)
|
||||||
@@ -591,7 +589,7 @@ sense:
|
|||||||
*/
|
*/
|
||||||
func SPCSendDiagnostics(host int, cmd *api.SCSICommand) api.SAMStat {
|
func SPCSendDiagnostics(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||||
// we only support SELF-TEST==1
|
// we only support SELF-TEST==1
|
||||||
if cmd.SCB.Bytes()[1]&0x04 == 0 {
|
if cmd.SCB[1]&0x04 == 0 {
|
||||||
goto sense
|
goto sense
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -640,9 +638,8 @@ func reportOpcodesAll(cmd *api.SCSICommand, rctd int) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buf := util.MarshalUint32(uint32(len(data) - 4))
|
copy(cmd.InSDBBuffer.Buffer, util.MarshalUint32(uint32(len(data)-4)))
|
||||||
buf = append(buf, data[4:]...)
|
copy(cmd.InSDBBuffer.Buffer[4:], data[4:])
|
||||||
cmd.InSDBBuffer.Buffer = bytes.NewBuffer(buf)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -651,7 +648,7 @@ func reportOpcodeOne(cmd *api.SCSICommand, rctd int, opcode byte, rsa uint16, se
|
|||||||
}
|
}
|
||||||
|
|
||||||
func SPCReportSupportedOperationCodes(host int, cmd *api.SCSICommand) api.SAMStat {
|
func SPCReportSupportedOperationCodes(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||||
scb := cmd.SCB.Bytes()
|
scb := cmd.SCB
|
||||||
reporting_options := scb[2] & 0x07
|
reporting_options := scb[2] & 0x07
|
||||||
opcode := scb[3]
|
opcode := scb[3]
|
||||||
rctd := int(scb[2] & 0x80)
|
rctd := int(scb[2] & 0x80)
|
||||||
@@ -692,54 +689,43 @@ sense:
|
|||||||
// This is useful for the various commands using the SERVICE ACTION format.
|
// This is useful for the various commands using the SERVICE ACTION format.
|
||||||
func SPCServiceAction(host int, cmd *api.SCSICommand) api.SAMStat {
|
func SPCServiceAction(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||||
|
|
||||||
scb := cmd.SCB.Bytes()
|
scb := cmd.SCB
|
||||||
opcode := int(scb[0])
|
opcode := int(scb[0])
|
||||||
action := uint8(scb[1] & 0x1F)
|
action := uint8(scb[1] & 0x1F)
|
||||||
serviceAction := cmd.Device.DeviceProtocol.PerformServiceAction(opcode, action)
|
serviceAction := cmd.Device.DeviceProtocol.PerformServiceAction(opcode, action)
|
||||||
if serviceAction == nil {
|
if serviceAction != nil {
|
||||||
cmd.InSDBBuffer.Resid = 0
|
|
||||||
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
|
|
||||||
return api.SAMStatCheckCondition
|
|
||||||
} else {
|
|
||||||
fnop := serviceAction.(*SCSIServiceAction)
|
fnop := serviceAction.(*SCSIServiceAction)
|
||||||
return fnop.CommandPerformFunc(host, cmd)
|
return fnop.CommandPerformFunc(host, cmd)
|
||||||
}
|
}
|
||||||
|
cmd.InSDBBuffer.Resid = 0
|
||||||
|
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
|
||||||
|
return api.SAMStatCheckCondition
|
||||||
}
|
}
|
||||||
|
|
||||||
func SPCPRReadKeys(host int, cmd *api.SCSICommand) api.SAMStat {
|
func SPCPRReadKeys(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||||
var (
|
var (
|
||||||
buf = &bytes.Buffer{}
|
addBuf []byte = []byte{}
|
||||||
data []byte = []byte{}
|
|
||||||
addBuf = &bytes.Buffer{}
|
|
||||||
allocationLength uint16
|
allocationLength uint16
|
||||||
additionLength uint32
|
additionLength uint32
|
||||||
|
l int = 0
|
||||||
)
|
)
|
||||||
tgtName := cmd.Target.Name
|
tgtName := cmd.Target.Name
|
||||||
devUUID := cmd.Device.UUID
|
devUUID := cmd.Device.UUID
|
||||||
scsiResOp := GetSCSIReservationOperator()
|
scsiResOp := GetSCSIReservationOperator()
|
||||||
PRGeneration, _ := scsiResOp.GetPRGeneration(tgtName, devUUID)
|
PRGeneration, _ := scsiResOp.GetPRGeneration(tgtName, devUUID)
|
||||||
resList := scsiResOp.GetReservationList(tgtName, devUUID)
|
resList := scsiResOp.GetReservationList(tgtName, devUUID)
|
||||||
length, _ := SCSICDBBufXLength(cmd.SCB.Bytes())
|
|
||||||
|
|
||||||
allocationLength = uint16(length)
|
|
||||||
if allocationLength < 8 {
|
if allocationLength < 8 {
|
||||||
goto sense
|
goto sense
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, res := range resList {
|
for _, res := range resList {
|
||||||
addBuf.Write(util.MarshalUint64(res.Key))
|
addBuf = append(addBuf, util.MarshalUint64(res.Key)...)
|
||||||
}
|
}
|
||||||
additionLength = uint32(len(addBuf.Bytes()))
|
additionLength = uint32(len(addBuf))
|
||||||
|
|
||||||
buf.Write(util.MarshalUint32(PRGeneration))
|
l += copy(cmd.InSDBBuffer.Buffer[l:], util.MarshalUint32(PRGeneration))
|
||||||
buf.Write(util.MarshalUint32(additionLength))
|
l += copy(cmd.InSDBBuffer.Buffer[l:], util.MarshalUint32(additionLength))
|
||||||
buf.Write(addBuf.Bytes())
|
l += copy(cmd.InSDBBuffer.Buffer[l:], addBuf)
|
||||||
data = buf.Bytes()
|
|
||||||
if allocationLength < uint16(additionLength) {
|
|
||||||
cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data[0:allocationLength])
|
|
||||||
} else {
|
|
||||||
cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.InSDBBuffer.Resid = uint32(additionLength)
|
cmd.InSDBBuffer.Resid = uint32(additionLength)
|
||||||
return api.SAMStatGood
|
return api.SAMStatGood
|
||||||
@@ -763,7 +749,7 @@ func SPCPRReadReservation(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
PRGeneration, _ := scsiResOp.GetPRGeneration(tgtName, devUUID)
|
PRGeneration, _ := scsiResOp.GetPRGeneration(tgtName, devUUID)
|
||||||
curRes := scsiResOp.GetCurrentReservation(tgtName, devUUID)
|
curRes := scsiResOp.GetCurrentReservation(tgtName, devUUID)
|
||||||
|
|
||||||
length, _ := SCSICDBBufXLength(cmd.SCB.Bytes())
|
length, _ := SCSICDBBufXLength(cmd.SCB)
|
||||||
allocationLength = uint16(length)
|
allocationLength = uint16(length)
|
||||||
if allocationLength < 8 {
|
if allocationLength < 8 {
|
||||||
goto sense
|
goto sense
|
||||||
@@ -791,9 +777,9 @@ func SPCPRReadReservation(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
buf.Write(addBuf.Bytes())
|
buf.Write(addBuf.Bytes())
|
||||||
data = buf.Bytes()
|
data = buf.Bytes()
|
||||||
if allocationLength < uint16(additionLength) {
|
if allocationLength < uint16(additionLength) {
|
||||||
cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data[0:allocationLength])
|
copy(cmd.InSDBBuffer.Buffer, data[0:allocationLength])
|
||||||
} else {
|
} else {
|
||||||
cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data)
|
copy(cmd.InSDBBuffer.Buffer, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.InSDBBuffer.Resid = uint32(additionLength)
|
cmd.InSDBBuffer.Resid = uint32(additionLength)
|
||||||
@@ -807,40 +793,34 @@ sense:
|
|||||||
|
|
||||||
func SPCPRReportCapabilities(host int, cmd *api.SCSICommand) api.SAMStat {
|
func SPCPRReportCapabilities(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||||
var (
|
var (
|
||||||
buf []byte = make([]byte, 8)
|
availLength uint32 = 8
|
||||||
availLength uint32 = 8
|
actualLength uint32 = 0
|
||||||
actualLength uint32 = 0
|
|
||||||
data *bytes.Buffer = cmd.InSDBBuffer.Buffer
|
|
||||||
)
|
)
|
||||||
allocationLength := uint32(util.GetUnalignedUint16(cmd.SCB.Bytes()[7:9]))
|
allocationLength := uint32(util.GetUnalignedUint16(cmd.SCB[7:9]))
|
||||||
if allocationLength < 8 {
|
if allocationLength < 8 {
|
||||||
goto sense
|
goto sense
|
||||||
}
|
}
|
||||||
if cmd.InSDBBuffer.Length < allocationLength {
|
if cmd.InSDBBuffer.Length < allocationLength {
|
||||||
goto sense
|
goto sense
|
||||||
}
|
}
|
||||||
binary.BigEndian.PutUint16(buf[0:2], uint16(8))
|
copy(cmd.InSDBBuffer.Buffer, util.MarshalUint16(uint16(8)))
|
||||||
// Persistent Reservation Type Mask format
|
// Persistent Reservation Type Mask format
|
||||||
// Type Mask Valid (TMV)
|
// Type Mask Valid (TMV)
|
||||||
buf[3] |= 0x80
|
cmd.InSDBBuffer.Buffer[3] |= 0x80
|
||||||
// PR_TYPE_EXCLUSIVE_ACCESS_ALLREG
|
// PR_TYPE_EXCLUSIVE_ACCESS_ALLREG
|
||||||
buf[4] |= 0x80
|
cmd.InSDBBuffer.Buffer[4] |= 0x80
|
||||||
// PR_TYPE_EXCLUSIVE_ACCESS_REGONLY
|
// PR_TYPE_EXCLUSIVE_ACCESS_REGONLY
|
||||||
buf[4] |= 0x40
|
cmd.InSDBBuffer.Buffer[4] |= 0x40
|
||||||
// PR_TYPE_WRITE_EXCLUSIVE_REGONLY
|
// PR_TYPE_WRITE_EXCLUSIVE_REGONLY
|
||||||
buf[4] |= 0x20
|
cmd.InSDBBuffer.Buffer[4] |= 0x20
|
||||||
// PR_TYPE_EXCLUSIVE_ACCESS
|
// PR_TYPE_EXCLUSIVE_ACCESS
|
||||||
buf[4] |= 0x08
|
cmd.InSDBBuffer.Buffer[4] |= 0x08
|
||||||
// PR_TYPE_WRITE_EXCLUSIVE
|
// PR_TYPE_WRITE_EXCLUSIVE
|
||||||
buf[4] |= 0x02
|
cmd.InSDBBuffer.Buffer[4] |= 0x02
|
||||||
// PR_TYPE_EXCLUSIVE_ACCESS_ALLREG
|
// PR_TYPE_EXCLUSIVE_ACCESS_ALLREG
|
||||||
buf[5] |= 0x01
|
cmd.InSDBBuffer.Buffer[5] |= 0x01
|
||||||
|
|
||||||
if err := binary.Write(data, binary.BigEndian, buf); err != nil {
|
actualLength = availLength
|
||||||
goto sense
|
|
||||||
} else {
|
|
||||||
actualLength = availLength
|
|
||||||
}
|
|
||||||
cmd.InSDBBuffer.Resid = uint32(actualLength)
|
cmd.InSDBBuffer.Resid = uint32(actualLength)
|
||||||
return api.SAMStatGood
|
return api.SAMStatGood
|
||||||
sense:
|
sense:
|
||||||
@@ -852,9 +832,9 @@ sense:
|
|||||||
func reservationCheck(host int, cmd *api.SCSICommand) bool {
|
func reservationCheck(host int, cmd *api.SCSICommand) bool {
|
||||||
var (
|
var (
|
||||||
paramLen uint32
|
paramLen uint32
|
||||||
buf []byte = cmd.OutSDBBuffer.Buffer.Bytes()
|
buf []byte = cmd.OutSDBBuffer.Buffer
|
||||||
)
|
)
|
||||||
length, _ := SCSICDBBufXLength(cmd.SCB.Bytes())
|
length, _ := SCSICDBBufXLength(cmd.SCB)
|
||||||
paramLen = uint32(length)
|
paramLen = uint32(length)
|
||||||
if paramLen != 24 {
|
if paramLen != 24 {
|
||||||
return false
|
return false
|
||||||
@@ -871,8 +851,8 @@ func reservationCheck(host int, cmd *api.SCSICommand) bool {
|
|||||||
|
|
||||||
func SPCPRRegister(host int, cmd *api.SCSICommand) api.SAMStat {
|
func SPCPRRegister(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||||
var (
|
var (
|
||||||
buf []byte = cmd.OutSDBBuffer.Buffer.Bytes()
|
buf []byte = cmd.OutSDBBuffer.Buffer
|
||||||
scb []byte = cmd.SCB.Bytes()
|
scb []byte = cmd.SCB
|
||||||
ignoreKey bool = false
|
ignoreKey bool = false
|
||||||
ok bool = false
|
ok bool = false
|
||||||
resKey uint64
|
resKey uint64
|
||||||
@@ -930,7 +910,7 @@ sense:
|
|||||||
|
|
||||||
func SPCPRReserve(host int, cmd *api.SCSICommand) api.SAMStat {
|
func SPCPRReserve(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||||
var (
|
var (
|
||||||
scb []byte = cmd.SCB.Bytes()
|
scb []byte = cmd.SCB
|
||||||
curRes *api.SCSIReservation
|
curRes *api.SCSIReservation
|
||||||
res *api.SCSIReservation
|
res *api.SCSIReservation
|
||||||
ok bool = false
|
ok bool = false
|
||||||
@@ -992,8 +972,8 @@ sense:
|
|||||||
|
|
||||||
func SPCPRRelease(host int, cmd *api.SCSICommand) api.SAMStat {
|
func SPCPRRelease(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||||
var (
|
var (
|
||||||
buf []byte = cmd.OutSDBBuffer.Buffer.Bytes()
|
buf []byte = cmd.OutSDBBuffer.Buffer
|
||||||
scb []byte = cmd.SCB.Bytes()
|
scb []byte = cmd.SCB
|
||||||
curRes *api.SCSIReservation
|
curRes *api.SCSIReservation
|
||||||
res *api.SCSIReservation
|
res *api.SCSIReservation
|
||||||
resList []*api.SCSIReservation
|
resList []*api.SCSIReservation
|
||||||
@@ -1073,7 +1053,7 @@ sense:
|
|||||||
|
|
||||||
func SPCPRClear(host int, cmd *api.SCSICommand) api.SAMStat {
|
func SPCPRClear(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||||
var (
|
var (
|
||||||
buf []byte = cmd.OutSDBBuffer.Buffer.Bytes()
|
buf []byte = cmd.OutSDBBuffer.Buffer
|
||||||
curRes *api.SCSIReservation
|
curRes *api.SCSIReservation
|
||||||
res *api.SCSIReservation
|
res *api.SCSIReservation
|
||||||
ok bool = false
|
ok bool = false
|
||||||
@@ -1127,8 +1107,8 @@ sense:
|
|||||||
|
|
||||||
func SPCPRPreempt(host int, cmd *api.SCSICommand) api.SAMStat {
|
func SPCPRPreempt(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||||
var (
|
var (
|
||||||
buf []byte = cmd.OutSDBBuffer.Buffer.Bytes()
|
buf []byte = cmd.OutSDBBuffer.Buffer
|
||||||
scb []byte = cmd.SCB.Bytes()
|
scb []byte = cmd.SCB
|
||||||
ok bool = false
|
ok bool = false
|
||||||
resKey uint64
|
resKey uint64
|
||||||
sAResKey uint64
|
sAResKey uint64
|
||||||
@@ -1227,8 +1207,8 @@ sense:
|
|||||||
|
|
||||||
func SPCPRRegisterAndMove(host int, cmd *api.SCSICommand) api.SAMStat {
|
func SPCPRRegisterAndMove(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||||
var (
|
var (
|
||||||
buf []byte = cmd.OutSDBBuffer.Buffer.Bytes()
|
buf []byte = cmd.OutSDBBuffer.Buffer
|
||||||
scb []byte = cmd.SCB.Bytes()
|
scb []byte = cmd.SCB
|
||||||
resKey uint64
|
resKey uint64
|
||||||
sAResKey uint64
|
sAResKey uint64
|
||||||
curRes, dstReg, res *api.SCSIReservation
|
curRes, dstReg, res *api.SCSIReservation
|
||||||
@@ -1322,28 +1302,23 @@ func SPCRequestSense(host int, cmd *api.SCSICommand) api.SAMStat {
|
|||||||
var (
|
var (
|
||||||
allocationLength uint32
|
allocationLength uint32
|
||||||
actualLength uint32
|
actualLength uint32
|
||||||
data = &bytes.Buffer{}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
allocationLength = util.GetUnalignedUint32(cmd.SCB.Bytes()[4:8])
|
allocationLength = util.GetUnalignedUint32(cmd.SCB[4:8])
|
||||||
if allocationLength > cmd.InSDBBuffer.Length {
|
if allocationLength > cmd.InSDBBuffer.Length {
|
||||||
allocationLength = cmd.InSDBBuffer.Length
|
allocationLength = cmd.InSDBBuffer.Length
|
||||||
}
|
}
|
||||||
BuildSenseData(cmd, NO_SENSE, NO_ADDITIONAL_SENSE)
|
BuildSenseData(cmd, NO_SENSE, NO_ADDITIONAL_SENSE)
|
||||||
if cmd.SenseLength < allocationLength {
|
if cmd.SenseBuffer.Length < allocationLength {
|
||||||
actualLength = cmd.SenseLength
|
actualLength = cmd.SenseBuffer.Length
|
||||||
} else {
|
} else {
|
||||||
actualLength = allocationLength
|
actualLength = allocationLength
|
||||||
}
|
}
|
||||||
if cmd.SenseBuffer != nil {
|
copy(cmd.InSDBBuffer.Buffer, cmd.SenseBuffer.Buffer[:actualLength])
|
||||||
data.Write(cmd.SenseBuffer.Bytes()[:actualLength])
|
|
||||||
}
|
|
||||||
cmd.InSDBBuffer.Resid = uint32(actualLength)
|
cmd.InSDBBuffer.Resid = uint32(actualLength)
|
||||||
cmd.InSDBBuffer.Buffer = data
|
|
||||||
|
|
||||||
// reset sense buffer in cmnd
|
// reset sense buffer in cmnd
|
||||||
cmd.SenseBuffer = &bytes.Buffer{}
|
cmd.SenseBuffer = &api.SenseBuffer{}
|
||||||
cmd.SenseLength = 0
|
|
||||||
|
|
||||||
return api.SAMStatGood
|
return api.SAMStatGood
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2016 The GoStor Authors All rights reserved.
|
Copyright 2017 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -35,26 +35,28 @@ func TestSPCReportLuns(t *testing.T) {
|
|||||||
target := new(api.SCSITarget)
|
target := new(api.SCSITarget)
|
||||||
target.Devices = map[uint64]*api.SCSILu{0: lu}
|
target.Devices = map[uint64]*api.SCSILu{0: lu}
|
||||||
cmd.Target = target
|
cmd.Target = target
|
||||||
cmd.SCB = &bytes.Buffer{}
|
scb := &bytes.Buffer{}
|
||||||
cmd.SenseBuffer = &bytes.Buffer{}
|
cmd.InSDBBuffer = &api.SCSIDataBuffer{}
|
||||||
cmd.InSDBBuffer.Length = 16
|
cmd.InSDBBuffer.Length = 16
|
||||||
cmd.InSDBBuffer.Buffer = &bytes.Buffer{}
|
cmd.InSDBBuffer.Buffer = []byte{}
|
||||||
cmd.SCB.WriteByte(byte(api.REPORT_LUNS))
|
scb.WriteByte(byte(api.REPORT_LUNS))
|
||||||
for i := 0; i < 5; i++ {
|
for i := 0; i < 5; i++ {
|
||||||
cmd.SCB.WriteByte(0x00)
|
scb.WriteByte(0x00)
|
||||||
}
|
}
|
||||||
binary.Write(cmd.SCB, binary.BigEndian, uint32(16))
|
binary.Write(scb, binary.BigEndian, uint32(16))
|
||||||
|
cmd.SCB = scb.Bytes()
|
||||||
|
|
||||||
if err := SPCReportLuns(0, cmd); err.Err != nil {
|
if err := SPCReportLuns(0, cmd); err.Err != nil {
|
||||||
t.Errorf("Expected not error, but got %v", err)
|
t.Errorf("Expected not error, but got %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.SCB = &bytes.Buffer{}
|
scb = &bytes.Buffer{}
|
||||||
cmd.SCB.WriteByte(byte(api.REPORT_LUNS))
|
scb.WriteByte(byte(api.REPORT_LUNS))
|
||||||
for i := 0; i < 5; i++ {
|
for i := 0; i < 5; i++ {
|
||||||
cmd.SCB.WriteByte(0x00)
|
scb.WriteByte(0x00)
|
||||||
}
|
}
|
||||||
binary.Write(cmd.SCB, binary.BigEndian, uint32(10))
|
binary.Write(scb, binary.BigEndian, uint32(10))
|
||||||
|
cmd.SCB = scb.Bytes()
|
||||||
if err := SPCReportLuns(0, cmd); err.Err == nil {
|
if err := SPCReportLuns(0, cmd); err.Err == nil {
|
||||||
t.Error("Expected error, but got nothing")
|
t.Error("Expected error, but got nothing")
|
||||||
}
|
}
|
||||||
|
|||||||
30
pkg/util/pool/pool.go
Normal file
30
pkg/util/pool/pool.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2017 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 pool provides memory pool for buffer.
|
||||||
|
package pool
|
||||||
|
|
||||||
|
import "sync"
|
||||||
|
|
||||||
|
func NewBuffer(size int) []byte {
|
||||||
|
var bytePool = sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
return make([]byte, size)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytePool.Get().([]byte)
|
||||||
|
}
|
||||||
@@ -73,6 +73,15 @@ func MarshalKVText(kv []KeyValue) []byte {
|
|||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MarshalUint16(i uint16) []byte {
|
||||||
|
var data []byte
|
||||||
|
for j := 8; j >= 0; j -= 8 {
|
||||||
|
b := byte(i >> uint16(j))
|
||||||
|
data = append(data, b)
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
func MarshalUint32(i uint32) []byte {
|
func MarshalUint32(i uint32) []byte {
|
||||||
var data []byte
|
var data []byte
|
||||||
for j := 24; j >= 0; j -= 8 {
|
for j := 24; j >= 0; j -= 8 {
|
||||||
|
|||||||
Reference in New Issue
Block a user