From ca14aab4c2e7fda38b2bddc019f572357a85470d Mon Sep 17 00:00:00 2001 From: Lei Xue Date: Tue, 30 Aug 2016 17:04:11 +0800 Subject: [PATCH] date: 2016-08-30/17:00 --- pkg/port/iscsit/cmd.go | 30 +++++++++++++++++++++++++++++- pkg/port/iscsit/iscsid.go | 25 +++++++++++++++++++++++-- pkg/scsi/backingstore/common.go | 8 ++++++-- pkg/scsi/lun.go | 8 ++++---- 4 files changed, 62 insertions(+), 9 deletions(-) diff --git a/pkg/port/iscsit/cmd.go b/pkg/port/iscsit/cmd.go index b690bd1..e7f71b0 100644 --- a/pkg/port/iscsit/cmd.go +++ b/pkg/port/iscsit/cmd.go @@ -110,6 +110,8 @@ func (cmd *ISCSICommand) Bytes() []byte { return cmd.textRespBytes() case OpNoopIn: return cmd.noopInBytes() + case OpSCSITaskResp: + return cmd.scsiTMFRespBytes() } return nil } @@ -176,7 +178,7 @@ func parseHeader(data []byte) (*ISCSICommand, error) { m.DataLen = int(ParseUint(data[5:8])) m.TaskTag = uint32(ParseUint(data[16:20])) switch m.OpCode { - case OpSCSICmd: + case OpSCSICmd, OpSCSITaskReq: m.LUN = [8]uint8{data[9]} m.ExpectedDataLen = uint32(ParseUint(data[20:24])) m.CmdSN = uint32(ParseUint(data[24:28])) @@ -364,3 +366,29 @@ func (m *ISCSICommand) noopInBytes() []byte { buf.Write(rd) return buf.Bytes() } + +func (m *ISCSICommand) scsiTMFRespBytes() []byte { + // rfc7143 11.6 + buf := &bytes.Buffer{} + buf.WriteByte(byte(OpSCSITaskResp)) + buf.WriteByte(0x80) + buf.WriteByte(0x00) + buf.WriteByte(0x00) + + // Skip through to byte 16 + for i := 0; i < 3*4; i++ { + buf.WriteByte(0x00) + } + buf.Write(util.MarshalUint64(uint64(m.TaskTag))[4:]) + for i := 0; i < 4; i++ { + buf.WriteByte(0x00) + } + buf.Write(util.MarshalUint64(uint64(m.StatSN))[4:]) + buf.Write(util.MarshalUint64(uint64(m.ExpCmdSN))[4:]) + buf.Write(util.MarshalUint64(uint64(m.MaxCmdSN))[4:]) + for i := 0; i < 3*4; i++ { + buf.WriteByte(0x00) + } + + return buf.Bytes() +} diff --git a/pkg/port/iscsit/iscsid.go b/pkg/port/iscsit/iscsid.go index 4917738..b67f5cf 100644 --- a/pkg/port/iscsit/iscsid.go +++ b/pkg/port/iscsit/iscsid.go @@ -139,8 +139,8 @@ func (s *ISCSITargetService) rxHandler(conn *iscsiConnection) { conn.rxIOState = IOSTATE_RX_INIT_AHS break } - glog.Infof("got command: \n%s", cmd.String()) - glog.Infof("got buffer: %v", buf) + glog.V(2).Infof("got command: \n%s", cmd.String()) + glog.V(2).Infof("got buffer: %v", buf) final = true case IOSTATE_RX_INIT_AHS: conn.rxIOState = IOSTATE_RX_DATA @@ -204,6 +204,7 @@ func (s *ISCSITargetService) rxHandler(conn *iscsiConnection) { default: iscsiExecReject(conn) } + glog.V(1).Infof("connection state is %v", conn.state) glog.Infof("%#v", conn.resp.String()) s.handler(DATAOUT, conn) } @@ -347,6 +348,20 @@ func iscsiExecNoopOut(conn *iscsiConnection) error { return nil } +func iscsiExecTMFunction(conn *iscsiConnection) error { + cmd := conn.req + conn.resp = &ISCSICommand{ + OpCode: OpSCSITaskResp, + Final: true, + NSG: FullFeaturePhase, + StatSN: cmd.ExpStatSN, + TaskTag: cmd.TaskTag, + ExpCmdSN: cmd.CmdSN + 1, + MaxCmdSN: cmd.CmdSN + 10, + } + return nil +} + func iscsiExecReject(conn *iscsiConnection) error { conn.resp = &ISCSICommand{ OpCode: OpReject, @@ -432,6 +447,7 @@ func (s *ISCSITargetService) txHandler(conn *iscsiConnection) { case CONN_STATE_SCSI: conn.txTask = nil default: + glog.Infof("unexpected connection state: %d", conn.state) conn.rxIOState = IOSTATE_RX_BHS s.handler(DATAIN, conn) } @@ -487,6 +503,11 @@ func (s *ISCSITargetService) scsiCommandHandler(conn *iscsiConnection) (err erro } conn.resp = resp } + case OpSCSITaskReq: + // task management function + conn.txTask = &iscsiTask{conn: conn, cmd: conn.req, tag: conn.req.TaskTag} + conn.txIOState = IOSTATE_TX_BHS + iscsiExecTMFunction(conn) case OpSCSIOut: case OpNoopOut: conn.txTask = &iscsiTask{conn: conn, cmd: conn.req, tag: conn.req.TaskTag} diff --git a/pkg/scsi/backingstore/common.go b/pkg/scsi/backingstore/common.go index 34efc2f..dcd4ff4 100644 --- a/pkg/scsi/backingstore/common.go +++ b/pkg/scsi/backingstore/common.go @@ -19,6 +19,7 @@ package backingstore import ( "bytes" "fmt" + "io" "os" "github.com/golang/glog" @@ -74,7 +75,7 @@ func (bs *FileBackingStore) CommandSubmit(cmd *api.SCSICommand) (err error) { key = scsi.ILLEGAL_REQUEST asc = scsi.ASC_INVALID_FIELD_IN_CDB wbuf []byte = []byte{} - rbuf []byte = []byte{} + rbuf = make([]byte, cmd.TL) length int doVerify bool = false doWrite bool = false @@ -98,6 +99,9 @@ func (bs *FileBackingStore) CommandSubmit(cmd *api.SCSICommand) (err error) { doWrite = true goto write case api.SYNCHRONIZE_CACHE, api.SYNCHRONIZE_CACHE_16: + if err = util.Fdatasync(lu.File); err != nil { + panic(err) + } break case api.WRITE_VERIFY, api.WRITE_VERIFY_12, api.WRITE_VERIFY_16: doVerify = true @@ -110,7 +114,7 @@ func (bs *FileBackingStore) CommandSubmit(cmd *api.SCSICommand) (err error) { break case api.READ_6, api.READ_10, api.READ_12, api.READ_16: length, err = lu.File.ReadAt(rbuf, int64(offset)) - if err != nil { + if err != nil && err != io.EOF { key = scsi.MEDIUM_ERROR asc = scsi.ASC_READ_ERROR break diff --git a/pkg/scsi/lun.go b/pkg/scsi/lun.go index 1a2849e..983f1e5 100644 --- a/pkg/scsi/lun.go +++ b/pkg/scsi/lun.go @@ -35,13 +35,13 @@ func NewSCSILu(lun uint64, target *api.SCSITarget) (*api.SCSILu, error) { DeviceProtocol: sbc, Storage: backing, BlockShift: 0, - Size: 1024 * 1024 * 1024, + Size: 1024 * 1024 * 10, } // hack this - if _, err = os.Stat("/tmp/data.txt"); err != nil && os.IsExist(err) { - os.Create("/tmp/data.txt") + if _, err = os.Stat("/var/tmp/disk.img"); err != nil && os.IsExist(err) { + panic(err) } - f, err := backing.Open(lu, "/tmp/data.txt") + f, err := backing.Open(lu, "/var/tmp/disk.img") if err != nil { return nil, err }