Skip to content

Commit e08d227

Browse files
authored
Add mounts from /proc/1/mountinfo (#1007)
Some systems do not expose all mount information in /proc/self/mountinfo. This PR fixes the issue by reading entries from /proc/self/mountinfo and /proc/1/mountinfo. Signed-off-by: Bala.FA <bala@minio.io>
1 parent 049dc23 commit e08d227

File tree

6 files changed

+72
-38
lines changed

6 files changed

+72
-38
lines changed

pkg/device/probe_linux.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,15 @@ func newDevice(
3535
majorMinor string,
3636
udevData map[string]string,
3737
) (device *Device, err error) {
38-
var mountPoints []string
38+
mountPoints := make(utils.StringSet)
3939
for _, mountEntry := range mountInfo.FilterByMajorMinor(majorMinor).List() {
40-
mountPoints = append(mountPoints, mountEntry.MountPoint)
40+
mountPoints.Set(mountEntry.MountPoint)
4141
}
4242

4343
device = &Device{
4444
Name: name,
4545
MajorMinor: majorMinor,
46-
MountPoints: mountPoints,
46+
MountPoints: mountPoints.ToSlice(),
4747
CDROM: cdroms.Exist(name),
4848
SwapOn: swaps.Exist(utils.AddDevPrefix(name)),
4949
udevData: udevData,

pkg/device/sync.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,12 @@ func updateDrive(ctx context.Context, driveName string, deviceMap map[string][]d
195195
mountPoint := types.GetDriveMountDir(drive.Status.FSUUID)
196196
legacyMountPoint := path.Join(consts.LegacyAppRootDir, "mnt", drive.Status.FSUUID)
197197

198-
var mountPoints []string
198+
mountPoints := make(utils.StringSet)
199199
for _, mountEntry := range mountInfo.FilterByMountSource(devices[0].MajorMinor).FilterByRoot("/").List() {
200200
switch mountEntry.MountPoint {
201201
case mountPoint, legacyMountPoint:
202202
default:
203-
mountPoints = append(mountPoints, mountEntry.MountPoint)
203+
mountPoints.Set(mountEntry.MountPoint)
204204
}
205205

206206
check := func() error {
@@ -224,7 +224,7 @@ func updateDrive(ctx context.Context, driveName string, deviceMap map[string][]d
224224
}
225225

226226
if len(mountPoints) != 0 {
227-
klog.ErrorS(fmt.Errorf("device mounted outside of DirectPV"), "device", devices[0].Name, "mountPoints", mountPoints, "drive", drive.GetDriveID(), drive.GetDriveName())
227+
klog.ErrorS(fmt.Errorf("device mounted outside of DirectPV"), "device", devices[0].Name, "mountPoints", mountPoints.ToSlice(), "drive", drive.GetDriveID(), drive.GetDriveName())
228228
}
229229

230230
updated = syncDrive(drive, devices[0])

pkg/drive/event.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -229,15 +229,16 @@ func (handler *driveEventHandler) unmountDrive(drive *types.Drive, skipDriveMoun
229229
}
230230
}
231231

232-
if filteredMountInfo.Length() > 1 {
233-
var devices []string
234-
for _, mountEntry := range filteredMountInfo.List() {
235-
devices = append(devices, mountEntry.MountSource)
236-
}
237-
return fmt.Errorf("multiple devices [%v] are mounted for FSUUID %v", strings.Join(devices, ","), drive.Status.FSUUID)
232+
devices := make(utils.StringSet)
233+
for _, mountEntry := range filteredMountInfo.List() {
234+
devices.Set(mountEntry.MountSource)
235+
}
236+
237+
if len(devices) > 1 {
238+
return fmt.Errorf("multiple devices [%v] are mounted for FSUUID %v", strings.Join(devices.ToSlice(), ","), drive.Status.FSUUID)
238239
}
239240

240-
for _, mountEntry := range mountInfo.FilterByMountSource(filteredMountInfo.List()[0].MountSource).List() {
241+
for _, mountEntry := range mountInfo.FilterByMountSource(devices.ToSlice()[0]).List() {
241242
if skipDriveMount && mountEntry.MountPoint == driveMountPoint {
242243
continue
243244
}

pkg/drive/repair.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"github.com/minio/directpv/pkg/consts"
3131
"github.com/minio/directpv/pkg/sys"
3232
"github.com/minio/directpv/pkg/types"
33+
"github.com/minio/directpv/pkg/utils"
3334
"github.com/minio/directpv/pkg/xfs"
3435
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3536
"k8s.io/client-go/util/retry"
@@ -108,17 +109,17 @@ func repair(ctx context.Context, drive *types.Drive, force, disablePrefetch, dry
108109
return err
109110
}
110111

111-
var mountPoints []string
112+
mountPoints := make(utils.StringSet)
112113
for _, mountEntry := range mountInfo.FilterByMountSource(device).List() {
113114
switch mountEntry.MountPoint {
114115
case target, legacyTarget:
115116
default:
116-
mountPoints = append(mountPoints, mountEntry.MountPoint)
117+
mountPoints.Set(mountEntry.MountPoint)
117118
}
118119
}
119120

120121
if len(mountPoints) != 0 {
121-
return fmt.Errorf("unable to run xfs repair; device %v still mounted in [%v]", device, strings.Join(mountPoints, ","))
122+
return fmt.Errorf("unable to run xfs repair; device %v still mounted in [%v]", device, strings.Join(mountPoints.ToSlice(), ","))
122123
}
123124

124125
if err = unmount(target); err != nil {

pkg/initrequest/event.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -235,13 +235,13 @@ func (handler *initRequestEventHandler) initDevice(device pkgdevice.Device, forc
235235
return err
236236
}
237237

238-
var mountPoints []string
238+
mountPoints := make(utils.StringSet)
239239
for _, mountEntry := range mountInfo.FilterByMajorMinor(device.MajorMinor).List() {
240-
mountPoints = append(mountPoints, mountEntry.MountPoint)
240+
mountPoints.Set(mountEntry.MountPoint)
241241
}
242242

243243
if len(mountPoints) != 0 {
244-
return fmt.Errorf("device %v mounted at %v", devPath, mountPoints)
244+
return fmt.Errorf("device %v mounted at %v", devPath, mountPoints.ToSlice())
245245
}
246246

247247
fsuuid := uuid.New().String()

pkg/sys/mount_linux.go

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,10 @@ import (
3232
"k8s.io/klog/v2"
3333
)
3434

35-
func parseMount(s string) *MountEntry {
35+
func parseMount(s string, xxHash uint64) *MountEntry {
3636
// Refer https://man7.org/linux/man-pages/man5/proc_pid_mountinfo.5.html
3737
// to know about this logic.
3838
s = strings.TrimSpace(s)
39-
xxHash := xxhash.Sum64String(s)
4039
tokens := strings.Fields(s)
4140
if len(tokens) < 8 {
4241
return nil
@@ -70,12 +69,22 @@ func parseMount(s string) *MountEntry {
7069
return &mount
7170
}
7271

73-
func parseMountInfo(r io.Reader) (*MountInfo, error) {
74-
infoMap := map[uint64]*MountEntry{}
75-
mountPointMap := map[string][]uint64{}
76-
mountSourceMap := map[string][]uint64{}
77-
majorMinorMap := map[string][]uint64{}
78-
rootMap := map[string][]uint64{}
72+
func parseMountInfo(r io.Reader, info *MountInfo) (*MountInfo, error) {
73+
if info == nil {
74+
info = &MountInfo{
75+
infoMap: map[uint64]*MountEntry{},
76+
mountPointMap: map[string][]uint64{},
77+
mountSourceMap: map[string][]uint64{},
78+
majorMinorMap: map[string][]uint64{},
79+
rootMap: map[string][]uint64{},
80+
}
81+
}
82+
83+
infoMap := info.infoMap
84+
mountPointMap := info.mountPointMap
85+
mountSourceMap := info.mountSourceMap
86+
majorMinorMap := info.majorMinorMap
87+
rootMap := info.rootMap
7988

8089
reader := bufio.NewReader(r)
8190

@@ -88,7 +97,12 @@ func parseMountInfo(r io.Reader) (*MountInfo, error) {
8897
return nil, err
8998
}
9099

91-
mount := parseMount(s)
100+
xxHash := xxhash.Sum64String(s)
101+
if _, found := infoMap[xxHash]; found {
102+
continue
103+
}
104+
105+
mount := parseMount(s, xxHash)
92106
if mount == nil {
93107
continue
94108
}
@@ -100,23 +114,41 @@ func parseMountInfo(r io.Reader) (*MountInfo, error) {
100114
rootMap[mount.Root] = append(rootMap[mount.Root], mount.xxHash)
101115
}
102116

103-
return &MountInfo{
104-
infoMap: infoMap,
105-
mountPointMap: mountPointMap,
106-
mountSourceMap: mountSourceMap,
107-
majorMinorMap: majorMinorMap,
108-
rootMap: rootMap,
109-
}, nil
117+
return info, nil
110118
}
111119

112120
func newMountInfo() (*MountInfo, error) {
113-
file, err := os.Open("/proc/self/mountinfo")
121+
parseSelfInfo := func() (*MountInfo, error) {
122+
file, err := os.Open("/proc/self/mountinfo")
123+
if err != nil {
124+
return nil, err
125+
}
126+
127+
defer file.Close()
128+
return parseMountInfo(file, nil)
129+
}
130+
131+
parseRootInfo := func(info *MountInfo) (*MountInfo, error) {
132+
file, err := os.Open("/proc/1/mountinfo")
133+
if err != nil {
134+
switch {
135+
case errors.Is(err, os.ErrInvalid), errors.Is(err, os.ErrPermission), errors.Is(err, os.ErrExist), errors.Is(err, os.ErrNotExist), errors.Is(err, os.ErrClosed):
136+
default:
137+
klog.ErrorS(err, "unable to read /proc/1/mountinfo; open an issue in SUBNET with this log")
138+
}
139+
return info, nil
140+
}
141+
142+
defer file.Close()
143+
return parseMountInfo(file, info)
144+
}
145+
146+
info, err := parseSelfInfo()
114147
if err != nil {
115148
return nil, err
116149
}
117150

118-
defer file.Close()
119-
return parseMountInfo(file)
151+
return parseRootInfo(info)
120152
}
121153

122154
var mountFlagMap = map[string]uintptr{

0 commit comments

Comments
 (0)