This commit is contained in:
Lei Xue
2017-08-02 19:01:41 +08:00
parent 4ae643e9f8
commit fcb96b323d
6 changed files with 91 additions and 101 deletions

View File

@@ -278,7 +278,7 @@ func parseHeader(data []byte) (*ISCSICommand, error) {
func (m *ISCSICommand) scsiCmdRespBytes() []byte {
// rfc7143 11.4
buf := &bytes.Buffer{}
buf := bytes.Buffer{}
buf.WriteByte(byte(OpSCSIResp))
var flag byte = 0x80
if m.Resid > 0 {
@@ -321,8 +321,12 @@ func (m *ISCSICommand) scsiCmdRespBytes() []byte {
func (m *ISCSICommand) dataInBytes() []byte {
// rfc7143 11.7
buf := &bytes.Buffer{}
buf.WriteByte(byte(OpSCSIIn))
dl := m.DataLen
for dl%4 > 0 {
dl++
}
var buf = make([]byte, (48 + dl))
buf[0] = byte(OpSCSIIn)
var flag byte
if m.FinalInSeq || m.Final == true {
flag |= 0x80
@@ -338,44 +342,29 @@ func (m *ISCSICommand) dataInBytes() []byte {
flag |= 0x02
}
}
buf.WriteByte(flag)
buf.WriteByte(0x00)
buf[1] = flag
//buf.WriteByte(0x00)
if m.HasStatus && m.Final == true {
flag = byte(m.Status)
}
buf.WriteByte(flag)
buf.WriteByte(0x00) // 4
buf.Write(util.MarshalUint64(uint64(m.DataLen))[5:]) // 5-8
//buf.WriteByte(flag)
buf[3] = flag
copy(buf[5:], util.MarshalUint64(uint64(m.DataLen))[5:])
// Skip through to byte 16 Since A bit is not set 11.7.4
for i := 0; i < 8; i++ {
buf.WriteByte(0x00)
}
buf.Write(util.MarshalUint64(uint64(m.TaskTag))[4:])
for i := 0; i < 4; i++ {
// 11.7.4
buf.WriteByte(0xff)
}
buf.Write(util.MarshalUint64(uint64(m.StatSN))[4:])
buf.Write(util.MarshalUint64(uint64(m.ExpCmdSN))[4:])
buf.Write(util.MarshalUint64(uint64(m.MaxCmdSN))[4:])
buf.Write(util.MarshalUint64(uint64(m.DataSN))[4:])
buf.Write(util.MarshalUint64(uint64(m.BufferOffset))[4:])
buf.Write(util.MarshalUint64(uint64(m.Resid))[4:])
buf.Write(m.RawData[m.BufferOffset : m.BufferOffset+uint32(m.DataLen)])
dl := m.DataLen
for dl%4 > 0 {
dl++
buf.WriteByte(0x00)
}
copy(buf[16:], util.MarshalUint32(m.TaskTag))
copy(buf[24:], util.MarshalUint32(m.StatSN))
copy(buf[28:], util.MarshalUint32(m.ExpCmdSN))
copy(buf[32:], util.MarshalUint32(m.MaxCmdSN))
copy(buf[36:], util.MarshalUint32(m.DataSN))
copy(buf[40:], util.MarshalUint32(m.BufferOffset))
copy(buf[44:], util.MarshalUint32(m.Resid))
copy(buf[48:], m.RawData[m.BufferOffset:m.BufferOffset+uint32(m.DataLen)])
return buf.Bytes()
return buf
}
func (m *ISCSICommand) textRespBytes() []byte {
buf := &bytes.Buffer{}
buf := bytes.Buffer{}
buf.WriteByte(byte(OpTextResp))
var b byte
if m.Final {
@@ -415,8 +404,7 @@ func (m *ISCSICommand) textRespBytes() []byte {
}
func (m *ISCSICommand) noopInBytes() []byte {
buf := &bytes.Buffer{}
buf := bytes.Buffer{}
buf.WriteByte(byte(OpNoopIn))
var b byte
b |= 0x80
@@ -452,7 +440,7 @@ func (m *ISCSICommand) noopInBytes() []byte {
func (m *ISCSICommand) scsiTMFRespBytes() []byte {
// rfc7143 11.6
buf := &bytes.Buffer{}
buf := bytes.Buffer{}
buf.WriteByte(byte(OpSCSITaskResp))
buf.WriteByte(0x80)
buf.WriteByte(m.Result)
@@ -477,9 +465,8 @@ func (m *ISCSICommand) scsiTMFRespBytes() []byte {
}
func (m *ISCSICommand) r2tRespBytes() []byte {
// rfc7143 11.8
buf := &bytes.Buffer{}
buf := bytes.Buffer{}
buf.WriteByte(byte(OpReady))
var b byte
if m.Final {

View File

@@ -155,7 +155,7 @@ func (conn *iscsiConnection) buildRespPackage(oc OpCode, task *iscsiTask) error
if task == nil {
task = conn.rxTask
}
resp := &ISCSICommand{
conn.resp = &ISCSICommand{
StatSN: conn.req.ExpStatSN,
TaskTag: conn.req.TaskTag,
ExpCmdSN: conn.session.ExpCmdSN,
@@ -164,55 +164,55 @@ func (conn *iscsiConnection) buildRespPackage(oc OpCode, task *iscsiTask) error
}
switch oc {
case OpReady:
resp.OpCode = OpReady
resp.R2TSN = task.r2tSN
resp.BufferOffset = uint32(task.offset)
resp.DesiredLength = uint32(task.r2tCount)
conn.resp.OpCode = OpReady
conn.resp.R2TSN = task.r2tSN
conn.resp.BufferOffset = uint32(task.offset)
conn.resp.DesiredLength = uint32(task.r2tCount)
if val := conn.loginParam.sessionParam[ISCSI_PARAM_MAX_BURST].Value; task.r2tCount > int(val) {
resp.DesiredLength = uint32(val)
conn.resp.DesiredLength = uint32(val)
}
case OpSCSIIn, OpSCSIResp:
resp.OpCode = oc
resp.Immediate = true
resp.Final = true
resp.SCSIResponse = 0x00
resp.HasStatus = true
conn.resp.OpCode = oc
conn.resp.Immediate = true
conn.resp.Final = true
conn.resp.SCSIResponse = 0x00
conn.resp.HasStatus = true
scmd := task.scmd
resp.Status = scmd.Result
conn.resp.Status = scmd.Result
if scmd.Result != 0 && scmd.SenseBuffer != nil {
length := util.MarshalUint32(scmd.SenseBuffer.Length)
resp.RawData = append(length[2:4], scmd.SenseBuffer.Buffer...)
conn.resp.RawData = append(length[2:4], scmd.SenseBuffer.Buffer...)
} else if scmd.Direction == api.SCSIDataRead || scmd.Direction == api.SCSIDataWrite {
if scmd.InSDBBuffer != nil {
resp.Resid = scmd.InSDBBuffer.Resid
if resp.Resid != 0 && resp.Resid < scmd.InSDBBuffer.Length {
resp.RawData = scmd.InSDBBuffer.Buffer[:resp.Resid]
conn.resp.Resid = scmd.InSDBBuffer.Resid
if conn.resp.Resid != 0 && conn.resp.Resid < scmd.InSDBBuffer.Length {
conn.resp.RawData = scmd.InSDBBuffer.Buffer[:conn.resp.Resid]
} else {
resp.RawData = scmd.InSDBBuffer.Buffer
conn.resp.RawData = scmd.InSDBBuffer.Buffer
}
} else {
resp.RawData = []byte{}
conn.resp.RawData = []byte{}
}
}
case OpNoopIn, OpReject:
resp.OpCode = oc
resp.Final = true
resp.NSG = FullFeaturePhase
resp.ExpCmdSN = conn.req.CmdSN + 1
conn.resp.OpCode = oc
conn.resp.Final = true
conn.resp.NSG = FullFeaturePhase
conn.resp.ExpCmdSN = conn.req.CmdSN + 1
case OpSCSITaskResp:
resp.OpCode = oc
resp.Final = true
resp.NSG = FullFeaturePhase
resp.ExpCmdSN = conn.req.CmdSN + 1
resp.Result = task.result
conn.resp.OpCode = oc
conn.resp.Final = true
conn.resp.NSG = FullFeaturePhase
conn.resp.ExpCmdSN = conn.req.CmdSN + 1
conn.resp.Result = task.result
case OpLoginResp:
resp.OpCode = OpLoginResp
resp.Transit = conn.loginParam.tgtTrans
resp.CSG = conn.req.CSG
resp.NSG = conn.loginParam.tgtNSG
resp.ExpCmdSN = conn.req.CmdSN
resp.MaxCmdSN = conn.req.CmdSN
conn.resp.OpCode = OpLoginResp
conn.resp.Transit = conn.loginParam.tgtTrans
conn.resp.CSG = conn.req.CSG
conn.resp.NSG = conn.loginParam.tgtNSG
conn.resp.ExpCmdSN = conn.req.CmdSN
conn.resp.MaxCmdSN = conn.req.CmdSN
negoKeys, err := conn.processLoginData()
if err != nil {
return err
@@ -221,11 +221,10 @@ func (conn *iscsiConnection) buildRespPackage(oc OpCode, task *iscsiTask) error
negoKeys = loginKVDeclare(conn, negoKeys)
conn.loginParam.keyDeclared = true
}
resp.RawData = util.MarshalKVText(negoKeys)
conn.resp.RawData = util.MarshalKVText(negoKeys)
conn.txTask = nil
}
conn.resp = resp
return nil
}

View File

@@ -156,7 +156,6 @@ func (s *ISCSITargetDriver) Run() error {
log.Error(err)
os.Exit(1)
}
defer l.Close()
for {
log.Info("Listening ...")
@@ -178,6 +177,7 @@ func (s *ISCSITargetDriver) Run() error {
// start a new thread to do with this command
go s.handler(DATAIN, iscsiConn)
}
l.Close()
return nil
}
@@ -476,10 +476,12 @@ SendRemainingData:
for {
switch conn.txIOState {
case IOSTATE_TX_BHS:
log.Debug("ready to write response")
log.Debugf("response is %s", resp.String())
if log.GetLevel() == log.DebugLevel {
log.Debug("ready to write response")
log.Debugf("response is %s", resp.String())
}
if l, err := conn.write(resp.Bytes()); err != nil {
log.Error(err)
log.Errorf("failed to write data to client: %v", err)
return
} else {
conn.txIOState = IOSTATE_TX_INIT_AHS
@@ -538,7 +540,7 @@ SendRemainingData:
case CONN_STATE_SCSI:
conn.txTask = nil
default:
log.Warnf("unexpected connection state: %d", conn.state)
log.Warnf("unexpected connection state: %v", conn.State())
conn.rxIOState = IOSTATE_RX_BHS
s.handler(DATAIN, conn)
}

View File

@@ -54,16 +54,15 @@ 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
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))
scb = cmd.SCB
offset = cmd.Offset
opcode = api.SCSICommandType(scb[0])
lu = cmd.Device
length int
doVerify bool = false
doWrite bool = false
rbuf, wbuf []byte
tl int64 = int64(cmd.TL)
)
key = HARDWARE_ERROR
asc = ASC_INTERNAL_TGT_FAILURE
@@ -105,6 +104,7 @@ func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error, key
// TODO
break
case api.READ_6, api.READ_10, api.READ_12, api.READ_16:
rbuf = pool.NewBuffer(int(tl))
rbuf, err = bs.Read(int64(offset), tl)
if err != nil && err != io.EOF {
key = MEDIUM_ERROR
@@ -141,7 +141,6 @@ func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error, key
}
write:
if doWrite {
// hack: wbuf = []byte("hello world!")
err = bs.Write(wbuf, int64(offset))
if err != nil {
log.Error(err)
@@ -176,6 +175,7 @@ write:
}
verify:
if doVerify {
rbuf = pool.NewBuffer(int(tl))
rbuf, err = bs.Read(int64(offset), tl)
if err != nil {
key = MEDIUM_ERROR
@@ -187,9 +187,6 @@ verify:
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)

View File

@@ -19,12 +19,16 @@ package pool
import "sync"
var bytePool sync.Pool = sync.Pool{}
func NewBuffer(size int) []byte {
var bytePool = sync.Pool{
New: func() interface{} {
return make([]byte, size)
},
bytePool.New = func() interface{} {
return make([]byte, size)
}
return bytePool.Get().([]byte)
}
func ReleaseBuffer(b []byte) {
bytePool.Put(b)
}

View File

@@ -91,13 +91,14 @@ func MarshalUint32(i uint32) []byte {
return data
}
func MarshalUint64(i uint64) []byte {
var data []byte
func MarshalUint64(v uint64) []byte {
var data = [8]byte{}
var i = 0
for j := 56; j >= 0; j -= 8 {
b := byte(i >> uint32(j))
data = append(data, b)
data[i] = byte(v >> uint32(j))
i++
}
return data
return data[0:8]
}
func StringToByte(str string, align int, maxlength int) []byte {