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

View File

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

View File

@@ -156,7 +156,6 @@ func (s *ISCSITargetDriver) Run() error {
log.Error(err) log.Error(err)
os.Exit(1) os.Exit(1)
} }
defer l.Close()
for { for {
log.Info("Listening ...") log.Info("Listening ...")
@@ -178,6 +177,7 @@ func (s *ISCSITargetDriver) Run() error {
// start a new thread to do with this command // start a new thread to do with this command
go s.handler(DATAIN, iscsiConn) go s.handler(DATAIN, iscsiConn)
} }
l.Close()
return nil return nil
} }
@@ -476,10 +476,12 @@ SendRemainingData:
for { for {
switch conn.txIOState { switch conn.txIOState {
case IOSTATE_TX_BHS: case IOSTATE_TX_BHS:
log.Debug("ready to write response") if log.GetLevel() == log.DebugLevel {
log.Debugf("response is %s", resp.String()) log.Debug("ready to write response")
log.Debugf("response is %s", resp.String())
}
if l, err := conn.write(resp.Bytes()); err != nil { if l, err := conn.write(resp.Bytes()); err != nil {
log.Error(err) log.Errorf("failed to write data to client: %v", err)
return return
} else { } else {
conn.txIOState = IOSTATE_TX_INIT_AHS conn.txIOState = IOSTATE_TX_INIT_AHS
@@ -538,7 +540,7 @@ SendRemainingData:
case CONN_STATE_SCSI: case CONN_STATE_SCSI:
conn.txTask = nil conn.txTask = nil
default: default:
log.Warnf("unexpected connection state: %d", conn.state) log.Warnf("unexpected connection state: %v", conn.State())
conn.rxIOState = IOSTATE_RX_BHS conn.rxIOState = IOSTATE_RX_BHS
s.handler(DATAIN, conn) 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) { func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error, key byte, asc SCSISubError) {
var ( var (
scb = cmd.SCB 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
length int length int
doVerify bool = false doVerify bool = false
doWrite bool = false doWrite bool = false
wbuf []byte rbuf, wbuf []byte
tl int64 = int64(cmd.TL) 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
@@ -105,6 +104,7 @@ func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error, key
// TODO // TODO
break break
case api.READ_6, api.READ_10, api.READ_12, api.READ_16: 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) rbuf, err = bs.Read(int64(offset), tl)
if err != nil && err != io.EOF { if err != nil && err != io.EOF {
key = MEDIUM_ERROR key = MEDIUM_ERROR
@@ -141,7 +141,6 @@ func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error, key
} }
write: write:
if doWrite { if doWrite {
// hack: wbuf = []byte("hello world!")
err = bs.Write(wbuf, int64(offset)) err = bs.Write(wbuf, int64(offset))
if err != nil { if err != nil {
log.Error(err) log.Error(err)
@@ -176,6 +175,7 @@ write:
} }
verify: verify:
if doVerify { if doVerify {
rbuf = pool.NewBuffer(int(tl))
rbuf, err = bs.Read(int64(offset), tl) rbuf, err = bs.Read(int64(offset), tl)
if err != nil { if err != nil {
key = MEDIUM_ERROR key = MEDIUM_ERROR
@@ -187,9 +187,6 @@ verify:
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

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

View File

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