From fcb96b323dff35da037d8b5cd0edc315d52d0dd8 Mon Sep 17 00:00:00 2001 From: Lei Xue Date: Wed, 2 Aug 2017 19:01:41 +0800 Subject: [PATCH] perf2 --- pkg/port/iscsit/cmd.go | 63 ++++++++++++++--------------------- pkg/port/iscsit/conn.go | 69 +++++++++++++++++++-------------------- pkg/port/iscsit/iscsid.go | 12 ++++--- pkg/scsi/backingstore.go | 25 +++++++------- pkg/util/pool/pool.go | 12 ++++--- pkg/util/util.go | 11 ++++--- 6 files changed, 91 insertions(+), 101 deletions(-) diff --git a/pkg/port/iscsit/cmd.go b/pkg/port/iscsit/cmd.go index 3dd22d9..2ebb3c2 100644 --- a/pkg/port/iscsit/cmd.go +++ b/pkg/port/iscsit/cmd.go @@ -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 { diff --git a/pkg/port/iscsit/conn.go b/pkg/port/iscsit/conn.go index bb027fb..59efd6b 100644 --- a/pkg/port/iscsit/conn.go +++ b/pkg/port/iscsit/conn.go @@ -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 } diff --git a/pkg/port/iscsit/iscsid.go b/pkg/port/iscsit/iscsid.go index ddd6902..02fb338 100644 --- a/pkg/port/iscsit/iscsid.go +++ b/pkg/port/iscsit/iscsid.go @@ -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) } diff --git a/pkg/scsi/backingstore.go b/pkg/scsi/backingstore.go index 5d8f7da..7cf0315 100644 --- a/pkg/scsi/backingstore.go +++ b/pkg/scsi/backingstore.go @@ -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) diff --git a/pkg/util/pool/pool.go b/pkg/util/pool/pool.go index f744668..5e922a3 100644 --- a/pkg/util/pool/pool.go +++ b/pkg/util/pool/pool.go @@ -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) +} diff --git a/pkg/util/util.go b/pkg/util/util.go index d23a3be..5ef830f 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -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 {