PR implementation
This commit is contained in:
@@ -0,0 +1,324 @@
|
||||
package scsi
|
||||
|
||||
import (
|
||||
"github.com/gostor/gotgt/pkg/api"
|
||||
"github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
type SCSIReservationOperator interface {
|
||||
GetCurrentReservation(tgtName string, devUUID uint64) *api.SCSIReservation
|
||||
SetCurrentReservation(tgtName string, devUUID uint64, res *api.SCSIReservation) bool
|
||||
IsCurrentReservation(tgtName string, devUUID uint64, res *api.SCSIReservation) bool
|
||||
|
||||
GetPRGeneration(tgtName string, devUUID uint64) (uint32, bool)
|
||||
IncPRGeneration(tgtName string, devUUID uint64) bool
|
||||
|
||||
AddReservation(tgtName string, devUUID uint64, res *api.SCSIReservation) bool
|
||||
GetReservation(tgtName string, devUUID uint64, ITNexusID uuid.UUID) *api.SCSIReservation
|
||||
GetReservationList(tgtName string, devUUID uint64) []*api.SCSIReservation
|
||||
DeleteAndRemoveReservation(tgtName string, devUUID uint64, res *api.SCSIReservation)
|
||||
RemoveReservation(tgtName string, devUUID uint64, res *api.SCSIReservation)
|
||||
RemoveAllReservation(tgtName string, devUUID uint64)
|
||||
|
||||
IsKeyExists(tgtName string, devUUID uint64, key uint64) bool
|
||||
|
||||
Save(tgtName string, devUUID uint64) bool
|
||||
}
|
||||
|
||||
var onePROperator SCSIReservationOperator
|
||||
|
||||
func GetSCSIReservationOperator() SCSIReservationOperator {
|
||||
if onePROperator == nil {
|
||||
onePROperator = &SCSISimpleReservationOperator{
|
||||
targetReservations: make(map[string]SCSILUReservationMap),
|
||||
}
|
||||
}
|
||||
return onePROperator
|
||||
}
|
||||
|
||||
type SCSILUReservation struct {
|
||||
TargetName string
|
||||
DeviceUUID uint64
|
||||
PRGeneration uint32
|
||||
Reservations []*api.SCSIReservation
|
||||
CurrentReservation *api.SCSIReservation
|
||||
}
|
||||
|
||||
type SCSILUReservationMap map[uint64]*SCSILUReservation /* device uuid as the key */
|
||||
|
||||
type SCSISimpleReservationOperator struct {
|
||||
SCSIReservationOperator
|
||||
targetReservations map[string]SCSILUReservationMap /* target name as the key*/
|
||||
}
|
||||
|
||||
func (op *SCSISimpleReservationOperator) InitLUReservation(tgtName string, devUUID uint64) {
|
||||
var (
|
||||
targetRes SCSILUReservationMap
|
||||
ok bool
|
||||
)
|
||||
|
||||
if targetRes, ok = op.targetReservations[tgtName]; !ok {
|
||||
op.targetReservations[tgtName] = make(SCSILUReservationMap)
|
||||
targetRes = op.targetReservations[tgtName]
|
||||
}
|
||||
if _, ok = targetRes[devUUID]; !ok {
|
||||
targetRes[devUUID] = &SCSILUReservation{TargetName: tgtName,
|
||||
DeviceUUID: devUUID,
|
||||
PRGeneration: 0,
|
||||
Reservations: []*api.SCSIReservation{},
|
||||
CurrentReservation: nil,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (op *SCSISimpleReservationOperator) GetReservation(tgtName string, devUUID uint64, ITNexusID uuid.UUID) *api.SCSIReservation {
|
||||
var (
|
||||
LURes *SCSILUReservation
|
||||
SCSIRes *api.SCSIReservation
|
||||
targetRes SCSILUReservationMap
|
||||
ok bool
|
||||
)
|
||||
if targetRes, ok = op.targetReservations[tgtName]; !ok {
|
||||
return nil
|
||||
}
|
||||
if LURes, ok = targetRes[devUUID]; !ok {
|
||||
return nil
|
||||
}
|
||||
for _, SCSIRes = range LURes.Reservations {
|
||||
if uuid.Equal(SCSIRes.ITNexusID, ITNexusID) {
|
||||
return SCSIRes
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (op *SCSISimpleReservationOperator) GetPRGeneration(tgtName string, devUUID uint64) (uint32, bool) {
|
||||
var (
|
||||
LURes *SCSILUReservation
|
||||
targetRes SCSILUReservationMap
|
||||
ok bool
|
||||
)
|
||||
if targetRes, ok = op.targetReservations[tgtName]; !ok {
|
||||
return 0, false
|
||||
}
|
||||
if LURes, ok = targetRes[devUUID]; !ok {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return LURes.PRGeneration, true
|
||||
}
|
||||
|
||||
func (op *SCSISimpleReservationOperator) IncPRGeneration(tgtName string, devUUID uint64) bool {
|
||||
var (
|
||||
LURes *SCSILUReservation
|
||||
targetRes SCSILUReservationMap
|
||||
ok bool
|
||||
)
|
||||
if targetRes, ok = op.targetReservations[tgtName]; !ok {
|
||||
return false
|
||||
}
|
||||
if LURes, ok = targetRes[devUUID]; !ok {
|
||||
return false
|
||||
}
|
||||
LURes.PRGeneration++
|
||||
return true
|
||||
}
|
||||
|
||||
func (op *SCSISimpleReservationOperator) GetCurrentReservation(tgtName string, devUUID uint64) *api.SCSIReservation {
|
||||
var (
|
||||
LURes *SCSILUReservation
|
||||
targetRes SCSILUReservationMap
|
||||
ok bool
|
||||
)
|
||||
if targetRes, ok = op.targetReservations[tgtName]; !ok {
|
||||
return nil
|
||||
}
|
||||
if LURes, ok = targetRes[devUUID]; !ok {
|
||||
return nil
|
||||
}
|
||||
return LURes.CurrentReservation
|
||||
}
|
||||
|
||||
func (op *SCSISimpleReservationOperator) SetCurrentReservation(tgtName string, devUUID uint64, res *api.SCSIReservation) bool {
|
||||
var (
|
||||
LURes *SCSILUReservation
|
||||
targetRes SCSILUReservationMap
|
||||
ok bool
|
||||
)
|
||||
if targetRes, ok = op.targetReservations[tgtName]; !ok {
|
||||
return false
|
||||
}
|
||||
if LURes, ok = targetRes[devUUID]; !ok {
|
||||
return false
|
||||
}
|
||||
LURes.CurrentReservation = res
|
||||
return true
|
||||
}
|
||||
|
||||
func (op *SCSISimpleReservationOperator) GetReservationList(tgtName string, devUUID uint64) []*api.SCSIReservation {
|
||||
var (
|
||||
LURes *SCSILUReservation
|
||||
targetRes SCSILUReservationMap
|
||||
ok bool
|
||||
)
|
||||
if targetRes, ok = op.targetReservations[tgtName]; !ok {
|
||||
return nil
|
||||
}
|
||||
if LURes, ok = targetRes[devUUID]; !ok {
|
||||
return nil
|
||||
}
|
||||
return LURes.Reservations
|
||||
}
|
||||
|
||||
func (op *SCSISimpleReservationOperator) DeleteAndRemoveReservation(tgtName string, devUUID uint64, res *api.SCSIReservation) {
|
||||
var (
|
||||
i int = -1
|
||||
ok bool
|
||||
tmpRes *api.SCSIReservation
|
||||
LURes *SCSILUReservation
|
||||
targetRes SCSILUReservationMap
|
||||
)
|
||||
if targetRes, ok = op.targetReservations[tgtName]; !ok {
|
||||
return
|
||||
}
|
||||
if LURes, ok = targetRes[devUUID]; !ok {
|
||||
return
|
||||
}
|
||||
|
||||
resArray := LURes.Reservations
|
||||
curRes := LURes.CurrentReservation
|
||||
|
||||
for i, tmpRes = range resArray {
|
||||
if tmpRes == res {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if i >= 0 {
|
||||
resArray[i] = resArray[len(resArray)-1]
|
||||
resArray[len(resArray)-1] = nil
|
||||
resArray = resArray[:len(resArray)-1]
|
||||
}
|
||||
|
||||
if curRes == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !op.IsCurrentReservation(tgtName, devUUID, res) {
|
||||
return
|
||||
}
|
||||
|
||||
if (curRes.Type != PR_TYPE_WRITE_EXCLUSIVE_ALLREG &&
|
||||
curRes.Type != PR_TYPE_EXCLUSIVE_ACCESS_ALLREG) ||
|
||||
len(resArray) == 0 {
|
||||
curRes.Scope = 0
|
||||
curRes.Type = 0
|
||||
LURes.CurrentReservation = nil
|
||||
for i, tmpRes = range resArray {
|
||||
if tmpRes == res {
|
||||
continue
|
||||
}
|
||||
//TODO send sense code
|
||||
}
|
||||
LURes.PRGeneration++
|
||||
} else {
|
||||
for i, tmpRes = range resArray {
|
||||
if tmpRes != res {
|
||||
//kep scope and type
|
||||
LURes.CurrentReservation = tmpRes
|
||||
tmpRes.Scope = curRes.Scope
|
||||
tmpRes.Type = curRes.Type
|
||||
break
|
||||
}
|
||||
}
|
||||
LURes.PRGeneration++
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (op *SCSISimpleReservationOperator) RemoveReservation(tgtName string, devUUID uint64, res *api.SCSIReservation) {
|
||||
var (
|
||||
i int = -1
|
||||
tmpRes *api.SCSIReservation
|
||||
)
|
||||
|
||||
resArray := op.GetReservationList(tgtName, devUUID)
|
||||
|
||||
for i, tmpRes = range resArray {
|
||||
if tmpRes == res {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if i >= 0 {
|
||||
resArray[i] = resArray[len(resArray)-1]
|
||||
resArray[len(resArray)-1] = nil
|
||||
resArray = resArray[:len(resArray)-1]
|
||||
}
|
||||
}
|
||||
|
||||
func (op *SCSISimpleReservationOperator) AddReservation(tgtName string, devUUID uint64, res *api.SCSIReservation) bool {
|
||||
var (
|
||||
LURes *SCSILUReservation
|
||||
targetRes SCSILUReservationMap
|
||||
ok bool
|
||||
)
|
||||
if targetRes, ok = op.targetReservations[tgtName]; !ok {
|
||||
return false
|
||||
}
|
||||
if LURes, ok = targetRes[devUUID]; !ok {
|
||||
return false
|
||||
}
|
||||
LURes.Reservations = append(LURes.Reservations, res)
|
||||
return true
|
||||
}
|
||||
|
||||
func (op *SCSISimpleReservationOperator) IsKeyExists(tgtName string, devUUID uint64, key uint64) bool {
|
||||
|
||||
resList := op.GetReservationList(tgtName, devUUID)
|
||||
for _, tmpRes := range resList {
|
||||
if tmpRes.Key == key {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (op *SCSISimpleReservationOperator) IsCurrentReservation(tgtName string, devUUID uint64, res *api.SCSIReservation) bool {
|
||||
curRes := op.GetCurrentReservation(tgtName, devUUID)
|
||||
if curRes == nil {
|
||||
return false
|
||||
}
|
||||
if curRes.Type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG ||
|
||||
curRes.Type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG {
|
||||
return true
|
||||
}
|
||||
|
||||
if curRes == res {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (op *SCSISimpleReservationOperator) RemoveAllReservation(tgtName string, devUUID uint64) {
|
||||
var (
|
||||
LURes *SCSILUReservation
|
||||
targetRes SCSILUReservationMap
|
||||
ok bool
|
||||
)
|
||||
if targetRes, ok = op.targetReservations[tgtName]; !ok {
|
||||
return
|
||||
}
|
||||
if LURes, ok = targetRes[devUUID]; !ok {
|
||||
return
|
||||
}
|
||||
LURes.Reservations = []*api.SCSIReservation{}
|
||||
|
||||
}
|
||||
|
||||
func (op *SCSISimpleReservationOperator) Save(tgtName string, devUUID uint64) bool {
|
||||
return true
|
||||
}
|
||||
Reference in New Issue
Block a user