github.com/kata-containers/runtime@v0.0.0-20210505125100-04f29832a923/virtcontainers/device/drivers/generic.go (about) 1 // Copyright (c) 2017-2018 Intel Corporation 2 // Copyright (c) 2018-2019 Huawei Corporation 3 // 4 // SPDX-License-Identifier: Apache-2.0 5 // 6 7 package drivers 8 9 import ( 10 "fmt" 11 12 "github.com/kata-containers/runtime/virtcontainers/device/api" 13 "github.com/kata-containers/runtime/virtcontainers/device/config" 14 persistapi "github.com/kata-containers/runtime/virtcontainers/persist/api" 15 ) 16 17 // GenericDevice refers to a device that is neither a VFIO device, block device or VhostUserDevice. 18 type GenericDevice struct { 19 ID string 20 DeviceInfo *config.DeviceInfo 21 22 RefCount uint 23 AttachCount uint 24 } 25 26 // NewGenericDevice creates a new GenericDevice 27 func NewGenericDevice(devInfo *config.DeviceInfo) *GenericDevice { 28 return &GenericDevice{ 29 ID: devInfo.ID, 30 DeviceInfo: devInfo, 31 } 32 } 33 34 // Attach is standard interface of api.Device 35 func (device *GenericDevice) Attach(devReceiver api.DeviceReceiver) error { 36 _, err := device.bumpAttachCount(true) 37 return err 38 } 39 40 // Detach is standard interface of api.Device 41 func (device *GenericDevice) Detach(devReceiver api.DeviceReceiver) error { 42 _, err := device.bumpAttachCount(false) 43 return err 44 } 45 46 // DeviceType is standard interface of api.Device, it returns device type 47 func (device *GenericDevice) DeviceType() config.DeviceType { 48 return config.DeviceGeneric 49 } 50 51 // GetDeviceInfo returns device information used for creating 52 func (device *GenericDevice) GetDeviceInfo() interface{} { 53 return device.DeviceInfo 54 } 55 56 // GetAttachCount returns how many times the device has been attached 57 func (device *GenericDevice) GetAttachCount() uint { 58 return device.AttachCount 59 } 60 61 // DeviceID returns device ID 62 func (device *GenericDevice) DeviceID() string { 63 return device.ID 64 } 65 66 // GetMajorMinor returns device major and minor numbers 67 func (device *GenericDevice) GetMajorMinor() (int64, int64) { 68 return device.DeviceInfo.Major, device.DeviceInfo.Minor 69 } 70 71 // GetHostPath return the device path in the host 72 func (device *GenericDevice) GetHostPath() string { 73 if device.DeviceInfo != nil { 74 return device.DeviceInfo.HostPath 75 } 76 return "" 77 } 78 79 // Reference adds one reference to device 80 func (device *GenericDevice) Reference() uint { 81 if device.RefCount != intMax { 82 device.RefCount++ 83 } 84 return device.RefCount 85 } 86 87 // Dereference remove one reference from device 88 func (device *GenericDevice) Dereference() uint { 89 if device.RefCount != 0 { 90 device.RefCount-- 91 } 92 return device.RefCount 93 } 94 95 // bumpAttachCount is used to add/minus attach count for a device 96 // * attach bool: true means attach, false means detach 97 // return values: 98 // * skip bool: no need to do real attach/detach, skip following actions. 99 // * err error: error while do attach count bump 100 func (device *GenericDevice) bumpAttachCount(attach bool) (skip bool, err error) { 101 if attach { // attach use case 102 switch device.AttachCount { 103 case 0: 104 // do real attach 105 device.AttachCount++ 106 return false, nil 107 case intMax: 108 return true, fmt.Errorf("device was attached too many times") 109 default: 110 device.AttachCount++ 111 return true, nil 112 } 113 } else { // detach use case 114 switch device.AttachCount { 115 case 0: 116 return true, fmt.Errorf("detaching a device that wasn't attached") 117 case 1: 118 // do real work 119 device.AttachCount-- 120 return false, nil 121 default: 122 device.AttachCount-- 123 return true, nil 124 } 125 } 126 } 127 128 // Save converts Device to DeviceState 129 func (device *GenericDevice) Save() persistapi.DeviceState { 130 dss := persistapi.DeviceState{ 131 ID: device.ID, 132 Type: string(device.DeviceType()), 133 RefCount: device.RefCount, 134 AttachCount: device.AttachCount, 135 } 136 137 info := device.DeviceInfo 138 if info != nil { 139 dss.DevType = info.DevType 140 dss.Major = info.Major 141 dss.Minor = info.Minor 142 dss.DriverOptions = info.DriverOptions 143 dss.ColdPlug = info.ColdPlug 144 } 145 return dss 146 } 147 148 // Load loads DeviceState and converts it to specific device 149 func (device *GenericDevice) Load(ds persistapi.DeviceState) { 150 device.ID = ds.ID 151 device.RefCount = ds.RefCount 152 device.AttachCount = ds.AttachCount 153 154 device.DeviceInfo = &config.DeviceInfo{ 155 DevType: ds.DevType, 156 Major: ds.Major, 157 Minor: ds.Minor, 158 DriverOptions: ds.DriverOptions, 159 ColdPlug: ds.ColdPlug, 160 } 161 }