From 448bb661d6759c1e20c18084604b150bff08ada4 Mon Sep 17 00:00:00 2001 From: holyfei Date: Tue, 18 Aug 2020 11:49:26 +0800 Subject: [PATCH 36/50] mount: limit the maximum number of virtio-scsi bus slots reason: 1. add SCSIBus functions for add or remove device about ScsiBus 2. limit the maximum number of virtio-scsi bus slots to 25 Signed-off-by: yangfeiyu --- virtcontainers/qemu.go | 20 +++++++++++++++++ virtcontainers/types/scsi.go | 53 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 virtcontainers/types/scsi.go diff --git a/virtcontainers/qemu.go b/virtcontainers/qemu.go index bb83b1bb..c2b65376 100644 --- a/virtcontainers/qemu.go +++ b/virtcontainers/qemu.go @@ -65,6 +65,7 @@ type CPUDevice struct { // QemuState keeps Qemu's state type QemuState struct { Bridges []types.Bridge + ScsiBus *types.SCSIBus // HotpluggedCPUs is the list of CPUs that were hot-added HotpluggedVCPUs []CPUDevice HotpluggedMemory int @@ -411,6 +412,13 @@ func (q *qemu) buildDevices(initrdPath string) ([]govmmQemu.Device, *govmmQemu.I var ioThread *govmmQemu.IOThread if q.config.BlockDeviceDriver == config.VirtioSCSI { + if q.state.ScsiBus == nil { + // only use `scsi0.0` + q.state.ScsiBus = &types.SCSIBus{ + Address: make(map[uint32]int), + ID: fmt.Sprintf("%s.0", scsiControllerID), + } + } return q.arch.appendSCSIController(devices, q.config.EnableIOThreads) } @@ -1168,6 +1176,16 @@ func (q *qemu) hotplugAddBlockDevice(drive *config.BlockDrive, op operation, dev // Bus exposed by the SCSI Controller bus := scsiControllerID + ".0" + var err error + if err = q.state.ScsiBus.AddDevToScsiBus(drive.Index); err != nil { + return err + } + + defer func() { + if err != nil { + q.state.ScsiBus.RemoveDevFromScsiBus(drive.Index) + } + }() // Get SCSI-id and LUN based on the order of attaching drives. scsiID, lun, err := utils.GetSCSIIdLun(drive.Index) @@ -1234,6 +1252,8 @@ func (q *qemu) hotplugBlockDevice(drive *config.BlockDrive, op operation) error if err := q.arch.removeDeviceFromBridge(drive.ID); err != nil { return err } + } else if q.config.BlockDeviceDriver == config.VirtioSCSI { + q.state.ScsiBus.RemoveDevFromScsiBus(drive.Index) } if err := q.qmpMonitorCh.qmp.ExecuteDeviceDel(q.qmpMonitorCh.ctx, devID); err != nil { diff --git a/virtcontainers/types/scsi.go b/virtcontainers/types/scsi.go new file mode 100644 index 00000000..f4d489f0 --- /dev/null +++ b/virtcontainers/types/scsi.go @@ -0,0 +1,53 @@ +// Copyright (c) Huawei Technologies Co., Ltd. 2019. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// Description: common functions +// Author: leizhongkai +// Create: 2019-06-30 + +package types + +import ( + "fmt" +) + +const ( + scsiMaxCapacity = 25 +) + +type SCSIBus struct { + // Address contains information about devices plugged and number limit + Address map[uint32]int + + // ID is used to identify the bus exposed by the SCSI Controller + ID string +} + +func (sb *SCSIBus) AddDevToScsiBus(index int) error { + var addr uint32 + + // looking for the first available address + for i := uint32(1); i <= scsiMaxCapacity; i++ { + if _, ok := sb.Address[i]; !ok { + addr = i + break + } + } + + if addr == 0 { + return fmt.Errorf("Scsi bus capacity limited.") + } + + // save address and device + sb.Address[addr] = index + + return nil +} + +func (sb *SCSIBus) RemoveDevFromScsiBus(index int) { + for addr, i := range sb.Address { + if i == index { + delete(sb.Address, addr) + return + } + } +} -- 2.14.3 (Apple Git-98)