diff --git a/pkg/api/types.go b/pkg/api/types.go index 7238de3..3b6a247 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -17,6 +17,7 @@ package api import ( "errors" + "io" "sync" uuid "github.com/satori/go.uuid" @@ -406,3 +407,14 @@ type UnmapBlockDescriptor struct { Offset uint64 TL uint32 } + +type ReaderWriterAt interface { + io.ReaderAt + io.WriterAt +} + +type RemoteBackingStore interface { + ReaderWriterAt + Sync() (int, error) + Unmap(int64, int64) (int, error) +} diff --git a/pkg/scsi/backingstore/remote/remote.go b/pkg/scsi/backingstore/remote/remote.go new file mode 100644 index 0000000..71f15cc --- /dev/null +++ b/pkg/scsi/backingstore/remote/remote.go @@ -0,0 +1,107 @@ +/* +Copyright 2016 openebs 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. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package remote + +import ( + "fmt" + + "github.com/gostor/gotgt/pkg/api" + "github.com/gostor/gotgt/pkg/scsi" + log "github.com/sirupsen/logrus" +) + +func init() { + scsi.RegisterBackingStore("RemBs", newRemBs) +} + +// RemBackingStore +type RemBackingStore struct { + scsi.BaseBackingStore + // Remote backing store, remote server exposing + // read and write methods. + RemBs api.RemBackingStore +} + +func newRemBs() (api.BackingStore, error) { + return &RemBackingStore{ + BaseBackingStore: scsi.BaseBackingStore{ + Name: "RemBs", + OflagsSupported: 0, + }, + }, nil +} + +func (bs *RemBackingStore) Open(dev *api.SCSILu, path string) error { + bs.DataSize = uint64(dev.Size) + bs.RemBs = scsi.GetTargetBSMap(path) + return nil +} + +func (bs *RemBackingStore) Close(dev *api.SCSILu) error { + /* TODO return bs.File.Close()*/ + return nil +} + +func (bs *RemBackingStore) Init(dev *api.SCSILu, Opts string) error { + return nil +} + +func (bs *RemBackingStore) Exit(dev *api.SCSILu) error { + return nil +} + +func (bs *RemBackingStore) Size(dev *api.SCSILu) uint64 { + return bs.DataSize +} + +func (bs *RemBackingStore) Read(offset, tl int64) ([]byte, error) { + tmpbuf := make([]byte, tl) + length, err := bs.RemBs.ReadAt(tmpbuf, offset) + if err != nil { + return nil, err + } + if length != len(tmpbuf) { + return nil, fmt.Errorf("Incomplete read expected:%d actual:%d", tl, length) + } + return tmpbuf, nil +} + +func (bs *RemBackingStore) Write(wbuf []byte, offset int64) error { + length, err := bs.RemBs.WriteAt(wbuf, offset) + if err != nil { + log.Error(err) + return err + } + if length != len(wbuf) { + return fmt.Errorf("Incomplete write expected:%d actual:%d", len(wbuf), length) + } + return nil +} + +func (bs *RemBackingStore) DataAdvise(offset, length int64, advise uint32) error { + return nil +} + +func (bs *RemBackingStore) DataSync(offset, length int64) (err error) { + _, err = bs.RemBs.Sync() + return +} + +func (bs *RemBackingStore) Unmap(bd []api.UnmapBlockDescriptor) (err error) { + _, err = bs.RemBs.Unmap() + return +} diff --git a/pkg/scsi/scsilumap.go b/pkg/scsi/scsilumap.go index b6106cc..ac5bb27 100644 --- a/pkg/scsi/scsilumap.go +++ b/pkg/scsi/scsilumap.go @@ -17,6 +17,7 @@ limitations under the License. package scsi import ( + "errors" "fmt" "strconv" "sync" @@ -33,9 +34,15 @@ type SCSILUMap struct { AllDevices api.LUNMap // use target name as the key for target's LUN map TargetsLUNMap map[string]api.LUNMap + + TargetsBSMap map[string]api.RemoteBackingStore /* use target name as the key for target's Backing Store (temp) */ } -var globalSCSILUMap = SCSILUMap{AllDevices: make(api.LUNMap), TargetsLUNMap: make(map[string]api.LUNMap)} +var globalSCSILUMap = SCSILUMap{ + AllDevices: make(api.LUNMap), + TargetsLUNMap: make(map[string]api.LUNMap), + TargetsBSMap: make(map[string]api.RemoteBackingStore), +} type LUNMapping struct { TargetName string @@ -71,6 +78,15 @@ func GetTargetLUNMap(tgtName string) api.LUNMap { return lunMap } +func GetTargetBSMap(tgtName string) api.RemoteBackingStore { + /* TODO check for lock held by caller + globalSCSILUMap.mutex.RLock() + defer globalSCSILUMap.mutex.RUnlock()*/ + + lunMap := globalSCSILUMap.TargetsBSMap[tgtName] + return lunMap +} + func AddBackendStorage(bs config.BackendStorage) error { globalSCSILUMap.mutex.Lock() defer globalSCSILUMap.mutex.Unlock() @@ -130,3 +146,33 @@ func InitSCSILUMap(config *config.Config) error { } return nil } + +func InitSCSILUMapEx(tgtName, devpath string, deviceID, lun, size, sectorSize uint64, bs api.RemoteBackingStore) error { + globalSCSILUMap.mutex.Lock() + defer globalSCSILUMap.mutex.Unlock() + + if bs == nil { + return errors.New("Remote backing store is nil") + } + + globalSCSILUMap.TargetsBSMap[tgtName] = bs + + lu, err := NewSCSILu(&config.BackendStorage{ + DeviceID: deviceID, + Path: "RemBs:" + devpath, + Online: true, + }, + ) + if err != nil { + return errors.New("Init SCSI LU map error.") + } + globalSCSILUMap.AllDevices[deviceID] = lu + + mappingLUN(LUNMapping{ + DeviceID: deviceID, + LUN: lun, + TargetName: tgtName, + }, + ) + return nil +}