Skip to content

Commit 51c421d

Browse files
committed
filesystem: make FindMount() fall back to search by path
This is needed to make FindMount() work on btrfs filesystems. Update #339
1 parent 65a445d commit 51c421d

1 file changed

Lines changed: 25 additions & 5 deletions

File tree

filesystem/mountpoint.go

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -364,18 +364,38 @@ func FindMount(path string) (*Mount, error) {
364364
if err := loadMountInfo(); err != nil {
365365
return nil, err
366366
}
367+
// First try to find the mount by the number of the containing device.
367368
deviceNumber, err := getNumberOfContainingDevice(path)
368369
if err != nil {
369370
return nil, err
370371
}
371372
mnt, ok := mountsByDevice[deviceNumber]
372-
if !ok {
373-
return nil, errors.Errorf("couldn't find mountpoint containing %q", path)
373+
if ok {
374+
if mnt == nil {
375+
return nil, filesystemLacksMainMountError(deviceNumber)
376+
}
377+
return mnt, nil
374378
}
375-
if mnt == nil {
376-
return nil, filesystemLacksMainMountError(deviceNumber)
379+
// The mount couldn't be found by the number of the containing device.
380+
// Fall back to walking up the directory hierarchy and checking for a
381+
// mount at each directory path. This is necessary for btrfs, where
382+
// files report a different st_dev from the /proc/self/mountinfo entry.
383+
curPath, err := canonicalizePath(path)
384+
if err != nil {
385+
return nil, err
386+
}
387+
for {
388+
mnt := mountsByPath[curPath]
389+
if mnt != nil {
390+
return mnt, nil
391+
}
392+
// Move to the parent directory unless we have reached the root.
393+
parent := filepath.Dir(curPath)
394+
if parent == curPath {
395+
return nil, errors.Errorf("couldn't find mountpoint containing %q", path)
396+
}
397+
curPath = parent
377398
}
378-
return mnt, nil
379399
}
380400

381401
// GetMount is like FindMount, except GetMount also returns an error if the path

0 commit comments

Comments
 (0)