This commit is contained in:
Lei Xue
2017-07-31 21:47:38 +08:00
parent 957564305a
commit 4ae643e9f8
12 changed files with 258 additions and 221 deletions

View File

@@ -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
} }

View File

@@ -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
} }
} }

View File

@@ -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{}
} }

View File

@@ -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 {

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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
} }

View File

@@ -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
View 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)
}

View File

@@ -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 {