Skip to content

Commit 6863cc2

Browse files
authored
fix(node-disk-manager): support nvme virtual paths (#678)
Enhance getParentBlockDevice() by looking not only for /nvme/ in the path, but also /nvme-subystem/, which is the name under /sys/devices/virtual on OpenSUSE 15.3. Clean up the osdiskexcludefilter.go Start() routine so that for each mount point it will first check /proc/1/mounts and if that fails, then check /proc/self/mounts, and then if that also fails, finally log an error message. The observation is that things will be found in one or the other, but not both, so the old code would print out an error message in once case, even when the mountpoint had been added to the filter list by the other case. Change "make test" so that it will run all the go tests and not stop at the first failure. Signed-off-by: David Borman <77121405+dborman-hpe@users.noreply.github.com>
1 parent 683879d commit 6863cc2

File tree

6 files changed

+63
-26
lines changed

6 files changed

+63
-26
lines changed

build/test.sh

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,17 @@ if [ "$ARCH" != "amd64" ]; then
3030
exit 0
3131
fi
3232

33+
exit_val=0
3334
echo "" > coverage.txt
3435
PACKAGES=$(go list ./... | grep -v '/vendor/\|/pkg/apis/\|/pkg/client/\|integration_test')
3536
for d in $PACKAGES; do
36-
go test -coverprofile=profile.out -covermode=atomic "$d"
37+
if ! go test -coverprofile=profile.out -covermode=atomic "$d"; then
38+
exit_val=1
39+
fi
3740
if [ -f profile.out ]; then
3841
cat profile.out >> coverage.txt
3942
rm profile.out
4043
fi
4144
done
45+
46+
exit ${exit_val}

cmd/ndm_daemonset/filter/osdiskexcludefilter.go

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -80,33 +80,31 @@ func newNonOsDiskFilter(ctrl *controller.Controller) *oSDiskExcludeFilter {
8080

8181
// Start set os disk devPath in nonOsDiskFilter pointer
8282
func (odf *oSDiskExcludeFilter) Start() {
83-
/*
84-
process1 check for mentioned mountpoint in host's /proc/1/mounts file
85-
host's /proc/1/mounts file mounted inside container it checks for
86-
every mentioned mountpoints if it is able to get parent disk's devpath
87-
it adds it in Controller struct and make isOsDiskFilterSet true
88-
*/
8983
for _, mountPoint := range mountPoints {
84+
var err error
85+
var devPath string
86+
87+
// Check for mountpoints in both:
88+
// the host's /proc/1/mounts file
89+
// the /proc/self/mounts file
90+
// If it is found in either one and we are able to get the
91+
// disk's devpath, add it to the Controller struct. Otherwise
92+
// log an error.
93+
9094
mountPointUtil := mount.NewMountUtil(hostMountFilePath, "", mountPoint)
91-
if devPath, err := mountPointUtil.GetDiskPath(); err != nil {
92-
klog.Errorf("unable to configure os disk filter for mountpoint: %s, error: %v", mountPoint, err)
93-
} else {
95+
if devPath, err = mountPointUtil.GetDiskPath(); err == nil {
9496
odf.excludeDevPaths = append(odf.excludeDevPaths, devPath)
97+
continue
9598
}
96-
}
97-
/*
98-
process2 check for mountpoints in /proc/self/mounts file if it is able to get
99-
disk's path of it adds it in Controller struct and make isOsDiskFilterSet true
100-
*/
101-
for _, mountPoint := range mountPoints {
102-
mountPointUtil := mount.NewMountUtil(defaultMountFilePath, "", mountPoint)
103-
if devPath, err := mountPointUtil.GetDiskPath(); err != nil {
104-
klog.Errorf("unable to configure os disk filter for mountpoint: %s, error: %v", mountPoint, err)
105-
} else {
99+
100+
mountPointUtil = mount.NewMountUtil(defaultMountFilePath, "", mountPoint)
101+
if devPath, err = mountPointUtil.GetDiskPath(); err == nil {
106102
odf.excludeDevPaths = append(odf.excludeDevPaths, devPath)
103+
continue
107104
}
108-
}
109105

106+
klog.Errorf("unable to configure os disk filter for mountpoint: %s, error: %v", mountPoint, err)
107+
}
110108
}
111109

112110
// Include contains nothing by default it returns false

pkg/mount/mountutil.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -240,13 +240,18 @@ func parseRootDeviceLink(file io.Reader) (string, error) {
240240
// syspath looks like - /sys/devices/pci0000:00/0000:00:1f.2/ata1/host0/target0:0:0/0:0:0:0/block/sda/sda4
241241
// parent disk is present after block then partition of that disk
242242
//
243-
// for blockdevices that belong to the nvme subsystem, the symlink has a different format,
244-
// /sys/devices/pci0000:00/0000:00:0e.0/nvme/nvme0/nvme0n1/nvme0n1p1. So we search for the nvme subsystem
245-
// instead of `block`. The blockdevice will be available after the NVMe instance, nvme/instance/namespace.
243+
// for blockdevices that belong to the nvme subsystem, the symlink has different formats
244+
// /sys/devices/pci0000:00/0000:00:0e.0/nvme/nvme0/nvme0n1/nvme0n1p1.
245+
// /sys/devices/virtual/nvme-subsystem/nvme-subsys0/nvme0n1/nvme0n1p1
246+
// So we search for the "nvme" or "nvme-subsystem" subsystem instead of `block`. The
247+
// blockdevice will be available after the NVMe instance,
248+
// nvme/instance/namespace
249+
// nvme-subsystem/instance/namespace
246250
// The namespace will be the blockdevice.
247251
func getParentBlockDevice(sysPath string) (string, bool) {
248252
blockSubsystem := "block"
249253
nvmeSubsystem := "nvme"
254+
nvmeSubsysClass := "nvme-subsystem"
250255
parts := strings.Split(sysPath, "/")
251256

252257
// checking for block subsystem, return the next part after subsystem only
@@ -262,7 +267,7 @@ func getParentBlockDevice(sysPath string) (string, bool) {
262267
// nvme namespace. Length checking is to avoid index out of range in case of malformed
263268
// links (extremely rare case)
264269
for i, part := range parts {
265-
if part == nvmeSubsystem &&
270+
if (part == nvmeSubsystem || part == nvmeSubsysClass) &&
266271
len(parts)-1 >= i+2 {
267272
return parts[i+2], true
268273
}

pkg/mount/mountutil_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,16 @@ func TestGetParentBlockDevice(t *testing.T) {
291291
expectedParentBlockDevice: "nvme0n1",
292292
expectedOk: true,
293293
},
294+
"getting parent of main virtual NVMe blockdevice": {
295+
syspath: "/sys/devices/virtual/nvme-subsystem/nvme-subsys0/nvme0n1",
296+
expectedParentBlockDevice: "nvme0n1",
297+
expectedOk: true,
298+
},
299+
"getting parent of partitioned virtual NVMe blockdevice": {
300+
syspath: "/sys/devices/virtual/nvme-subsystem/nvme-subsys0/nvme0n1/nvme0n1p1",
301+
expectedParentBlockDevice: "nvme0n1",
302+
expectedOk: true,
303+
},
294304
"getting parent of wrong disk": {
295305
syspath: "/sys/devices/pci0000:00/0000:00:0e.0/nvme/nvme0",
296306
expectedParentBlockDevice: "",

pkg/sysfs/syspath.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const (
3131
BlockSubSystem = "block"
3232
// NVMeSubSystem is the key used to represent nvme subsystem in sysfs
3333
NVMeSubSystem = "nvme"
34+
NVMeSubSysClass = "nvme-subsystem"
3435
// sectorSize is the sector size as understood by the unix systems.
3536
// It is kept as 512 bytes. all entries in /sys/class/block/sda/size
3637
// are in 512 byte blocks
@@ -86,7 +87,7 @@ func (s Device) getParent() (string, bool) {
8687
// nvme namespace. Length checking is to avoid index out of range in case of malformed
8788
// links (extremely rare case)
8889
for i, part := range parts {
89-
if part == NVMeSubSystem {
90+
if part == NVMeSubSystem || part == NVMeSubSysClass {
9091
// check if the length is greater to avoid panic. Also need to make sure that
9192
// the same device is not returned if the given device is a parent.
9293
if len(parts)-1 >= i+2 && s.deviceName != parts[i+2] {

pkg/sysfs/syspath_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,24 @@ func TestGetParent(t *testing.T) {
6868
wantedDeviceName: "nvme0n1",
6969
wantOk: true,
7070
},
71+
"[nvme-subsystem] given blockdevice is a parent": {
72+
sysfsDevice: &Device{
73+
deviceName: "nvme0n1",
74+
path: "/dev/nvme0n1",
75+
sysPath: "/sys/devices/virtual/nvme-subsystem/nvme-subsys0/nvme0n1/",
76+
},
77+
wantedDeviceName: "",
78+
wantOk: false,
79+
},
80+
"[nvme-subsystem] given blockdevice is a partition": {
81+
sysfsDevice: &Device{
82+
deviceName: "nvme0n1p1",
83+
path: "/dev/nvme0n1p1",
84+
sysPath: "/sys/devices/virtual/nvme-subsystem/nvme-subsys0/nvme0n1/nvme0n1p1/",
85+
},
86+
wantedDeviceName: "nvme0n1",
87+
wantOk: true,
88+
},
7189
}
7290
for name, test := range tests {
7391
t.Run(name, func(t *testing.T) {

0 commit comments

Comments
 (0)