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