Skip to content

Commit 96ff793

Browse files
committed
WIP
Signed-off-by: Niclas Schad <niclas.schad@stackit.cloud>
1 parent 37699cf commit 96ff793

2 files changed

Lines changed: 35 additions & 20 deletions

File tree

pkg/csi/blockstorage/nodeserver.go

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -310,19 +310,14 @@ func (ns *nodeServer) NodeGetInfo(ctx context.Context, _ *csi.NodeGetInfoRequest
310310
maxVolumesPerNode := DetermineMaxVolumesByFlavor(flavor)
311311

312312
// Subtract already mounted Volumes
313-
emptyPCIeRootPorts, err := mount.GetEmptyPCIeRootPorts()
313+
emptyPCIeRootPorts, err := mount.CountNonVirtioBlockDevices()
314314
if err != nil {
315315
klog.Errorf("[NodeGetInfo] unable to retrieve PCIe root ports %v", err)
316-
} else {
317-
klog.Infof("[NodeGetInfo] found empty PCIe root ports: %d", emptyPCIeRootPorts)
318-
if emptyPCIeRootPorts == 0 {
319-
klog.Warningf("[NodeGetInfo] node does not have any free PCIe ports")
320-
maxVolumesPerNode = 0
321-
} else {
322-
maxVolumesPerNode = emptyPCIeRootPorts
323-
}
316+
emptyPCIeRootPorts = 0
324317
}
325318

319+
maxVolumesPerNode -= emptyPCIeRootPorts
320+
326321
klog.V(4).Infof("Determined node to support %d volumes", maxVolumesPerNode)
327322

328323
nodeInfo := &csi.NodeGetInfoResponse{

pkg/csi/util/mount/mount.go

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ var (
4747
pciAddressRegex = regexp.MustCompile(`^[0-9a-fA-F]{4}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}\.[0-9a-fA-F]$`)
4848
)
4949

50+
const (
51+
REDHAT_VENDOR = "0x1af4"
52+
VIRTIO_BLOCK_DEVICE = "1042"
53+
)
54+
5055
type IMount interface {
5156
Mounter() *mount.SafeFormatAndMount
5257
ScanForAttach(devicePath string) error
@@ -125,11 +130,10 @@ func probeVolume() error {
125130
return nil
126131
}
127132

128-
// GetEmptyPCIeRootPorts returns the number of PCIe Root ports who currently
129-
// do not have ANY downstream devices, therefore considered "empty". This
130-
// function is used dynamically how many more devices (in this case "volumes")
131-
// can be mounted to the given node.
132-
func GetEmptyPCIeRootPorts() (int64, error) {
133+
// CountNonVirtioBlockDevices returns the number of PCIe Root ports who
134+
// are currently occupied by anything else than an VIRTIO 1.0 Block Device
135+
// returns zero when something went wrong
136+
func CountNonVirtioBlockDevices() (int64, error) {
133137
const pciPath = "/sys/bus/pci/devices"
134138

135139
// Get all PCI devices
@@ -138,7 +142,7 @@ func GetEmptyPCIeRootPorts() (int64, error) {
138142
return 0, fmt.Errorf("failed to read PCI bus: %w", err)
139143
}
140144

141-
emptyCount := 0
145+
pcieSlotsOccupiedByNonBlockDevice := 0
142146

143147
for _, dev := range devices {
144148
devPath := filepath.Join(pciPath, dev.Name())
@@ -158,7 +162,7 @@ func GetEmptyPCIeRootPorts() (int64, error) {
158162
// 2. Check if the port has downstream devices
159163
// If the bridge has children, they appear as subdirectories
160164
// matching the PCI address format (e.g., 0000:01:00.0)
161-
hasChild := false
165+
isNonBLockDevice := false
162166
files, err2 := os.ReadDir(devPath)
163167
if err2 != nil {
164168
klog.Errorf("failed to read dir %s : %v", devPath, err2)
@@ -167,20 +171,36 @@ func GetEmptyPCIeRootPorts() (int64, error) {
167171
// Ignore PCI bus directories such as pci001 pci002 and pci010
168172
// Devices must follow <domain:bus:device.function> format
169173
if pciAddressRegex.MatchString(file.Name()) {
170-
hasChild = true
174+
isNonBLockDevice = probePCIeDevice(devPath, file, isNonBLockDevice)
171175
break
172176
}
173177
}
174178

175-
if !hasChild {
176-
emptyCount++
179+
if !isNonBLockDevice {
180+
pcieSlotsOccupiedByNonBlockDevice++
177181
}
178182
} else {
179183
klog.Infof("skipping class %s: path: %s", class, devPath)
180184
}
181185
}
182186

183-
return int64(emptyCount), nil
187+
return int64(pcieSlotsOccupiedByNonBlockDevice), nil
188+
}
189+
190+
func probePCIeDevice(devPath string, file os.DirEntry, isNonBLockDevice bool) bool {
191+
pciDevicePath := filepath.Join(devPath, file.Name())
192+
deviceBuf, err := os.ReadFile(filepath.Join(pciDevicePath, "device"))
193+
if err != nil {
194+
klog.Errorf("failed to read PCI device file %s : %v", pciDevicePath, err)
195+
}
196+
vendorBuf, err := os.ReadFile(filepath.Join(pciDevicePath, "vendor"))
197+
if err != nil {
198+
klog.Errorf("failed to read PCI device vendor %s : %v", pciDevicePath, err)
199+
}
200+
if strings.TrimSpace(string(vendorBuf)) == REDHAT_VENDOR && strings.TrimSpace(string(deviceBuf)) != VIRTIO_BLOCK_DEVICE {
201+
isNonBLockDevice = true
202+
}
203+
return isNonBLockDevice
184204
}
185205

186206
// GetDevicePath returns the path of an attached block storage volume, specified by its id.

0 commit comments

Comments
 (0)