diff --git a/pkg/scsi/backingstore.go b/pkg/scsi/backingstore.go index f497e30..1ee1172 100644 --- a/pkg/scsi/backingstore.go +++ b/pkg/scsi/backingstore.go @@ -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"); you may not use this file except in compliance with the License. @@ -51,14 +51,12 @@ func NewBackingStore(name string) (api.BackingStore, error) { return f() } -func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error) { +func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error, key byte, asc SCSISubError) { var ( scb = cmd.SCB.Bytes() offset = cmd.Offset opcode = api.SCSICommandType(scb[0]) lu = cmd.Device - key = ILLEGAL_REQUEST - asc = ASC_INVALID_FIELD_IN_CDB wbuf []byte = []byte{} tl int64 = int64(cmd.TL) rbuf = make([]byte, tl) @@ -66,6 +64,8 @@ func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error) { doVerify bool = false doWrite bool = false ) + key = HARDWARE_ERROR + asc = ASC_INTERNAL_TGT_FAILURE switch opcode { case api.ORWRITE_16: tmpbuf := []byte{} @@ -181,13 +181,13 @@ verify: bs.DataAdvise(int64(offset), int64(length), util.POSIX_FADV_WILLNEED) } } - return nil + return nil, key, asc sense: if err != nil { log.Error(err) - return err + return err, key, asc } err = fmt.Errorf("sense data encounter, key: %v, asc: %v", key, asc) - return err + return err, key, asc } diff --git a/pkg/scsi/backingstore/common.go b/pkg/scsi/backingstore/common.go index b8827d1..4d78fab 100644 --- a/pkg/scsi/backingstore/common.go +++ b/pkg/scsi/backingstore/common.go @@ -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"); you may not use this file except in compliance with the License. diff --git a/pkg/scsi/sbc.go b/pkg/scsi/sbc.go index 421066d..9868f09 100644 --- a/pkg/scsi/sbc.go +++ b/pkg/scsi/sbc.go @@ -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"); you may not use this file except in compliance with the License. @@ -339,14 +339,12 @@ func SBCReadWrite(host int, cmd *api.SCSICommand) api.SAMStat { case api.READ_10, api.READ_12, api.READ_16, api.WRITE_10, api.WRITE_12, api.WRITE_16, api.ORWRITE_16, api.WRITE_VERIFY, api.WRITE_VERIFY_12, api.WRITE_VERIFY_16, api.COMPARE_AND_WRITE: // We only support protection information type 0 - /* - if scb[1]&0xe0 != 0 { - key = ILLEGAL_REQUEST - asc = ASC_INVALID_FIELD_IN_CDB - log.Warnf("sense") - goto sense - } - */ + if scb[1]&0xe0 != 0 { + key = ILLEGAL_REQUEST + asc = ASC_INVALID_FIELD_IN_CDB + log.Warnf("sense data(ILLEGAL_REQUEST,ASC_INVALID_FIELD_IN_CDB) encounter") + goto sense + } if cmd.OutSDBBuffer.Buffer == nil { cmd.OutSDBBuffer.Buffer = &bytes.Buffer{} } @@ -384,7 +382,7 @@ func SBCReadWrite(host int, cmd *api.SCSICommand) api.SAMStat { api.PRE_FETCH_10, api.PRE_FETCH_16, api.COMPARE_AND_WRITE: key = DATA_PROTECT asc = ASC_WRITE_PROTECT - log.Warnf("sense") + log.Warnf("sense data(data protect) and asc(ASC_WRITE_PROTECT) encounter") goto sense } } @@ -397,14 +395,14 @@ func SBCReadWrite(host int, cmd *api.SCSICommand) api.SAMStat { if lba+uint64(tl) < lba || lba+uint64(tl) > dev.Size>>dev.BlockShift { key = ILLEGAL_REQUEST asc = ASC_LBA_OUT_OF_RANGE - log.Warnf("sense: lba: %d, tl: %d, size: %d", lba, tl, dev.Size>>dev.BlockShift) + log.Warnf("sense data(ILLEGAL_REQUEST,ASC_LBA_OUT_OF_RANGE) encounter: lba: %d, tl: %d, size: %d", lba, tl, dev.Size>>dev.BlockShift) goto sense } } else { if lba >= dev.Size>>dev.BlockShift { key = ILLEGAL_REQUEST asc = ASC_LBA_OUT_OF_RANGE - log.Warnf("sense") + log.Warnf("sense data(ILLEGAL_REQUEST,ASC_LBA_OUT_OF_RANGE) encounter: lba: %d, size: %d", lba, dev.Size>>dev.BlockShift) goto sense } } @@ -435,11 +433,9 @@ func SBCReadWrite(host int, cmd *api.SCSICommand) api.SAMStat { */ } - err = bsPerformCommand(dev.Storage, cmd) + err, key, asc = bsPerformCommand(dev.Storage, cmd) if err != nil { - log.Error(err) - key = HARDWARE_ERROR - asc = ASC_INTERNAL_TGT_FAILURE + goto sense } else { return api.SAMStatGood } @@ -577,14 +573,11 @@ func SBCVerify(host int, cmd *api.SCSICommand) api.SAMStat { cmd.Offset = lba << dev.BlockShift cmd.TL = tl << dev.BlockShift - err = bsPerformCommand(dev.Storage, cmd) + err, key, asc = bsPerformCommand(dev.Storage, cmd) if err != nil { - log.Error(err) - key = HARDWARE_ERROR - asc = ASC_INTERNAL_TGT_FAILURE - } else { - return api.SAMStatGood + goto sense } + return api.SAMStatGood sense: cmd.InSDBBuffer.Resid = 0 BuildSenseData(cmd, key, asc) @@ -616,7 +609,54 @@ func SBCReadCapacity16(host int, cmd *api.SCSICommand) api.SAMStat { } func SBCGetLbaStatus(host int, cmd *api.SCSICommand) api.SAMStat { + var ( + key = ILLEGAL_REQUEST + asc = ASC_INVALID_FIELD_IN_CDB + dev = cmd.Device + scb = cmd.SCB.Bytes() + lba uint64 + tl uint32 + ) + if dev.Attrs.Removable && !dev.Attrs.Online { + key = NOT_READY + asc = ASC_MEDIUM_NOT_PRESENT + goto sense + } + + if cmd.SCB.Bytes()[1]&0xe0 != 0 { + // We only support protection information type 0 + key = ILLEGAL_REQUEST + asc = ASC_INVALID_FIELD_IN_CDB + goto sense + } + + if cmd.SCB.Bytes()[1]&0x02 == 0 { + // no data compare with the media + return api.SAMStatGood + } + lba = getSCSIReadWriteOffset(scb) + tl = getSCSIReadWriteCount(scb) + // Verify that we are not doing i/o beyond the end-of-lun + if tl != 0 { + if lba+uint64(tl) < lba || lba+uint64(tl) > dev.Size>>dev.BlockShift { + key = ILLEGAL_REQUEST + asc = ASC_LBA_OUT_OF_RANGE + log.Warnf("sense: lba: %d, tl: %d, size: %d", lba, tl, dev.Size>>dev.BlockShift) + goto sense + } + } else { + if lba >= dev.Size>>dev.BlockShift { + key = ILLEGAL_REQUEST + asc = ASC_LBA_OUT_OF_RANGE + log.Warnf("sense") + goto sense + } + } return api.SAMStatGood +sense: + cmd.InSDBBuffer.Resid = 0 + BuildSenseData(cmd, key, asc) + return api.SAMStatCheckCondition } func SBCServiceAction(host int, cmd *api.SCSICommand) api.SAMStat { @@ -626,6 +666,8 @@ func SBCServiceAction(host int, cmd *api.SCSICommand) api.SAMStat { return SBCReadCapacity(host, cmd) case api.SAI_READ_CAPACITY_16: return SBCReadCapacity16(host, cmd) + case api.SAI_GET_LBA_STATUS: + return SBCGetLbaStatus(host, cmd) } return api.SAMStatGood } diff --git a/pkg/scsi/scsi.go b/pkg/scsi/scsi.go index 3aa31e7..bfc5c66 100644 --- a/pkg/scsi/scsi.go +++ b/pkg/scsi/scsi.go @@ -149,8 +149,8 @@ func BuildSenseData(cmd *api.SCSICommand, key byte, asc SCSISubError) { for i := 0; i < 4; i++ { senseBuffer.WriteByte(0x00) } - senseBuffer.WriteByte((byte(asc) >> 8) & 0xff) - senseBuffer.WriteByte(byte(asc) & 0xff) + senseBuffer.WriteByte(byte((uint16(asc) >> 8) & 0xff)) + senseBuffer.WriteByte(byte(asc & 0x00ff)) for i := 0; i < 4; i++ { senseBuffer.WriteByte(0x00) } diff --git a/pkg/scsi/spc.go b/pkg/scsi/spc.go index 0308b9b..b577720 100644 --- a/pkg/scsi/spc.go +++ b/pkg/scsi/spc.go @@ -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"); you may not use this file except in compliance with the License. @@ -566,7 +566,7 @@ func reportOpcodesAll(cmd *api.SCSICommand, rctd int) error { } func reportOpcodeOne(cmd *api.SCSICommand, rctd int, opcode byte, rsa uint16, serviceAction bool) error { - return nil + return fmt.Errorf("non support") } func SPCReportSupportedOperationCodes(host int, cmd *api.SCSICommand) api.SAMStat { @@ -731,7 +731,7 @@ func SPCPRReportCapabilities(host int, cmd *api.SCSICommand) api.SAMStat { actualLength uint32 = 0 data *bytes.Buffer = cmd.InSDBBuffer.Buffer ) - allocationLength := util.GetUnalignedUint32(cmd.SCB.Bytes()[7:9]) + allocationLength := uint32(util.GetUnalignedUint16(cmd.SCB.Bytes()[7:9])) if allocationLength < 8 { goto sense }