enable UNMAP when LUN is thin provisioned
- support Block Limits VPD page (0xB0) - add UNMAP to REPORT SUPPORTED OPERATION CODES - READ CAPACITY(16): set LBPME when Thin provisioning is enabled - move Thinprovisioning and BlockShift to config - add Unmap to BackingStore
This commit is contained in:
@@ -19,7 +19,7 @@ import (
|
||||
"errors"
|
||||
"sync"
|
||||
|
||||
"github.com/satori/go.uuid"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
type SCSICommandType byte
|
||||
@@ -351,6 +351,7 @@ type BackingStore interface {
|
||||
Write([]byte, int64) error
|
||||
DataSync() error
|
||||
DataAdvise(int64, int64, uint32) error
|
||||
Unmap() error
|
||||
}
|
||||
|
||||
type SCSIDeviceProtocol interface {
|
||||
|
||||
@@ -101,9 +101,11 @@ var (
|
||||
)
|
||||
|
||||
type BackendStorage struct {
|
||||
DeviceID uint64 `json:"deviceID"`
|
||||
Path string `json:"path"`
|
||||
Online bool `json:"online"`
|
||||
DeviceID uint64 `json:"deviceID"`
|
||||
Path string `json:"path"`
|
||||
Online bool `json:"online"`
|
||||
Thinprovisioning bool `json:"thinprovisioning"`
|
||||
BlockShift uint `json:"blockShift"`
|
||||
}
|
||||
|
||||
type ISCSIPortalInfo struct {
|
||||
|
||||
@@ -135,7 +135,11 @@ func bsPerformCommand(bs api.BackingStore, cmd *api.SCSICommand) (err error, key
|
||||
doVerify = true
|
||||
goto verify
|
||||
case api.UNMAP:
|
||||
// TODO
|
||||
err = bs.Unmap()
|
||||
if err != nil {
|
||||
key = MEDIUM_ERROR
|
||||
asc = NO_ADDITIONAL_SENSE
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
@@ -149,3 +149,7 @@ func (bs *CephBackingStore) DataSync() error {
|
||||
func (bs *CephBackingStore) DataAdvise(offset, length int64, advise uint32) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (bs *CephBackingStore) Unmap() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -113,3 +113,7 @@ func (bs *FileBackingStore) DataSync() error {
|
||||
func (bs *FileBackingStore) DataAdvise(offset, length int64, advise uint32) error {
|
||||
return util.Fadvise(bs.file, offset, length, advise)
|
||||
}
|
||||
|
||||
func (bs *FileBackingStore) Unmap() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -74,3 +74,7 @@ func (bs *NullBackingStore) DataSync() error {
|
||||
func (bs *NullBackingStore) DataAdvise(offset, length int64, advise uint32) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (bs *NullBackingStore) Unmap() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -20,13 +20,13 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/gostor/gotgt/pkg/api"
|
||||
"github.com/gostor/gotgt/pkg/config"
|
||||
)
|
||||
|
||||
// NewSCSILu: create a new SCSI LU
|
||||
// path format <protocol>:/absolute/file/path
|
||||
func NewSCSILu(device_uuid uint64, path string, online bool) (*api.SCSILu, error) {
|
||||
|
||||
pathinfo := strings.SplitN(path, ":", 2)
|
||||
func NewSCSILu(bs *config.BackendStorage) (*api.SCSILu, error) {
|
||||
pathinfo := strings.SplitN(bs.Path, ":", 2)
|
||||
if len(pathinfo) < 2 {
|
||||
return nil, errors.New("invalid device path string")
|
||||
}
|
||||
@@ -43,8 +43,8 @@ func NewSCSILu(device_uuid uint64, path string, online bool) (*api.SCSILu, error
|
||||
PerformCommand: luPerformCommand,
|
||||
DeviceProtocol: sbc,
|
||||
Storage: backing,
|
||||
BlockShift: api.DefaultBlockShift,
|
||||
UUID: device_uuid,
|
||||
BlockShift: bs.BlockShift,
|
||||
UUID: bs.DeviceID,
|
||||
}
|
||||
|
||||
err = backing.Open(lu, backendPath)
|
||||
@@ -53,7 +53,8 @@ func NewSCSILu(device_uuid uint64, path string, online bool) (*api.SCSILu, error
|
||||
}
|
||||
lu.Size = backing.Size(lu)
|
||||
lu.DeviceProtocol.InitLu(lu)
|
||||
lu.Attrs.Online = online
|
||||
lu.Attrs.Thinprovisioning = bs.Thinprovisioning
|
||||
lu.Attrs.Online = bs.Online
|
||||
lu.Attrs.Lbppbe = 3
|
||||
return lu, nil
|
||||
}
|
||||
|
||||
@@ -295,7 +295,13 @@ sense:
|
||||
}
|
||||
|
||||
func SBCUnmap(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
return api.SAMStatGood
|
||||
err, key, asc := bsPerformCommand(cmd.Device.Storage, cmd)
|
||||
if err == nil {
|
||||
return api.SAMStatGood
|
||||
}
|
||||
|
||||
BuildSenseData(cmd, key, asc)
|
||||
return api.SAMStatCheckCondition
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -594,7 +600,11 @@ func SBCReadCapacity16(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
if allocationLength > 12 {
|
||||
copy(cmd.InSDBBuffer.Buffer[8:], util.MarshalUint32(uint32(1<<bshift)))
|
||||
if allocationLength > 16 {
|
||||
val := (cmd.Device.Attrs.Lbppbe << 16) | cmd.Device.Attrs.LowestAlignedLBA
|
||||
var lbpme int
|
||||
if cmd.Device.Attrs.Thinprovisioning {
|
||||
lbpme = 1
|
||||
}
|
||||
val := (cmd.Device.Attrs.Lbppbe << 16) | (lbpme << 15) | cmd.Device.Attrs.LowestAlignedLBA
|
||||
copy(cmd.InSDBBuffer.Buffer[12:], util.MarshalUint32(uint32(val)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ func InitSCSILUMap(config *config.Config) error {
|
||||
defer globalSCSILUMap.mutex.Unlock()
|
||||
|
||||
for _, bs := range config.Storages {
|
||||
lu, err := NewSCSILu(bs.DeviceID, bs.Path, bs.Online)
|
||||
lu, err := NewSCSILu(&bs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Init SCSI LU map error: %v", err)
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import (
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/gostor/gotgt/pkg/api"
|
||||
"github.com/gostor/gotgt/pkg/util"
|
||||
"github.com/satori/go.uuid"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
func SPCIllegalOp(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
@@ -58,6 +58,7 @@ func InquiryPage0x00(host int, cmd *api.SCSICommand) (*bytes.Buffer, uint16) {
|
||||
descBuf.WriteByte(0x00)
|
||||
descBuf.WriteByte(0x80)
|
||||
descBuf.WriteByte(0x83)
|
||||
descBuf.WriteByte(0xB0)
|
||||
/*
|
||||
TODO:
|
||||
descBuf.WriteByte(0x86)
|
||||
@@ -188,6 +189,42 @@ func InquiryPage0x83(host int, cmd *api.SCSICommand) (*bytes.Buffer, uint16) {
|
||||
return buf, pageLength
|
||||
}
|
||||
|
||||
func InquiryPage0xB0(host int, cmd *api.SCSICommand) (*bytes.Buffer, uint16) {
|
||||
var (
|
||||
buf = &bytes.Buffer{}
|
||||
pageLength uint16 = 0x3C
|
||||
maxUnmapLbaCount uint32 = 0
|
||||
maxUnmapBlockDescriptorCount uint32 = 0
|
||||
)
|
||||
|
||||
if cmd.Device.Attrs.Thinprovisioning {
|
||||
maxUnmapLbaCount = 0xFFFFFFFF
|
||||
maxUnmapBlockDescriptorCount = 0xFFFFFFFF
|
||||
}
|
||||
|
||||
//byte 0
|
||||
if cmd.Device.Attrs.Online {
|
||||
buf.WriteByte(PQ_DEVICE_CONNECTED | byte(cmd.Device.Attrs.DeviceType))
|
||||
} else {
|
||||
buf.WriteByte(PQ_DEVICE_NOT_CONNECT | byte(cmd.Device.Attrs.DeviceType))
|
||||
}
|
||||
//PAGE CODE
|
||||
buf.WriteByte(0xB0)
|
||||
//PAGE LENGTH
|
||||
binary.Write(buf, binary.BigEndian, pageLength)
|
||||
|
||||
buf.Write(make([]byte, 16))
|
||||
|
||||
//MAXIMUM UNMAP LBA COUNT
|
||||
binary.Write(buf, binary.BigEndian, maxUnmapLbaCount)
|
||||
|
||||
//MAXIMUM UNMAP BLOCK DESCRIPTOR COUNT
|
||||
binary.Write(buf, binary.BigEndian, maxUnmapBlockDescriptorCount)
|
||||
|
||||
buf.Write(make([]byte, 36))
|
||||
return buf, pageLength
|
||||
}
|
||||
|
||||
/*
|
||||
* SPCInquiry Implements SCSI INQUIRY command
|
||||
* The INQUIRY command requests the device server to return information regarding the logical unit and SCSI target device.
|
||||
@@ -231,6 +268,8 @@ func SPCInquiry(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
buf, _ = InquiryPage0x80(host, cmd)
|
||||
case 0x83:
|
||||
buf, _ = InquiryPage0x83(host, cmd)
|
||||
case 0xB0:
|
||||
buf, _ = InquiryPage0xB0(host, cmd)
|
||||
default:
|
||||
goto sense
|
||||
}
|
||||
@@ -610,7 +649,7 @@ func reportOpcodesAll(cmd *api.SCSICommand, rctd int) error {
|
||||
var (
|
||||
data = []byte{0x00, 0x00, 0x00, 0x00}
|
||||
)
|
||||
for _, i := range []api.SCSICommandType{api.TEST_UNIT_READY, api.WRITE_6, api.INQUIRY, api.READ_CAPACITY, api.WRITE_10, api.WRITE_16, api.REPORT_LUNS, api.WRITE_12} {
|
||||
for _, i := range []api.SCSICommandType{api.TEST_UNIT_READY, api.WRITE_6, api.INQUIRY, api.READ_CAPACITY, api.WRITE_10, api.WRITE_16, api.REPORT_LUNS, api.WRITE_12, api.UNMAP} {
|
||||
data = append(data, byte(i))
|
||||
// reserved
|
||||
data = append(data, 0x00)
|
||||
@@ -627,7 +666,7 @@ func reportOpcodesAll(cmd *api.SCSICommand, rctd int) error {
|
||||
}
|
||||
// cdb length
|
||||
length := getSCSICmdSize(i)
|
||||
data = append(data, (length>>8)&0xff)
|
||||
data = append(data, 0)
|
||||
data = append(data, length&0xff)
|
||||
// timeout descriptor
|
||||
if rctd != 0 {
|
||||
|
||||
Reference in New Issue
Block a user