diff --git a/pkg/api/types.go b/pkg/api/types.go index 5cfd965..59576fb 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -351,7 +351,7 @@ type BackingStore interface { Write([]byte, int64) error DataSync() error DataAdvise(int64, int64, uint32) error - Unmap() error + Unmap([]UnmapBlockDescriptor) error } type SCSIDeviceProtocol interface { @@ -401,3 +401,8 @@ type SCSILu struct { } type LUNMap map[uint64]*SCSILu + +type UnmapBlockDescriptor struct { + Offset uint64 + TL uint32 +} diff --git a/pkg/scsi/backingstore.go b/pkg/scsi/backingstore.go index 6dcb541..f5d91b3 100644 --- a/pkg/scsi/backingstore.go +++ b/pkg/scsi/backingstore.go @@ -64,6 +64,7 @@ func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error, key rbuf, wbuf []byte tl int64 = int64(cmd.TL) ) + key = HARDWARE_ERROR asc = ASC_INTERNAL_TGT_FAILURE switch opcode { @@ -134,12 +135,6 @@ func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error, key } doVerify = true goto verify - case api.UNMAP: - err = bs.Unmap() - if err != nil { - key = MEDIUM_ERROR - asc = NO_ADDITIONAL_SENSE - } default: break } diff --git a/pkg/scsi/backingstore/cephstore_linux.go b/pkg/scsi/backingstore/cephstore_linux.go index c77820a..9e99f42 100644 --- a/pkg/scsi/backingstore/cephstore_linux.go +++ b/pkg/scsi/backingstore/cephstore_linux.go @@ -150,6 +150,6 @@ func (bs *CephBackingStore) DataAdvise(offset, length int64, advise uint32) erro return nil } -func (bs *CephBackingStore) Unmap() error { +func (bs *CephBackingStore) Unmap([]api.UnmapBlockDescriptor) error { return nil } diff --git a/pkg/scsi/backingstore/common.go b/pkg/scsi/backingstore/common.go index fc35bad..2a2d4b3 100644 --- a/pkg/scsi/backingstore/common.go +++ b/pkg/scsi/backingstore/common.go @@ -114,6 +114,6 @@ func (bs *FileBackingStore) DataAdvise(offset, length int64, advise uint32) erro return util.Fadvise(bs.file, offset, length, advise) } -func (bs *FileBackingStore) Unmap() error { +func (bs *FileBackingStore) Unmap([]api.UnmapBlockDescriptor) error { return nil } diff --git a/pkg/scsi/backingstore/null.go b/pkg/scsi/backingstore/null.go index f718d9a..8c74739 100644 --- a/pkg/scsi/backingstore/null.go +++ b/pkg/scsi/backingstore/null.go @@ -75,6 +75,6 @@ func (bs *NullBackingStore) DataAdvise(offset, length int64, advise uint32) erro return nil } -func (bs *NullBackingStore) Unmap() error { +func (bs *NullBackingStore) Unmap([]api.UnmapBlockDescriptor) error { return nil } diff --git a/pkg/scsi/sbc.go b/pkg/scsi/sbc.go index 36e668e..87ba500 100644 --- a/pkg/scsi/sbc.go +++ b/pkg/scsi/sbc.go @@ -18,6 +18,7 @@ limitations under the License. package scsi import ( + "encoding/binary" "fmt" "unsafe" @@ -295,13 +296,34 @@ sense: } func SBCUnmap(host int, cmd *api.SCSICommand) api.SAMStat { - err, key, asc := bsPerformCommand(cmd.Device.Storage, cmd) - if err == nil { + // check ANCHOR + if cmd.SCB[1]&0x01 != 0 { + BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB) + return api.SAMStatCheckCondition + } + + const blockDescLen = 16 + + var blockDescs []api.UnmapBlockDescriptor + for off := 8; uint32(off+blockDescLen) <= cmd.OutSDBBuffer.Length; off += blockDescLen { + lba := binary.BigEndian.Uint64(cmd.OutSDBBuffer.Buffer[off : off+8]) + num := binary.BigEndian.Uint32(cmd.OutSDBBuffer.Buffer[off+8 : off+12]) + blockDescs = append(blockDescs, api.UnmapBlockDescriptor{ + Offset: lba << cmd.Device.BlockShift, + TL: num << cmd.Device.BlockShift, + }) + } + + if len(blockDescs) == 0 { return api.SAMStatGood } - BuildSenseData(cmd, key, asc) - return api.SAMStatCheckCondition + if err := cmd.Device.Storage.Unmap(blockDescs); err != nil { + BuildSenseData(cmd, MEDIUM_ERROR, NO_ADDITIONAL_SENSE) + return api.SAMStatCheckCondition + } + + return api.SAMStatGood } /*