mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-07-03 02:26:37 +00:00
devices: address some comments
Address some review comments: * remove unnecessary rollback logics * add vfio hot unplug handling. Signed-off-by: Wei Zhang <zhangwei555@huawei.com>
This commit is contained in:
parent
44c37bf774
commit
b7464899ec
@ -1113,6 +1113,9 @@ func (c *Container) removeDrive() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) attachDevices() error {
|
func (c *Container) attachDevices() error {
|
||||||
|
// there's no need to do rollback when error happens,
|
||||||
|
// because if attachDevices fails, container creation will fail too,
|
||||||
|
// and rollbackFailingContainerCreation could do all the rollbacks
|
||||||
for _, dev := range c.devices {
|
for _, dev := range c.devices {
|
||||||
if err := c.sandbox.devManager.AttachDevice(dev.ID, c.sandbox); err != nil {
|
if err := c.sandbox.devManager.AttachDevice(dev.ID, c.sandbox); err != nil {
|
||||||
if err == manager.ErrDeviceAttached {
|
if err == manager.ErrDeviceAttached {
|
||||||
@ -1124,7 +1127,6 @@ func (c *Container) attachDevices() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := c.sandbox.storeSandboxDevices(); err != nil {
|
if err := c.sandbox.storeSandboxDevices(); err != nil {
|
||||||
//TODO: roll back?
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -1134,13 +1136,16 @@ func (c *Container) detachDevices() error {
|
|||||||
for _, dev := range c.devices {
|
for _, dev := range c.devices {
|
||||||
if err := c.sandbox.devManager.DetachDevice(dev.ID, c.sandbox); err != nil {
|
if err := c.sandbox.devManager.DetachDevice(dev.ID, c.sandbox); err != nil {
|
||||||
if err == manager.ErrDeviceNotAttached {
|
if err == manager.ErrDeviceNotAttached {
|
||||||
// skip if device is already attached before
|
// skip if device isn't attached
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := c.sandbox.storeSandboxDevices(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +34,10 @@ func NewBlockDevice(devInfo *config.DeviceInfo) *BlockDevice {
|
|||||||
// Attach is standard interface of api.Device, it's used to add device to some
|
// Attach is standard interface of api.Device, it's used to add device to some
|
||||||
// DeviceReceiver
|
// DeviceReceiver
|
||||||
func (device *BlockDevice) Attach(devReceiver api.DeviceReceiver) (err error) {
|
func (device *BlockDevice) Attach(devReceiver api.DeviceReceiver) (err error) {
|
||||||
|
if device.DeviceInfo.Hotplugged {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Increment the block index for the sandbox. This is used to determine the name
|
// Increment the block index for the sandbox. This is used to determine the name
|
||||||
// for the block device in the case where the block device is used as container
|
// for the block device in the case where the block device is used as container
|
||||||
// rootfs and the predicted block device name needs to be provided to the agent.
|
// rootfs and the predicted block device name needs to be provided to the agent.
|
||||||
@ -87,6 +91,10 @@ func (device *BlockDevice) Attach(devReceiver api.DeviceReceiver) (err error) {
|
|||||||
// Detach is standard interface of api.Device, it's used to remove device from some
|
// Detach is standard interface of api.Device, it's used to remove device from some
|
||||||
// DeviceReceiver
|
// DeviceReceiver
|
||||||
func (device *BlockDevice) Detach(devReceiver api.DeviceReceiver) error {
|
func (device *BlockDevice) Detach(devReceiver api.DeviceReceiver) error {
|
||||||
|
if !device.DeviceInfo.Hotplugged {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
deviceLogger().WithField("device", device.DeviceInfo.HostPath).Info("Unplugging block device")
|
deviceLogger().WithField("device", device.DeviceInfo.HostPath).Info("Unplugging block device")
|
||||||
|
|
||||||
if err := devReceiver.HotplugRemoveDevice(device, config.DeviceBlock); err != nil {
|
if err := devReceiver.HotplugRemoveDevice(device, config.DeviceBlock); err != nil {
|
||||||
|
@ -27,11 +27,19 @@ func NewGenericDevice(devInfo *config.DeviceInfo) *GenericDevice {
|
|||||||
|
|
||||||
// Attach is standard interface of api.Device
|
// Attach is standard interface of api.Device
|
||||||
func (device *GenericDevice) Attach(devReceiver api.DeviceReceiver) error {
|
func (device *GenericDevice) Attach(devReceiver api.DeviceReceiver) error {
|
||||||
|
if device.DeviceInfo.Hotplugged {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detach is standard interface of api.Device
|
// Detach is standard interface of api.Device
|
||||||
func (device *GenericDevice) Detach(devReceiver api.DeviceReceiver) error {
|
func (device *GenericDevice) Detach(devReceiver api.DeviceReceiver) error {
|
||||||
|
if !device.DeviceInfo.Hotplugged {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +46,10 @@ func NewVFIODevice(devInfo *config.DeviceInfo) *VFIODevice {
|
|||||||
// Attach is standard interface of api.Device, it's used to add device to some
|
// Attach is standard interface of api.Device, it's used to add device to some
|
||||||
// DeviceReceiver
|
// DeviceReceiver
|
||||||
func (device *VFIODevice) Attach(devReceiver api.DeviceReceiver) error {
|
func (device *VFIODevice) Attach(devReceiver api.DeviceReceiver) error {
|
||||||
|
if device.DeviceInfo.Hotplugged {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
vfioGroup := filepath.Base(device.DeviceInfo.HostPath)
|
vfioGroup := filepath.Base(device.DeviceInfo.HostPath)
|
||||||
iommuDevicesPath := filepath.Join(config.SysIOMMUPath, vfioGroup, "devices")
|
iommuDevicesPath := filepath.Join(config.SysIOMMUPath, vfioGroup, "devices")
|
||||||
|
|
||||||
@ -85,6 +89,20 @@ func (device *VFIODevice) Attach(devReceiver api.DeviceReceiver) error {
|
|||||||
// Detach is standard interface of api.Device, it's used to remove device from some
|
// Detach is standard interface of api.Device, it's used to remove device from some
|
||||||
// DeviceReceiver
|
// DeviceReceiver
|
||||||
func (device *VFIODevice) Detach(devReceiver api.DeviceReceiver) error {
|
func (device *VFIODevice) Detach(devReceiver api.DeviceReceiver) error {
|
||||||
|
if !device.DeviceInfo.Hotplugged {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// hotplug a VFIO device is actually hotplugging a group of iommu devices
|
||||||
|
if err := devReceiver.HotplugRemoveDevice(device, config.DeviceVFIO); err != nil {
|
||||||
|
deviceLogger().WithError(err).Error("Failed to remove device")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceLogger().WithFields(logrus.Fields{
|
||||||
|
"device-group": device.DeviceInfo.HostPath,
|
||||||
|
"device-type": "vfio-passthrough",
|
||||||
|
}).Info("Device group attached")
|
||||||
device.DeviceInfo.Hotplugged = false
|
device.DeviceInfo.Hotplugged = false
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,10 @@ type VhostUserBlkDevice struct {
|
|||||||
// Attach is standard interface of api.Device, it's used to add device to some
|
// Attach is standard interface of api.Device, it's used to add device to some
|
||||||
// DeviceReceiver
|
// DeviceReceiver
|
||||||
func (device *VhostUserBlkDevice) Attach(devReceiver api.DeviceReceiver) (err error) {
|
func (device *VhostUserBlkDevice) Attach(devReceiver api.DeviceReceiver) (err error) {
|
||||||
|
if device.DeviceInfo.Hotplugged {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// generate a unique ID to be used for hypervisor commandline fields
|
// generate a unique ID to be used for hypervisor commandline fields
|
||||||
randBytes, err := utils.GenerateRandomBytes(8)
|
randBytes, err := utils.GenerateRandomBytes(8)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -48,6 +52,10 @@ func (device *VhostUserBlkDevice) Attach(devReceiver api.DeviceReceiver) (err er
|
|||||||
// Detach is standard interface of api.Device, it's used to remove device from some
|
// Detach is standard interface of api.Device, it's used to remove device from some
|
||||||
// DeviceReceiver
|
// DeviceReceiver
|
||||||
func (device *VhostUserBlkDevice) Detach(devReceiver api.DeviceReceiver) error {
|
func (device *VhostUserBlkDevice) Detach(devReceiver api.DeviceReceiver) error {
|
||||||
|
if !device.DeviceInfo.Hotplugged {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
device.DeviceInfo.Hotplugged = false
|
device.DeviceInfo.Hotplugged = false
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,10 @@ type VhostUserNetDevice struct {
|
|||||||
// Attach is standard interface of api.Device, it's used to add device to some
|
// Attach is standard interface of api.Device, it's used to add device to some
|
||||||
// DeviceReceiver
|
// DeviceReceiver
|
||||||
func (device *VhostUserNetDevice) Attach(devReceiver api.DeviceReceiver) (err error) {
|
func (device *VhostUserNetDevice) Attach(devReceiver api.DeviceReceiver) (err error) {
|
||||||
|
if device.DeviceInfo.Hotplugged {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// generate a unique ID to be used for hypervisor commandline fields
|
// generate a unique ID to be used for hypervisor commandline fields
|
||||||
randBytes, err := utils.GenerateRandomBytes(8)
|
randBytes, err := utils.GenerateRandomBytes(8)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -48,6 +52,10 @@ func (device *VhostUserNetDevice) Attach(devReceiver api.DeviceReceiver) (err er
|
|||||||
// Detach is standard interface of api.Device, it's used to remove device from some
|
// Detach is standard interface of api.Device, it's used to remove device from some
|
||||||
// DeviceReceiver
|
// DeviceReceiver
|
||||||
func (device *VhostUserNetDevice) Detach(devReceiver api.DeviceReceiver) error {
|
func (device *VhostUserNetDevice) Detach(devReceiver api.DeviceReceiver) error {
|
||||||
|
if !device.DeviceInfo.Hotplugged {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
device.DeviceInfo.Hotplugged = false
|
device.DeviceInfo.Hotplugged = false
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,10 @@ type VhostUserSCSIDevice struct {
|
|||||||
// Attach is standard interface of api.Device, it's used to add device to some
|
// Attach is standard interface of api.Device, it's used to add device to some
|
||||||
// DeviceReceiver
|
// DeviceReceiver
|
||||||
func (device *VhostUserSCSIDevice) Attach(devReceiver api.DeviceReceiver) (err error) {
|
func (device *VhostUserSCSIDevice) Attach(devReceiver api.DeviceReceiver) (err error) {
|
||||||
|
if device.DeviceInfo.Hotplugged {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// generate a unique ID to be used for hypervisor commandline fields
|
// generate a unique ID to be used for hypervisor commandline fields
|
||||||
randBytes, err := utils.GenerateRandomBytes(8)
|
randBytes, err := utils.GenerateRandomBytes(8)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -48,6 +52,10 @@ func (device *VhostUserSCSIDevice) Attach(devReceiver api.DeviceReceiver) (err e
|
|||||||
// Detach is standard interface of api.Device, it's used to remove device from some
|
// Detach is standard interface of api.Device, it's used to remove device from some
|
||||||
// DeviceReceiver
|
// DeviceReceiver
|
||||||
func (device *VhostUserSCSIDevice) Detach(devReceiver api.DeviceReceiver) error {
|
func (device *VhostUserSCSIDevice) Detach(devReceiver api.DeviceReceiver) error {
|
||||||
|
if !device.DeviceInfo.Hotplugged {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
device.DeviceInfo.Hotplugged = false
|
device.DeviceInfo.Hotplugged = false
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -1459,28 +1459,10 @@ func (s *Sandbox) HotplugAddDevice(device api.Device, devType config.DeviceType)
|
|||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("device type mismatch, expect device type to be %s", devType)
|
return fmt.Errorf("device type mismatch, expect device type to be %s", devType)
|
||||||
}
|
}
|
||||||
addedDev := []*config.VFIODev{}
|
|
||||||
var err error
|
|
||||||
defer func() {
|
|
||||||
// if err happens,roll back and remove added device!
|
|
||||||
if err != nil {
|
|
||||||
for _, dev := range addedDev {
|
|
||||||
if _, rollbackErr := s.hypervisor.hotplugRemoveDevice(dev, vfioDev); rollbackErr != nil {
|
|
||||||
s.Logger().
|
|
||||||
WithFields(logrus.Fields{
|
|
||||||
"sandboxid": s.id,
|
|
||||||
"vfio device ID": dev.ID,
|
|
||||||
"vfio device BDF": dev.BDF,
|
|
||||||
}).WithError(rollbackErr).
|
|
||||||
Error("failed to remove vfio device for rolling back")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// adding a group of VFIO devices
|
// adding a group of VFIO devices
|
||||||
for _, dev := range vfioDevices {
|
for _, dev := range vfioDevices {
|
||||||
if _, err = s.hypervisor.hotplugAddDevice(dev, vfioDev); err != nil {
|
if _, err := s.hypervisor.hotplugAddDevice(dev, vfioDev); err != nil {
|
||||||
s.Logger().
|
s.Logger().
|
||||||
WithFields(logrus.Fields{
|
WithFields(logrus.Fields{
|
||||||
"sandboxid": s.id,
|
"sandboxid": s.id,
|
||||||
@ -1489,7 +1471,6 @@ func (s *Sandbox) HotplugAddDevice(device api.Device, devType config.DeviceType)
|
|||||||
}).WithError(err).Error("failed to hotplug VFIO device")
|
}).WithError(err).Error("failed to hotplug VFIO device")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
addedDev = append(addedDev, dev)
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
case config.DeviceBlock:
|
case config.DeviceBlock:
|
||||||
@ -1515,28 +1496,10 @@ func (s *Sandbox) HotplugRemoveDevice(device api.Device, devType config.DeviceTy
|
|||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("device type mismatch, expect device type to be %s", devType)
|
return fmt.Errorf("device type mismatch, expect device type to be %s", devType)
|
||||||
}
|
}
|
||||||
removedDev := []*config.VFIODev{}
|
|
||||||
var err error
|
|
||||||
defer func() {
|
|
||||||
// if err happens,roll back and add the removed devices back!
|
|
||||||
if err != nil {
|
|
||||||
for _, dev := range removedDev {
|
|
||||||
if _, rollbackErr := s.hypervisor.hotplugAddDevice(dev, vfioDev); rollbackErr != nil {
|
|
||||||
|
|
||||||
s.Logger().WithError(rollbackErr).
|
|
||||||
WithFields(logrus.Fields{
|
|
||||||
"sandboxid": s.id,
|
|
||||||
"vfio device ID": dev.ID,
|
|
||||||
"vfio device BDF": dev.BDF,
|
|
||||||
}).Error("failed to add vfio device for rolling back")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// remove a group of VFIO devices
|
// remove a group of VFIO devices
|
||||||
for _, dev := range vfioDevices {
|
for _, dev := range vfioDevices {
|
||||||
if _, err = s.hypervisor.hotplugRemoveDevice(dev, vfioDev); err != nil {
|
if _, err := s.hypervisor.hotplugRemoveDevice(dev, vfioDev); err != nil {
|
||||||
s.Logger().WithError(err).
|
s.Logger().WithError(err).
|
||||||
WithFields(logrus.Fields{
|
WithFields(logrus.Fields{
|
||||||
"sandboxid": s.id,
|
"sandboxid": s.id,
|
||||||
@ -1545,7 +1508,6 @@ func (s *Sandbox) HotplugRemoveDevice(device api.Device, devType config.DeviceTy
|
|||||||
}).Error("failed to hot unplug VFIO device")
|
}).Error("failed to hot unplug VFIO device")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
removedDev = append(removedDev, dev)
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
case config.DeviceBlock:
|
case config.DeviceBlock:
|
||||||
|
Loading…
Reference in New Issue
Block a user